Tài liệu Khóa luận Kiểm chứng đặt tả uml cho tác tử phần mềm: ĐẠ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...
93 trang |
Chia sẻ: haohao | Lượt xem: 1214 | Lượt tải: 0
Bạn đang xem trước 20 trang mẫu tài liệu Khóa luận Kiểm chứng đặt tả uml cho tác tử phần mềm, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
ĐẠ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
[extends class-or-aspect-name]
[implements interface-list]
[(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
18
Chương 3. Agent UML và JADE framework
3.1 Ngôn ngữ mô hình hóa UML
3.1.1 Khái niệm
UML (Unified Modeling Language) là ngôn ngữ mô hình hóa đư ợc sử dụng để
biểu diễn, đặc tả và xây dựng các thành phần của hệ thống phần mềm. Nó là một
chuẩn của tổ chức OMG (Object management Group) [11]. UML giúp người sử dụng
mô tả được các tài liệu đặc tả yêu cầu, tài liệu phân tích và tài liệu thiết kế ứng dụng.
Hiện nay, nó được dùng để mô tả hình hóa gần như toàn bộ các hệ thống phần mềm từ
nhỏ tới lớn, từ đơn giản tới phức tạp trên thế giới.
UML sử dụng một hệ thống ký hiệu thống nhất để biểu diễn các phần tử mô hình.
Tập các phần tử mô hình tạo nên các biểu đồ UML. Có nhiều loại biểu đồ UML như:
biểu đồ ca sử dụng, biểu đồ lớp, biểu đồ tuần tự, biểu đồ trạng thái, biểu đồ hoạt
động… Ở đây tôi chỉ trình bày hai loại biểu đồ được sử dụng làm đầu vào cho nghiên
cứu của tôi; đó là: biểu đồ trạng thái (State Diagram) và biểu đồ trình tự (Sequence
Diagram).
3.1.2 Biểu đồ trạng thái (State Diagram)
Biểu đồ trạng thái là một sự bổ sung cho lời miêu tả biểu đồ lớp. Nó mô tả chu
kỳ tồn tại của đối tương từ khi sinh ra đến khi bị phá hủy. Nó chỉ ra tất cả các trạng
thái mà đối tượng của lớp này có thể có, các hành vi của đối tượng và những sự kiện
tác động làm thay đổi trạng thái.
Ví dụ:
Hình 3.1: Biểu đồ trạng thái thực hiện hóa đơn
Một trạng thái có thể có ba phần sau:
- Name: Tên của trạng thái, Ví dụ: Paid, Unpaid.
19
- State variables (các biến trạng thái – không bắt buộc): đây là những thuộc
tính của lớp được thể hiện qua biểu đồ trạng thái
- Activities (sự kiện – không bắt buộc): Đây là phần dành cho hoạt động nơi
mà các sự kiện và hành động và liệt kê. Có ba loại sự kiện chuẩn hóa có
thể được sử dụng cho hành động:
o Entry: Xác định các hành động tạo trạng thái.
o Exit: Xác định các hành động khi rời bỏ trạng thái.
o Do: Xác định các hành động cần phải thực hiện trong trạng thái.
Sự kiện là nguyên nhân của chuyển trạng thái. Một sự kiện có thể kích hoạt một
hoặc nhiều hành động bởi một tác nhân. Trong UML, có các kiểu sư kiện:
- Change events: Xuất hiện khi điều kiện thỏa mãn.
- Signal events: Chỉ ra việc nhận một tín hiệu ngoài từ một đối tượng sang
đối tượng khác.
- Call events: Chỉ ra việc nhận một lời gọi hàm bởi một đối tượng hoặc tác
nhân.
- Time events: Đánh dấu việc chuyển trạng thái sau một khoảng thời gian.
3.1.3 Biểu đồ trình tự (Sequence Diagram)
Biểu đồ trình tự minh họa các đối tượng tương tác với nhau ra sao. Chúng tập
trung vào các chuỗi thông điệp, có nghĩa là các thông điệp gửi và nhận giữa một loạt
các đối tượng như thế nào. Biểu đồ tuần tự có hai trục: trục dọc chỉ thời gian, trục nằm
ngang chỉ ra một tập các đối tượng. Ví dụ:
Hình 3.2: Biểu đồ tuần tự rút tiền từ máy ATM
Một biểu đồ tuần tự cũng nêu bật sự tương tác giữa các đối tượng trong một kịch
bản – một tương tác sẽ xảy ra tại một thời điểm nào đó trong quá trình thực thi hệ
thống.
20
Biểu đồ tuần tự gồm hai thành phần chính:
- Các đối tượng.
- Các thông điệp trao đổi giữa các đối tượng.
3.2 XML (eXtensible Markup Language)
3.2.1 Cơ bản về XML
XML kết hợp những ưu điểm của các ngôn ngữ trước đó (sự đơn giản của HTML
và cấu trúc mô tả tài liệu của SGML), có khả năng mô tả nhiều loại dữ liệu khác nhau
với mục đích là đơn giản hóa việc chia sẻ dữ liệu giữa các hệ thống khác nhau, đặc
biệt là các hệ thống được kết nối với Internet. XML là ngôn ngữ đánh dấu với mục
đích chung cho W3C đề nghị [6].
XML là một ngôn ngữ đánh dấu, nó gần giống với HTML (Hypertext markup
Language). Nó cung cấp một phương tiện dùng văn bản để mô tả thông tin và áp dụng
một cấu trúc kiểu cây cho thông tin đó. Mọi thông tin đều hiển thị dưới dạng văn bản
(text), chen giữa các thẻ đánh dấu (markup) với nhiệm vụ ký hiệu sự phân chia thông
tin thành một cấu trúc có thứ bậc của các dữ liệu ký tự [6].
Nội dung của một tài liệu XML gồm hai phần chính:
- Nội dung chính: Hệ thống các thẻ đánh dấu tương ứng với các thông tin
cần biểu diễn và có một node gốc.
- Nội dung phụ: Bổ sung thông tin cho tài liệu XML, một số thẻ phụ:
o Thẻ khai báo tham số:
Một số tham số thường dùng như: tham số version (phiên bản chỉ
định của XML), tham số encoding (cách mã hóa các ký tự), tham số
standalone (liên kết với tài liệu xml khác).
o Thẻ chỉ thị xử lý: Mô tả một số thông tin cho tài liệu XML nhưng có
ý nghĩa riêng đối với một vài công cụ xử lý nào đó. C ấu trúc: <?
Bo_Xu_Ly_Du_Lieu >
Ví dụ:
Định dạng thể hiện tài liệu XML với “chương trình đ ịnh dạng”
theo ngôn ngữ CSS được lưu trữ bên trong tệp tin a.css. Thẻ này
có ý nghĩa với một số trình duyệt như IE5, Netscape.
o Thẻ ghi chú: Không ảnh hưởng đến tài liệu XML.
21
Cấu trúc:
o Thẻ CDATA: Yêu cầu các bộ phân tích tài liệu XML bỏ qua không
phân tích vào nội dung bên trong của thẻ này. Mục đích chính của thẻ
này là cho phép sử dụng trực tiếp bên trong thẻ một số ký hiệu không
được phép sử dụng bên ngoài. Ví dụ các ký tự ‘’.
Cấu trúc: .
o Thẻ khai báo thực thể: cho phép tài liệu XML tham chiếu đến một
tập hợp các giá trị đã chuẩn bị trước dưới dạng một tên gợi nhớ (tên
thực thể).
Khai báo: <!DOCTYPE Ten_goc[
Khai báo thực thể tên X
Khai báo thực thể tên Y]
o Thẻ khai báo cấu trúc.
Các thẻ XML không được định nghĩa trước trong cú pháp XML, người sử dụng
có thể tự định nghĩa theo các thẻ theo ý thích khi sử dụng XML. XML sử dụng DTD
hoặc XML schema để mô tả dữ liệu. XML biểu diễn dữ liệu bằng cách sử dụng các
thành phần XML, trong đó chứa một trong các thành phần sau đây:
- Thẻ bắt đầu: Chứa tên của thành phần.
- XML attributes: Các thuộc tính, mỗi thuộc tính có tên và giá trị
- Nội dung: Có thể chứa một đoạn văn bản hoặc thuộc tính, cũng có th ể
chứa cả hai.
- Thẻ kết thúc, giống với tên của thẻ bắt đầu.
Ví dụ về một tài liệu XML:
<?xml
XML đã trở thành một công cụ rất mạnh và đơn giản để lưu trữ dữ liệu trên các
file. Nó cho phép bạn lưu trữ dữ liệu theo mẫu và có thể truy xuất được bằng các ứng
version="1.0" encoding="UTF-8"?>
An edge of one graph
Có 6 thành phần XML trong tài liệu này. Đầu tiên là chỉ thị xử lý, Phần tử edge
chứa thuộc tính có tên là type và giá trị là directed. Phần tử edge chứa hai phần tử con
là from và to chúng có hai thuộc tính là id. Phần tử comment chứa nội dung là một
đoạn văn bản (text).
22
dụng khác nhau, nhưng nó không thể tạo ra dữ liệu. Bằng cách sử dụng các API như
DOM, SAX, bạn có thể truy xuất dữ liệu từ một tài liệu XML rất dễ dàng.
3.2.2 XML DOM
3.2.2.1 DOM
“The W3C Document Object Model (DOM) is a platform and language-neutral
interfacethat allows programs and scripts to dynamically access and update the
content, structure, and style of a document” [].
DOM gồm ba phần riêng biệt:
- Core DOM: Định nghĩa các đối tượng chuẩn cho các tài liệu có cấu trúc.
- XML DOM: Định nghĩa tập hợp các đối tượng chuẩn cho tài liệu XML
- HTML DOM: Định nghĩa tập các đối tượng chuẩn cho tài liệu HTML.
3.2.2.2 XML DOM
XML DOM định nghĩa các đối tượng và thuộc tính của tất cả các thẻ của tài liệu
XML và các phương thức (giao diện) để truy xuất chúng. Nó là một chuẩn để truy
xuất, thêm, xóa, sửa các thẻ XML.
Trong DOM, mọi thứ trong tài liệu đều là nút (node):
- Toàn bộ tài liệu là một nút tài liệu (document node) – cây node
o Một cây gồm nhiều node.
o Node cao nhất gọi là root.
o Mỗi node, trừ root ra có chính xác một node cha.
o Một node có nhiều node con.
o Node lá là node không có node con.
- Mọi thẻ XML là một nút thẻ (element node).
- Text trong các thẻ XML là nút text (text node).
- Mọi thuộc tính là nút thuộc tính (attribute node).
- Ghi chú là nút ghi chú (comment node).
3.2.2.3 XML DOM Parser
Để đọc, cập nhật và thao tác trên một tài liệu XML ta cần một XML Parser. Có
nhiều XML Parser được hỗ trợ trong hầu hết các ngôn ngữ (Java, .Net…). Parser nạp
tài liệu XML vào trong bộ nhớ của máy tính và được xem dưới dạng cây node. Sau đó
dữ liệu sẽ được thao tác và xử lý thông qua tập hàm XML DOM API.
23
Hình 3.3: XML DOM Parser
3.2.2.4 XML DOM API
Cung cấp các phương thức xử lý tài liệu XML. Trong XML DOM API có rất
nhiều phương thức để có thể thao tác với tài liệu XML, ở đây tôi xin chỉ ra một số
phương thức thường sử dụng nhất để thao tác với tài liệu XML:
- Duyệt node:
o ParentNode: Lấy node cha của node hiện tại
o ChildNodes: Lấy các node con của node hiện tại
o firstChild: Lấy node con đầu tiên của node hiện tại
o lastChild: Lấy node con cuối cùng của node hiện tại
o nextSibling: Lấy node kết tiếp node hiện tại.
o previousSibling: Lấy node trước node hiện tại.
- Thao tác trên các node:
o getElementsByTagName(String tagname): Trả về một tập các node
có thuộc tính tên là: tagname.
o getElementById(String id): Trả về một node có thuộc tính id là: id
o setAttribute(String name, String value): Đặt thuộc tính cho node với
tên thuộc tính là name, giá trị là value.
o getAttribute(String name): lấy giá trị của thuộc tính có tên là name
o removeChild: Xóa node con của node hiện tại
o removeAttribute: Xóa bỏ thuộc tính của node hiện tại
24
o replaceChild: Thay thế node con của node hiện tại bằng một node
mới.
o createNode: Dùng để tạo ra tất cả các loại node.
o createElement: = createNode với loại element node.
o createTextNode: = createNode với loại text node
o createAttribute: = createNode với loại attribute node.
o nodeCha.appendChild: thêm vào phần tử cuối cùng của danh sách
các node con của nodeCha.
o nodeCha.insertBefore: thêm node mới vào trước node nào đó trong
danh sách node con của nodeCha.
3.3 XMI (XML Metadata Interchange)
XMI là một chuẩn OMG cho việc trao đổi siêu dữ liệu (metadata) giữa các công
cụ, các kho dữ liệu và các ứng dụng. Nó là một chuẩn cho phép người dùng mô tả đối
tượng bằng cách sử dụng XML. Nó làm việc dựa trên các chuẩn như W3C XML,
OMG UML và MOF [14].
Mặc dù XML có rất nhiều ưu điểm, nhưng vẫn có một khoảng cách nhất định
giữa XML với các đối tượng (objects). XML định nghĩa các phần tử XML, các thuộc
tính, không phải là đối tượng. Nó không cung cấp các đặc điểm của hướng đối tượng
như đa thừa kế và nó không chứa mô hình đối tượng. Tồn tại nhiều cách khác nhau để
lưu trữ dữ liệu XML và nếu sử dụng các công cụ khác nhau để lưu trữ XML thì sẽ gây
ra khó khăn trong việc trao đổi dữ liệu. Khi ta lưu trữ đối tượng bằng XML cũng vậy,
nếu đối tượng được lưu trữ khác nhau trong XML thì rất khó khăn để trao đổi giữa các
công cụ. Tuy nhiên, XMI ra chính là cầu nối liền khoảng cách giữa đối tượng và XML.
Nó cung cấp một chuẩn để tạo ra một ánh xạ từ một đối tượng được định nghĩa bằng
UML đến XML.
25
Hình 3.4: Sử dụng XMI trao đổi thông tin giữa các công cụ khác nhau.
XMI được xây dựng dựa trên XML, vì vậy chúng ta hoàn toàn có thể sử dụng các
API chuẩn thao tác với XML như DOM, SAX để thao tác với tài liệu XMI. Trong
nghiên cứu của tôi, tôi sử dụng DOM XML cho ngôn ngữ Java để thao tác với tài liệu
XMI.
3.4 AUML (Agent UML)
Trước khi đi vào tìm hi ểu về AUML, tôi xin giới thiệu qua một số khái niệm cơ
bản về tác tử phần mềm (agent) và phần mềm hướng tác tử để ta có một cái nhìn tổng
quan nhất về một phần mềm hướng tác tử.
3.4.1 Tác tử phần mềm là gì?
Theo từ điển Heritage của Mỹ: “Agent là một đối tượng mà có ảnh hưởng hay có
khả năng và có quyền tác động hay đại diện cho một đối tượng khác”.
Theo Ressel và Norvig: “Một agent có thể được xét tới bởi khả năng nhận thức
về môi trườn nó đang tồn tại qua bộ cảm biến (sensor) và khả năng tác động lên môi
trường đó qua cơ quan phản ứng (effector)”.
Theo Pattie Maes: “Agent tự chủ là các hệ tính toán tồn tại trong môi trường
động phức tạp, tri giác và hành động tự chủ trong môi trường này, qua đó hình dung
được nhiệm vụ hoặc mục đích của mình”.
Theo như các định nghĩa trên thì agent có thể là hệ thống phần cứng (điều nhiệt,
tàu vũ trụ, xe tự hành…) hoặc phần mềm (kiểm tra thư, Antivirus, …) Ở đây ta đi vào
một vấn đề nhỏ hơn, đó là tác tử phần mềm. Vậy tác tử phần mềm là gì?
26
Tác tử phần mềm là một chương trình máy tính t ồn tại trong môi trường nhất
định, tự động hành động phản ứng lại sự thay đổi của môi trường nhằm đáp ứng mục
tiêu đã được thiết kế trước []. Và có các tính chất như:
- Antonomy (Tính tự chủ): Một agent có khả năng kiểm soát hành vi của
mình độc lập với các thực thể khác.
- Reactivity (Tính phản xạ): Agent có khả năng phản ứng lại các tác động
từ môi trường theo một cơ chế nào đó.
- Pro-activeness (Tính chủ động): Agent không chỉ phản ứng lại môi
trường, chúng có thể hành động có mục đích và chủ động để tranh thủ thời
cơ đạt được mục đích đó. Từ một mục tiêu, agent có khả năng xác định các
hành động cần thiết và nó thực hiện một cách linh hoạt các hành vi đó để
đạt được mục tiêu đề ra.
- Social Ability (Tính cộng đồng): Agent có thể tương tác với những agent
khác hay con người để hoàn thành công việc riêng của mình hay trợ giúp
các agent khác trong những hoạt động nào đó.
Dựa vào mức độ thông minh, tính di động hay số lượng agent, người ta phân
agent ra một số loại như: agent cộng tác, agent giao diện, agent di dộng, agent thông
tin, agent phản xạ, agent thông minh.
3.4.2 Phần mềm hướng Agent
Công nghệ phần mềm hướng Agent phân rã bài toán thành nhiều thành phần
tương tác và tự trị (agents) mà có các mục tiêu cụ thể để đạt tới. Phần mềm hướng
agent là một phương pháp luận mới hỗ trợ cách tiếp cận được công nghệ hóa: phân
tích và thiết kế hệ thống.
- Phân tích hướng agent: Cũng giống như các phương pháp phân tích hệ
thống khác, phân tích hướng agent cũng bắt đầu từ việc định nghĩa các yêu
cầu và mục đích của hệ thống. Các mục đích toàn thể của ứng dụng được
phân rã thành những mục tiêu con, nhỏ hơn; cho tới khi nào có thể quản lý
được chúng. Việc phân tích hướng agent phải nhận ra được nhiệm vụ của
một agent.
- Thiết kế phần mềm hướng agent: Mỗi agent trong hệ thống được giao
cho một hoặc một số nhiệm vụ riêng biệt. Các agent phải nắm được đầy đủ
trách nhiệm đối với việc hoàn thành các nhiệm vụ được giao. Các nhiệm
vụ cộng đồng biểu diễn các chức năng toàn cục của hệ thống agent.
27
Phát triển phần mềm hướng agent dựa vào các hệ đa agent – là một cộng đồng
các agent, nơi mà tương tác qua lại giữa các agent và với môi trường của chúng tạo ra
một hành vi toàn thể, hữu ích. Một hệ đa agent bao gồm các thành phần:
- Các agent được xem như là các cá thể.
- Tương tác giữa các agent
- Sự phụ thuộc qua lại giữa agent và các quan hệ cộng đồng.
Để hiểu rõ hơn phương pháp phân tích thi ết kế phần mềm hướng agent, tôi xin
trình bày qua một số khái niệm cơ bản trong lý thuyết Gaia [10] – một lý thuyết dùng
trong phân tích và thiết kế phần mềm hướng agent.
Hình 3.5: Các khái niệm cơ bản của lý thuyết Gaia
Trong pha phân tích:
- Xác định các vai trò trong hệ thống và định nghĩa một dãy các vai trò
chính bằng ngôn ngữ miêu tả phi hình thức. Với mỗi vai trò cần xác định
các giao thức liên kết.
- Đầu ra của pha phân tích là mô hình hoàn thiện của các vai trò – mô tả về
trách nhiệm, quyền hạn, các giao thức tương tác, hoạt động và mô hình
tương tác. Mỗi giao thức mô tả về sự chuyển đổi dữ liệu và các thành phần
có liên quan.
Pha thiết kế: Tập trung vào việc định nghĩa h ệ thống agent để nó có thể hoạt
động. Nó bao gồm một số giai đoạn như sau:
- Thứ nhất: Xác định mô hình agent, kết hợp vai trò vào các loại agent từ
đó xây dựng hệ thống phân cấp các loại agent và ước lượng số lượng các
thể hiện (instance) được yêu cầu đối với mỗi lớp.
28
- Thứ hai: Xác định các dịch vụ mà agent phải cung cấp để hoàn thành các
nhiệm vụ mà chúng được giao bằng cách phân tích các nhiệm vụ và hoạt
động. Đó chính là các giao thức được định nghĩa cho mỗi vai trò.
- Thứ ba: Xác định các mô hình tích hợp để xác định các khả năng thiếu sót
trong thiết kế.
Kết quả đầu ra của pha thiết kế chính là kiến trúc thực tế của hệ thống agent.
Nói đến agent cũng như phần mềm hướng agent còn rất nhiều vấn đề cần bàn
như: kiến trúc agent, hệ đa agent, liên lạc/truyền thông trong hệ agent… trong phạm vi
khóa luận của tôi, tôi không đề cập tới tất cả các kiến thức về agent, cách thức phân
tích thiết kế, xây dựng phần mềm hướng agent; mà ở đây tôi chỉ trình bày một số khái
niêm cơ bản nhất, đưa ra một cái nhìn tổng quan nhất về agent và phần mềm hướng
agent. Các vấn đề này được trình bày kỹ trong [1, 3, 10].
3.4.3 AUML (Agent Unified Modeling Language)
Như ta đã biết UML là ngôn ngữ rất mạnh để mô hình hóa các đối tượng và thao
tác của các đối tượng. Nó cung cấp các mô hình tĩnh (các bi ểu đồ lớp và gói) và các
mô hình động (biểu đồ tương tác, biểu đồ trạng thái, biểu đồ hoạt động) để mô tả hệ
thống phần mềm. Quá trình xây dựng các hệ thống dựa tác tử cũng đòi hỏi tất cả các
quá trình của công nghệ phần mềm như: phân tích, thiết kế, đanh giá, bảo trì… Tuy
nhiên, agent có nhiều điểm khác biệt so với các đối tượng nên có nhiều lúc UML
không thể hỗ trợ toàn bộ để mô hình hóa hệ thống dựa agent. Vì vậy, để đặc tả cho hệ
thống dựa tác tử, FIFA (Foundation for Intelligent Physical Agents) sử dụng UML mở
rộng, gọi là AUML (Agent Unified Modeling Language) để mô hình hóa các hệ dựa
tác tử, đặc tả giao thức tương tác tác tử (AIP – Agent Interaction Protocols).
AUML là một hướng tiếp cận giao thức phân mức. Một giao thức tương tác tác
tử (AIP) mô tả các mẫu truyền thông như một dãy các thông đi ệp giữa các agent và
ràng buộc nội dung của các thông điệp này. AIP được mô tả gồm ba mức [8, 9]:
- Mức 1: Mô tả giao thức liên lạc (UML Package and Template).
- Mức 2: Mô tả tương tác giữa các agent (các biểu đồ tuần tự, cộng tác, hoạt
động biểu đồ trạng thái).
- Mức 3: Mô tả quá trình xử lý bên trong agent (activity diagram và
statechart)
29
3.4.3.1 Mức 1 – biểu diễn giao thức liên lạc ở mức tổng quan
UML cung cấp hai kỹ thuật nhằm biểu diễn các giải pháp cho giao thức, đó là
package và template.
- Package: Là tập các nhân tố mô hình hóa ở mức khái niệm
Ví dụ sau được lấy trong [8]
Hình 3.6: Ví dụ package
Các gói cung cấp một kỹ thuật chung cho việc phân chia các mô hình và
nhóm các thành phần mô hình. Mỗi gói được biểu diễn như sau:
o Mỗi gói đóng là nhóm thành phần có quan hệ logic với nhau.
o Kiến trúc của hệ thống được biểu diễn nhờ mô hình liên kết giữa các
gói đóng
o Một gói đóng có thể chứa các gói đóng khác.
o Dùng một gói mô tả giao thức lồng nhau.
- Template: là một thành phần mô hình được tham số hóa có các tham số bị
ràng buộc. Ví dụ sau được lấy trong [8]
30
Hình 3.7: Một kịch bản giữa người mua hàn và ngời bán hàng
3.4.3.2 Mức 2 – biểu diễn tương tác giữa các agent
Ở mức này, ta sử dụng các biểu đồ trong UML để biểu diễn các giao thức:
- Biểu đồ tuần tự
- Biểu đồ cộng tác
- Biểu đồ hoạt động
- Biểu đồ trạng thái
Trong đó, biểu đồ tuần tự và biểu đồ cộng tác mô tả tương tác giữa các agent;
còn biểu đồ hoạt động và biểu đồ trạng thái biểu diễn các luông xử lý. Các biểu đồ này
biểu diễn các agent gần giống với UML biểu diễn các đối tượng, và mở rộng ra một
chút cho phù hợp với agent. Như: AUML thêm các phần biểu diễn tương tác đa luồng
ví dụ [8]:
Hình 3.8 Tương tác đa luồng trong AUML
Hình (a) biểu diễn các luồng được gửi đi song song (phép AND). Hình (b) bao
gồm một hộp quyết định xác định xem luồng nào sẽ được gửi đi tiếp (phép OR). Hình
(c) xác định trong một thời điểm chỉ có một luồng được phép gửi đi (phép XOR).
31
3.4.3.3 Mức 3 – biểu diễn xử lý bên trong Agent
Tại mức thấp nhất, đặc tả về một giao thức. Agent yêu cầu giải thích rõ ràng
những xử lý chi tiết bên trong agent để tiến hành giao thức. Các mô hình mức cao hơn
(gọi là holon) bao gồm tập các agent ở mức thấp hơn. Các hành vi bên trong có thể
được biểu diễn bằng việc sử dụng đệ quy các cách biểu diễn ở mức 2.
Ví dụ:
Hình 3.9: Các hành vi bên trong của agent Initiator (a) và Participant(b)
3.5 Java Agent DEvelopment Framework (JADE)
3.5.1 Khái niệm về JADE
“JADE (Java Agent DEvelopment Framework) is a software Framework fully
implemented in Java language. It simplifies the implementation of multi-agent systems
through a middle-ware that complies with the FIPA specifications and through a set of
graphical tools that supports the debugging and deployment phases” [3].
Ta có thể tóm tắt lại định nghĩ trên như sau:
- JADE là phần mềm dạng middle-ware phục vụ cho việc phát triển hệ đa
tác tử. Nó hỗ trợ việc xây dựng từng agent trong hệ đa agent. Cung cấp các
dịch vụ cho từng hoạt động của agent, các công cụ phục vụ cho việc debug
và agent xây dựng dựa trên chuẩn FIFA.
- JADE là một hệ thống mã nguồn mở, được xây dựng trên ngôn ngữ Java.
32
3.5.2 Cấu trúc của JADE platform
Platform JADE là môi trường hỗ trợ agent hoạt động, trao đổi thông tin. Platform
JADE chứa nhiều container, các container có thể hoạt động độc lập trên các host khác
nhau. Có hai loại container chính:
- JADE main-container: Mỗi platform chỉ có một main-container.
Container này được khở tạo và hủy cùng với platform. Nó chứa một số
agent quan trọng của JADE platform như:
o RMA (Remote Management Agent): Hoạt động như màn hình đi ều
khiển, phục vụ việc quản lý platform.
o DF (Directory Facilitator): Là một agent cung cấp dịch vụ trang
vàng (yellow-page) trong platform.
Trang vàng (Yellow-page): Là một dịch vụ cung cấp chức
năng quản lý việc giao tiếp giữa các agent, đối chiếu thông tin
trao đổi.
o AMS (Agent Management System): Là agent theo dõi quản lý sự truy
cập và sử dụng agent platform. Cung cấp dịch vụ trang trắng (white-
page).
Trang trắng (White-page) cung cấp chức năng quản lý việc
đăng ký của agent, quản lý ID của các agent đã đăng ký và
quản lý vòng đời của agent.
- JADE agent-container: Chứa các agent của người sử dụng, nó có thể nằm
trên các host khác nhau.
Hình 3.10: Cấu trúc phân tán của JADE
33
3.5.3 Một số lớp quan trọng trong thư viện JADE
- Gói jade.core: Cài đặt các thành phần cơ bản của hệ thống. Nó chứa lớp
Agent, các agent được tạo ra bắt buộc phải kế thừa từ lớp này. Ngoài ra nó
còn chứa gói jade.core.behavior: cung cấp các hàm cài đặt nhiệm vụ cho
agent.
o Lớp jade.core.Agent: cung cấp các phương thức đăng ký với
platform, các phương thức xác định trạng thái của agent, quản lý
trạng thái và các phương thức hoạt động của agent.
Cách tạo agent:
public class MyAgent extends Agent
{
// some attributes
public void setup()
{
// registry with AMS..
// other activities
addBehaviour(myBehaviour)
}
// other methods
}
o Gói jade.core.behavior: Chứa các lớp cho phép tạo ra các hoạt động
của agent từ đơn giản đến phức tạp. Ta có thể tạo ra các hành động
cho agent bằng việc kế thừa từ các lớp này.
Cách tạo behavior:
public class MyBehaviour extends Behaviour
{
// some attributes
public MyBehaviour(Agent agent){super(agent)}
public void action()
{
// agent action
}
// other methods
}
- Gói jade.lang.acl: cung cấp các phương thức xử lý giao tiếp giữa các
agent theo chuẩn FIFA.
- Gói jade.domain: mô tả các thực thể quản lý agent theo chuẩn FIFA. Nó
cung cấp một số dịch vụ như: life-cycle, yellow-page, white-page.
Ngoài ra còn một số gói khác như: jade.wrapper, jade.content, jade.tools…
Hoạt động của một agent:
34
Hình 3.11: Hoạt động của agent
3.6 Kết luận
Các kiến thức về UML, XML, XMI, AUML mà tôi trình bày trong chương này
không phải quá mới mẻ và cũng không thật sự đầy đủ. Nhưng đó là những nền tảng
kiến thức cơ bản tôi sử dụng trong khóa luận để xây dựng công cụ tự động sinh mô-
đun aspect kiểm chứng. Để giải quyết bài toán “kiểm chứng đặc tả UML cho tác tử
phần mềm”, tôi chia bài toán ra làm hai bước nhỏ: Bước thứ nhất là xây dựng FSM từ
tài liệu XMI mô tả các biểu đồ UML. Bước thứ hai là xây dựng bộ sinh aspect tự động
từ FSM. Hai bước này sẽ được trình bày cụ thể ở các chương sau.
35
Chương 4. Xây dựng máy trạng thái từ biểu đồ UML
Trong chương 2 và 3 tôi đã trình bày các ki ến thức nền tảng cơ bản để xây dựng
công cụ Protocol Verification Generator(PVG). Trong chương này, tôi sẽ trình bày
bước thứ nhất trong phương pháp xây dựng công cụ tự động sinh mô-đun aspect, đó là
phân tích tài liệu XMI được xuất ra từ một biểu đồ UML, từ đó xây dựng máy trạng
thái.
Như vậy, trong bước này ta có:
- Input: Một tài liệu XMI mô tả biểu đồ trạng thái hoặc biểu đồ trình tự
UML.
- Output: Máy trạng thái nếu xây dựng được, nếu không sẽ báo lỗi.
Để xây dựng được máy trạng thái, trước tiên tôi sẽ xây dựng các cấu trúc dữ liệu
để đặc tả các thành phần của biểu đồ UML bằng các đối tượng trong Java, cấu trúc dữ
liệu của máy trạng thái mà tôi sử dụng. Tiếp theo, tôi sẽ trình bày cách thức tạo ra máy
trạng thái từ tài liệu XMI và các cấu trúc dữ liệu đã xây dựng trước đó.
4.1 Biểu đồ trạng thái
4.1.1 Quy tắc biểu diễn giao thức bằng biểu đồ trạng thái
Ngoài cách vẽ biểu đồ trạng thái như trong UML đề cập, tôi xin đưa ra thêm một
số quy tắc dùng biểu đồ trạng thái để biểu diễn giao thức. Công cụ PVG mà tôi xây
dựng sẽ sử dụng các quy tắc này như là một chuẩn để nó có thể hiểu được giao thức
mà người dùng đặc tả bằng UML. Nếu người dùng không tuân thủ các quy tắc này,
chương trình sẽ không đưa ra được kết quả như ý.
Một số quy tắc:
- Trong một tài liệu UML, chỉ có một biểu đồ trạng thái thể hiện giao thức
cần kiểm tra.
- Biểu đồ trạng thái bắt buộc phải có trạng thái bắt đầu và trạng thái kết
thúc.
- Trạng thái bắt đẩu có tên bắt đầu bằng “Initial”, và chỉ có các cạnh đi ra
chứ không có cạnh đi vào trạng thái này.
- Trạng thái kết thúc có tên bắt đầu bằng “FinalState” và chỉ có cạnh đi vào,
không có cạnh đi ra từ trạng thái này.
36
- Các trạng thái khác phải có ít nhất một cạnh đi vào và một cạnh đi ra. Tên
của các trạng thái này không bắt đầu bằng “Initial” hoặc “FinalState”.
- Các cạnh là chữ ký (signature) của các hàm, phương thức sẽ được gọi dùng
để thay đổi trạng thái. Chữ ký này được định nghĩa gi ống như tên hàm
trong mã nguồn của chương trình cần kiểm chứng, bao gồm cả kiểu giá trị
trả về, tên hàm, danh sách các tham số truyền vào. Ví dụ:
o Trong mã nguồn, ta gọi hàm init() không có tham số truyền vào, kiểu
trả về là void thì tên của cạnh trong biểu đồ UML sẽ là: void init().
o Hàm int setAge(int age) được gọi trong mã nguồn thì tên của cạnh
tương ứng sẽ là: int setAge(int age). Đối số age là không bỏ được.
- Chú ý rằng tên của tham số truyền vào phải giống với tên biến đã khai báo
trong mã nguồn của chương trình cần kiểm chứng.
- Điều kiện tiên quyết (precondition) để hàm được gọi sẽ được mô tả trong
“GuardCondition” của cạnh. Điều kiện này cũng phải giống với điều kiện
trong mã nguồn của chương trình. Hoặc nó là đoạn code trả về giá trị
boolean (ví dụ như một phương thức tĩnh (static) boolean isTrue())
Sau đây là ví dụ mô tả một cạnh trong biểu đồ trạng thái UML:
- Đoạn mã trong chương trình:
if(temp.isTrue())
{
init();
.....
}
- Ta sẽ mô tả cạnh của biểu đồ trạng thái UML như sau:
Hình 4.1: UMLTransition
o Tên của cạnh (Name): void init().
o Điều kiện tiên quyết (GủadCondition): temp.isTrue()
4.1.2 Xây dựng cấu trúc dữ liệu mô tả biểu đồ trạng thái UML
Ta có thể thấy một biểu đồ trạng thái UML gồm hai thành phần chính: Các trạng
thái (State) và các cạnh (Transition). Tôi sẽ xây dựng hai lớp để mô tả hai
thành này phần của biểu đồ trạng thái UML.
37
4.1.2.1 Lớp State – mô tả các trạng thái (các đỉnh)
Trong biểu đồ trạng thái UML, đỉnh được mô tả gồm có tên của đỉnh, các cạnh đi
vào đỉnh và các cạnh đi ra từ đỉnh. Trạng thái bắt đầu chỉ có cạnh đi ra, không có cạnh
đi vào. Trạng thái kết thúc, chỉ có các cạnh đi vào đỉnh, không có các cạnh đi ra từ
đỉnh. Như vậy, để mô tả một trạng thái ít nhất ta cần mô tả ba dữ liệu: tên đỉnh, các
cạnh đi vào và các cạnh đi ra. Để xét xem còn dữ liệu nào cần mô tả nữa không, ta
xem cách tài liệu XMI mô tả một trạng thái của biểu đồ trạng thái UML (Phụ lục A).
<UML:SimpleState xmi.id="UMLCompositeState.17" name="State1"
visibility="public" isSpecification="false"
container="UMLCompositeState.15" outgoing="UMLTransition.22"
incoming="UMLTransition.21"
4.1.2.2 Lớp Transition – mô tả các cạnh của biểu đồ trạng thái UML
/>
Nhìn vào cách tài liệu XMI mô tả một trạng thái, ta thấy cần mô tả thêm một dữ
liệu nữa về một trạng thái, đó là id của trạng thái (xmi.id). Tài liệu XMI dùng id của
trạng thái để đại diện cho một trạng thái bất kỳ trong các liên kết của trạng thái đó với
các thành phần khác của biểu dồ, vì vậy dữ liệu về id của trạng thái là rất quan trọng,
không thể bỏ qua.
Tóm lại, ta cần bốn dữ liệu để mô tả một trạng thái: id của trạng thái, tên trạng
thái, các cạnh đi vào và các cạnh đi ra. Và lớp State mô tả trạng thái được xây dựng
cơ bản như sau:
public class State {
private String xmiId;
private String name;
private String[] incoming;
private String[] outgoing;
// các phương thức khác.
}
Một cạnh được mô tả gồm có tên của cạnh và là một đường liên kết giữa hai đỉnh
trong biểu đồ trạng thái UML, bắt đầu từ một đỉnh (trạng thái) của biểu đồ và kết thúc
ở một đỉnh khác. Vì vậy, để mô tả một cạnh của biểu đồ, ta phải mô tả tên của cạnh,
đỉnh bắt đầu của cạnh và đỉnh kết thúc của cạnh. Ngoài ra, tài liệu XMI dùng id để mô
tả các thành phần của biểu đồ, như vậy đỉnh bắt đầu và đỉnh kết thúc của cạnh sẽ là id
của đỉnh bắt đầu và kết thúc. Mặt khác ta cũng cần thêm id để mô tả id của cạnh. Như
vậy, ta đã có 4 dữ liệu cần thiết phải mô tả một cạnh, đó là: id của cạnh, tên của cạnh,
38
id của đỉnh bắt đầu, id của đỉnh kết thúc. Ta xét xem XMI mô tả biểu cạnh của biểu đồ
trạng thái như thế nào:
<UML:Transition xmi.id="UMLTransition.11" name="void init()"
visibility="public" isSpecification="false"
stateMachine="UMLStateMachine.4" source="UMLPseudostate.6"
target="UMLCompositeState.7">
<UML:BooleanExpression xmi.id="X.17" body="a
>= b"
- Id của cạnh: xmi.id
/>
Như vậy sau khi xét tài liệu XMI, ta thấy: Ngoài bốn dữ liệu cần thiết đã chỉ ra ở
trên, tài liệu XMI còn mô tả điều kiện tiên quyết để phương thức được thực hiện trong
phần tử là phần tử con của .
Tóm lại, để mô tả một cạnh, ta cần năm dữ liệu sau:
- Tên cạnh: name
- Id của đỉnh mà từ đó cạnh đi ra: source
- Id của đỉnh mà cạnh đi vào: target
- Điều kiện tiên quyết: guard.expression.
Lớp Transition được xây dựng như sau:
public class Transition {
private String xmiId; // ID của cạnh
private String name; // Tên cạnh
private String source; // ID của đỉnh mà cạnh đi ra
private String target; // ID của đỉnh mà cạnh đi vào
private String preCondition; // điều kiện để chuyển trạng thái
.....
}
4.1.2.3 Mô tả biểu đồ trạng thái bằng các đối tượng trong Java
Hai lớp State và Transition mô tả hai thành phần chính của biểu đồ trạng
thái UML. Tuy nhiên, một biểu đồ trạng thái thường có nhiều State và nhiều
Transition, vì vậy để tiện cho việc truy xuất dữ liệu về các thành phần này tôi xây
dựng thêm hai lớp nữa mô tả danh sách các State (ListStates) và danh sách các
Transition (ListTransitions) có trong biểu đồ trạng thái UML. Hai lớp này
39
có nhiệm vụ duyệt tài liệu XMI và lấy dữ liệu về các State, các Transition. Sơ đồ lớp
mô tả các đối tượng được minh họa như hình vẽ dưới đây:
Hình 4.2: Sơ đồ lớp biểu diễn biểu đồ trạng thái bằng các đối tượng trong Java
Trong hai lớp ListStates và ListTransitions, tôi xây dựng thêm một số
phương thức khác để lấy các thành phần dữ liệu của một State và Transition một
cách dễ dàng như: lấy dữ liệu về một State khi biết id của State hay lấy dữ liệu về một
Transition khi biết id của Transition đó. Cách xây dựng các hàm này hết sức
đơn giản, khi ta đã có m ột danh sách các State và Transition, ta chỉ việc duyệt
trong danh sách này, so sánh id của State hoặc Transition với tham số id truyền
vào, nếu đúng thì ta xuất dữ liệu ra theo ý muốn.
Như đã trình bày ở chương 3, tôi sử dụng thư viện XML DOM trong Java để đọc
thông tin từ tài liệu XMI. Cấu trúc của tài liệu XMI này tôi chỉ rõ ở phụ lục A; Ở đây,
tôi sẽ chỉ ra các node (thẻ XML) cần đọc để lấy dữ liệu.
- Các trạng thái:
o Trạng thái bắt đầu: : .
o Trạng thái kết thúc: .
o Trạng thái trung gian: .
o Với mỗi trạng thái, các thuộc tính (attribute) cần đọc để lấy dữ liệu
là:
xmi.id
name
incoming
outgoing
40
điều kiện sẽ được lấy thông qua thuộc tính body của phần tử
con: .
- Các cạnh (Transition)
o Các node cần duyệt:
.
o Các thuộc tính cần đọc để lấy dữ liệu:
xmi.id
name
source
target
Khi đã xác đ ịnh được các node, các thuộc tính cần đọc để lấy dữ liệu, công việc
còn lại là đọc tài liệu XMI và tạo ra danh sách các trạng thái và danh sách các
Transition là hết sức đơn giản như sau:
- Khởi tạo ListState, ListTransition
- Lấy danh sách các node (NodeList) của Transition và State.
- Duyệt từng node trong NodeList
- Tạo ra một Transition và một State mới, thêm vào danh sách.
Sau bước này, ta sẽ có một danh sách mô tả các State và Transition có trong
biểu đồ UML. Bước tiếp theo, tôi sẽ trình bày cách tạo ra FSM từ hai danh sách này.
4.1.3 Xây dựng FSM mô tả biểu đồ trạng thái UML
Như ta đã bi ết, để chuyển từ trạng thái này, sang trạng thái kia thì cần có hàm
chuyển trạng thái. Trong nghiên cứu của tôi, hàm chuyển trạng thái được mô tả trong
các cạnh của biểu đồ trạng thái. Tập hợp các hàm chuyển trạng thái sẽ tạo thành giao
thức mô tả hoạt động của đối tượng. FSM được xây dựng cần phải mô tả được giao
thức này. Mặt khác, trong mã nguồn của chương trình, các tr ạng thái hầu như không
có ý nghĩa, các đoạn mã chỉ mô tả các phương thức được thực hiện – chính là các cạnh
của biểu đồ, và mục đích của việc kiểm chứng ở đây chính là kiểm tra xem các phương
thức trong mã nguồn của chương trình có được gọi theo đúng giao thức đã được chỉ ra
hay không. Để kiểm tra việc này, công cụ tự sinh aspect cần phải biết phương thức nào
được gọi trước, phương thức nào được gọi sau từ đó sẽ kiểm tra được các vi phạm các
giao thức ràng buộc đối tượng. FSM được xây dựng cần phải mô tả được điều này.
Dựa vào bài báo [5] tôi xây dựng FSM gồm các thành phần dữ liệu sau:
HashMap> fsm = null;
HashSet entrySigs, exitSigs;
41
HashMap> stateMap = null;
Trong đó:
- entrySigs: Mô tả các cạnh đi ra từ trạng thái bắt đầu.
- exitSigs: Mô tả các cạnh đi vào trạng thái kết thúc.
- fsm: Là một HashMap, với key chính là một cạnh đi ra từ một trạng thái
trung gian. Value chính là các cạnh đi vào trạng thái này.
- stateMap: Biểu diễn các trạng thái và các cạnh đi vào trạng thái.
Hashmap này sẽ được dùng để đánh số các trạng thái của biểu đồ.
Thuật toán xây dựng FSM như sau:
- Input: tài liệu XMI mô tả biểu đồ trạng thái UML
- Output: FSM nếu xây dựng được, nếu không sẽ báo lỗi.
- Các bước thực hiện:
o Khởi tạo fsm, entrySigs, exitSigs, stateMap.
o Đọc file XMI, lấy ListStates và ListTransitions.
o Duyệt từng State trong ListStates
Tạo giá trị cho stateMap:
• Nếu nó là trạng thái bắt đầu: thêm một phần tử mới với
key là “START”, value = null.
• Ngược lại thêm vào stateMap một phần tử với với key
là tên trạng thái hiện tại, value là tên của các cạnh đi vào
đỉnh.
Nếu nó là trạng thái bắt đầu, lấy tên + precondition cho vào
entrySigs và cho vào fsm (biến fsm) với key là tên +
precondition còn value là: “START”.
Nếu nó là trạng thái kết thúc, lấy tên + precondition cho vào
exitSigs.
Nếu nó là trạng thái trung gian.
• Lấy tên của tất cả các cạnh đi vào trạng thái cho vào cấu
trúc dữ liệu dạng “Set” trong Java.
• Duyệt từng cạnh đi ra từ trạng thái. Lấy tên +
precondition. Thêm vào fsm key là tên + precondition
của cạnh đi ra và value là “Set” chứa các cạnh đi vào ở
trên.
42
4.2 Biểu đồ trình tự UML
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
Một biểu đồ trình tự bao gồm hai thành phần chính, đó là các đối tượng và các
thông điệp trao đổi giữa các đối tượng. Các đối tượng ở đây, chính là tên của các lớp
trong mã nguồn của chương trình. Các thông điệp trao đổi giữa các đối tượng chính là
các phương thức của các lớp trong mã nguồn mà ta cần kiểm chứng. Khi mô tả giao
thức giữa các lớp bằng biểu đồ trình tự UML, ta sẽ mô tả như sau:
- Tên của lớp trong mã nguồn – cũng chính là tên của đối tượng
(UMLObject) trong biểu đồ. Và đối với lớp, ta chỉ cần mô tả tên của lớp
đó.
- Các thông điệp trao đổi giữa các đối tượng được (UMLStimulus) mô tả đầy
đủ các thành phần giống như mô tả phương thức của các lớp trong mã
nguồn. Cũng gồm có tên phương thức, các tham số truyền vào, kiểu giá trị
trả về và thông điệp là phương thức của lớp nào thì nó đư ợc bắt đầu đi ra
từ lớp đó.
o Tên phương thức mô tả thông qua thuộc tính name.
o Các tham số truyền vào được mô tả thông qua thuộc tính Arguments.
Các tham số truyền vào, được mô tả bao gồm cả kiểu dữ liệu và tên
của tham số. Tên tham số giống như tên của tham số truyền vào trong
lời gọi phương thức ở mã nguồn chính của chương trình.
o Kiểu giá trị trả về được mô tả bằng thuộc tính Return.
Cụ thể các thành phần này được mô tả chi tiết như hình dưới đây:
43
Hình 4.3: StarUML mô tả các thành phần trong biểu đồ trình tự
Hoàn toàn tương tự cách xây dựng FSM từ biểu đồ trạng thái, FSM mô tả biểu đồ
trình tự UML cũng được xây dựng hoàn toàn tương tự như vậy. Cũng gồm hai bước
nhỏ: Thứ nhất là xây dựng cấu trúc dữ liệu mô tả các thành phần của biểu đồ, cách mô
tả biểu đồ bằng các thành phần này. Thứ hai là xây dựng FSM từ các thành phần dữ
liệu đã được cấu trúc hóa thành các đối tượng được định nghĩa ở bước thứ nhất.
Biểu đồ trình tự UML gồm hai thành phần chính: Các đối tượng (Object) và các
thông điệp trao đổi giữa các đối tượng (Stimulus). Tôi cũng xây dựng cấu trúc dữ liệu
mô tả hai thành phần này như sau:
4.2.2 Xây dựng cấu trúc dữ liệu mô tả biểu đồ trình tự UML
Phương pháp xây dựng cấu trúc dữ liệu mô tả biểu đồ trình tự UML hoàn toàn
tương tự với cách xây dựng cấu trúc dữ liệu mô tả biểu đồ trạng thái mà tôi đã trình
bày ở phần trước. Đầu tiên là tôi xem xét các thành phần chính của biểu đồ, ta sẽ mô tả
dữ liệu gì thông qua các thành phần này. Tiếp theo là phân tích tài liệu XMI được xuất
ra từ một biểu đồ trình tự UML, xem xét xem tài liệu XMI dùng các thẻ gì để mô tả
các thành phần chính này, các thành phần dữ liệu trong thẻ (thuộc tính) gồm những gì.
Cuối cùng, tôi sẽ lọc ra các dữ liệu cần thiết nhất và xây dựng các lớp Java để mô tả
các thành phần chính của biểu đồ. Đây cũng chính là phương pháp phân tích tài li ệu
XMI mà tôi sử dụng trong khóa luận.
Áp dụng phương pháp phân tích tài liệu XMI ở trên, tôi xây dựng các lớp mô tả
biểu đồ trình tự UML theo như biểu đồ lớp được mô tả trong hình vẽ dưới đây:
44
Hình 4.4: Sơ đồ lớp biểu diễn các thành phần của biểu đồ trình tự UML
4.2.2.1 Lớp ClassifierRole mô tả các đối tượng
Mô tả các lớp trong biểu đồ trạng thái, ta chỉ mô tả tên của lớp, ngoài ra XMI mô
tả thêm id của lớp, như vậy để mô tả một ClassifierRole, ta chỉ cần mô tả hai
thành phần dữ liệu, đó là: id của lớp và tên của lớp:
public class ClassifierRole {
private String id; // ID cua lop
private String name; // Ten lop
}
Tài liệu XMI, mô tả các lớp thông qua thành phần (thẻ) <UML:
ClassifierRole>, trong đó:
- xmi.id: Mô tả id của ClassifierRole.
- name: Mô tả tên của ClassifierRole.
Đây cũng chính là tên thẻ và tên các thuộc tính của thẻ khi ta duyệt tài liệu UML
và lấy dữ liệu mô tả các ClassifierRole.
4.2.2.2 Lớp Message mô tả thông điệp trao đổi giữa các đối tượng
Thông điệp – hay chính là tên của phương thức được gọi trong mã nguồn. Mà
như ta đã biết, một phương thức được mô tả bởi các thành phần như: tên phương thức,
các tham số truyền vào, kiểu giá trị trả về của phương thức và một thành phần quan
trọng không kém là ta cần xác định xem phương thức đó thuộc lớp (class) nào. Nhưng
khi phân tích tài liệu XMI ta thấy: Không giống như các thành phần khác của biểu đồ
UML, các dữ liệu mô tả một thành phần đều là các thuộc tính của một loại thẻ nào đó.
Ví dụ như thẻ mô tả các cạnh của biểu đồ trạng thái, thẻ <UML:
45
ClassifierRole> mô tả các đối tượng của biểu đồ trình tự. Dữ liệu mô tả về một
thông điệp của biểu đồ trình tự UML được thể hiện qua hai loại thẻ khác nhau:
- Thẻ chứa các dữ liệu mô tả tên phương thức, lớp chứa
phương thức đó.
- Thẻ mô tả các tham số, kiểu giá trị trả về của
phương thức.
Vì vậy, tôi xây dựng hai lớp độc lập nhau để lưu trữ những thành phần dữ liệu
khác nhau của một thông điệp được mô tả trên hai loại thẻ XML khác nhau. Đó là lớp
Message và lớp TaggedValue. Lớp Message mô tả hai dữ liệu về thông điệp được
mô tả trong thẻ đó là tên phương thức và id của lớp chứa phương
thức đó. Lớp TaggedValue đại diện cho thẻ mô tả về tên
các tham số và kiểu giá trị trả về của phương thức:
- Class Message:
public class Message {
private String id; //ID cua message
private String name; // Ten cua message
private String sender; // ID cua lop
}
- Class TaggedValue:
public class TaggedValue {
private String value; // gia tri cua TaggedValue
private String ID; // ID cua Message
}
Một thông điệp sẽ là sự kết hợp của Message và TagedValue. Thông qua
thuộc tính id của thông điệp.
4.2.2.3 Mô tả biểu đồ trình tự UML bằng các đối tượng trong Java
Ta đã có ba lớp cơ bản: ClassifierRole, Message, TagedValue để mô
tả hai thành phần quan trọng của biểu đồ trạng thái UML, đó là đối tượng và thông
điệp trao đổi giữa các đối tượng. Trong một biểu đồ trình tự, không chỉ có một đối
tượng hay một thông điệp, mà nó chứa mỗi chuỗi các đối tượng và các thông điệp trao
đổi giữa các đối tượng, tạo nên giao thức trao đổi thông điệp giữa các đối tượng. Do
đó, cũng giống như mô tả biểu đồ trình tự, để mô tả các thành phần có trong biểu đồ
trình tự, tôi cũng dùng một danh sách các ClassifierRole để lưu trữ tất cả các đối
tượng có trong biểu đồ. Danh sách các Message và danh sách các TagedValue để
lưu trữ tất cả các thông điệp trao đổi giữa các đối tượng trong biểu đồ. Các lớp này
được mô tả trong hình 4.3.
46
Ngoài ra tôi cũng xây dựng thêm các phương thức giúp truy xuất dữ liệu về từng
thành phần trong danh sách các đối tượng trong lớp được dễ dàng hơn thông qua id
của đối tượng đó.
4.2.3 Xây dựng FSM mô tả biểu đồ trình tự UML
Giao thức được mô tả bằng biểu đồ trình tự là giao thức liên quan đến nhiều lớp
đối tượng khác nhau, nhưng xét cho cùng, nó cũng g ần giống với giao thức trên một
lớp đối tượng được mô tả bằng biểu đồ trạng thái. Nó cũng quy đ ịnh dãy các phương
thức sẽ được gọi trong chương trình và l ập trình viên sẽ phải gọi các phương thức
trong các lớp khác nhau đúng theo trình tự như vậy. Việc kiểm chứng, xét cho cùng
cũng chính là để kiểm tra xem lập trình viên gọi các phương thức có đúng như giao
thức đặc tả ban đầu không. Do đó, Máy trạng thái mô tả biểu đồ trình tự tôi xây dựng
cũng tương tự với máy trạng thái mô tả biểu đồ trạng thái. Gồm ba thành phần dữ liệu:
HashMap> fsm = null;
HashSet entrySigs, exitSigs;
- entrySigs: Mô tả phương thức bắt đầu của giao thức
- exitSigs: Mô tả phương thức kết thúc giao thức
- fsm: Là một HashMap, với key một phương thức bất kỳ khác phương thức
mở đầu và phương thức kết thúc giao thức. Value chính là phương thức
ngay trước nó trong giao thức.
Một câu hỏi đặt ra là: Trong biểu đồ trình tự, các phương thức (thông điệp) được
mô tả theo một dãy và đư ợc đánh số thứ tự tự động bắt đầu từ 1, như vậy thì cần ba
thành phần dữ liệu để mô tả một dãy gọi phương thức như vậy có phải là thừa không?
Tôi xin trả lời là không hề thừa chút nào. Vì trong khi kiểm chứng, theo như bài báo
[5] đề cập, không phải trong chương trì nh, mỗi lớp đối tượng được đặc tả ở đây chỉ
được khởi tạo và thực hiện một lần. Lập trình viên có thể thực hiện giao thức nhiều lần
bằng cách khai báo các biến khác nhau của các lớp đối tượng này. Ví dụ: Ta mô tả
giao thức giữa hai đối tượng A và B với hai thông điệp A -> B và B -> A. Ta có thể
khai báo hai đối tượng của lớp A: là a1, a2 và hai đối tượng của lớp B là b1, b2 cùng
thực hiện giao thức này. Cụ thể việc tự động ánh xạ giao thức cho từng đối tượng của
lớp như thế nào, tôi sẽ trình bày ở phần sau. Phần này tôi chỉ tập trung vào việc mô tả
thuật toán xây dựng máy trạng thái mô tả biểu đồ trình tự UML dựa vào tài liệu XMI
đặc tả biểu đồ trình tự và các cấu trúc dữ liệu đã được xây dựng ở phần trước.
Thuật toán xây dựng FSM mô tả biểu đồ trình tự UML:
47
- Input: tài liệu XMI
- Output: FSM nếu xây dựng được, nếu không sẽ báo lỗi.
- Các bước thực hiện:
o Khởi tạo fsm, entrySigs, exitSigs.
o Đọc file XMI, lấy ListMessage, ListClasfierRoles,
ListReturn, ListArgument và ListTransitions.
o Duyệt từng Message trong ListMessage.
Nếu nó là message đầu tiên, lấy các dữ liệu về tên lớp, kiểu
trả về, các tham số truyền vào cho vào entrySigs và cho
vào fsm với key là tên thông điệp hoàn chỉnh, value là
“START”.
Nếu nó là message kết thúc, lấy dữ liệu tạo thành message
hoàn chỉnh (bao gồm tên lớp, kiểu trả về…), lưu vào
exitSigs. Lưu vào fsm với key là message hoàn chỉnh vừa
lưu vào exitSigs và value là Set chứa hàm ngay hoàn chỉnh
ngay trước đó.
Nếu nó là message trung gian, lấy dữ liệu hoàn chỉnh về
message hiện thời và message ngay trước đó. Lưu vào fsm
với key là message hiện thời, value là Set chứa message
ngay trước đó.
4.3 Kết luận
Trong chương này, tôi đã trình bày phương pháp xây d ựng FSM từ một tài liệu
XMI đặc tả biểu đồ UML. Nó gồm một số bước cơ bản như: phân tích tài liệu XMI,
đánh dấu các thẻ cần lấy dữ liệu, chọn ra các thuộc tính cần lấy dữ liệu, từ đó xây dựng
các cấu trúc dữ liệu mô tả các thành phần cơ bản của biểu đồ. Tiếp theo, xây dựng các
cấu trúc dữ liệu mở rộng để có thể lưu trữ được toàn bộ các dữ liệu quan trọng về các
thành phần của biểu đồ. Cuối cùng là xây dựng FSM từ các dữ liệu mô tả biểu đồ
UML bằng các đối tượng trong Java. Kết quả của bước này chính là FSM mô tả giao
thức mà biểu đồ UML đã đ ặc tả. Đây cũng chính là đ ầu vào cho bộ sinh mô-đun
aspect tự động trong công cụ PVG của tôi.
48
Chương 5. Xây dựng công cụ tự động sinh aspect từ
máy trạng thái
Xây dựng công cụ tự động sinh aspect từ máy trạng thái chính là bước thứ hai
trong nghiên cứu của tôi về “phương pháp kiểm chứng đặc tả UML cho tác tử phần
mềm”. Mục tiêu của bước này là tạo dựng được công cụ tự sinh aspect từ máy trạng
thái đã được tạo ra theo phương pháp đã trình bày ở chương 4. Aspect này sẽ được đan
vào chương trình chính thông qua trình biên d ịch AspectJ nhằm thực thi nhiệm vụ
kiểm chứng.
5.1 Đặt vấn đề
Trong chương 2 nói về lập trình hư ớng khía cạnh, tôi đã trình bày chi ti ết về
aspect và cấu trúc của nó. Một aspect phải có đầy đủ các thông tin về các quy tắc đan
(join point và pointcut) và mã kiểm chứng (được cài đặt trong advice). Từ đó trình
biên dịch AspectJ mới có thể đan chúng vào chương trình chính ph ục vụ quá trình
kiểm chứng. Từ nội dung nghiên cứu của bài báo “Checking Interface Interaction
Protocols Using Aspect-Oriented Programming” [5] và khóa luận của tôi, phương
pháp cài đặt aspect từ máy trạng thái bao gồm các bước cơ bản sau:
Bước 1: Xác định quy tắc đan – căn cứ vào các giao thức cần kiểm chứng để
xác định các join point sẽ cần theo dõi xem có vi phạm hay không trong thời gian
chạy. Từ các join point này sẽ xây dựng các pointcut trong aspect.
Bước 2: Xây dựng hành vi đan – đây chính là bước viết mã kiểm chứng trong
phần advice. Ta cần xác định các hành vi mà hệ thống cần thực thi và những điều kiện
làm cho ràng buộc về giao thức bị vi phạm.
Bước 3: Tổng hợp aspect – Khi đã xác đ ịnh được pointcut và advice, aspect sẽ
được hình thành theo mẫu sau:
aspect
{
Vùng pointcut;
Vùng advice;
}
49
5.2 Sinh aspect từ FSM mô tả biểu đồ trạng thái UML
Mô tả giao thức bằng biểu đồ trạng thái, ta quan tâm tới các trạng thái và các
hành vi chuyển trạng thái. Hành vi chuyển trạng thái chỉ được thực hiện khi nó thỏa
mãn hai điều kiện:
- Trạng thái trước đó có gọi được hàm chuyển trạng thái hay không.
- Điểu kiện chuyển trạng thái được thỏa mãn.
Khi thỏa mãn hai điều kiện này, hàm chuyển trạng thái được thực thi và trạng
thái của chương trình s ẽ thay đổi sang một trạng thái mới. Như vậy, các join point
được xác định chính là điểm gọi các hàm chuyển trạng thái; before advice sẽ chứa mã
kiểm tra vi phạm hai điều kiện chuyển trạng thái; after advice chứa mã thay đổi trạng
thái. Cấu trúc tổng quát sẽ có dạng:
pointcut pc_METHOD: ARGS && call (METHOD_RETURN
METHOD_NAME(METHOD_ARG_TYPE))
before(METHOD_ARG): pc_METHOD_NAME(METHOD_ARG_NAME) {
if (PRE-CONDITIONS){
// Định nghĩa các hành động khi vi phạm điều kiện
}
}
after(METHOD_ARG): pc_METHOD_NAME(METHOD_ARG_NAME) {
// Thay đổi trạng thái
}
Để tiện cho việc quản lý các trạng thái, ta đặt giá trị cho các trạng thái đặc tả
trong giao thức bằng các số tự nhiên bắt đầu từ 0 – HashMap stateMap sẽ được dùng
vào việc này. Và dùng một biến khác để lưu giá trị của trạng thái hiện thời (int
state).
Before advice sẽ kiểm tra xem giá trị của biến state hiện thời có bằng giá trị của
các trạng thái trước đó có thể sẽ được chuyển trạng thái khi gọi phương thức hiện thời
hay không? Nếu vi phạm, sẽ báo lỗi. Giá trị của biến state sẽ được đặt bằng 0 khi trạng
thái hiện tại là “START”.
After advice sẽ đặt lại giá trị mới cho biến state sau khi hàm thay đổi trạng thái
được gọi. giá trị của biến state sẽ được đặt bằng 0 nếu sau khi thay đổi trạng thái, trạng
thái mới là “FINAL”.
Thuật toán sinh mã aspect sẽ được cài đặt như sau:
- Duyệt lần lượt các key trong FSM – đây chính là các hàm chuyển trạng
thái
- Nếu key không phải là “START” hay “FINAL”
50
o Dùng các hàm xử lý xâu, cắt chuỗi key thành các phần như: tên hàm,
kiểu trả về, kiểu tham số truyền vào, tên tham số truyền vào, điều
kiện chuyển trạng thái.
o Duyệt từng thành phần trong value của FSM, tạo ra các điều kiện
kiểm tra vi phạm.
o Tạo ra các pointcut, advice bằng cách thay thế các xâu vừa được tạo
ra ở trên vào các vị trí đã được định nghĩa sẵn trong mẫu pointcut và
advice được định nghĩa trước đó.
- Kết hợp các pointcut, advice lại thành aspect.
5.3 Sinh aspect từ FSM mô tả biểu đồ trình tự UML
Kiểm chứng giao thức trên nhiều lớp đối tượng giống như việc gọi tuần tự các
phương thức trong biểu đồ trình tự được đề cập rất rõ trong bài báo [5]. Ở đây, tác giả
của bài báo dùng hai lớp là SharedState và SharedStateManager để kiểm chứng giao
thức trên nhiều lớp đối tượng. SharedState để ràng buộc các đối tượng của các lớp
trong giao thức và SharedStateManager cung cấp một vài phương thức để tạo ra
SharedState, liên kết SharedState với các đối tượng. Các pointcut trong aspect này
được chia ra làm ba loại:
- pc_entry: pointcut dùng để bắt phương thức đầu tiên trong giao thức
- pc_exit: pointcut dùng để bắt phương thức cuối cùng trong giao thức
- pc: pointcut dùng để bắt các phương thức khác.
Before advice của pc_entry sẽ tạo ra một đối tượng SharedState mới nếu nó chưa
có ràng buộc với bất kỳ đối tượng SharedState nào.
Before advice của pc và pc_exit dùng để kiểm tra đối tượng khi nó còn ràng buộc
với bất kỳ đối tượng SharedState nào đó. Nó kiểm tra xem có vi phạm các ràng buộc
không và đưa ra các thông báo khi có vi phạm xảy ra.
After advice của pc_entry và pc pointcut là giống nhau, chúng được sử dụng để
lưu lại trạng thái và đặt giá trị mới cho biến trạng thai sau khi mỗi phương thức được
gọi.
After advice của pc_exit ngoài việc lưu lại trạng thái, nó xóa bỏ đối tượng
SharedState đã được tạo ra trong before advice của pc_entry.
Thuật toán sinh mã aspect được cài đặt như sau:
51
- Duyệt lần lượt các hàm trong entrySigs tạo ra loại pointcut pc_entry và các
advice.
- Duyệt lần lượt các hàm trong exitSigs tạo ra loại pointcut pc_exit và các
advice.
- Duyệt lần lượt các hàm trong key của fsm, tạo ra loại pointcut pc và các
advice
- Ba loại pointcut này đều được tạo ra bằng cách xử lý các xâu ký tự, tách
chuỗi thành tên hàm, kiểu trả về, tên tham số truyền vào, kiểu tham số
truyền vào…
- Kết hợp các pointcut và advice đã tạo ra ở trên thành aspect kiểm chứng
hoàn chỉnh.
- Thêm nữa, để quản lý trạng thái của SharedState, ta cần phải có dữ liệu
của FSM mô tả biểu đồ trình tự UML. Vì vậy, trong aspect này sẽ chứa
thêm phần mã nguồn tạo ra FSM từ biểu đồ trình tự UML như trong
chương 4 đã trình bày.
5.4 Mở rộng
Trong bài báo “Checking Interface Interaction Protocols Using Aspect-oriented
Programming” [5] chưa xử lý các hàm trùng tên nhưng có các tham s ố truyền vào
khác nhau hay kiểu dữ liệu trả về khác nhau và không kiểm tra điều kiện tiên quyết
cần thiết trước khi hàm được gọi (precondition của hàm). Trong khóa luận của tôi, tôi
đã mở rộng thêm hai phần này:
- Kiểm tra precondition được mô tả trong biểu đồ trạng thái UML: Như
trong phần 4.1.1, tôi có nói đến các quy tắc biểu diễn giao thức bằng biểu
đồ trạng thái UML. Biểu thức điều kiện ở đây giống với biểu thức điều
kiện trong mã nguồn của chương trình. Như v ậy, để kiểm tra xem có vi
phạm điểu kiện hay không, tôi sẽ quy về một đoạn mã nguồn có thể là biểu
thức, có thể chứa các lời gọi hàm và trả về kiểu boolean. Như vậy ta sẽ
kiểm tra được vi phạm. Tuy nhiên, do việc mô tả precondition bằng cách
rất hạn chế mà công cụ PVG chỉ tạo ra aspect với các mô tả có trong biểu
đồ, do đó đôi khi precondition sẽ không kiểm tra được trong thực tế (ví dụ:
precondition liên quan đến dữ liệu của nhiều lớp khác nhau chẳng hạn).
Điều này có thể khắc phục bằng cách sửa lại mô-đun aspect do công cụ
PVG tạo ra, thêm một số các đoạn mã để có thể kiểm tra được precondition
trong mô-đun aspect.
52
- Thêm tham số truyền vào cho hàm: ở đây tôi sử dụng các thao tác với
xâu khí tự trong Java, cắt chuỗi phương thức thành các phần nhỏ như: các
chuỗi lưu tên hàm, tên tham số truyền vào, tên kiểu dữ liệu của tham số,
tên tham số, kiểu giá trị trả về từ đó tạo ra các advice bằng cách thay thế
các chuỗi con này vào trong các phần của aspect mẫu đã được định nghĩa
từ trước. Khi cắt xâu ký tự mô tả phương thức thành nhiều phần nhỏ như
vậy, việc tạo ra hai pointcut cho hai hàm trùng tên nhưng khác tham số
truyền vào rất đơn giản, tôi chỉ cần thêm chuỗi mô tả kiểu của các tham số
vào ngay sau xâu định nghĩa tên pointcut; như vậy sẽ giải quyết được mọi
vấn đề của các hàm trùng tên, khác tham số truyền vào.
5.5 Sinh mã aspect kiểm chứng giao thức (AB)n
Trong phần tìm hiểu của tôi, tôi sử dụng phương pháp tạo ra mã kiểm chứng ở
trên để xây dựng thêm một chức năng khác cho công cụ “PVG”, đó là sinh mã aspect
kiểm chứng giao thức (AB)n. Trong phần này tôi sẽ trình bày phần mở rộng này.
5.5.1 Giao thức (AB)n là gì?
A và B là tên của các phương thức còn n là số lần các phương thức được gọi
trong chương trình. Nói một cách đơn giản, (AB)n mô tả việc hàm A và B phải được
gọi n lần trong mã nguồn của chương trình.
Giao thức (AB)n được mô tả bằng biểu thức chính quy như sau: [A*B] n.
Ở đây, * có thể là rỗng (null) hoặc là một dãy các phương thức khác.
Ví dụ:
- Giao thức: [void open() void close()]3 - mô tả việc gọi 3 cặp phương thức
void open(), void close() trong chương trình; gi ữa hai phương thức này
không có bất kỳ phương thức nào khác được gọi:
- …open() close()…open() close()…open() close()…
- Giao thức: [void open() * void close()]3 – mô tả việc gọi cặp hàm void
open() và void close() trong chương trình như sau:
- …open()…close()…open()…close()…open()…close(). Ở đây “…” đại
diện cho một phương thức hay một chuỗi phương thức bất kỳ.
Công cụ PVG chỉ hiểu giao thức (AB)n được định nghĩa theo đúng như biểu thức
chính quy mô tả ở trên.
53
5.5.2 Thuật toán kiểm chứng giao thức (AB)n
5.5.2.1 [A * B] n
Việc kiểm chứng giao thức [A * B] n nảy sinh hai vấn đề lớn:
- Thứ nhất: phương thức A và B được gọi liên tiếp nhau (), tức là việc
gọi hai phương thức A B phải tạo thành một dãy: A … B … A … B…
Vấn đề này được giải quyết bằng một biến đếm kiểu nguyên num như sau:
o Ban đầu đặt num = 0.
o Trước khi gọi A, kiểm tra num, nếu num != 0 -> báo lỗi
o Sau khi gọi A, tăng num lên 1.
o Sau khi gọi B, giảm num đi 1. Và sau khi giảm n đi 1 kiểm tra num,
nếu num != 0 -> báo lỗi.
- Thứ hai: cặp (A B) được gọi đúng n lần.
Việc gọi cặp (A B) đúng n lần nảy sinh ra hai trường hợp: gọi lớn hơn n
lần và gọi nhỏ hơn n lần. Kiểm tra cặp A, B gọi đúng lớn hơn n lần rất đơn
giản, ta cũng dùng một biến kiểu nguyên khác để kiểm tra (ví dụ: biến int
count):
o Sau khi gọi A, tăng biến count lên 1 và kiểm tra, nếu count > n thì
báo lỗi.
o Ở đây ta chỉ cần kiểm tra A có được gọi > n lần hay không mà không
cần kiểm tra B vì nếu A đã được gọi > n lần thì ta đã bắt được lỗi và
nếu A và B được gọi với số lần khác nhau, ta cũng đã b ắt được lỗi
bằng biến num ở trên. Như vậy chỉ cần kiểm tra A là đủ.
Kiểm tra (A B) được gọi < n lần khó khăn hơn, ta không thể dùng
các join point tại các phương thức A và B kiểm tra được mà phải
dùng một join point khác là điểm mà sau khi tất cả các hàm A, B
được gọi. Để đơn giản, tôi tạo ra một phương thức mới trong mã
nguồn của chương trình (void checkAnBn()). Phương thức này không
ảnh hưởng gì đ ến chương trình, nó đư ợc gọi ở điểm kết thúc của
chương trình. Sau khi tạo được một join point tại điểm kết thúc của
chương trình thì vi ệc kiểm tra A có được gọi n lần hay không tôi
cũng dùng chính ngay biến count ở trên để kiểm tra. Before advice sẽ
kiểm tra xem, nếu count != n thì sẽ báo lỗi.
Quay trở lại, ta có thể thấy việc tạo ra một phương thức mới làm
điểm đánh dấu kết thúc chương trình sẽ giải quyết được tất cả vấn đề
54
liên quan tới việc gọi hàm A đúng n lần. Trong công cụ PVG tôi sử
dụng cả hai cách đã được chỉ ra ở trên.
5.5.2.2 [A B] n
[A B] n là mở trường hợp đặc biệt của [A * B] n khi * = null. Ở đây, ta phải gọi
hai phương thức A, B theo một cặp (A B). Để kiểm chứng giao thức [A B] n ta cũng kế
thừa từ thuật toán kiểm chứng giao thức [A * B] n, và mở rộng thêm một phần kiểm tra
gọi hai phương thức A, B theo cặp (A B).
Để làm được điều này, ta phải bắt được tất cả các điểm gọi hàm khác. Khi bắt
được tất cả các điểm gọi hàm khác thì việc kiểm tra vi phạm sẽ rất đơn giản, ta chỉ cần
dùng một biến check kiểu nguyên. Mỗi khi chương trình g ọi hàm, biến check được
tăng lên 1. Sau khi chương trình gọi hàm A, biến check được đặt lại giá trị = 0. Và ta
sẽ kiểm tra sau khi gọi hàm B, nếu biến check != 1 thì chương trình sẽ báo lỗi. Vì nếu
check != 1 thì tức là đã có một hàm khác được gọi ở giữa A và B.
5.5.3 Sinh mã aspect kiểm chứng giao thức (AB)n
Phương pháp này có ý tưởng hoàn toàn giống với phương pháp sinh aspect kiểm
chứng từ biểu đồ UML, nó chỉ khác nhau ở các mẫu aspect được định nghĩa khác
nhau. Đầu tiên là phân tích chuỗi [A * B] n lấy ra các phương thức A, B và biến n. Sau
đó dùng các phương thức xử lý xâu ký tự, tách các hàm A, B này ra thành các phần:
tên hàm, kiểu giá trị trả về, tham số… giống như khi xử lý tạo ra aspect từ biểu đồ
UML. Sau đó tạo ra các aspect theo mẫu đã định nghĩa trước.
5.6 Kết luận
Trong chương này, tôi đã trình bày phương pháp tự động sinh mô-đun aspect từ
FSM mô tả biểu đồ UML. Nội dung chính của phương pháp chính là duyệt các trạng
thái trong FSM, phân tích vào các vị trí thích hợp trong xâu aspect mẫu được khai báo
từ trước. Xâu aspect mẫu sẽ tuân theo cú pháp của một aspect cơ bản, bao gồm tên
aspect, vùng pointcut và vùng advice. Thuật toán duyệt các trạng thái trong máy trạng
thái thực chất là việc duyệt các key của FSM, lấy dữ liệu của từng trạng thái, sử dụng
các phương thức thao tác với xâu ký tự để tạo ra các aspect. Đồng thời, tôi đưa ra
phương pháp kiểm chứng giao thức (AB)n – một mở rộng cho công cụ PVG có thể
kiểm chứng giao thức (AB)n.
Kết quả thu được sau bước này là mã aspect. Mã aspect này sẽ được đan vào
chương trình chính để thực hiện chức năng kiểm chứng chương trình.
55
Chương 6. Thực nghiệm
Để minh họa cho phương pháp xây dựng công cụ sinh aspect được giới thiệu
trong các chương trước, chương này sẽ mô tả chi tiết các bước cài đặt mà tôi đã thực
hiện và kết quả thực hiện kiểm chứng trên một số giao thức thực tế.
Các file đính kèm theo tài liệu này:
- LUẬN VĂN-KIỂM CHỨNG ĐẶT TẢ UML CHO TÁC TỬ PHẦN MỀM.pdf