1. Trang chủ
  2. » Giáo Dục - Đào Tạo

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

12 389 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 12
Dung lượng 564,32 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Trong lớp đối tượng, nó là những phương thức truy xuất đến những thuộc tính của các thể hiện của một lớp.. Hàm trừu tượngHình 11-1: Sự biến đổi giữa những đối tượng trừu tượng và cụ thể

Trang 1

trong giới hạn cho phép Điều kiện bất biến biểu diễn mối quan hệ giữa count,

lower và upper; nó cho phép count được cài đặt như một hàm chứ không phải một thuộc tính

indexing

description: "Mảng giá trị cùng kiểu, truy xuất các phần

tử thông qua các chỉ số mảng"

class ARRAY [G] creation

make

feature Khởi tạo

make (minindex, maxindex: INTEGER) is

Xác định 2 biên của mảng với minidex và maxindex

Mảng rỗng nếu minindex > maxindex

require

meaningful_bounds: maxindex >=

minindex - 1

do

ensure

exact_bounds_if_non_empty: (maxindex >=

minindex) implies

((lower = minindex) and (upper =

maxindex)) conventions_if_empty: (maxindex < minindex)

implies ((lower = 1) and (upper = 0))

end feature – Truy cập

lower, upper, count: INTEGER

Chỉ số cao nhất vào thấp nhất hợp lệ; kích thước mảng

infix "@", item (i: INTEGER): G is

Giá trị mảng tại chỉ số i

Trang 2

require

index_not_too_small: lower <= i index_not_too_large: i <= upper

do … end feature -– Thay đổi thành phần

put (v: G; i: INTEGER) is

Gán giá trị v cho phần tử có chỉ số

require

index_not_too_small: lower <= i index_not_too_large: i <= upper

do

ensure

element_replaced: item (i) = v

end invariant

consistent_count: count = upper – lower + 1

non_negative_count: count >= 0

end class ARRAY

Phần trống duy nhất còn lại là phần cài đặt của thân những thường trình

itemvà put

Chương 11: Kết nối với kiểu dữ liệu trừu tượng

Trong phần này, ta sẽ củng cố thêm khái niệm “xác nhận” bằng việc tìm hiểu

về sự kết nối giữa các xác nhận và những thành phần của một đặc tả của một kiểu

dữ liệu trừu tượng (ADT – Abstract Data Type)

Một ADT được tạo bởi 4 thành phần:

− Tên kiểu, có thể cùng với những tham số chung (phần TYPES)

Trang 3

− Danh sách các hàm với những ký hiệu của chúng (phần FUNCTIONS)

− Tiên đề (AXIOMS) mô tả những thuộc tính của kết quả

− Những quy định để sử dụng được hàm (phần PRECONDITIONS)

Ví dụ: ADT của lớp STACK

TYPES

• STACK [G]

FUNCTIONS

• put: STACK [G] × G → STACK [G]

• remove: STACK [G] →STACK [G]

• item: STACK [G] → G

• empty: STACK [G] → BOOLEAN

• new: STACK [G]

AXIOMS

For any x: G, s: STACK [G]

A1 • item (put (s, x)) = x

A2 • remove (put (s, x)) = s

A3 • empty (new)

A4 • not empty (put (s, x))

PRECONDITIONS

• remove (s: STACK [G]) require not empty (s)

• item (s: STACK [G]) require not empty (s)

11.1 So sánh đặc tính của lớp với những hàm ADT

Để hiểu được mối liên hệ giữa những xác nhận và ADT, trước tiên ta cần tìm

hiểu mối liên hệ giữa những đặc tính của lớp và phần tương ứng của ADT – những hàm của ADT Những hàm này gồm 3 loại: creator, query và command

Trang 4

Sự phân loại của một hàm f: A × B × … Æ X phụ thuộc vào vị trí xuất hiện của ADT (A, B, …, X) so với mũi tên , gọi là T

Nếu T chỉ xuất hiện ở bên phải của mũi tên thì f là hàm creator Trong lớp đối tượng, nó là phương thức khởi tạo Ví dụ: hàm new

Nếu T chỉ có mặt ở bên trái của mũi tên thì f là hàm query Trong lớp đối tượng, nó là những phương thức truy xuất đến những thuộc tính của các thể hiện của một lớp Ví dụ: hàm itemempty.

Nếu T xuất hiện ở cả 2 bên mũi tên thì f là hàm command Những hàm này tạo ra những đối tượng mới từ những đối tượng đã có Trong lớp đối tượng, những hàm này thường được biểu diễn như một phương thức để làm thay đổi một đối tượng hơn là tạo ra một đối tượng mới Ví dụ hàm putremove

11.2 Biểu diễn những tiên đề

