Tải bản đầy đủ (.pdf) (93 trang)

LUẬN VĂN:KIỂM CHỨNG ĐẶT TẢ UML CHO TÁC TỬ PHẦN MỀM docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.16 MB, 93 trang )

ĐẠI HỌC QUỐC GIA HÀ NỘI
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ


Vũ Sỹ Vương

KIỂM CHỨNG ĐẶT TẢ UML CHO TÁC TỬ
PHẦN MỀM





KHOÁ LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY
Ngành: Công nghệ phần mềm







HÀ NỘI - 2009

ĐẠI HỌC QUỐC GIA HÀ NỘI
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ

Vũ Sỹ Vương

KIỂM CHỨNG ĐẶT TẢ UML CHO TÁC TỬ
PHẦN MỀM








KHOÁ LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY
Ngành
: Công nghệ phần mềm


Cán bộ hướng dẫn:
Tiến sỹ Trương Anh Hoàng




HÀ NỘI - 2009
Lời cám ơn
Trước tiên tôi xin gửi lời cảm ơn sâu sắc tới TS. Trương Anh Hoàng, Bộ môn
Công nghệ phần mềm, Khoa Công nghệ thông tin, Trường Đại học Công Nghệ, Đại
Học Quốc Gia Hà Nội – người đã định hướng đề tài và tận tình hướng dẫn chỉ bảo tôi
trong suốt quá trình thực hiện khóa luận tốt nghiệp này.
Tôi cũng xin trân trọng cảm ơn quý th ầy cô trong Khoa Công nghệ thông tin
trường Đại học Công Nghệ, Đại Học Quốc Gia Hà Nội đã tận tình giảng dạy, truyền
đạt những kiến thức quý báu trong suốt bốn năm học làm nền tảng cho tôi thực hiện
khóa luận tốt nghiệp này.
Con xin cảm ơn cha mẹ và gia đình đã sinh ra và nuôi d ạy con khôn lớn, luôn
bên cạnh động viên và ủng hộ con trên con đường mà con đã yêu thích và lựa chọn.
Cảm ơn các bạn sinh viên Khoa Công nghệ thông tin khóa 2005 – 2009. Các bạn

đã giúp đỡ và ủng hộ tôi rất nhiều cũng như đóng góp nhiều ý kiến quý báu, qua đó,
giúp tôi hoàn thiện khóa luận tốt hơn.
Mặc dù đã rất nỗ lực, cố gắng nhưng chắc hẳn khóa luận của tôi vẫn còn nhiều
thiếu sót. Tôi rất mong nhận được nhiều những ý kiến đánh giá, phê bình của quý thầy
cô, của các anh chị và các bạn.
Một lần nữa, tôi xin chân thành cảm ơn.
Hà Nội, tháng 5 năm 2009
Vũ Sỹ Vương

Tóm tắt nội dung

Trong quy trình phát triển phần mềm, kiểm chứng phần mềm đóng vai trò quan
trọng trong việc đảm bảo tính đúng đắn của hệ thống trong suốt quá trình thực thi. Nó
có nhiệm vụ phát hiện và dò tìm lỗi cho giai đoạn kiểm thử phần mềm. Phương pháp
lập trình hướng khía cạnh (AOP) cùng với công nghệ AspectJ ra đời đã tạo ra hướng
phát triển mới cho kiểm chứng phần mềm, giúp nâng cao chức năng dò tìm, s ửa lỗi
phần mềm mà không ảnh hưởng tới mã nguồn hệ thống. Từ yêu cầu thực tế, khi mà
mô hình UML đang là sự lựa chọn phổ biến cho việc mô hình hóa hệ thống phần mềm
ở giai đoạn thiết kế, việc kiểm chứng các giao thức ràng buộc đối tượng, giao thức
ràng buộc giữa các tác tử trong hệ đa tác tử được mô tả trong biểu đồ trạng thái và biểu
đồ trình tự UML, AUML là rất cần thiết trong thời gian chạy. Dựa vào yêu cầu thực tế
đặt ra cùng với việc lựa chọn AOP làm giải pháp giải quyết vấn đề, trong phạm vi
khóa luận, tôi xin trình bày phương pháp sinh mã aspect phục vụ cho mục đích kiểm
chứng phần mềm và xây dựng công cụ Protocol Verification Generator (PVG) tự động
sinh mã aspect dựa trên phương pháp này. Nội dung chính của phương pháp là dựa
vào các kiến thức về AOP và UML, XML, AUML, JADE framework để chuyển đổi
các giao thức ràng buộc đối tượng được đặc tả bởi biểu đồ UML, giao thức tương tác
giữa các tác tử trong hệ đa tác tử được đặc tả bởi biểu đổ AUML sang các mô-đun
aspect phục vụ quá trình kiể
m chứng. Ý nghĩa th ực tiễn của bài toán là việc sử dụng

mã aspect vừa được tạo ra đan vào chương trình chính thông qua b ộ đan (aspect
weaver) của AspectJ để thực hiện nhiệm vụ kiểm chứng các giao thức ràng buộc giữa
các đối tượng, các tác tử trong thời gian chạy.

Mục lục
Chương 1. Mở đầu 1
1.1 Đặt vấn đề 1
1.2 Nội dung bài toán 2
1.3 Tổng quan phương pháp “Kiểm chứng đặc tả UML cho tác tử phần
mềm” 3

1.4 Cấu trúc khóa luận 4
Chương 2. Giới thiệu lập trình hướng khía cạnh (Aspect-Oriented Programming)
và AspectJ 6

