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

Kiểm chứng một số ràng buộc trong chương trình java sử dụng AOP

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

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

Lê Ngọc Minh

KIỂM CHỨNG MỘT SỐ RÀNG BUỘC TRONG
CHƢƠNG TRÌNH JAVA SỬ DỤNG AOP

LUẬN VĂN THẠC SĨ

HÀ NỘI - 2015


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

Lê Ngọc Minh

KIỂM CHỨNG MỘT SỐ RÀNG BUỘC TRONG
CHƢƠNG TRÌNH JAVA SỬ DỤNG AOP
LUẬN VĂN THẠC SĨ
Ngành:
Chuyên ngành:
Mã số:

Công Nghệ Thông Tin
Kỹ thuật phần mềm
60 48 01 03

NGƢỜI HƢỚNG DẪN KHOA HỌC
TS. Trịnh Thanh Bình



HÀ NỘI - 2015


LỜI CAM ĐOAN
Tôi xin cam đoan đây là công trình nghiên cứu của riêng tôi. Các kết quả trình bày
trong luận văn là hoàn toàn trung thực, chưa được công bố trong bất kỳ công trình
nào khác.
Tôi xin cam đoan các trích dẫn tài liệu tham khảo trong luận văn đều đã được ghi rõ
nguồn gốc.
Hà Nội, ngày 10 tháng 9 năm 2015
TÁC GIẢ

Lê Ngọc Minh

iii


LỜI CẢM ƠN

Trong quá trình thực hiện đề tài, tôi đã gặp rất nhiều khó khăn và bỡ ngỡ. Nếu
không có sự giúp đỡ, động viên chân thành của các thầy cô và bạn bè đồng nghiệp
có lẽ tôi khó có thể hoàn thành tốt luận văn này.
Trước hết tôi xin tỏ lòng biết ơn sâu sắc đến TS Trịnh Thanh Bình đã tận tình
hướng dẫn trong suốt quá trình viết luận văn.
Tôi xin trân trọng cảm ơn quý Thầy, Cô và bạn bè 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 truyền
đạt kiến thức, sát cánh và trải nghiệm cùng tôi trong suốt những năm học tập tại
đây. Với vốn kiến thức được tiếp thu trong quá trình học là nền tảng cho quá trình
nghiên cứu luận văn.

Tôi xin trân trọng cảm ơn Đảng ủy, Ban Giám hiệu, Ban chủ nhiệm khoa
Công nghệ thông tin trường Đại học Hải Phòng đã tạo điều kiện cho tôi trong suốt
quá trình học tập và làm luận văn này.
Cuối cùng tôi gửi lời cảm ơn đến vợ con, gia đình đã động viên giúp đỡ tôi trong
những lúc khó khăn trong công tác và học tập.
Xin trân trọng cảm ơn!

iv


DANH MỤC CÁC BẢNG
Số bảng

Tên bảng

Trang

2.1

Ánh xạ giữa các loại join point và pointcut tương ứng

8

2.2

Ví dụ về một khía cạnh với mã hành vi trước và sau

9

2.3


Cấu trúc cơ bản của một khía cạnh

10

3.1

Đặc tả kịch bản mô tả chức năng rút tiền tự động của máy
ATM

14

3.2

Mẫu aspect tổng quát

15

4.1

Cài đặt chương trình cho kịch bản kiểm tra các assertion

23

4.2

Cài đặt kịch bản mô tả chức năng rút tiền từ tài khoản

24


4.3

Cài đặt kịch bản mô tả chức năng chuyển khoản

28

4.4

Kết quả kiểm chứng cho kịch bản 4

30

v


DANH MỤC CÁC HÌNH
Số hình

Tên hình

Trang

1.1

Kịch bản biểu diễn phép chia hai số nguyên

1

2.1


Điểm nối thực thi và triệu gọi phương thức

7

2.2

Ví dụ minh họa về đặc tả JML

11

3.1

Phương pháp kiểm chứng ràng buộc của kịch bản trong
chương trình Java sử dụng AOP.

15

4.1

Giao diện chính của chương trình.

20

4.2

Sinh mã Aspect cho kịch bản 1.

21

4.3


Kết quả kiểm chứng kịch bản 1 vi phạm đặc tả

22

4.4

Kết quả kiểm chứng kịch bản 1 không vi phạm

22

4.5

là kết quả kiểm tra các assertion cho kịch bản được cài đặt sai.

24

4.6

Kết quả kiểm tra các assertion cho kịch bản cài đặt đúng

24

4.7

Mô tả tạo Aspect với bài toán rút tiền đơn giản.

27

4.8


Kết quả đan xen mã.

27

4.9

Kết quả kiểm chứng

28

vi


DANH MỤC CÁC TỪ VIẾT TẮT
Chữ viết tắt

Giải thích

AOP

Aspect oriented programming

ATM

Automatic Teller Machine

JDK

Java Development Kit


JML

Java modeling language

JPF

Java Path Finder

JRE

Java Runtime Environment

