ĐẠ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Ệ
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
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
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
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
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
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
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
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
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.
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ằ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
đá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)
pointcut updateDisplay(): execution(void *.moveBy(int,int))
Ta có thể xây dựng các advice như sau:
- Before advice thự hiện lưu vết
before() : updateDisplay() {
14
// logging
}
- After advice thực hiện cập nhật hình
after() : updateDisplay() {
display.update(this);
}
Ví dụ về around advice dùng để kiểm tra thuộc tính age của lớp Person trong
phương thức setAge() có vi phạm điều khiện không (điều kiện: age > 0).
void around(Person person, int age):setAge(person, age)
{
if(age > 0)
Process(person,age);
else
System.out.println("Invalid Age!");
}
2.2.4 Aspect
Aspect là phần tử trung tâm của AspectJ, giống như class trong Java. Aspect chứa
mã thể hiện các luật đan kết cho các concern. Join point, pointcut, advice được kết hợp
trong aspect [7, 12].
Aspect được khai báo theo mẫu sau:
[access specification] aspect <AspectName>
[extends class-or-aspect-name]
- 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.
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