2.1 Phương pháp lập trình hướng khía cạnh 6
2.1.1 Sự hạn chế của lập trình hướng đối tượng (OOP) 6
2.1.2 Lập trình hướng khía cạnh (AOP) 9
2.2 AspectJ 12
2.2.1 Join point 12
2.2.2 Pointcut 12
2.2.3 Advice 13
2.2.4 Aspect 14
2.2.5 Cơ chế họa động của AspectJ 15
2.3 Sử dụng AOP Phát triển ứng dụng và phương pháp kiểm chứng dựa
trên AOP 15

2.4 Kết luận 17
Chương 3. Agent UML và JADE framework 18
3.1 Ngôn ngữ mô hình hóa UML 18

3.1.1 Khái niệm 18
3.1.2 Biểu đồ trạng thái (State Diagram) 18
3.1.3 Biểu đồ trình tự (Sequence Diagram) 19
3.2 XML (eXtensible Markup Language) 20
3.2.1 Cơ bản về XML 20
3.2.2 XML DOM 22
3.3 XMI (XML Metadata Interchange) 24
3.4 AUML (Agent UML) 25
3.4.1 Tác tử phần mềm là gì? 25
3.4.2 Phần mềm hướng Agent 26
3.4.3 AUML (Agent Unified Modeling Language) 28
3.5 Java Agent DEvelopment Framework (JADE) 31
3.5.1 Khái niệm về JADE 31
3.5.2 Cấu trúc của JADE platform 32
3.5.3 Một số lớp quan trọng trong thư viện JADE 33
3.6 Kết luận 34
Chương 4. Xây dựng máy trạng thái từ biểu đồ UML 35
4.1 Biểu đồ trạng thái 35
4.1.1 Quy tắc biểu diễn giao thức bằng biểu đồ trạng thái 35
4.1.2 Xây dựng cấu trúc dữ liệu mô tả biểu đồ trạng thái UML 36
4.1.3 Xây dựng FSM mô tả biểu đồ trạng thái UML 40
4.2 Biểu đồ trình tự UML 42
4.2.1 Cách biểu diễn giao thức giữa nhiều đối tượng bằng biểu đồ trình tự
UML 42

4.2.2 Xây dựng cấu trúc dữ liệu mô tả biểu đồ trình tự UML 43
4.2.3 Xây dựng FSM mô tả biểu đồ trình tự UML 46
4.3 Kết luận 47
Chương 5. Xây dựng công cụ tự động sinh aspect từ máy trạng thái 48
5.1 Đặt vấn đề 48

5.2 Sinh aspect từ FSM mô tả biểu đồ trạng thái UML 49
5.3 Sinh aspect từ FSM mô tả biểu đồ trình tự UML 50
5.4 Mở rộng 51
5.5 Sinh mã aspect kiểm chứng giao thức (AB)
n
52
5.5.1 Giao thức (AB)
n
là gì? 52
5.5.2 Thuật toán kiểm chứng giao thức (AB)
n
53
5.5.3 Sinh mã aspect kiểm chứng giao thức (AB)
n
54
5.6 Kết luận 54
Chương 6. Thực nghiệm 55
6.1 Xây dựng công cụ PVG 55
6.2 Kiểm chứng một số giao thức thực tế 56
6.2.1 Giao thức của các ứng dụng Applet 56
6.2.2 Kiểm chứng giao thức biểu diễn giao thức ghi nợ ở một máy ATM 60
6.2.3 Kiểm chứng giao thức [A*B]
n
64
6.2.4 Kiểm chứng giao thức tương tác tác tử 66
6.3 Kết luận 70
Chương 7. Kết luận 71
7.1 Kết luận về khóa luận 71
7.2 Hướng phát triển trong tương lai 72
Phụ lục 73

Phụ lục A: Tài liệu XMI mô tả biểu đồ trạng thái UML 73
Phụ lục B: Tài liệu XMI mô tả biểu đồ trình tự UML 75
Phụ lục C: Agent Customer (Customer.java) 78
Phụ lục D: Agent ShoppingCart (ShoppingCart.java) 81
Phụ lục E: Aspect Template 83


Danh mục ký hiệu, từ viết tắt

AOP Aspect-Oriented Programming
FSM Finite State Machine
JADE Java Agent DEvelopment Framework
OOP Object Oriented Programming
PVG Protocol Verification Generator
XMI XML Metadata Interchange
XML eXtensible Markup Language
UML Unified Modeling Language


1

Chương 1. Mở đầu

1.1 Đặt vấn đề
Ngày nay công nghệ thông tin đã được ứng dụng vào tất cả các lĩnh vực của đời
sống xã hội. Nó đã tạo ra một diện mạo mới cho xã hội và nhờ đó nền văn minh nhân
loại đã được nâng lên một tầm cao mới. Nói đến công nghệ thông tin là nói đến công
nghệ phần mềm – một phần không thể tách rời của công nghệ thông tin. Hiện nay
ngành công nghệ phần mềm trên thế giới đã và đang phát triển như vũ bão. Những tiến
bộ vượt bậc của khoa học kỹ thuật phần cứng đã tạo điều kiện thuận lợi cho công nghệ