Từ sự tương ứng giữa những hàm ADT và những đặc tính của lớp, ta có thể suy ra sự tương ứng giữa ngữ nghĩa thuộc tính ADT và những xác nhận

Tiền điều kiện của ADT xuất hiện lại như những mệnh đề tiền điều kiện (precondition clauses) của các thủ tục tương ứng

Một tiên đề, bao gồm một hàm command và một hay nhiều hàm query, xuất hiện lại như những mệnh đề hậu điều kiện (postcondition clauses) trong những thủ tục tương ứng

Những tiên đề chỉ bao gồm những hàm query xuất hiện lại như những hậu điều kiện của những hàm tương ứng hoặc những mệnh đề của điều kiện bất biến

Tiên đề bao gồm những hàm khởi tạo xuất hiện lại trong hậu điều kiện của những thủ tục khởi tạo tương ứng

Trang 5

11.3 Hàm trừu tượng

Hình 11-1: Sự biến đổi giữa những đối tượng trừu tượng và cụ thể

Alà một ADT và C là một lớp được cài đặt từ A Lúc này tương ứng với hàm trừu tượng af của Asẽ có hàm cụ thể cf trong lớp C

Mũi tên a mô tả cho sự trừu tượng hóa hàm, với mỗi đối tượng cụ thể (thể hiện của lớp), sự trừu tượng hoá này sẽ sinh ta một đối tượng trừu tượng (thể hiện của ADT) Những hàm trừu tượng này thường là từng phần

Sự tương ứng giữa lớp và ADT

(cf ; a) = (a ; af)

Trong đó dấu “; ” là toán tử kết hợp giữa các hàm Nói cách khác, nếu ta có hai hàm fg thì f;g là hàm h sao cho h(x) = g(f(x)) với mọi x(f;g còn được viết dưới dạng g o f )

Trang 6

Hai đường đứt khúc cùng chỉ đến đối tượng trừu tượng ABST_2 Kết quả vẫn như nhau ngay cả khi bạn:

- Áp dụng sự biến đối cụ thể cf, sau đó trừu tượng hóa kết quả, sinh ra

a(cf(CONC_1))

- Trừu tượng hóa trước, sau đó áp dụng sự biến đổi trừu tượng af, sinh ra

af(a(CONC_1))

11.4 Cài đặt những điều kiện bất biến

Một số xác nhận xuất hiện trong những điều kiện bất biến nhưng chúng lại không là bản sao trực tiếp trong đặc tả ADT Những xác nhận này bao hàm những thuộc tính, một số là thuộc tính ẩn mà lúc định nghĩa thì chúng sẽ không có ý nghĩa trong ADT Một ví dụ đơn giản là những thuộc tính dưới đây xuất hiện trong điều kiện bất biến của lớp STACK4

count_non_negative: 0<=count

count_bounded: count<=capacity

Những xác nhận như thế này là những điều kiện bất biến của lớp, gọi là cài đặt của điều kiện bất biến (implementation invariant) Chúng đáp ứng cho việc biểu diễn tính vững chắc của những đại diện được chọn trong lớp (ở đây là count,

capacityrepresentation) có quan hệ với những ADT tương ứng

Hình 10-1 đã giúp ta hiểu rõ về cài đặt của điều kiện bất biến Nó minh họa cho những thuộc tính đặc trưng của hàm trừu tượng a (biểu diễn bằng những mũi tên dọc) Gọi hàm a sẽ nối mỗi thành phần nguồn với nhiều nhất một thành phần đích Nếu ta đi theo chiều ngược lại của mũi tên để xét nghịch đảo của a (có thể gọi

là quan hệ biểu diễn) , ta sẽ thấy rằng đó không phải là một hàm, bởi vì có thể có nhiều biểu diễn của một đối tượng trừu tượng

Xét mảng thể hiện cho STACK thông qua cặp <representation, count>, một STACK trừu tượng có nhiều biểu diễn khác nhau, tất cả đều có giá trị

count và các phần tử từ 1 đến count của mảng representation giống nhau, nhưng giá trị capacity thể hiện kích thước mảng có thể là bất kỳ giá trị nào lớn

Trang 7

hơn hoặc bằng count, và những phần tử có chỉ số vượt quá count có thể có giá trị tùy ý

Quan hệ cài đặt thường không phải là một hàm, nhưng sự nghịch đảo của nó (mũi tên hướng lên) là một hàm thật sự vì mỗi đối tượng cụ thể biểu diễn cho nhiều nhất một đối tượng trừu tượng Trong ví dụ về lớp STACK của chúng ta, mỗi cặp

<representation,count> hợp lệ chỉ biểu diễn cho một STACK trừu tượng

Hình 11-2: Hai cài đặt của cùng một đối tượng trừu tượng