JVM

Java Virtual Machine

LTL

Linear Temporal Logic

UC

Use Case

vii


Mục Lục
LỜI CAM ĐOAN ........................................................................................................ iii

LỜI CẢM ƠN .............................................................................................................. iv
DANH MỤC CÁC BẢNG............................................................................................v
DANH MỤC CÁC HÌNH ........................................................................................... vi
DANH MỤC CÁC TỪ VIẾT TẮT ........................................................................... vii
CHƢƠNG 1. GIỚI THIỆU ...........................................................................................1
1.1 Đặt vấn đề ..........................................................................................................1
1.2

Mục tiêu .............................................................................................................2

1.3
1.4

Đóng góp của luận văn ......................................................................................2
Cấu trúc luận văn ...............................................................................................2

CHƢƠNG 2. KIẾN THỨC CƠ SỞ .............................................................................4
2.1 Kiểm chứng phần mềm .........................................................................................4
2.2. Phương pháp lập trình hướng khía cạnh...............................................................5
2.2.1. Thực thi cắt ngang .........................................................................................6
2.2.2.Điểm nối .........................................................................................................6
2.2.3. Hướng cắt (pointcut) .....................................................................................7
2.2.4. Mã hành vi .....................................................................................................8
2.4.5. Khía cạnh .......................................................................................................9
2.3 Ngôn ngữ mô hình hóa JML (Java modeling language) .....................................10
2.4. Kết luận ..............................................................................................................11
CHƢƠNG 3: KIỂM CHỨNG MỘT SỐ RÀNG BUỘC CHƢỜNG TRÌNH JAVA
SỬ DỤNG AOP............................................................................................................12
3.1 Giới thiệu .............................................................................................................12
3.2. Bài toán ...............................................................................................................12

3.3 Phương pháp kiểm chứng sử dụng AOP .............................................................13
3.3.1 Sinh mã aspect từ đặc tả JML.......................................................................14
3.3.2 Đan xen mã ...................................................................................................16
CHƢƠNG 4. CHƢƠNG TRÌNH THỰC NGHIỆM ................................................17
4.1 Chức năng đã cài đặt ...........................................................................................17
4.2 Công cụ và môi trường xây dựng chương trình thực nghiệm .............................17
4.2.1 JDK ...............................................................................................................17

vi


4.2.2 Netbean IDE .................................................................................................17
4.2.3 AJDT ............................................................................................................17
4.3 Thực nghiệm ........................................................................................................18
4.5 Kết luận ...............................................................................................................28
CHƢƠNG 5: KẾT LUẬN ...........................................................................................29
5.1. Kết quả đạt được ................................................................................................29
5.2. Hướng phát triển .................................................................................................29
TÀI LIỆU THAM KHẢO...........................................................................................29

vii


CHƢƠNG 1. GIỚI THIỆU
1.1

Đặt vấn đề

Phân tích và đặc tả yêu cầu đóng vai trò quan trọng trong quá trình xây dựng và
phát triển phần mềm. Các yêu cầu phần mềm thường được đặc tả dưới dạng các

ca sử dụng (use case-UC) mô tả toàn bộ sự tương tác giữa người dùng và hệ
thống. Trong mỗi tài liệu đặc tả, mô hình UC biểu diễn kịch bản mô tả các bước
mà hệ thống cần tuân thủ để thực hiện một nhiệm vụ. Một kịch bản thường gồm
các thành phần như : sự kiện, sự tương tác giữa các sự kiện, các biểu thức tiền
điều kiện (precondition) và hậu điều kiện (postcondition), xác nhận (assertion)...
Trong đó, tiền điều kiện và hậu điều kiện định nghĩa các ràng buộc mà kịch bản
buộc phải thỏa mãn khi bắt đầu và kết thúc thực thi một nhiệm vụ, assertion đặc
tả một thuộc tính mà kịch bản phải thoả mãn tại một thời điểm nào đó. Cuối
cùng, kịch bản sẽ được được cài đặt bởi các đoạn mã nguồn chương trình. Hình
1.1 biểu diễn một kịch bản ở mức mã nguồn thực hiện phép chia hai số nguyên
dương, với biểu thức tiền điều kiện là y khác không và hậu điều kiện là kết quả
của phép chia x cho y.

Precondition: y != 0
Postcondition: (x / y <= x)
double divide(int x, int y) {
return (x / y);
}

Hình 1.1. Kịch bản biểu diễn phép chia hai số nguyên.

Việc kiểm tra tính đúng đắn của một kịch bản bao gồm kiểm tra các biểu thức
tiền-hậu điều kiện và các assertion có thể thực hiện ở các giai đoạn đặc tả hoặc
mã nguồn chương trình. Hiện nay, đã có một vài phương pháp khác nhau được
đề xuất nhằm kiểm tra tính đúng đắn của kịch bản tại các giai đoạn thiết kế và
mã nguồn chương trình như các phương pháp kiểm chứng[1], kiểm thử[4]. Mỗi
phương pháp đều có những ưu và nhược điểm nhất định. Các phương pháp kiểm
thử yêu cầu phải có mã nguồn và các ca kiểm thử (test case) thường chỉ phát
hiện được các lỗi về giá trị đầu ra (output) nhưng không phát hiện được các lỗi
vi phạm ràng buộc thiết kế. Trong khi đó, một vi phạm ràng buộc thiết kế có thể