phần mềm ngày càng phát triển không ngừng.
Phần mềm được coi là sản phẩm chính của công nghệ phần mềm, được phát triển
theo các mô hình, quy trình phát triển đặc biệt. Quá trình phát triển phần mềm bao
gồm rất nhiều giai đoạn: Thu thập yêu cầu, phân tích, thiết kế, xây dựng, kiểm tra,
triển khai và bảo trì phần mềm. Trong các giai đoạn đó giai đoạn kiểm tra, phát hiện,
xác định và sửa các lỗi phần mềm là rất quan trọng để đảm bảo chất lượng của một
phần mềm. Các lỗi phần mềm có thể gây thiệt hại to lớn về tiền bạc, thời gian và công
sức của con người. Lỗi phần mềm được phát hiện càng muộn thì càng gây hậu quả
nghiêm trọng, tốn rất nhiều thời gian và công sức để sửa chữa lỗi, thậm chí có thể phải
xây dựng lại toàn bộ hệ thống từ đầu. Chính ví vậy cần có các phương pháp phát hiện
lỗi sớm nhằm giảm thiểu công sức để sửa chúng. Để
phát hiện ra những lỗi phần mềm,
phần mềm cần phải được kiểm chứng (Verification) và thẩm định (Valication) [13].
Kiểm chứng phần mềm là kiểm tra xem phần mềm có được thiết kế đúng và thực thi
đúng như đặc tả yêu cầu hay không. Thẩm định phần mềm là giai đoạn có sự hỗ trợ
của khách hàng nhằm kiểm tra xem phần mềm có đáp ứng được các yêu cầu của họ
hay không.
Mục đích chính của kiểm chứng phần mềm là làm giảm thiểu lỗi phần mềm tới
mức có thể chấp nhận được. Chính vì vậy, nó có vai trò vô cùng quan trọng trong toàn
bộ quy trình phát triển phần mềm và trong ngành công nghệ phần mềm hiện nay. Nó
đã và đang thu hút được mối quan tâm của rất nhiều nhà nghiên cứu.
Giai đoạn kiểm thử trong quy trình phát triển phần mềm có mục đích kiểm tra
tính đúng đắn của sản phầm phần mềm. Trên thực tế, các thao tác kiểm thử đơn vị chỉ
đánh giá được tính đúng sai của đầu vào và đầu ra của chương trình, không kiểm tra
được quá trình hoạt động logic của chương trình có theo đúng đ ặc tả ban đầu hay
2

không. Những đơn vị chương trình nhỏ này nếu không được kiểm tra kỹ sẽ có thể gây
ra thiệt hại nặng nề khi tích hợp chúng để tạo thành chương trình hoàn chỉnh. Vấn đề
đặt ra là cần có phương pháp kiểm chứng các đặc tả giao thức giữa các đối tượng, các

tác tử ngay trong thời gian chạy, đánh giá xem trong thời gian chạy đối tượng hay tác
tử phần mềm có vi phạm các giao thức ràng buộc đã được đặc tả hay không, và từ đó
đảm bảo chắc chắn hơn tính đúng đắn của sản phầm phần mềm. Trong khóa luận này,
tôi xin giới thiệu phương pháp tự động sinh mã aspect kiểm chứng đặc tả giao thức
trong thời gian chạy, dựa trên phương pháp lập trình hư ớng khía cạnh (Aspect –
Oriented Programming).
1.2 Nội dung bài toán
Hiện nay có rất nhiều phương pháp kiểm chứng phần mềm như giả lập hay kiểm
chứng mô hình. Trong phạm vi bài toán được đặt ra ở đây, tôi muốn đề cập tới phương
pháp kiểm chứng phần mềm dựa trên phương pháp lập trình hư ớng khía cạnh (AOP)
[7, 12]. Lĩnh vực kiểm chứng cụ thể trong phạm vi bài toán là kiểm chứng giao thức
đặc tả hoạt động của các đối tượng Java và kiểm chứng giao thức giữa các tác tử trong
hệ đa tác tử (giao thức được mô tả bằng biểu đồ trạng thái và biểu đồ trình tự UML,
AUML) trong thời gian chạy.
Trong cách tiếp cận này, một ứng dụng hướng đối tượng được đặc tả bằng mô
hình UML và được cài đặt bằng ngôn ngữ Java; một hệ đa tác tử được đặc tả bằng các
biểu đồ AUML và được cài đặt dựa trên JADE framework. Các aspect sau đó sẽ được
đan vào khung mã Java đ ể kiểm tra tại bất kỳ thời điểm nào trong thời gian chạy, các
đối tượng Java, các tác tử phần mềm hoạt động vi phạm giao thức đã đặc tả (aspect là
mô-đun cắt ngang hệ thống). Bài toán có nhiệm vụ là tạo ra được các aspect từ biểu đồ
trạng thái và biểu đồ trình tự UML; dùng công cụ AspectJ để đan các aspect này vào
khung chương trình Java chính . Khi đó, trong quá trình ch ạy của chương trình, các
đoạn mã aspect sẽ tự động kiểm tra các đặc tả giao thức và đưa ra thông báo lỗi khi có
bất kỳ vi phạm nào xảy ra. Trong khi phương pháp kiểm thử đơn vị chỉ xác định được
tính đúng đắn c
ủa đầu vào và đầu ra của chương trình, không kiểm tra được những lỗi
logic thì phương pháp kiểm tra tính đúng đắn ngay tại thời gian chạy của chương trình
sẽ đem lại hiệu quả rất lớn.
Nhiệm vụ chính của bài toán là xây dựng phương pháp tạo ra các đoạn mã aspect
để kiểm chứng, xây dựng công cụ Protocol Verification Generator(PVG) tự động sinh

mã aspect kiểm chứng từ đặc tả giao thức bằng biểu đồ trạng thái và biểu đồ trình tự
UML, AUML. Tôi xin đề cập hướng nghiên cứu kiểm chứng đặc tả UML cho tác tử
3