Cả hai stack cụ thể trên đây đều là cài đặt (implementation) của stack trừu tượng bao gồm 3 phần tử 342, -133 và 5 Việc a là một hàm là một yêu cầu chung: nếu một đối tượng cụ thể là cài đặt của nhiều đối tượng trừu tượng, đại diện được chọn sẽ trở nên mơ hồ và không thích hợp Vì vậy mũi tên a nên vẽ theo chiều như trên để mô tả cho sự kết nối giữa kiểu cụ thể và trừu tượng

Trang 8

Cài đặt những điều kiện bất biến là một phần của những xác nhận không có bản đối chiếu trong đặc tả ADT Nó không liên hệ với ADT mà là với những biểu diễn của nó Nó định rõ khi một đối tượng cụ thể thật sự là cài đặt của một (và chỉ một) đối tượng trừu tượng

Chương 12: Một chỉ thị xác nhận

Những tiền điều kiện, hậu điều kiện và điều kiện bất biến của lớp là những thành phần trung tâm của phương pháp sử dụng chỉ thị xác nhận (assertion instruction) Chúng tạo nên sự kết nối giữa việc xây dựng phần mềm hướng đối tượng và những lý thuyết bên dưới về kiểu dữ liệu trừu tượng (Abstract Data Type)

Có những xác nhận mặc dù ít đặc thù hơn nhưng cũng có vai trò quan trọng trong quy trình phát triển phần mềm Trong đó có chỉ thị check và những vòng lặp

có bất biến và điều kiện biến đổi (loop invariant và variant)

Chỉ thị checkđược sử dụng để thể hiện sự tin chắc của người viết phần mềm rằng một thuộc tính nào đó sẽ thỏa mãn những tình huống nào đó trong việc tính toán Cú pháp:

check

assertion_clause 1 assertion_clause 2

assertion_clause n

end

Khi chương trình thực thi thì những xác nhận assertion_clauseX sẽ được bảo đảm

Đây là cách để chắc chắn một lần nữa rằng những thuộc tính nhất định được thỏa mãn, và quan trọng hơn, nó giúp những người đọc phần mềm hiểu được những giả thuyết mà ta dựa vào Việc viết phần mềm đòi hỏi sự xác nhận thường xuyên những thuộc tính của đối tượng Xét ví dụ về hàm sqrt(x), bất cứ hàm nào gọi

Trang 9

đến sqrt(x) đều dựa vào xác nhận rằng x không âm Xác nhận này có thể hiển hiện trong ngữ cảnh, ví dụ như một câu lệnh if then

if x >= 0 then y := sqrt (x) end

nhưng nó cũng có thể không trực tiếp như trên, ví dụ như x đã được gán trước đó:

x := a^2 + b^2

Chỉ thị check sẽ giúp biểu diễn xác nhận đó nếu nó không hiển hiện trong câu lệnh

x := a ^2 + b^2

… Other instructions …

check

x >= 0 Because x was computed above as a sum of squares

end

y := sqrt (x)

Không cần điều kiện if then cho lời gọi hàm sqrt trong trường hợp này, checkđã xác nhận rằng lời gọi hàm là đúng Lưu ý rằng chỉ thị checknày không làm ảnh hưởng đến thuật toán của thủ tục

Ví dụ trên đã cho ta thấy sự hữu ích của check, nó đóng vai trò một tiền điều kiện của một lời gọi hàm

Một trường hợp khác cần lưu ý, khi ta viết một lời gọi hàm có dạng x.f, ta

đã chắc chắn rằng x không rỗng, cho nên ta sẽ không viết

if x != Void then

nhưng sự không rỗng của x lại không hiển hiện trong ngữ cảnh này Ta đã gặp trường hợp này trong hàmputremovelớp STACK3

Thân hàm put gọi đến hàm tương ứng trong lớp STACK2:

Trang 10

if full then

error := Overflow

else

check representation /= Void end

representation.put (x); error := 0

end

Ở đây người đọc sẽ nghĩ rằng không an toàn khi gọi

representation.put(x); như vậy, bởi vì không có một sự kiểm tra nào trước

đó về sự không rỗng của representation Nhưng nếu để ý kỹ, bạn sẽ thấy rằng nếu full sai thì capacity phải là số dương Vì vậy, representation không thể là rỗng Đây là một điều rất quan trọng và sẽ là một phần trong cài đặt các ràng buộc của lớp Trong thực tế, với cài đặt đầy đủ của một ràng buộc được định trước,

ta nên viết chỉ thị checknhư sau:

check

representation_exists: representation /= Void

Because of clause

representation_exists_if_not_full of the

cài đặt điều kiện bất biến

end