gây ra lỗi hệ thống, đặc biệt khi tích hợp nhiều môđun thì việc xác định chính
xác vị trí gây lỗi sẽ rất khó khăn làm cho chi phí phát triển tăng cao [1]. Các
phương pháp kiểm chứng như chứng minh định lý (theorem proving)[5] và kiểm
1


chứng mô hình (model checking) [3] đã được ứng dụng thành công để kiểm
chứng bản thiết kế phần mềm nhằm phát hiện sớm những lỗi tiềm ẩn, giảm thời
gian và chi phí phát triển. Ngược lại, các phương pháp kiểm chứng tại mức mã
nguồn nhằm kiểm tra sự tuân thủ giữa bản thiết kế và cài đặt của phần mềm.

1.2

Mục tiêu

Luận văn đặt ra mục tiêu là nghiên cứu về một số kĩ thuật kiểm chứng phần
mềm từ đó đề xuất cách tiếp cận kiểm chứng các biểu thức tiền-hậu điều kiện và
các xác nhận của kịch bản tại mức mã nguồn sử dụng phương pháp lập trình
hướng khía cạnh (Aspect oriented programming-AOP). Các mục tiêu cụ thể cần
đạt được là:
 Khảo cứu một số phương pháp kiểm chứng chương trình; mô hình ca sử
dụng trong phân tích thiết kế và đặc tả yêu cầu phần mềm; phương pháp
lập trình hướng khía cạnh; ngôn ngữ mô hình hoá JML (Java modeling
language);
 Đề xuất một cách tiếp cận để kiểm chứng các biểu thức tiền-hậu điều kiện
và xác nhận của kịch bản sử dụng phương pháp lập trình hướng khía
cạnh;
 Xây dựng và thử nghiệm thành công công cụ kiểm chứng một số ràng
buộc của kịch bản tại mức mã nguồn chương trình.


1.3

Đóng góp của luận văn

Đóng góp chính của luận văn là đề xuất và xây dựng thành công một công cụ
kiểm chứng một số ràng buộc của một kịch bản tại thời điểm thực thi (mức mã
nguồn). Các kết quả chính như sau:
 Tìm hiểu và trình bày một số phương pháp kiểm chứng, kiểm thử phần
mềm; phương pháp lập trình hướng khía cạnh với Java (AspectJ); ngôn
ngữ mô hình hóa JML;
 Đề xuất và xây dựng thành công một công cụ để kiểm tra một số ràng
buộc kịch bản tại thời điểm thực thi, áp dụng cho các kịch bản được cài
đặt trên ngôn ngữ lập trình Java.

1.4

Cấu trúc luận văn

Luận văn gồm 4 chương chính được cấu trúc như sau:
 Chương 1: Giới thiệu bài toán kiểm chứng một số ràng buộc của kịch bản,
mục tiêu và các đóng góp của luận văn;
 Chương 2: Trình bày một số kiến thức cơ sở cho mục tiêu nghiên cứu và
các đóng góp của luận văn;
2


 Chương 3: Đề xuất phương pháp kiểm chứng một số ràng buộc của kịch
bản trong chương trình Java;
 Chương 4: Giới thiệu chương trình thực nghiệm và các đóng góp,
 Chương 5: Kết luận và hướng phát triển của luận văn.


3


CHƢƠNG 2. KIẾN THỨC CƠ SỞ
Trong chương này luận văn trình bày một số kiến thức nền về kiểm chứng phần
mềm tại thời điểm thực thi, phương pháp lập trình hướng khía cạnh, ngôn ngữ
mô hình hóa JML. Đây là các kiến thức cơ sở được sử dụng cho các đóng góp
của luận văn trong chương 3 và chương 4.
2.1 Kiểm chứng phần mềm
Kiểm chứng phần mềm (software verification) là tập các nguyên lý, phương
pháp và công cụ nhằm bảo đảm tính đúng đắn của phần mềm, trong mục này
luận văn trình bày hai phương pháp kiểm chứng phần mềm là kiểm chứng hình
thức và kiểm chứng tại thời điểm thực thi chương trình.
2.1.1. Kiểm chứng hình thức
Phương pháp kiểm chứng mô hình (model checking)[3] được sử dụng để xác
định tính hợp lệ của một hay nhiều tính chất mà người dùng quan tâm trong một
mô hình phần mềm cho trước. Cho mô hình M và thuộc tính p cho trước, nó
kiểm tra liệu thuộc tính p có thỏa mãn trong mô hình M hay không, ký hiệu M |=
p. Về mặt thực thi, kiểm chứng mô hình sẽ duyệt qua các trạng thái, các đường
thực thi có thể có trong mô hình M để xác định tính khả thỏa của p. Trong đó,
các thuộc tính được đặc tả bằng logic thời gian LTL hoặc CTL. Mô hình M là
một cấu trúc Kripke gồm bốn thành phần M = (S, S0, L,R) với S là một tập hữu
hạn các trạng thái, S0 ∈ S là trạng thái đầu, R ⊂ S×S là quan hệ chuyển trạng
thái, L : S → 2AP là hàm gán nhãn với AP là tập hữu hạn các mệnh đề nguyên tử
được xây dựng từ hệ thống.
Một bộ kiểm chứng mô hình (model checker ) sẽ kiểm tra tất cả các trạng thái có
thể có của mô hình để tìm ra tất cả các đường thực thi có thể gây ra lỗi. Do đó
không gian trạng thái thường là vô cùng lớn nếu không muốn nói là vô hạn. Vì
vậy việc phải duyệt qua tất cả các trạng thái là bất khả thi. Để đối phó với bài

