Constraint Language)
Ngôn ngữ ràng buộc đối tượng OCL (Object Constraint Language) ra đời nhằm mục tiêu khắc phục các hạn chế của UML trong việc biểu diễn một cách chính xác các khía cạnh chi tiết của bản thiết kế hệ thống [21]. OCL được phát triển lần đầu bởi tổ chức IBM vào năm 1995 và được tích hợp vào UML năm 1997.
Thời gian đầu, OCL chỉ được sử dụng như là một ngôn ngữ ràng buộc đối tượng bổ sung cho UML, tuy nhiên nó nhanh chóng được mở rộng phạm vi và trở thành một thành phần quan trọng trong bất kỳ kỹ nghệ hướng mơ hình nào. OCL được coi như một ngơn ngữ mặc định dùng biểu diễn các truy vấn trên mơ hình hoặc siêu mơ hình, thực hiện và đặc tả các yêu cầu. OCL cũng thường được sử dụng để mô tả các phép biến đổi mơ hình (như là một phần của các mơ hình nguồn và mơ hình đích trong các quy tắc biến đổi), biểu diễn sự hợp lệ của các quy tắc (như là một phần của định nghĩa đặc tả các miền mới), hoặc các mẫu sản sinh mã nguồn (mô tả các mẫu và quy tắc sản sinh mã), v.v. Để đáp ứng các mục tiêu này, OCL được phát triển và phát hành một số các phiên bản. OCL được phát triển như là một chuẩn công nghiệp bởi tổ chức Object Management Group1 (OMG) [12]. Phiên bản mới nhất của OCL là 2.4 được ra đời vào năm 2014, phiên bản này tương thích với phiên bản 2.4.1 của UML.
Mỗi biểu thức trong OCL đều xác định một kiểu nhất định (kiểu này có thể được định nghĩa trước trong OCL hoặc là một kiểu được định nghĩa trong mơ hình với các ràng buộc được mơ tả bởi OCL). Kiểu của các biểu thức trong OCL cũng phải phù hợp với các quy tắc và các phép tốn được áp dụng trên kiểu đó. Chú ý rằng OCL chỉ là một ngôn ngữ đặc tả thuần túy, bởi vậy khi các biểu thức OCL được thực thi, nó khơng gây bất cứ ảnh
hưởng nào đến trạng thái của mơ hình phần mềm mà nó đặc tả. Ngoài ra, tất cả các vấn đề liên quan đến cài đặt cũng nằm ngoại phạm vi và không thể biểu diễn bằng OCL. OCL có thể được sử dụng để mơ tả nhiều loại ràng buộc khác nhau trong mơ hình UML, sau đây là một số loại ràng buộc tập trung chủ yếu vào tác dụng của nó trên biểu đồ lớp:
– Biểu diễn các ràng buộc bất biến của lớp (class invariants);
– Khởi tạo giá trị cho thuộc tính của các biến trong biểu thức OCL; – Biểu diễn cách tính giá trị của các phần tử dẫn xuất dựa trên giá trị
của các phần tử nguồn;
– Thực hiện các câu lệnh truy vấn;
– Biểu diễn tiền/hậu điều kiện (pre/post-conditions) của các phương thức có trong mơ hình.
Các khả năng biểu diễn trên của OCL sẽ lần lượt được cụ thể hóa như sau:
OCL được dùng để biểu diễn các ràng buộc bất biến (Inva- riants): Các ràng buộc toàn vẹn trong OCL được biểu diễn dưới dạng các bất biến được định nghĩa trong một Context cụ thể, với tên của Context
là kiểu của ràng buộc. Phần thân của context, là các điều kiện logic (sau từ khóa inv) phải được kiểm tra và thỏa mãn bởi tất cả các thể hiện của Context đó.
Các bất biến là các biểu thức được sử dụng phổ biến nhất trong OCL vì nó cho phép các nhà thiết kế dễ dàng đặc tả tất cả các loại điều kiện mà hệ thống phải tn thủ. Ngồi ra, bất biến cịn có thể hạn chế giá trị của các đối tượng đơn lẻ. Biểu thức dưới đây phát biểu rằng, tất cả các quotesphải có giá trị dương. Chú ý rằng biến self đại diện cho một thể hiện tùy ý của lớp Quote và dấu chấm được sử dụng để truy cập vào các tính chất (thuộc tính hoặc phương thức) của biến self trong lớp Quote. Tất cả các thể hiện
của lớp Quote phải được đánh giá là thỏa mãn bất biến này và biến (self)
đương nhiên cũng phải thỏa mãn ràng buộc bất biến đó.
1 context Quote inv QuoteOverZero: self.value > 0
OCL sử dụng để khởi tạo giá trị cho thuộc tính của các biến:
một đối tượng khi đối tượng đó được tạo ra. Để thực hiện công việc này, kiểu của biểu thức OCL khởi tạo và kiểu của thuộc tính được dùng khởi tạo phải phù hợp với nhau.
Biểu thức OCL sau đây khởi tạo giá trị là falsecho thuộc tínhpremium
củaCustomer(trạng thái của premiumsẽ được chuyển thành truekhi khách hàng đã thuê một số xe).
1 context Customer::premium: boolean init: false
Biểu thức OCL xác định các quy tắc tính tốn giá trị của các thuộc tính trong mơ hình dẫn xuất: các phần tử dẫn xuất là các phần tử mà có giá trị được suy dẫn từ các giá trị của các phần tử thuộc vào mơ hình nguồn. OCL là một lựa chọn phổ biến cho việc xác định các quy tắc dẫn xuất này.
Hãy xem xét quy tắc sau đây cho việc chiết khấu các phần tử dẫn xuất từ lớp Customer, phát biểu rằng các khách hàngs có trạng thái của thuộc
tínhpremiumlàtruethì được hưởng 30%, các khách hàng có trạng thái của thuộc tínhpremiumlà falsevà có ít nhất 5 chiếc xe cho thuê thì được giảm giá 15%, còn lại tất cả các khách hàng khác đều không được giảm giá.
1 context Customer::discount: integer derive: 2 if not self.premium then
3 if self.rental.car.carGroup->select(c|c.category=’high’)->size ()>=5
4 then 15 else 0 endif 5 else 30 endif
Quy tắc này trong OCL sẽ cho phép tính các giá trị dẫn xuất phù hợp với từng trường hợp tương ứng.
Câu lệnh truy vấn: biểu thức OCL dạng này thực hiện truy vấn trên
cơ sở dữ liệu hệ thống và trả về thông tin cho người dùng.
Câu lệnh truy vấn sau sẽ trả về giá trị là true nếu chiếc car là chiếc được dùng nhiều nhất trong hệ thống xe cho thuê.
1 context Car::mostPopular(): boolean
2 body: Car::allInstances()->forAll(c1|c1<>self
3 implies c1.rentalAgreement->size()<=self.rentalAgreement->size ())
Biểu diễn tiền/hậu điều kiện của các phép tốn: có hai cách tiếp
cận để kiểm tra sự thỏa mãn của các ràng buộc về tiền/hậu điều kiện đối với các phép toán. Cách thứ nhất là dùng các câu lệnh chỉ thị và cách thứ hai là đặc tả các ràng buộc thông qua hợp đồng (contract). Trong cách tiếp cận đầu tiên, người thiết kế xác định rõ ràng tập các câu lệnh cấu trúc và các cấu trúc này sẽ được thực thi khi thực hiện phép toán. Theo cách tiếp cận thứ hai, nhà thiết kế sẽ cung cấp cho mỗi hoạt động một hợp đồng của nó. Mỗi hợp đồng bao gồm một tập các điều khoản về tiền/hậu điều kiện. Tiền điều kiện xác định một tập hợp các ràng buộc đầu vào trước khi hoạt động được thực thi, còn hậu điều kiện cho biết các ràng buộc mà hệ thống phải thỏa mãn khi kết thúc giao dịch. OCL là ngôn ngữ thường được lựa chọn để biểu diễn cho tiền/hậu điều kiện của hoạt động mức độ mơ hình.
1 context Rental::newRental(id:Integer, price:Real, startingDate: Date,
2 endingDate:Date, customer:Customer, carRegNum:String, pickupBranch: Branch, dropOffBranch: Branch)
3 pre: customer.licenseExpDate>endingDate
4 post: Rental.allInstances->one(r | r.oclIsNew() and 5 r.oclIsTypeOf(Rental) and r.endingDate=endingDate and r.
startingDate=startingDate
6 and r.driver=customer and r.pickupBranch=pickupBranch and r. dropOffBranch=dropOffBranch
7 and r.car=Car.allInstances()->any(c | c.regNum=carRegNum))
Biểu thức tiền điều kiện được đặt sau từ khóapre và hậu điều kiện được đặt sau từ khóa post.
Như vậy, trong Tiểu mục này luận án đã trình bày một số đặc trưng cơ bản của ngôn ngữ ràng buộc đối tượng OCL, cụ thể là các biểu thức OCL đặc tả bất biến (invariants), tiền/hậu điều kiện (pre/post-conditions)
bổ sung vào mơ hình thiết kế của hệ thống. Đặc biệt, luận án sẽ sử dụng các biểu thức đặc tả này để biểu diễn các ràng buộc về bất biến và hành vi cần kiểm chứng trong tiến trình tái cấu trúc trong các Chương 3 và 4. Nói cách khác, các ràng buộc cần kiểm chứng sự bảo tồn được biểu diễn một cách hình thức bằng các biểu thức OCL, điều này làm tăng tính chính xác cũng như tạo điều kiện dễ dàng cho các bước tiếp theo của tiến trình kiểm chứng.
2.6 Ngơn ngữ đặc tả cho Java (Java ModelingLanguage - JML)