Trong những sự tiếp cận thông thường của việc xây dựng phần mềm, mặc dù những lời gọi hàm và những phương thức khác thường tin tưởng vào sự đúng đắn của chúng nhờ những xác nhận khác nhau, nhưng chúng vẫn là những xác nhận không tường minh Lập trình viên sẽ tự thuyết phục mình rằng một thuộc tính luôn luôn được giữ ở một thời điểm nào đó, và đưa phân tích này vào trong mã nguồn; nhưng sau một thời gian, chỉ còn lại mã nguồn, không còn những phân tích đó nữa Vài tháng sau, một người nào đó (có thể là chính tác giả), muốn tìm hiểu lại phần mềm, sẽ không thể biết được những thừa nhận không tường minh đó, và sẽ phải mất nhiều công sức để hình dung lại được nó Chỉ thị checksẽ giúp ta tránh khỏi trường hợp đó

Trang 11

Chương 13: Vòng lặp có điều kiện bất biến và điều

kiện biến đổi

13.1 Vấn đề vòng lặp

Khả năng lặp lại một tính toán với một số lần tùy ý một cách dễ dàng là một khả năng vượt xa con người của máy tính Vì thế, vòng lặp có vai trò rất quan trọng trong ngôn ngữ lập trình

Nhưng vòng lặp cũng chứa đựng nhiều rủi ro vì rất khó khăn để có một vòng lặp chính xác Những vấn đề hay gặp là:

− Lỗi “off-by-one” (biểu diễn sự lặp lại quá nhiều hay quá ít)

− Kiểm soát không tốt ở biên, ví dụ như một vòng lặp làm việc tốt trên một mảng nhiều phần tử nhưng lại bị lỗi khi mảng rỗng hay chỉ có một phần tử)

− Vòng lặp vô tận

13.2 Những vòng lặp đúng

Việc sử dụng khôn ngoan xác nhận sẽ giúp ta giải quyết những vấn đề này Một vòng lặp có thể có một xác nhận liên kết, gọi là vòng lặp có điều kiện bất biến

(loop invariant) Cũng có khái niệm “loop variant (vòng lặp có điều kiện biến đổi)”

Đây không phải là một xác nhận mà là một biểu thức nguyên Hai khái niệm này sẽ giúp ta bảo đảm sự chính xác của vòng lặp

Xét ví dụ tính giá trị lớn nhất của một mảng số nguyên:

maxarray (t: ARRAY [INTEGER]): INTEGER is

Giá trị lớn nhất của mảng t

require

t.capacity >= 1

local

i: INTEGER

do

from

i := t.lower

Trang 12

Result := t @ lower

until i = t.upper loop

i := i + 1 Result := Result.max (t @ i)

end end

Ta thấy rằng ở đây ta có thể gán i := t.lowerResult := t@lower

mà không cần bận tâm đến việc mảng t tại vị trí lower có phần tử nào không, có được điều này là nhờ vào việc sử dụng xác nhận, chính là tiền điều kiện:

require

t.capacity >= 1

Đặc điểm của điều kiện bất biến này là mỗi lần lặp, Result luôn là giá trị lớn nhất của phần mảng số nguyên đã được xét

13.3 Những thành phần của một vòng lặp đúng

Ví dụ trên minh họa cho một lược đồ tổng quát của việc tính toán bằng vòng lặp Bạn đã xác định được rằng lời giải cho vấn đề là một phần tử của một mặt

phẳng n chiều POST, vì vậy việc giải quyết vấn đề chính là việc tìm một phần tử của POST Trong một số trường hợp, POST chỉ có một phần tử (chính là lời giải),

nhưng tổng quát thường có nhiều lời giải thích hợp Những vòng lặp trở nên hữu ích

khi bạn không có cách nào làm việc trực tiếp với POST nhưng lại thấy được một con đường gián tiếp: đầu tiên là nhắm vào một mặt phẳng m chiều INV chứa POST (m > n); sau đó tiếp cận POST, lặp đi lặp lại nhưng vẫn bám vào INV Xem hình

minh họa dưới đây:

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

HÌNH ẢNH LIÊN QUAN

Hình  11-1: Sự biến đổi giữa những đối tượng trừu tượng và cụ thể - TÌM HIỂU CÔNG NGHỆ DESIGN BY CONTRACT VÀ XÂY DỰNG CÔNG CỤ HỖ TRỢ CHO C# - 6 pps
nh 11-1: Sự biến đổi giữa những đối tượng trừu tượng và cụ thể (Trang 5)
Hình  11-2: Hai cài đặt của cùng một đối tượng trừu tượng - TÌM HIỂU CÔNG NGHỆ DESIGN BY CONTRACT VÀ XÂY DỰNG CÔNG CỤ HỖ TRỢ CHO C# - 6 pps
nh 11-2: Hai cài đặt của cùng một đối tượng trừu tượng (Trang 7)

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w