toán bùng nổ không gian trạng thái đã có một vài nghiên cứu liên quan đến các
kỹ thuật làm giảm không gian trạng thái như Abstraction, Slicing.
2.1.2 Chứng minh định lý
Phương pháp chứng minh định lý (theorem proving) [5] sử dụng các kĩ thuật suy
luận để chứng minh tính đúng đắn của một công thức hay tính khả thỏa của một
công thức F với tất cả các mô hình, ký hiệu |= F. Một hệ chứng minh bao gồm
các luật suy diễn bao gồm các tiên đề, định lý. Một hệ thống được gọi là đúng
(sound) nếu tất cả các định lý của nó đều được chứng minh.
2.1.3 Kiểm chứng tại thời điểm thực thi
Kiểm chứng tại thời điểm thực thi (runtime verification)[1] là kĩ thuật kết hợp
giữa kiểm chứng hình thức và thực thi chương trình nhằm phát hiện các lỗi của
hệ thống dựa trên quá trình quan sát đầu vào (input), đầu ra (output) trong khi
thực thi chương trình, các giá trị đầu ra được quan sát để kiểm tra tính thỏa được
so với đặc tả yêu cầu phần mềm. So với phương pháp kiểm chứng tĩnh thì kiểm
4


chứng tại thời điểm thực thi được thực hiện trong khi chạy chương trình.
Phương pháp này thường được sử dụng để kiểm tra sự tuân thủ giữa bản thiết kế
và sự cài đặt của nó áp dụng cho các ngôn ngữ lập trình cụ thể, điển hình là Java
với các công cụ kiểm chứng như JPF [8,15], JLO, ESC/Java,...Một số ưu điểm
của phương pháp kiểm chứng tại thời điểm thực thi[14] như sau:
- Có thể bảo đảm tính đúng đắn giữa sự cài đặt phần mềm sơ với bản thiết
kế của nó;
- Nhiều thông tin chỉ có sẵn hoặc phụ thuộc vào môi trường khi nó được
thực thi;
- Với các hệ thống an toàn và bảo mật cao đòi hỏi phải được kiểm chứng tại
tấ cả các giai đoạn trong quá trình phát triển.
2.2. Phƣơng pháp lập trình hƣớng khía cạnh
Phương pháp lập trình hướng khía cạnh (Aspect-Oriented Programming) [8,12]

