Mẫu thiết kế Strategy

Một phần của tài liệu (LUẬN ÁN TIẾN SĨ) Một số phương pháp kiểm chứng tái cấu trúc phần mềm Luận án TS. Máy tính 624801 (Trang 33)

Mẫu Strategy bao gồm các thành phần sau:

– IStrategy: Giao diện (Interface) được chia sẻ giữa các lớp con cụ thể trong họ các thuật toán. Lớp Context sử dụng giao diện để gọi đến các thuật toán đã được định nghĩa trong các lớp con;

– ConcreteStrategy: Nơi các thuật toán được cài đặt cụ thể;

– Context: Lớp dùng để tham chiếu đến kiểu ISstrategy. Trong một số trường hợp, Context có thể cài đặt các phương thức, bởi vậy các lớp

ConcreteStrategy có thể truy cập đến các dữ liệu này.

Sự hợp tác giữa các thành phần trong mẫu Strategy:

– IStrategy và Context tương tác để thực hiện việc lựa chọn các thuật toán. Một Context có thể truyền tất cả các dữ liệu cần thiết bằng các thuật toán đến IStrategy. Ngoài ra, Context có thể truyền chính nó như là một đối số cho các hoạt động của IStrategy. Điều đó cho phép

IStrategy gọi lại Context khi cần thiết;

– MộtContext chuyển tiếp yêu cầu từ máy khách (client) đến cácIStra- tegy của nó. Máy khách thường tạo và truyền đối tượng ConcreteStra- tegy đến Context; sau đó, nó tương tác riêng với Context. Thường có một gia đình các lớp ConcreteStrategy để máy khách lựa chọn.

Ưu điểm của việc sử dụng mẫu Strategy là đóng gói các thuật toán trong các lớp riêng biệt, điều này sẽ làm cho việc sử dụng lại mã được thuận tiện hơn nhiều và do đó, hành vi của lớp Context có thể thay đổi một cách linh hoạt tại thời điểm chạy chương trình.

2.5 Ngôn ngữ ràng buộc đối tượng OCL (ObjectConstraint Language) 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 toá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 tuân thủ. Ngoà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 toá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 toá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 toà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) Language - JML)

Tại giai đoạn thiết kế hệ thống, tổ chức OMG cung cấp cho chúng ta ngôn ngữ ràng buộc OCL để biểu diễn các điều kiện ràng buộc trên mô hình. Tại giai đoạn cài đặt mã nguồn, ngôn ngữ JML (Java Modeling Language) [36] là ngôn ngữ đặc tả hình thức được sử dụng để hỗ trợ cho ngôn ngữ lập trình Java trên khía cạnh đặc tả và kiểm chứng các ràng buộc về bất biến, tiền/hậu điều kiện của các phương thức trong chương trình. Đặc tả JML được nhúng vào mã nguồn Java (có thể ở cùng tệp mã nguồn của Java hoặc ở một tệp riêng biệt) và bắt đầu bởi kí hiệu //@<JML specification >hoặc /∗@ <JML specification > @∗/ theo sau là các thuộc tính cần đặc tả. Một số từ khóa cơ bản như requires, ensures định nghĩa các biểu thức tiền điều kiện, hậu điều kiện và invariant định nghĩa các bất biến. Đặc tả 2.1 biểu diễn các biểu thức tiền và hậu điều kiện để kiểm tra trạng thái cho phương thức analyzeTimeLimit() sử dụng ngôn ngữ JML. Các thuộc tính được đặc tả trong JML sẽ được biên dịch và thực thi cùng với mã nguồn để kiểm chứng sự thỏa mãn nó. 1 //@ ensures ((state==STATE.heavyTraffic)&&(signal==SIGNAL.red)) ==>(signalTime==\old(signalTime)-10); 2 //@ also 3 //@ensures ((state==STATE.heavyTraffic)&&(signal==SIGNAL.green) )==>(signalTime==\old(signalTime)+10); 4 //@ ensures ((state==STATE.lowTraffic)&&(signal==SIGNAL.red)) ==>(signalTime==\old(signalTime)+10); 5 //@also 6 //@ ensures ((state==STATE.lowTraffic)&&(signal==SIGNAL.green)) ==>(signalTime==\old(signalTime)-10);

Đặc tả 2.1: Biểu thức JML đặc tả cho phương thức

analyzeTimeLimit().

Hiện nay, đã có nhiều công cụ được xây dựng và phát triển để kiểm chứng mã Java cùng với đặc tả JML của nó như ESC/Java2 [25], RAC [13] hay OpenJML [17, 37], các công cụ này đều có thể tích hợp vào Eclipse.

Như vậy, xét về mặt vai trò ngôn ngữ ràng buộc OCL và ngôn ngữ đặc tả JML đều được sử dụng để đặc tả các ràng buộc về bất biến và hành vi của hệ thống phần mềm. Tuy nhiên, thời điểm sử dụng các ngôn ngữ này

là khác nhau, OCL được sử dụng bổ sung các đặc tả cho mô hình hệ thống còn JML lại biểu diễn các ràng buộc tại giai đoạn cài đặt hệ thống phần mềm.

2.7 Logic vị từ bậc 1 (First-Order Logic - FOL)