phần mềm để kiểm chứng giao thức giữa các đối tượng Java trong thời gian chạy và
kiểm chứng giao thức giữa các tác tử trong hệ đa tác tử được xây dựng trên JADE
framework. Từ một biểu đồ trạng thái hay biểu đồ trình tự UML, AUML xuất ra tài
liệu XMI đặc tả các biểu đồ này. Các tài liệu XMI chính là đầu vào cho công cụ cần
xây dựng. Dựa vào các kiến thức về UML, XML tôi sẽ phân tích tài liệu XMI, xây
dựng máy trạng thái (FSM) mô tả các biểu đồ UML, AUML. Sử dụng máy trạng thái
vừa tạo để sinh ra mã aspect phục vụ cho việc kiểm chứng sau này. Mã aspect chính là
đầu ra cuối cùng của công cụ.
1.3 Tổng quan phương pháp “Kiểm chứng đặc tả UML
cho tác tử phần mềm”
Bài toán bắt đầu với đầu vào là một biểu đồ trạng thái hay biểu đồ trình tự UML,
các biểu đồ này sẽ được xuất ra dạng XMI. Sau đó, lấy ra các thông tin cần thiết mô tả
các đối tượng của biểu đồ và chuyển thành một máy trạng thái (FSM). Lập trình viên
sẽ phát triển các mô-đun nghiệp vụ chính từ hai biểu đồ này và các biểu đồ UML khác
còn lại. Song song với nó là quá trình xây dựng các mô-đun cắt ngang hệ thống thành
các aspect từ máy trạng thái. Bài báo “Checking Interface Interaction Protocols Using
Aspect-oriented Programming” [5] đã xây dựng phương pháp kiểm chứng giao thức
xử dụng AOP. Dựa vào nội dung phương pháp này tôi đã xây d ựng công cụ tự động
hóa việc sinh các mô-đun aspect với đầu vào là tài liệu XMI mô tả biểu đồ trạng thái
hay biểu đồ trình tự UML. Phương pháp xây dựng công cụ Protocol Verification
Generator của tôi gồm hai bước:
- Bước1: Phân tích tài liệu XMI, lấy các thông tin cần thiết mô tả biểu đồ
UML để xây dựng máy trạng thái. Đầu tiên, tôi sẽ phân tích tài liệu XMI,
xây dựng các cấu trúc dữ liệu mô tả các thành phần của biểu đồ UML bằng
ngôn ngữ Java, sau đó sử dụng thư viện XML DOM đọc tài liệu XMI này,
lấy dữ liệu theo cấu trúc đã định nghĩa trước, tạo ra FSM.

- Bước 2: Xây dựng bộ sinh tự động aspect từ FSM: Sử dụng FSM vừa
được sinh ra, duyệt từng trạng thái trong FSM, áp dụng phương pháp cài
đặt aspect trong bài báo nói trên, tôi sẽ tạo ra các join point, pointcut và
advice từ các trạng thái đó để hình thành mô-đun aspect.
Trong hình minh họa dưới đây, tôi sẽ xây dựng công cụ Protocol Verification
Generator. Kết quả thu được là các đoạn mã aspect sẽ được đan vào chương trình Java
thông qua trình biên dịch AspectJ. Kết quả cuối cùng của quá trình này chính là hệ
4

thống có chứa những đoạn mã kiểm chứng. Trong quá trình thực thi, kể cả trong thời
gian chạy, bất cứ khi nào xảy ra vi phạm ràng buộc đã định nghĩa trong biểu đồ UML
thì chương trình đều báo thông báo lỗi cho lập trình viên, chỉ ra vị trí dòng mã nguồn
sai đặc tả trong mã nguồn của chương trình. Nhờ đó, lập trình viên có thể kiểm soát
được hệ thống và làm cho hệ thống chạy ổn định và đúng đắn hơn.
Use Case Diagram
Class Diagram
Sequence Diagram
State Diagram
…….
UML
XMI File
(*.xmi, *.xml)
Protocol
Specification
AspectJ Generator
Java code AspectJ codeAspectJ Weaver
Bytecode with
Protocol checking

Hình 1.1: Quy trình kiểm chứng phần mềm dựa vào AOP

1.4 Cấu trúc khóa luận
Các phần còn lại của khóa luận được phân bố như sau:
Chương 2: Giới thiệu về phương pháp lập trình hướng khía cạnh. Trong chương
này tôi sẽ đưa ra những so sánh giữa hai phương pháp OOP và AOP, từ đó nêu bật
những ưu điểm của AOP; vai trò và ý nghĩa c ủa AOP đối với công nghệ phần mềm
hiện nay. Đồng thời, tôi cũng giới thiệu công cụ AspectJ – một cài đặt của AOP cho
ngôn ngữ lập trình Java.
Chương 3: Trình bày sơ qua về các kiến thức về: UML, XML, XMI; trình bày
một số khái niệm về tác tử phần mềm, phần mềm hướng agent và AUML – mở rộng từ
UML để mô tả các hệ thống dựa tác tử. Giới thiệu JADE – một framework hỗ trợ xây
dựng hệ đa tác tử trên ngôn ngữ Java. Đây là nền tảng kiến thức căn bản để xây dựng
công cụ tự sinh mã aspect trong khóa luận của tôi.
Chương 4: Trình bày phương pháp xây dựng máy trạng thái mô tả biểu đồ trạng
thái và biểu đồ trình tự UML. Trong chương này, tôi sẽ trình bày cách phân tích tài
5

liệu XMI mô tả các biểu đồ UML, từ đó xây dựng các cấu trúc dữ liệu cần thiết để lấy
dữ liệu từ tài liệu XMI hình thành nên máy trạng thái.
Chương 5: Xây dựng công cụ tự sinh mã aspect từ máy trạng thái. Trong
chương này, tôi sẽ trình bày chi tiết thuật toán sinh mã aspect từ máy trạng thái mô tả
biểu đồ UML. Đồng thời tôi trình bày phương pháp sinh mã aspect kiểm chứng giao
thức (AB)
n
– một mở rộng cho công cụ Protocol Verification Generator.
Chương 6: Cài đặt công cụ Protocol Verification Generator tự sinh aspect. Sau
đó, tiến hành kiểm chứng một số giao thức thực tế.
Chương 7: Đưa ra các kết luận của khóa luận và hướng nghiên cứu tiếp theo
trong tương lai.