là phương pháp lập trình phát triển trên tư duy tách biệt các mối quan tâm khác
nhau thành các môđun khác nhau. Ở đây, một mối quan tâm thường không phải
là một chức năng nghiệp vụ cụ thể và có thể được đóng gói mà là một khía cạnh
(thuộc tính) chung mà nhiều môđun phần mềm trong cùng hệ thống nên có, ví
dụ như lưu vết thao tác và lỗi (error logging). Với AOP, chúng ta có thể cài đặt
các mối quan tâm chung cắt ngang hệ thống bằng các môđun đặc biệt gọi là khía
cạnh (aspect) thay vì dàn trải chúng trên các môđun nghiệp vụ liên quan. Các
khía cạnh sau đó được kết hợp tự động với các môđun nghiệp vụ khác bằng quá
trình gọi là đan (weaving) bằng bộ biên dịch đặc biệt. Các ưu điểm của phương
pháp AOP được tóm tắt như sau[8,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.
AspectJ [12] là một phương pháp lập trình AOP áp dụng cho ngôn ngữ Java.
Trình biên dịch AspectJ sẽ đan xen chương trình Java chính với các khía cạnh
thành các tệp mã bytecode chạy trên chính máy ảo Java. Trong các mục tiếp
theo của luận văn, tôi trình bày một số khái niệm liên quan trong AspectJ được
5


sử dụng để sinh mã kiểm chứng kịch bản với các ràng buộc về biểu thức tiền và

hậu điều kiện và các assertion
2.2.1. Thực thi cắt ngang
Trong AspectJ, quá trình trình biên dịch thực thi các quy tắc đan để đan kết các
môđun cắt ngang vào môđun nghiệp vụ chính được gọi là thực thi cắt ngang
(crosscutting). AspectJ định nghĩa hai loại thực thi cắt ngang là thực thi cắt
ngang động và thực thi cắt ngang tĩnh:
 Thực thi cắt ngang động (dynamic crosscutting) là việc đan các hành vi
mới vào quá trình thực thi một chương trình. Trình biên dịch sẽ dựa vào
tập các quy tắc đan để xác định điểm đan và chèn thêm hoặc thay thế
luồng thực thi chương trình chính bằng môđun cắt ngang, từ đó làm thay
đổi hành vi của hệ thống. Hầu hết việc thực thi cắt ngang trong AspectJ
đều là thực thi cắt ngang động.
 Thực thi cắt ngang tĩnh (static crosscutting) là quá trình đan một sửa đổi
vào cấu trúc tĩnh của lớp, giao diện hay các khía cạnh hệ thống. Chức
năng chính của thực thi cắt ngang tĩnh là hỗ trợ cho thực thi cắt ngang
động. Ví dụ như thêm dữ liệu và phương thức mới vào lớp đã có nhằm
định nghĩa trạng thái và hành vi của lớp đó để sử dụng trong các hành vi
cắt ngang động. Thực thi cắt ngang tĩnh còn được sử dụng nhằm khai báo
các cảnh báo và lỗi tại thời điểm biên dịch cho nhiều môđun.
Trong AOP, mỗi khía cạnh được coi là biểu diễn của một quy tắc đan, nó chỉ ra
môđun cần được đan, vị trí đan trong môđun đó, hành vi sẽ được đan vào thông
qua các định nghĩa của điểm nối, hướng cắt và mã hành vi.
2.2.2.Điểm nối
Điểm nối (joinpoint) là một điểm có thể xác định trong quá trình thực thi một
chương trình, điểm này chính là vị trí mà các hành động thực thi cắt ngang được
đan vào. Trong AspectJ có một số loại điểm nối được chia thành hai loại thực
thi và triệu hồi phương thức sau.
 Điểm nối thực thi phương thức (method execution joinpoint): điểm này
nằm trên chính phần thân của phương thức thực thi, nó gồm toàn bộ các
lệnh nằm trong thân phương thức,

 Điểm nối triệu gọi phương thức (method call joinpoint): điểm này nằm
trên phần chương trình gọi phương thức đang xét, nó chính là điểm mà
phương thức đang xét được gọi.

6


Hình 2.1. Điểm nối thực thi và triệu gọi phƣơng thức
2.2.3. Hƣớng cắt (pointcut)
Trong AspectJ, điểm nối thường được sử dụng trong một hướng cắt (pointcut),
mỗi hướng cắt chứa một nhóm các điểm nối cùng với ngữ cảnh của nó. Ta có
thể khai báo hướng cắt trong một khía cạnh, một lớp hoặc một giao diện. Giống
như phương thức, có thể sử dụng định danh truy cập (public, private) để giới hạn
quyền truy cập đến hướng cắt. Các hướng cắt có thể có tên hoặc không tên. Các
hướng cắt không tên, giống như các lớp không tên, được định nghĩa tại nơi sử
dụng. Các hướng cắt được đặt tên thì có thể được tham chiếu từ nhiều nơi khác.
Cú pháp khai báo hướng cắt như trong sau [12] [15].
[access specifier] pointcut pointcut-name([args]):
pointcut-definition

Ví dụ: pointcut callSayHello(): call(* *.sayHello());
Trong đó [access specifier] khai báo định danh truy cập có thể là public hoặc
private, [pointcut name] khai báo tên của hướng cắt, [args] khai báo các tham số,
cuối cùng [pointcut-definition]là định nghĩa hướng cắt.
Bảng 2.1 Ánh xạ giữa các loại join point và pointcut tƣơng ứng
Cú pháp pointcut

Loại join point

execution(MethodSignature)


Thực hiện phương thức

call(MethodSignature)

Gọi phương thức

execution(ConstructorSignature)

Thực hiện hàm dựng
7


call(ConstructorSignature)

Gọi hàm dựng

staticinitialization(TypeSignatur
e)
get(FieldSignature)

Khởi tạo lớp

set(FieldSignature)

Ghi thuộc tính

execution handler(TypeSignature)

Thực hiện điều khiển ngoại lệ


initialization(ConstructorSignatu
re)
preinitialization(ConstructorSign
ature)
adviceexecution()

Khởi tạo đối tượng

Đọc thuộc tính

Tiền khởi tạo đối tượng
Thực hiện advice

2.2.4. Mã hành vi
Mã hành vi (advice) là đoạn mã định nghĩa hành vi được đan vào mã nguồn tại
điểm điểm nối [12][15]. Mã hành vi được thực thi trước (before advice), sau
({after advice}), hoặc xung quanh (around advice) một điểm nối. Mã hành vi có
thể được sử dụng để đưa ra thông báo trước khi đoạn mã tại điểm nối được thực
thi lưu vết hoặc kiểm tra lỗi. Trong AspectJ định nghĩa ba loại mã hành vi sau.
 Mã hành vi trước là loại mã được thực thi trước các điểm nối,
 Mã hành vi sau là loại mã được thực thi ngay sau các điểm nối,
 Mã hành vi xung quanh là loại mã mạnh nhất, nó bao gồm cả mã hành vi
trước và sau. Mã hành vi xung quanh có thể chỉnh sửa đoạn mã tại điểm
nối, nó có thể thay thế, thậm chí bỏ qua sự thực thi của điểm nối đó. Mã
hành vi xung quanh phải khai báo giá trị trả về cùng kiểu với kiểu trả về
của điểm nối. Trong mã hành vi xung quanh, sự thực thi của điểm nối
được thể hiện thông qua proceed(). Nếu trong mã hành vi không gọi
proceed() thì sự thực thi của điểm nối sẽ bị bỏ qua.
Bảng 2.2 biểu diễn một khía cạnh với mã hành vi trước và sau. Như vậy điểm

nối và mã hành vi kết hợp với nhau tạo nên quy tắc thực thi cắt ngang động:
hướng cắt xác định các điểm cắt cần thiết còn mã hành vi cung cấp các hành
động sẽ xảy ra tại điểm nối đó.
Bảng 2.2. Ví dụ về một khía cạnh với mã hành vi trƣớc và sau.
Giả sử có pointcut được khai báo như sau
pointcut
updateTong():
*.tong(int,int))
8

