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 (ATM- Automatic 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
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 năng
chính 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;
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:
"+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 at:
"+thisJoinPointStaticPart.getSignature());
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ố
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("PRE- CONDITIONS",this.dieukientruoc);
aspectBodies = aspectBodies.replaceAll("POST- CONDITIONS",this.dieukiensau);
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.