6


Chương 2. Giới thiệu lập trình hư ớng khía cạnh
(Aspect-Oriented Programming) và AspectJ

2.1 Phương pháp lập trình hướng khía cạnh
Có lẽ các khái niệm về lập trình hướng khía cạnh (AOP) hiện nay đã được nhiều
người biết đến, vì vậy ở đây tôi sẽ chỉ trình bày lại ngắn gọn các khái niệm cơ bản và
đặc điểm chính của AOP. Để trả lời được câu hỏi AOP là gì? Tại sao phải có AOP?
chúng ta sẽ bắt đầu tìm hiểu sự hạn chế của các phương pháp lập trình hiện tại trong
việc đáp ứng các yêu cầu ngày càng phức tạp của các hệ thống phần mềm.
2.1.1 Sự hạn chế của lập trình hướng đối tượng (OOP)
Như chúng ta đã biết trong OOP người ta cố gắng mô tả thế giới thực thành các
đối tượng với các thuộc tính và phương thức; cùng với các tính chất của lập trình
hướng đối tượng như: tính trừu tượng, tính đóng gói, tính kế thừa và đa hình đã làm
thay đổi hoàn toàn ngành công nghiệp phần mềm.

Hình 2.1: OOP
Ta xét một bài toán cụ thể: Cần xây dựng một chương trình vẽ hình đơn giản như
hình vẽ mô tả dưới đây:

7


Hình 2.2: Mô tả chương trình vẽ hình đơn giản
Một phân tích đơn giản cho yêu cầu của bài toán:
- Các hình học cơ bản: điểm, đoạn thẳng, hình chữ nhật, hình tròn…
- Hiển thị các hình ở các vị trí khác nhau trong khung vẽ.
- Phải cập nhật lại hình tại vị trí mới mỗi khi di chuyển, co giãn hình.
Sử dụng OOP ta sẽ mô hình hóa yêu cầu thành các đối tượng như sau:
- Lớp Shape: là một lớp Abstract chứa phương thức moveBy(int, int) – di

chuyển hình.
- Lớp Display: hiển thị hình ảnh.
- Lớp Point: mô tả một điểm hình học. Chứa hai thuộc tính là hai tọa độ x, y
và được kế thừa từ lớp Shape.
- Lớp Line: mô tả đoạn thẳng, chứa hai thuộc tính là hai điểm mút của đoan
thẳng và cũng được kế thừa từ lớp Shape.
Ở đây tôi không đi quá sâu vào đặc tả bài toán, chỉ mô tả một số lớp đơn giản
nhất. Dưới đây là sơ đồ lớp cho bài toán vẽ hình:
8


Hình 2.3: Sơ đồ lớp cho bài toán vẽ hình
Mô hình hóa thành các lớp như vậy ta thấy bài toán đã tương đối ổn. Bây giờ vấn
đề đặt ra là mỗi khi ta thay đổi tọa độ của một điểm hay co giãn hình, di chuyển hình
ta lại phải vẽ lại hình ở vị trí mới – tức là phải update lại Display.
Xét lớp đơn giản nhất là lớp Point, Khi đặt lại tọa độ x, tọa độ y, hay di chuyển
Point từ vị trí này sang vị trí khác, ta đều phải update lại Display thông qua phương
thức display.update(this). Như vậy, cùng một phương thức display.update(this), ta
phải gõ lại ở ba vị trí khác nhau ứng với ba sự thay đổi. Hãy thử tưởng tượng xem nếu
chương trình của chúng ta đủ lớn và có khoảng vài ngàn sự thay đổi kiểu như thế thì
dòng mã nguồn display.update(this) sẽ phải xuất hiện ở hàng ngàn chỗ khác nhau.
Đối với lớp Line hay các lớp khác cũng vậy. Mỗi khi có sự thay đổi hình thì ngay
sau sự thay đổi đó sẽ có dòng mã nguồn display.update(this) đi kèm theo nó.

Hình 2.4: Cập nhật hình khi có sự thay đổi
9

Giả sử chương trình vẽ hình của chúng ta đã hoàn thành mỹ mãn với đầy đủ các
chức năng cơ bản. Đột nhiên, khách hàng yêu cầu cần phải ghi lại những sự thay đổi
khi vẽ hình ra một file log.txt. Ôi! Điều này thực sự là rất khổ sở cho lập trình viên khi