Lôgic vị từ bậc 1 (FOL) [63] cung cấp cho chúng ta khả năng biểu diễn các biểu thức logic mệnh đề (propositional logic) và cách thức định lượng hóa trên các đối tượng. Nhờ vào các lượng từ trong FOL chúng ta có thể mô tả các đối tượng và mối quan hệ giữa chúng một cách chính xác. Đây chính là ưu điểm của FOL so với logic mệnh đề. FOL có thể dùng để biểu diễn lý thuyết số, lý thuyết tập hợp và thậm chí biểu diễn sự tính toán trong máy Turing.

Bây giờ chúng ta sẽ mô tả một cách ngắn gọn các ký hiệu cơ bản dùng để xây dựng lên các công thức FOL. Các ký hiệu này được trình bày đầy đủ trong [63].

Các phép toán kết hợp (Logical connectives)(⇒,∧,∨, và ⇔), phủ định (¬), và dấu ngoặc. Chúng sẽ được sử dụng một cách đệ quy để tạo nên các công thức phức hợp.

Các ký hiệu hằng (Constants symbols) là các chuỗi (a, b, c, v.v.) dùng để biểu diễn thay thế cho các đối tượng.

Các ký hiệu biến (Variable symbols) sẽ được sử dụng như những “place holders” cho việc định lượng hóa trên các đối tượng.

Các ký hiệu vị từ (Predicate symbols) mỗi ký hiệu được liên kết với arity (ví dụ, số lượng các đối số), có thể là 0 hoặc một số xác định khác. Vị từ được dùng để biểu diễn cho thuộc tính của các đối tượng và mối quan hệ giữa chúng.

Các ký hiệu hàm (Function symbols) mỗi ký hiệu được đặc tả bởi arity (ví dụ, số lượng các đối số nhập vào) đây là một hàm ánh xạ từ một số lượng các đối tượng đến các đối tượng.

Các lượng từ với mọi và tồn tại (Universal and existential quan- tifier symbols) dùng để định lượng hóa trên các đối tượng.

Chương5của luận án trình bày về vấn đề phát triển công cụ hỗ trợ kiểm chứng tính nhất quán trong tái cấu trúc mô hình phần mềm. Như đã đề cập, tại giai đoạn thiết kế hành vi cần kiểm chứng được biểu diễn bằng ngôn ngữ ràng buộc đối tượng OCL. Tuy nhiên, cho tới thời điểm hiện tại, các công cụ phát triển cho OCL còn khá hạn chế trong khi công cụ sử dụng logic vị từ bậc nhất đã ở giai đoạn trưởng thành cả về số lương và chất lượng. Bởi vậy Tiểu mục này trình bày các kiến thức cơ sở về công thức FOL, các ràng buộc về hành vi biểu diễn bằng biểu thức OCL sẽ được chuyển đổi sang các công thức FOL này. Công cụ hỗ trợ kiểm chứng tính nhất quán CVT không thao tác trực tiếp trên các biểu thức OCL mà sẽ thực hiện kiểm tra tính nhất quán trên các công thức FOL tương ứng này.

2.8 Kết chương

Trong chương này luận án đã trình bày tóm tắt các kiến thức nền được sử dụng trong các chương tiếp theo. Mục 2.1 diễn tả về kỹ thuật tái cấu trúc với một số đặc điểm chính của kỹ thuật này. Mục 2.2 dành sự quan tâm đặc biệt đối với các khái niệm khóa của mô hình hướng đối tượng được hình thức hóa trong các Chương 3 và 4. Mục2.3 luận án trình bày về ngôn ngữ mô hình hóa thống nhất UML cùng với hai loại biểu đồ tiêu biểu là

biểu đồ lớp và biểu đồ tuần tự. Mục 2.4 diễn tả mẫu thiết kế Strategy thuộc về nhóm các mẫu hành vi, là mẫu thiết kế được áp dụng trong Chương 4. Ngôn ngữ ràng buộc đối tượng OCL được mô tả trong Mục 2.5. Cuối cùng là các kiến thức tổng quan về ngôn ngữ đặc tả cho Java (JML) và logic vị từ bậc 1 (FOL), đây là các phương tiện để biểu diễn các ràng buộc của hệ thống cần phải nghiên cứu sự bảo toàn trong tiến trình tái cấu trúc.

PHƯƠNG PHÁP BẢO TOÀN BẤT BIẾN TRONG TÁI CẤU TRÚC

Trong chương này, luận án đề xuất phương pháp bảo toàn các bất biến (class invariants) trong tái cấu trúc biểu đồ lớp của UML. Cụ thể, luận án tập trung vào việc xây dựng các luật tái cấu trúc (refactoring rules) cho các phép toán tái cấu trúc (refactoring operations). Đồng thời cũng chứng minh tính đúng đắn của các luật tái cấu trúc đã đề xuất khi áp dụng vào tiến trình tái cấu trúc.

3.1 Giới thiệu

Bất biến của lớp (class invariants) là khái niệm quan trọng sử dụng để mô tả một cách chính xác các ràng buộc ngữ nghĩa áp dụng cho các thành phần (thuộc tính, quan hệ) của biểu đồ lớp trong UML. Tái cấu trúc thực hiện trên biểu đồ lớp đương nhiên sẽ ảnh hưởng trực tiếp đến các ràng buộc

Một phần của tài liệu (LUẬN ÁN TIẾN SĨ) Một số phương pháp kiểm chứng tái cấu trúc phần mềm Luận án TS. Máy tính 624801 (Trang 33)

Tải bản đầy đủ (PDF)

(132 trang)