TÌM HIỂU CÔNG NGHỆ DESIGN BY CONTRACT VÀ XÂY DỰNG CÔNG CỤ HỖ TRỢ CHO C# - 4 ppsx

12 243 0
  • Loading ...
1/12 trang

Thông tin tài liệu

Ngày đăng: 30/07/2014, 20:20

Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 37 require not_empty: not empty i.e. count > 0 do Result := representation @ count end feature – Status report empty: BOOLEAN is Kiểm tra Stack rỗng? do Result := (count = 0) ensure empty_definition: Result = (count = 0) end full: BOOLEAN is Kiểm tra Stack đầy? do Result := (count = capacity) ensure full_definition: Result = (count = capacity) end feature – Element change put (x: G) is Thêm phần tử x vào Stack. require not_full: not full i.e. count < capacity in this representation do count := count + 1 representation . put ( count, x) ensure not_empty: not empty added_to_top: item = x Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 38 one_more_item: count = old count + 1 in_top_array_entry: representation @ count = x end remove is Xóa phần tử trên cùng của Stack. require not_empty: not empty i.e. count > 0 do count := count – 1 ensure not_full: not full one_fewer: count = old count – 1 end feature {NONE} Implementation representation: ARRAY [G] Mảng dùng để chứa các phần tử của Stack invariant … Sẽ tìm hiểu trong phần sau end class STACK2 Phần biểu diễn về lớp ở trên cho ta thấy sự đơn giản khi làm việc với những xác nhận. Ngoại trừ mệnh đề invariant còn thiếu sẽ được bổ sung trong phần sau, chúng ta hãy cùng nhau xem xét tỉ mỉ những thuộc tính khác nhau của nó. 8.2. Mệnh lệnh và yêu cầu Những xác nhận trong lớp STACK2 minh họa một khái niệm cơ bản mà ta đã có cái nhìn lướt qua về sự chuyển tiếp từ những kiểu dữ liệu trừu tượng sang những lớp: sự khác nhau giữa những khung nhìn “imperative” và “applicative”. Những xác nhận trong empty và full có thể làm bạn băn khoăn. Xét thủ tục full trong lớp trên: Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 39 full: BOOLEAN is Stack có đầy không? do Result := (count = capacity) ensure full_definition: Result = (count = capacity) end Hậu điều kiện yêu cầu rằng thực thể Result có giá trị luận lý bằng với giá trị của biểu thức count = capacity. Điều đó có nghĩa là Result có giá trị true nếu count bằng với capacity và nó có giá trị false nếu ngược lại. Result = (count = capacity) (1) Bởi vì trong thân thủ tục đã gán Result := (count = capacity) (2) Vậy thì liệu hậu điều kiện ở đây có dư thừa không? Có sự khác biệt rất lớn giữa (1) và (2), vì vậy không hề có sự dư thừa. (2) là một câu lệnh, thể hiện một hành động, gán giá trị true hay false của biểu thức count = capacity cho biến Result. Trong khi đó, (1) chỉ là một xác nhận, không làm gì hết. Nó chỉ đặc tả thuộc tính của trạng thái cuối cùng được mong đợi Một câu lệnh, tức (2), thì mang tính chất ra lệnh, còn một xác nhận, tức (1), thì chỉ mang tính chất mô tả. Câu lệnh mô tả cho câu hỏi “như thế nào”, còn xác nhận mô tả cho câu hỏi “cái gì”. Một câu lệnh là một phần của cài đặt, còn một xác nhận chỉ là một thành phần của đặc tả. Câu lệnh thì mang tính mệnh lệnh, bắt buộc, còn xác nhận thì chỉ mang tính yêu cầu. Hai thuật ngữ này nhấn mạnh sự khác nhau cơ bản giữa tin học và toán học. − Những thao tác của tin học có thể làm thay đổi trạng thái của máy tính. Những chỉ thị của các ngôn ngữ lập trình thông thường là những câu lệnh tác động trực tiếp đến máy tính. Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 40 − Những lý luận toán học không thể thay đổi bất cứ gì. Ví dụ như khi ta lấy căn bậc hai của 2 thì số 2 trước khi lấy căn và sau khi lấy căn vẫn như nhau. Tóm lại, xác nhận là mô tả một kết quả được mong đợi, còn chỉ thị (thân vòng lặp) là ra lệnh bằng cách nào đó đạt được kết quả. Ta không được nhằm lẫn giữa hai khái niệm này cũng như giữa hai khái niệm “:=” và “=”. Nh ững người sử dụng một lớp nào đó để tạo ra một môđun của riêng mình sẽ quan tâm đến các xác nhận hơn là các chỉ thị. Nguyên nhân của sự gần giống nhau giữa dấu gán (:=) và dấu bằng (=) là việc gán trong nhiều trường hợp là một cách đơn giản để đạt đến sự ngang bằng. Cài đặt Result := (count = capacity) thật sự là một ví dụ rõ ràng dễ nhầm lẫn. Nhưng trong những ví dụ cao hơn thì sự khác nhau giữa đặc tả và cài đặt sẽ lớn hơn, ngay cả trong một ví dụ đơn giản là hàm tính căn của số thực x có hậu điều kiện là abs(Result^2-x)<=tolerance (với abs là trị tuyệt đối, còn tolerance là dung sai). Các chỉ thị trong thân hàm sẽ có tầm quan trọng thấp hơn vì chúng là những cài đặt cho thuật toán chung của việc tính căn bậc hai. Thậm chí đối với thủ tục put trong STACK2, có cùng đặc tả nhưng có thể có sự thực thi khác nhau, mặc dù sự khác biệt có thể là rất nhỏ. Chẳng hạn nếu thân thủ tục như sau: if count=capacity then Result:=True else Result:=False end có thể được đơn giản (nhờ những quy tắc khởi tạo mặc định) thành: if count = capacity then Result:=True end Do đó, sự hiện diện của những thành tố giống nhau trong thủ tục và hậu điều kiện không phải là bằng chứng của sự dư thừa. Nó là bằng chứng của tính bền vững giữa cài đặt và đặc tả - có thể nói là của tính đúng đắn. Qua đây, ta thấy một đặc tính của những xác nhận mà sẽ được phát triển cao hơn: sự thích hợp của chúng đối với tác giả của các lớp client, người mà chúng ta không nên thắc mắc khi đọc những cài đặt thủ tục, nhưng là người cần một mô tả trừu tượng hơn về vai trò của thủ tục. Ý tưởng này đưa đến ý niệm về một dạng thức ngắn gọn (short form) sẽ được thảo luận sau. Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 41 Vì nguyên nhân thực tiễn, ta sẽ cho phép các xác nhận bao hàm một vài thành tố mệnh lệnh (các hàm). Để tóm tắt cho chương này, ta có bảng sau được chia thành 2 cột để thấy sự tương phản giữa 2 hạng mục của các thành tố phần mềm: Cài đặt Đặc tả Câu lệnh Biểu thức Như thế nào Cái gì Mệnh lệnh, bắt buộc Yêu cầu Ra lệnh Mô tả 8.3. Lưu ý về những cấu trúc rỗng Tiền điều kiện của thủ tục khởi tạo make trong lớp STACK1 yêu cầu một lời chú giải. Nó đưa ra n>=0, theo sau là một stack rỗng. Nếu n bằng 0, make sẽ gọi thủ tục khởi tạo mảng, cũng có tên là make, với đối số 1 và 0 cho khoảng tiệm cận dưới và trên. Đây không phải là một lỗi, mà là xuất phát từ quy ước trong thủ tục khởi tạo ARRAY: dùng đối số đầu tiên lớn hơn đối số thứ hai đưa ra một mảng rỗng. n có giá trị là 0, hoặc là đối số đầu tiên lớn hơn đối số thứ hai của mảng không hề sai mà đơn giản là stack hay mảng này rỗng. Lỗi chỉ xảy ra khi có lời gọi muốn truy xuất đến một phần tử trong cấu trúc, chẳng hạn một lời gọi put cho stack hay item cho mảng, cả hai tiền điều kiện của 2 thủ tục này sẽ luôn luôn sai vì cấu trúc rỗng (“Khách hàng luôn luôn sai.”). Khi định nghĩa một cấ u trúc dữ liệu nói chung như stack hay mảng, bạn nên xác định trường hợp một cấu trúc rỗng là có nghĩa hay không. Trong một số trường hợp thì không: Ví dụ: hầu hết định nghĩa của khái niệm tree bắt đầu từ sự giả định rằng có ít nhất một node (là node gốc). Nhưng trường hợp rỗng đưa ra không phải là không có khả năng hợp lý, cũng như mảng và stack, bạn nên lên kế hoạch thiết kế Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 42 cấu trúc dữ liệu của bạn, thừa nhận rằng mỗi lần khách hàng tạo ra những thể hiện rỗng thì không chấp nhận nó. Một hệ thống ứng dụng, ví dụ cần một stack có n phần tử, với n là tiệm cận trên của số phần tử được chứa trong stack, sẽ được tính toán bởi ứng dụng ngay trước khi nó tạo ra stack. Trong một số lần chạy, con số có th ể có giá trị 0. Đây không phải là lỗi mà nó là một trường hợp vô cùng. 8.4. Thiết kế tiền điều kiện: tolerant hay demanding? Ta chỉ có thể gắn những điều kiện cho một trong hai đối tác của hợp đồng: khách hàng (client) hay nhà cung cấp (supplier). Có 2 khả năng: − Nếu gán trách nhiệm cho khách hàng, điều kiện sẽ là một phần của tiền điều kiện. − Nếu đặt ở nhà cung cấp, những điều kiện này sẽ xuất hiện trong cấu trúc if then của mã lệnh. Ta gọi trường hợp thứ nhất là demanding và thứ hai là tolerant. Lớp stack ở trên là một minh hoạ cho kiểu demanding, phiên bản tolerant không có sự hiện diện của tiền điều kiện: remove is Xóa phần tử trên cùng của Stack do if empty then print ("Error: attempt to pop an empty stack") else count := count – 1 end end Dùng kiểu nào thì tốt hơn? Thoáng nhìn thì tolerant có vẻ tốt hơn (cả tính đáng tin cậy và tính tái sử dụng), nếu có nhiều khách hàng mà chỉ có một nhà cung cấp, tính tái sử dụng được Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 43 thể hiện rõ. Nhà cung cấp sẽ thực hiện việc kiểm tra chung chứ không cần mỗi khách hàng phải có sự kiểm tra riêng. Nhưng nếu chúng ta xem xét vấn đề gần hơn, lập luận trên sẽ không còn đúng. Điều kiện ở đây mô tả những gì cần thiết để thủ tục có thể làm công việc của nó. Trong ví dụ trên, nếu stack là rỗng, một thông báo lỗi sẽ được đưa ra, đ iều này không thích hợp. Bởi vì chỉ có khách hàng – mođun dùng stack trong ứng dụng cụ thể mới quyết định được việc xoá phần tử của một chuỗi rỗng như trên có ý nghĩa gì. 8.5. Một môđun tolerant Mặc dù ta đã thấy được rằng tolerant không phải là một sự tiếp cận đúng, nhưng cũng nên nghiên cứu xem lớp đối tượng sẽ trông như thế nào nếu ta quyết định tiếp cận theo cách này indexing description: " Stacks: Cấu trúc dữ liệu với quy tắc truy xuất LIFO, và có độ lớn cố định; phiên bản tolerant, đưa những dòng lệnh kiểm tra vào thẳng mã nguồn." class STACK3 [G] creation make feature Initialization make (n: INTEGER) is Cấp phát cho stack độ lớn n phần tử nếu n>0; Nếu không thì gán error = Negative_size. Không có tiền điều kiện! do if capacity >= 0 then capacity := n !! representation.make (capacity) Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 44 else error := Negative_size end ensure error_code_if_impossible: (n<0)=(error =Negative_size) no_error_if_possible: (n >= 0) = (error = 0) capacity_set_if_no_error:(error = 0) implies (capacity = n) allocated_if_no_error: (error=0) implies (representation/= Void) end feature Access item: G is là phần tử trên cùng của stack (nếu stack không rỗng). Nếu Stack rỗng thì gán error = Underflow. Không có tiền điều kiện! do if not empty then check representation /= Void end Result := representation.item error := 0 else error := Underflow Trong trường hợp này, Result có giá trị mặc định end ensure error_code_if_impossible: (old empty) = (error = Underflow) Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 45 no_error_if_ possible: (not (old empty)) = (error = 0) end feature Status report empty: BOOLEAN is Số phần tử của Stack do Result := (capacity = 0) or else representation.empty end error: INTEGER Xác định lỗi full: BOOLEAN is Số phần tử của Stack do Result := (capacity = 0) or else representation.full end Overflow, Underflow, Negative_size: INTEGER is unique Những lỗi có thể xảy ra feature Element change put (x: G) is Thêm vào phần tử x; nếu không được thì gán giá trị cho error. Không có tiền điều kiện! Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 46 do if full then error := Overflow else check representation /= Void end representation.put (x); error := 0 end ensure error_code_if_impossible: (old full) = (error = Overflow) no_error_if_possible: (not old full) = (error = 0) not_empty_if_no_error: (error = 0) implies not empty added_to_top_if_no_error: (error = 0) implies item = x one_more_item_if_no_error: (error = 0) implies count = old count + 1 end remove is Xóa phần tử trên cùng của Stack; nếu không được thì gán giá trị cho error. Không có tiền điều kiện! do if empty then error := Underflow else check representation /= Void end representation.remove error := 0 end [...]... thiết cho việc biểu diễn những thuộc tính toàn cục của những thể hiện (instance) của một lớp vì chúng phải được lưu giữ trong tất cả thủ tục Những thuộc tính như thế sẽ tạo nên điều kiện bất biến của lớp (class invariant) 47 Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# Chúng giữ những thuộc tính ngữ nghĩa sâu hơn và mô tả những ràng buộc toàn vẹn của một lớp 9.1 Định nghĩa và. . .Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# ensure error_code_if_impossible: (old empty) = (error = Underflow) no_error_if_possible: (not old empty) = (error = 0) not_full_if_no_error: (error = 0) implies not... STACK3 Ví dụ trên đã cho ta thấy sự nặng nề của một lớp dùng cách tiếp cận tolerant Đây là một minh chứng cho thấy tolerant sẽ dẫn đến một phần mềm phức tạp và không cần thiết Ngược lại, với demanding, theo tinh thần của Design By Contract, sẽ giúp những client trong phát hiện lỗi trong tất cả các trường hợp theo cách tốt nhất Chương 9: Những điều kiện bất biến của lớp Tiền điều kiện và hậu điều kiện mô... item, put, remove … capacity: INTEGER count: INTEGER feature {NONE} - Cài đặt representation: ARRAY [G] end Những thuộc tính của lớp bao gồm: representation kiểu mảng, capacity và count kiểu số nguyên tạo nên một stack tượng trưng Mặc dù những tiền điều kiện và hậu điều kiện của thủ tục được đưa ra trước đây có thể biểu diễn một vài thuộc tính ngữ nghĩa của stack nhưng chúng thất bại trong việc biểu... count = 0), và capacity là kích thước của mảng: capacity = representation.capacity Một điều kiện bất biến của lớp (class invariant) cũng như là một xác nhận, biểu diễn những ràng buộc nhất quán chung được dùng cho mọi thể hiện của lớp Nó khác với tiền điều kiện và hậu điều kiện là những cái chỉ mô tả cho những thủ tục riêng biệt Sự xác nhận ở trên chỉ liên... những cái chỉ mô tả cho những thủ tục riêng biệt Sự xác nhận ở trên chỉ liên quan đến những thuộc tính Những điều kiện bất biến cũng có thể biểu diễn mối quan hệ ngữ nghĩa giữa những hàm với nhau hay 48 . Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 41 Vì nguyên nhân thực tiễn, ta sẽ cho phép các xác nhận bao hàm một vài thành tố mệnh lệnh (các hàm). Để tóm tắt cho. Thêm vào phần tử x; nếu không được thì gán giá trị cho error. Không có tiền điều kiện! Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 46 do if. Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# 48 Chúng giữ những thuộc tính ngữ nghĩa sâu hơn và mô tả những ràng buộc toàn vẹn của một lớp. 9.1. Định nghĩa và
- Xem thêm -

Xem thêm: TÌM HIỂU CÔNG NGHỆ DESIGN BY CONTRACT VÀ XÂY DỰNG CÔNG CỤ HỖ TRỢ CHO C# - 4 ppsx, TÌM HIỂU CÔNG NGHỆ DESIGN BY CONTRACT VÀ XÂY DỰNG CÔNG CỤ HỖ TRỢ CHO C# - 4 ppsx, TÌM HIỂU CÔNG NGHỆ DESIGN BY CONTRACT VÀ XÂY DỰNG CÔNG CỤ HỖ TRỢ CHO C# - 4 ppsx

Mục lục

Xem thêm

Gợi ý tài liệu liên quan cho bạn

Nhận lời giải ngay chưa đến 10 phút Đăng bài tập ngay