phải dò lại toàn bộ mã nguồn, xem đoạn nào có sự thay đổi hình, chèn thêm vào đó
một dòng mã nguồn có chức năng lưu vết ra file log.txt.
Ta có thể chia các chức năng của một phần mềm ra làm hai loại chính:
- Thứ nhất là các chức năng thực hiện các nghiệp vụ chính, nghiệp vụ cơ
bản của hệ thống (ví dụ như chức năng vẽ điểm, vẽ đoạn thẳng, vẽ hình
khối trong bài toán vẽ hình ở trên).
- Thứ hai, những chức năng dàn trải trên rất nhiều các mô-đun nghiệp vụ
chính – được gọi là các chức năng cắt ngang hệ thống (ví dụ: cập nhật
hình, lưu vết, bảo mật) hay được gọi là crosscutting concern.
OOP có thể giải quết rất tốt những chức năng chính của hệ thống, nhưng lại gặp
rất nhiều khó khăn trong việc giải quyết các chức năng cắt ngang hệ thống. Khi sử
dụng OOP để thực hiện các chức năng cắt ngang hệ thống, hệ thống sẽ gặp phải hai
vấn đề chính, đó là: chồng chéo mã nguồn (Code tangling) và dàn trải mã nguồn
(Code scattering) [12].
- Chồng chéo mã nguồn: Mô-đun chính của hệ thống ngoài việc thực hiện
các yêu cầu chính, nó còn phải thực hiện các yêu cầu khác như: tính đồng
bộ, bảo mật, lưu vết, lưu trữ. Như vậy, trong một mô-đun có rất nhiều loại
mã khác nhau, hiện tượng này gọi là chồng chéo mã nguồn. Điều này làm
cho tính mô-đun hóa của hệ thống giảm đi, khả năng sử dụng lại mã nguồn
thấp, khó bảo trì hệ thống.
- Dàn trải mã nguồn: Cùng một mã nguồn của các chức năng cắt ngang hệ
thống được cài đặt lặp đi lặp lại rất nhiều lần ở nhiều mô-đun chính của hệ
thống. Ví dụ như trong chương trình vẽ hình ở trên, mã nguồn của chức
năng cập nhật hình, lưu v ết xuất hiện ở tất cả các mô-đun của hệ thống.
Hiện tượng này gọi là dàn trải mã nguồn.
2.1.2 Lập trình hướng khía cạnh (AOP)
Lập trình hướng khía cạnh được xây dựng trên các phương pháp lập trình hiện tại
như lập trình hư ớng đối tượng, lập trình có cấu trúc, bổ sung thêm các khái niệm và
cấu trúc để mô-đun hóa các chức năng cắt ngang hệ thống (crosscutting concern). Với
AOP, các quan hệ cơ bản sử dụng các phương pháp cơ bản. Nếu sử dụng OOP, sẽ thực

10

thi các quan hệ cơ bản dưới hình thức lớp (class). Các aspect trong hệ thống đóng gói
các chức năng cắt ngang hệ thống lại với nhau. Chúng sẽ quy định cách các mô-đun
khác nhau gắn kết với nhau để hình thành lên hệ thống cuối cùng.
Nền tảng cơ bản của AOP khác với OOP là cách quản lý các chức năng cắt
ngang hệ thống. Việc thực thi của từng chức năng cắt ngang AOP bỏ qua các hành vi
được tích hợp vào nó. Ví dụ một mô-đun nghiệp vụ sẽ không quan tâm nó cần được
lưu vết hoặc được xác thực như thế nào, kết quả là việc thực thi của từng concern tiến
triển một cách độc lập.
Quay trở lại với ví dụ về chương trình vẽ hình đơn giản ở phần trên. Nếu sử dụng
AOP, các chức năng cắt ngang hệ thống: cập nhật hình, lưu vết sẽ được giải quyết theo
cách sau:
Thay vì tích hợp chức năng các mô-đun cắt ngang hệ thống (cập nhật hình, lưu
vết) ngay trong mô-đun nghiệp vụ chính; lập trình viên sẽ tách chúng ra thành các mô-
đun mới, gọi là aspect. Hình 2.5 minh họa cho việc thực thi chức năng cập nhật hình
bằng AOP và dưới đây là mã nguồn của aspect đó
public aspect UpdateSignaling {
pointcut updateDisplay(): execution(void *.setX(int))
|| execution(void *.setY(int))
|| execution(void *.moveBy(int,int));

after(): updateDisplay()
{
display.update(this);
}
}


Hình 2.5: Dùng AOP giải quyết bài toán vẽ hình

11

Sau khi định nghĩa một aspect như vậy thì bất cứ khi nào có sự thay đổi về hình
(setX, setY, moveBy) chương trình s ẽ tự động gọi chức năng cập nhật hình, cụ thể ở
đây là phương thức display.update(this) mà ta không cần phải lục lọi lại các đoạn mã
nguồn để thêm nó dòng mã nguồn này vào. (các khái niệm cơ bản của aspect như:
advice, join point, pointcut, aspect tôi sẽ trình bày cụ thể trong phần 2.2 nói về
AspectJ).
2.1.2.1 Phương pháp luận của AOP
Vấn đề cốt lõi của AOP là cho phép chúng ta thực hiện các vấn đề riêng biệt một
cách linh hoạt và kết nối chúng lại để tạo nên hệ thống cuối cùng. AOP bổ xung cho
OOP bằng việc hỗ trợ một dạng mô-đun khác, cho phép kéo theo thể hiện chung của
các vấn đề đan nhau vào một khối. Khối này gọi là ‘aspect’ (tạm dịch là ‘lát’ – hàm ý
cắt ngang qua nhiều lớp đối tượng). Từ chữ ‘aspect’ này chúng ta có mội phương pháp
lập trình mới: Aspect-Oriented Programming. Nhờ mã được tách riêng biệt, các vấn đề
đan xen nhau trở nên dễ kiểm soát hơn. Các aspect của hệ thống có thể thay đổi, thêm
hoặc xóa lúc biên dịch và có thể tái sử dụng. Một dạng biên dịch đặc biệt có tên là
Aspect Weaver thực hiện việc kết hợp các thành phần riêng lẻ thành một hệ thống
thống nhất.
2.1.2.2 Ưu điểm của AOP
AOP là một kỹ thuật mới đầy triển vọng, hứa hẹn đem lại nhiều lợi ích cho việc
phát triển phần mềm, dưới đây là một số lợi ích cụ thể của AOP [12]:
- Mô-đun hóa những vấn đề đan xen nhau: AOP xác định vấn đề một
cách riêng biệt, cho phép mô-đun hóa những vấn đề liên quan đến nhiều
lớp đối tượng.
- Tái sử dụng mã nguồn tốt hơn: Các aspect là những mô-đun riêng biệt,
được kết hợp linh động – đây chính là yếu tố quan trọng để tái sử dụng mã
nguồn.
- Cho phép mở rộng hệ thống dễ dàng hơn: Một thiết kế tốt phải tính đến
cả những yêu cầu hiện tại và tương lai, việc xác định các yêu cầu trong