execution(void


Ta có thể xây dựng các advice như sau:
- Before advice thực hiện lưu vết
before() : updateTong(){
//logging
}
- After advice thực hiện cập nhập tổng
after() : updateTong(){
tong.update(this);
}

2.4.5. Khía cạnh
Trong AspectJ, khía cạnh (aspect) đóng vai trò là đơn vị trung tâm giống như
lớp là đơn vị trung tâm của Java. Nó là sự kết hợp của hướng cắt, mã hành vi,
điểm nối và các dữ liệu, phương thức khác. Một khía cạnh thông thường có các
đặc điểm sau, Bảng 2.3.
 Có thể sử dụng các định danh phạm vi truy cập ({public, private, protect})
cho nó. Ngoài ra khía cạnh còn có thể có định danh phạm vi truy cập

“privileged”, định danh này cho phép khía cạnh có thể truy cập đến các
thành viên riêng của các lớp mà chúng cắt ngang,
 Có thể khai báo khía cạnh trừu tượng bằng từ khóa abstract,
 Khía cạnh không thể được thể hiện hóa trực tiếp,
 Khía cạnh có thể kế thừa các lớp và các khía cạnh trừu tượng khác, có thể
thực thi các giao diện nhưng không thể kế thừa từ các khía cạnh cụ thể
(không trừu tượng),
 Khía cạnh có thể nằm trong các lớp và các giao diện.

Bảng 2.3 Cấu trúc cơ bản của một khía cạnh
[access specification] aspect <AspectName>
[extends class-or-aspect-name]
[implements interface-list]
[<association-specifier>(Pointcut)] {
... aspect body
}

9


2.3 Ngôn ngữ mô hình hóa JML (Java modeling language)
JML (Java Modeling Language)[7][10] là ngôn ngữ đặc tả hành vi, được sử
dụng để đặc tả hành vi của các mô đun trong ngôn ngữ Java. JML là sự kết hợp
phương pháp thỏa thuận với phương pháp đặc tả dựa trên mô hình của ngôn
ngữ Larch [13]. JML sử dụng logic Hoare [14] kết hợp với việc đặc tả các tiền/
hậu điều kiện (pre-/post-condition) và các bất biến (invariant) của các thuộc
tính, các cấu trúc.
Các đặc tả JML được thêm vào mã Java dưới dạng các chú giải (annotation)
bên trong các chú thích (comment). Các chú thích trong ngôn ngữ Java được
hiểu như là các chú giải JML khi nó bắt đầu bằng ký tự “@”. Ví dụ trong Hình

2 minh họa việc sử dụng JML đặc tả cho lớp Purse. Trong đó, trường balance
được đặc tả với bất biến (invariant) là balance luôn trong đoạn từ 0 đến
MAX_BALANCE. Trường pin là một mảng thuộc kiểu byte với bất biến là pin
có đúng 4 phần tử và các phần tử chỉ có giá trị từ 0 đến 9.
public class Purse { final int MAX_BALANCE; int balance;
//@ invariant 0 <= balance &&
balance <= MAX_BALANCE;
byte[] pin;
/*@ invariant pin != null &&
pin.length == 4 && (\forall int i; 0<=i&&i<4;
0<=pin[i]&&pin[i]<=9);
*/
/*@ requires amount >= 0;
@ assignable balance;
@ ensures balance==\old(balance)– amount && \result == balance;
@ signals (PurseException)
balance == \old(balance);
*/
int debit(int amount) throws PurseException {
if (amount <= balance) { balance -= amount; return balance; }
else { throw new PurseException("overdrawn by " + amount); }
}

10


}

Hình 2.2: Ví dụ minh họa về đặc tả JML
Phương thức debit nhận vào đối số amount là đầu vào. Phương thức này sẽ trừ

amount vào balance và trả về giá trị của balance sau khi trừ trong trường hợp
balance lớn hơn hoặc bằng amount .Trong trường hợp balance nhỏ hơn amount,
một ngoại lệ PurseException sẽ được trả về. Tiền điều kiện (requires) của
phương thức này là amount phải lớn hơn hoặc bằng 0; hậu điều kiện
(ensures) là balance bị trừ đi một lượng amount và trả về kết quả sau khi trừ.
Phương thức này còn có một hậu điều kiện nữa cho trường hợp phương thức trả
về ngoại lệ (signals).
2.4. Kết luận
Trong chương này luận văn đã trình bày một số kiến thức cơ sở được sử dụng
cho phương pháp kiểm chứng một số ràng buộc của kịch bản tại thời điểm thực
thi được trình bày trong chương 3 và chương 4.

11


CHƢƠNG 3: KIỂM CHỨNG MỘT SỐ RÀNG BUỘC
CHƢỜNG TRÌNH JAVA SỬ DỤNG AOP
3.1 Giới thiệu
Ràng buộc kịch bản trong chương trình đóng vai trò quan trong trong các hệ
thống phần mềm. Trong chương này, luận văn nghiên cứu cách tiếp cận kiểm
chứng một số ràng buộc về biểu thức tiền/hậu điều kiện và các xác nhận
(assertion) trong chương trình Java sử dụng phương pháp lập trình hướng khía
cạnh. Trong đó, các ràng buộc được đặc tả bằng ngôn ngữ mô hình hóa JML, từ
các đặc tả này mã aspect sẽ được tự động sinh ra và đan vào trong các chương
trình Java để kiểm chứng sự thỏa mãn của các ràng buộc trong chương trình so
với đặc tả. Luận văn đã xây dựng thành công công cụ sinh mã aspect và thử
nghiệm với một số kịch bản thực tế, kết quả thực nghiệm cho thấy phương pháp
được đề xuất có thể phát hiện được các vi phạm về ràng buộc kịch bản trong
chương trình Java.
3.2. Bài toán

Giả sử kịch bản mô tả chức năng rút tiền tự động của máy ATM (ATMAutomatic Teller Machine) với các sự kiện và ràng buộc được đặc tả như trong
Bảng 3.1.
Khi đó bài toán kiểm chứng sự thỏa mãn của ràng buộc của các kịch bản trong
chương trình được đặc tả như sau:
- Các biểu thức tiền-hậu điều kiện và các xác nhận được đặc tả dựa trên
ngôn ngữ mô hình hóa JML với các từ khóa @pre, @post, @assert,
- Khi thực hiện kịch bản cần kiểm tra tính thỏa mãn của các đặc tả JML nói

trên
Một cách tổng quát, bài toán kiểm chứng các biểu thức tiền-hậu điều kiện như
sau
{P}C{Q}, trong đó P và Q lần lượt là các biểu thức tiền-hậu điều kiện và các
assertion, C là kịch bản được cài đặt trên một ngôn ngữ lập trình cụ thể.
Bảng 3.1. Đặc tả kịch bản mô tả chức năng rút tiền tự động của máy ATM

12


Tên kịch bản

Chức năng rút tiền tự động

Mô tả

Người sử dụng rút tiền từ tài khoản ATM

Tiền điều kiện

Người sử dụng đăng nhập thành công


Hậu điều kiện

Người sử dụng rút tiền và nhận hóa đơn

Các chức
chính

năng

Thứ tự

Hành động

1

Hệ thống hiển thị loại tài khoản để người sử dụng
lựa chọn

2

Người sử dụng chọn tài khoản muốn rút

3

Hệ thống yêu cầu nhập số tiền cần rút

4

Người sử dụng nhập số tiền cần rút


5

Hệ thống thực hiện rút tiền từ tài khoản tài khoản
và khấu trừ số tiền trong tài khoản

6

Người sử dụng nhận tiền từ máy ATM

7

Hệ thống in biên lai và hiển thị số dư còn lại trong
tài khoản

8

Người dùng nhận biên lai, và nhận lại thẻ, kết thúc
giao dịch

3.3 Phƣơng pháp kiểm chứng sử dụng AOP
Luận văn đề xuất phương pháp kiểm chứng một số ràng buộc kịch bản trong
chương trình Java như sau (Hình 3.1).
1. Sử dụng ngôn ngữ mô hình hóa JML để đặc tả các ràng buộc về biểu thức

tiền-hậu điều kiện, assertion của kịch bản trong chương trình Java;
2. Tự động sinh mã kiểm chứng aspect từ đặc tả JML;
3. Tự động sinh mã kiểm chứng aspect;
13



4. Mã aspect được sinh ra được đan vào chương trình Java nhằm phát hiện

các vi phạm của chương trình so với đặc tả JML. Trong khi đó các hành
vi của chương trình sẽ không bị thay đổi.

Hình 3.1: Phƣơng pháp kiểm chứng ràng buộc của kịch bản trong chƣơng
trình Java sử dụng AOP.
3.3.1 Sinh mã aspect từ đặc tả JML
Dựa vào đặc tả bài toán và phương pháp kiểm chứng, luận văn xây dựng một
mẫu aspect tổng quát để kiểm tra một số ràng buộc của kịch bản như sau, Bảng
3.2.
Bảng 3.2. Mẫu aspect tổng quát
public aspect AspectName{
public AspectName(){
System.out.println("Aspect instance is created:" +this);
}
pointcut aspect_user_MethodName():

call (* *.MethodName());

before(): aspect_user_ MethodName () {
System.out.println("Before call:MethodName");
if ($PRE-CONDITIONS$){
System.out.print("Wrong

at:
14


"+thisJoinPointStaticPart.getSignature());

System.out.print("In
file:
"+thisJoinPointStaticPart.getSourceLocation().getFileName());
System.out.println("At
line:
"+thisJoinPointStaticPart.getSourceLocation().getLine());
}
}
after(): aspect_user_ MethodName() {
if ($POST-CONDITIONS$)
System.out.println("Valid specification");
else

{
System.out.println("Invalid specification");

if ($PRE-CONDITIONS$){
System.out.print("Wrong
"+thisJoinPointStaticPart.getSignature());

at:

System.out.print("In
file:
"+thisJoinPointStaticPart.getSourceLocation().getFileName());
System.out.println("At
line:
"+thisJoinPointStaticPart.getSourceLocation().getLine());
}
}

}

Trong aspect mẫu trên AspectName là tên của aspect; MethodName là tên
các phương thức tại join point. Các MethodName sẽ được thay thế bởi tên các
phương thức được triệu gọi trong kịch bản. Xâu $PRE-CONDITIONS$ và
$POST-CONDITIONS$ sẽ lần lượt được thay thế bằng các điều kiện kiểm tra
trước, sau, các điều kiện này được đọc từ đặc tả JML trong kịch bản bắt đầu bởi
từ khóa @pre và @post. Các hàm getSignature(), getFileName(),
getLine() được gọi để sẽ thông báo các chính xác tên phương thức và vị
trí của nó khi vi phạm đặc tả.
Để tách được các biểu thức điều kiện của kịch bản đưa vào mẫu aspect, tôi thực
hiện duyệt tuần tự các đặc tả JML áp dụng thuật toán xử lý trên 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ố
15


truyền vào. Sau đó sử dụng các hàm thay thế (replaceAll) để nhúng vào mẫu
aspect tổng quát trong Bảng 3.2, các hàm thực hiện thay thế như sau:
String aspectBodies = new String(aspectTemplate);
aspectBodies
aspectBodies.replaceAll("METHODNAME",this.phuongthuc);

=

aspectBodies=aspectBodies.replaceAll("PRECONDITIONS",this.dieukientruoc);
aspectBodies
=
CONDITIONS",this.dieukiensau);

aspectBodies.replaceAll("POST-


aspectSrc = aspectSrc + aspectBodies;

3.3.2 Đan xen mã
AspectJ cho phép đan xen mã aspect với các chương trình Java ở ba mức khác
nhau: mức mã nguồn, mã bytecode và tại thời điểm nạp chương trình khi
chương trình gốc chuẩn bị được thực hiện. Đan ở mức mã nguồn, Aspect sẽ nạp
các mã aspect và các Java ở mức mã nguồn (.aj và .java), sau đó thực hiện biên
dịch để sinh ra được mã đan xen bytecode, dạng .class. Đan xen ở mức mã
bytecode, AspectJ sẽ dịch lại và sinh mã dạng .class từ các mã aspect và Java đã
được biên dịch ở dạng (.class). Đan xen tại thời điểm nạp chương trình (local
time weaving), các mã của aspect và Java dạng .class được cung cấp cho máy ảo
Java (JVM). Khi JVM nạp chương trình để chạy, bộ nạp của lớp AspectJ sẽ thực
hiện đan mã và chạy chương trình. Với việc đan xen mã ở mức bytecode và tại
thời điểm nạp chương trình thì phương pháp này có thể được sử dụng mà không
yêu cầu phải có mã nguồn. Khi thay đổi lại đặc tả thì mới phải sinh và biên dịch
lại mã Aspect.
3.4. Kết luận
Trong chương này luận văn đã giới thiệu bài toán kiểm chứng ràng buộc của
kịch bản trong chương trình Java và nghiên cứu phương pháp giải quyết bài toán
này sử dụng phương pháp lập trình hướng khía cạnh với AOP. Các kết quả thực
nghiệm, đánh giá về phương pháp này được trình bày trong chương 4.

16


×