tương lai là một công việc khó khăn. Nhưng nếu bỏ qua các yêu cầu trong
tương lai, có thể bạn sẽ phải thay đổi hay thực hiện lại nhiều phần của hệ
thống. Với AOP, người thiết kế hệ thống có thể để lại quyết định thiết kế
cho những yêu cầu trong tương lai nhờ thực hiện các aspect riêng biệt.
12

2.2 AspectJ
AspectJ là sự mở rộng theo mô hình AOP của ngôn ngữ Java, với sự mở rộng
này mã chương trình viết bằng Java sẽ tương thích với chương trình viết bằng AspectJ.
AspectJ gồm hai phần cơ bản là:
- Đặc tả ngôn ngữ: Chỉ ra cách viết mã, với AspectJ các chức năng cơ bản
của hệ thống sẽ được viết bằng Java còn các chức năng cắt ngang hệ thống
sẽ được thực hiện bởi AspectJ.
- Phần thực thi: Cung cấp các công cụ biên dịch, gỡ lỗi. AspectJ đã đư ợc
plugin vào công cụ phát triển Eclipse (
và được
đánh giá là sản phẩm tốt nhất hiện nay về AOP.
Một số khái niệm cơ bản trong AspectJ:
2.2.1 Join point
Join point là bất kỳ điểm nào có thể xác định được khi thực hiện chương trình [7,
12]. Ví dụ: lời gọi hàm, khởi tạo đối tượng. Join point chính là vị trí mà các hành động
thực thi cắt ngang được đan vào. Trong AspectJ mọi thứ đều xoay quanh join point.
Một số loại join point chính trong AspectJ:
- Join point tại hàm khởi tạo (constructor).
- Join point tại các phương thức.
- Join point tại các điểm truy cập thuộc tính.
- Join point tại các điểm điều khiển ngoại lệ: Được điều khiển trong khối
điều khiển ngoại lệ.
2.2.2 Pointcut
Pointcut là một cấu trúc chương trình mà nó chọn các join point và ngữ cảnh tại

các join point đó [7, 12]. Ví dụ một pointcut có thể chọn một join point là lời gọi đến
một phương thức và lấy thông tin ngữ cảnh của phương thức đó như đối tượng chứa
phương thức đó, các tham số của phương thức đó.
Cú pháp của pointcut được khai báo như sau:
[access specifier] pointcut pointcut-name([args]) : pointcut-
definition;
Ví dụ:
public pointcut test(): call(void Line.setP1(Point));
13

Bảng 2.1: Ánh xạ giữa các loại join point và pointcut tương ứng:
Loại join point
Cú pháp pointcut
Thực hiện phương thức
execution(MethodSignature)
Gọi phương thức
call(MethodSignature)
Thực hiện hàm dựng
execution(ConstructorSignature)
Gọi hàm dựng
call(ConstructorSignature)
Khởi tạo lớp
staticinitialization(TypeSignature)
Đọc thuộc tính
get(FieldSignature)
Ghi thuộc tính
set(FieldSignature)
Thực hiện điều khiển ngoại
lệ
execution handler(TypeSignature)

Khởi tạo đối tượng
initialization(ConstructorSignature)
Tiền khởi tạo đối tượng
preinitialization(ConstructorSignature)
Thực hiện advice
adviceexecution()

2.2.3 Advice
Advice là mã thực hiện tại một join point mà được chọn bởi pointcut [7, 12]. Hay
nói cách khác, nếu ta coi pointcut là khai báo tên phương thức, thì advice là phần thân
của phương thức đó. Pointcut và advice sẽ hình thành nên các luật đan kết các quan hệ
đan xen.
Advice được chia ra làm ba loại sau:
- Before: Được thực hiện trước join point.
- After: Được thực hiện sau join point.
- Around: Thực thi xung quanh join point.
Giả sử ta có pointcut được khai báo như sau:
pointcut updateDisplay(): execution(void *.moveBy(int,int))
Ta có thể xây dựng các advice như sau:
- Before advice thự hiện lưu vết
before() : updateDisplay() {
14

// logging
}

- After advice thực hiện cập nhật hình
after() : updateDisplay() {
display.update(this);
}


Ví dụ về around advice dùng để kiểm tra thuộc tính age của lớp Person trong
phương thức setAge() có vi phạm điều khiện không (điều kiện: age > 0).
void around(Person person, int age):setAge(person, age)
{
if(age > 0)
Process(person,age);
else
System.out.println("Invalid Age!");
}
2.2.4 Aspect
Aspect là phần tử trung tâm của AspectJ, giống như class trong Java. Aspect chứa
mã thể hiện các luật đan kết cho các concern. Join point, pointcut, advice được kết hợp
trong aspect [7, 12].
Aspect được khai báo theo mẫu sau:
[access specification] aspect <AspectName>
[extends class-or-aspect-name]
[implements interface-list]
[<association-specifier>(Pointcut)] {
aspect body
}

Ví dụ:
public abstract aspect AbstractLogging {

public abstract pointcut logPoints();
public abstract Loger getLogger();

before():logPoints()
{

getLogger().log(Level.INFO, “Before” + thisJoinPoint);
}
}
Tuy có gần giống các đặc điểm của class trong Java như: chứa thuộc tính,
phương thức, có thể khai báo trừu tượng, có thể kế thừa… Tuy nhiên, Aspect có một
số khác biệt cơ bản sau:
15

- Aspect không thể khởi tạo trực tiếp.
- Aspect không thể kế thừa từ một aspect cụ thể (không phải trừu tượng)
Aspect có thể được đánh dấu là có quyền bằng định danh privileged. Nhờ đó nó
có thể truy cập đến các thành viên của lớp mà chúng cắt ngang.
2.2.5 Cơ chế họa động của AspectJ
Aspect compiler là thành phần trung tâm của AspectJ, nó có nhiệm vụ kết hợp
các file mã nguồn Java với các aspect lại với nhau để tạo ra chương trình cu ối cùng.
Quá trình dệt có thể xảy ra ở các thời điểm khác nhau: compile – time, link – time và
load – time [7]:
- Compile – time: Dệt trong thời gian biên dịch là cách đơn giản nhất. Mã
nguồn Java và các aspect sẽ được kết hợp với nhau trước khi trình biên
dịch dịch mã nguồn ra dạng byte code. Hay nói cách khác, trước khi biên
dịch, các mã aspect sẽ được phân tích, chuyển đổi sang dạng mã Java và
được chèn chính xác vào các vị trí đã định nghĩa sẵn trong mã nguồn Java
chính của chương trình. Sau đó trình biên dịch sẽ dịch mã đã được dệt này
ra dạng byte code. AspectJ 1.0.x sử dụng cách này để dệt chương trình.
- Link – time: Quá trình dệt được thực hiện sau khi mã nguồn Java và các
aspect được biên dịch ra dạng byte code. Một bộ xử lý tĩnh được sử dụng
để đánh dấu các điểm gọi hàm trong mã được viết bằng java. Khi một hàm
được thực thi. Runtime system sẽ phát hiện ra điểm nào cần gọi đến mã
aspect để thực thi và khi đó mã aspect sẽ được gọi để đan vào chương trình
chính. AspectJ 1.1.x sử dụng cách này để dệt chương trình.

- Load – time: Quá trình dệt được thực hiện khi máy ảo Java tải một class
vào để chạy. Theo cách này, mã nguồn Java và các aspect được biên dịch
ra dạng byte code. Quá trình dệt diễn ra khi classloader nạp một class.
AspectJ 1.5.x sử dụng cách này để dệt chương trình.
2.3 Sử dụng AOP Phát triển ứng dụng và phương pháp
kiểm chứng dựa trên AOP
Ngày nay, AOP được ứng dụng rộng rãi trong việc phát triển phần mềm. Phát
triển hệ thống sử dụng AOP tương tự như phát triển hệ thống sử dụng các phương
pháp khác, cũng g ồm các bước như: xác định concern, cài đặt concern và kết hợp
16

chúng lại tạo thành hệ thống cuối cùng. Cộng đồng nghiên cứu AOP đề xuất ba bước
[12] thực hiện như sau:
- Phân tích bài toán theo khía cạnh (Aspectual decomposition): Trong
bước này chúng ta phân tích các yêu cầu nhằm xác định các chức năng
chính của hệ thống và các chức năng cắt ngang hệ thống. Các phương thức
cắt ngang hệ thống được tách ra khỏi các chức năng chính.
- Xây dựng các chức năng (Concern Implementation): Cài đặt các chức
năng một cách độc lập.
- Kết hợp các khía cạnh lại để tạo nên hệ thống hoàn chỉnh (Aspectual
Recompositon): Trong bước này chúng ta chỉ ra các quy luật kết hợp bằng
cách tạo ra các aspect. Quá trình này gọi là quá trình dệt mã, sử dụng các
thông tin trong aspect để cấu thành hệ thống cuối cùng.

Hình 2.6: Các giai đoạn phát triển ứng dụng sử dụng AOP
AOP đã được nghiên cứu và áp dụng vào rất nhiều ngôn ngữ lập trình như: Java,
C, C#, PHP. Một số dự án được liệt kê trong bảng dưới đây:
Bảng 2.2: Các dự án nghiên cứu AOP
Tên dự án
Địa chỉ

1. AspectJ

1. AspectWerkz

2. Jboss AOP

3. Sping AOP

4. Aspect#

5. AspectC++

6. JAC

17


Từ khả năng mô-đun hóa các quan hệ đan xen, các chức năng cắt ngang hệ
thống; tách rời sự hoạt động của các mô-đun cũng như nhiều ưu điểm khác của AOP
so với OOP mà hiện nay AOP đã trở thành sự lựa chọn phù hợp cho rất nhiều hệ thống
phần mềm; đặc biệt là trong các chức năng lưu vết, bảo mật, xác thực của hệ thống
phần mềm. Ngoài ra, do các mã aspect độc lập với mã nguồn chính của chương trình,
có thể sửa đổi tùy theo ý muốn của lập trình viên, chính vì vậy AOP còn đư ợc ứng
dụng rất lớn vào các loại kiểm chứng trong quá trình thiết kế phần mềm. Ví dụ như:
kiểm chứng giao thức [5], kiểm tra việc gọi tuần tự các hàm trong chương trình [15]…
Nội dung chính của các phương pháp kiểm chứng dựa trên AOP là dựa vào
những kiến khái niệm cơ bản của AOP như: join point, pointcut, advice, aspect để xây
dựng nên các mô-đun kiểm chứng (các aspect) từ các chức năng cắt ngang hệ thống.
Các aspect này sẽ được đan vào khung mã ngu ồn chương trình thông qua trình biên
dịch AspectJ để thực hiện chức năng kiểm chứng.

2.4 Kết luận
Trong chương 2 này, tôi trình bày tất cả những khái niệm cơ bản về phương pháp
lập trình hướng khía cạnh AOP và AspectJ – sự mở rộng của AOP cho Java. Ứng dụng
của AOP vào phát triển và kiểm chứng phần mềm. AOP vẫn là một ý tưởng mới, vẫn
cần có thời gian để đánh giá, tìm hiểu các kỹ thuật hiện có và để phát triển, ứng dụng
rộng rãi

×