Tìm hiểu công nghệ Design By Contract và Xây dựng công cụ hỗ trợ cho C# nhỏ hơn một giá trị cho trước Yêu cầu đối tượng nhập vào LessThanOrEqual hoặc trả về phải nhỏ hơn hoặc cho trước Yêu cầu số thành phần của đối tượng nhập MaxCount vào hoặc trả về phải nhỏ hơn hoặc bằng một giá trị cho trước Quy ước chiều dài tối đa của MaxLength một chuỗi là một giá trị cho trước Yêu cầu số thành phần của đối tượng nhập MinCount vào hoặc trả về phải lớn hơn hoặc bằng một giá trị...
Trang 1nhỏ hơn một giá trị cho trước
LessThanOrEqual
Yêu cầu đối tượng nhập vào hoặc trả về phải nhỏ hơn hoặc bằng một giá trị cho trước
Void
SetData([LessThanOrEqual (5)]
int value) {}
//value <= 5
MaxCount
Yêu cầu số thành phần của đối tượng nhập vào hoặc trả về phải nhỏ hơn hoặc bằng một giá trị cho trước
Void SetData([MaxCount (10)]
ArrayList arr) {}
//arr.Count <= 10
MaxLength
Quy ước chiều dài tối đa của một chuỗi là một giá trị cho trước
Void SetData([MinLength (10)]
String str) {}
//str.Length <= 10
MinCount
Yêu cầu số thành phần của đối tượng nhập vào hoặc trả về phải lớn hơn hoặc bằng một giá trị cho trước
Void SetData([MinCount (10)]
ArrayList arr) {}
//arr.Count >= 10
MinLength Quy ước chiều Void SetData([MinLength (10)]
Trang 2một chuỗi là một giá trị cho trước
//str.Length >= 10
NotEqual
Yêu cầu đối tượng nhập vào hoặc trả về phải
“not equal” với một giá trị cho trước
Void SetData([NotEqual (5)] int
value) {}
//value != 5
OneOf
Quy ước giá trị nhập vào hay trả
về của một giá trị phải nằm trong các giá trị cho trước
Void SetData([OneOf (1,3,5,7,9,10)] int value) {}
//value có giá trị là một trong các giá trị sau : [1,3,5,7,9,10]
…
15.4 Ví dụ lớp Stack
private Object[] representation;
public int count; // inv: count>=0 (count khong am)
public int capacity;// inv: count<=capacity private int current;// inv: current>=0
// [Requires ("size >= 0")]
[Ensures ("representation != null && capacity
== size && IsEmpty()")]
public MyStack([GreaterThanOrEqual (0)]int size)
{
Trang 3capacity = size;
representation = new Object[capacity]; }
[Requires ("!IsFull()")]
[Ensures ("!IsEmpty() &&
(int)representation[count-1] == obj")]
public void put(int obj)
{
representation[count++] = obj;
}
[Requires ("!IsEmpty()")]
[Ensures ("!IsFull()")]
public void remove()
{
count;
}
[Ensures ("result == (count == capacity)")] public bool IsFull()
{
}
[Ensures ("result == (count == 0)")]
public bool IsEmpty()
{
}
Trang 4[Requires ("position >= 0 && position <
count")]
[Ensures ("current == position")]
public void SetCurrentItem(int position)
{
current = position;
}
[Ensures ("current == count - 1")]
public void ResetCurrentItem()
{
current = count - 1;
}
[Requires ("!IsEmpty()")]
[Ensures ("result != null && current >= 0")] public Object nextItem()
{ return representation[current ];
}
Chương 16: Kết quả thực nghiệm: công cụ DCS
16.1 Nguyên lý làm việc
DCS là một Add-In trong môi trường Visual C#, nguyên lý làm việc của DCS là bắt sự kiện OnBuildBegin của project, thực hiện những bước sau:
Duyệt qua tất cả những lớp của project (mỗi lớp ứng với một file *.cs, trừ file AssemblyInfo.cs) và lưu thông tin của mỗi lớp (tên lớp, tên file, tên những lớp dẫn xuất) Trong mỗi lớp, chương trình thực hiện những bước sau:
− Kiểm tra xem lớp có chứa những xác nhận (Invariant, PreCondition, PostCondition) hay không Lưu thông tin của Invariant (các mệnh đề và thông báo
Trang 5tương ứng của Invariant) nếu có, sau đó, duyệt qua từng hàm trong lớp, trong mỗi hàm, thực hiện những bước sau:
+ Kiểm tra hàm có PreCondition hoặc PostCondition hay không Nếu có, lưu lại thông tin của hàm Thông tin lưu trữ gồm có: Tên hàm, PreCondition và PostCondition (lưu các mệnh đề và thông báo)
+ Đổi tên hàm, nếu lớp có Invariant, tất cả tên hàm sẽ được đổi, nếu không có Invariant, chỉ những hàm có PreCondition hoặc PostCondition mới được đổi tên Tên hàm được đổi như sau:
Tên hàm mới = @origin_[Tên hàm cũ]
− Dựa vào thông tin đã lưu trữ được, bổ sung thông tin về những xác nhận của các lớp dẫn xuất cho mỗi lớp Việc lưu trữ này thực hiện bằng cách duyệt qua tất cả các lớp Trong đó, ở mỗi lớp:
+ Duyệt qua tất cả tất cả những lớp dẫn xuất của lớp này (đã được lưu trữ), lưu thông tin Invariant của những lớp dẫn xuất
+ Duyệt qua các hàm, hàm nào là hàm cài đặt lại sẽ được lưu trữ thông tin về Assertion của lớp dẫn xuất
Phát sinh source code bổ sung để kiểm tra các xác nhận cho các lớp Trong mỗi lớp, source code sẽ được thêm vào phía dưới của source code hiện tại Mỗi hàm sẽ phát sinh source code tương ứng của mình Với mỗi hàm, dựa vào thông tin đã lưu trữ, source code được phát sinh như sau:
[Khai báo hàm theo tên hàm cũ]
{
Gọi hàm kiểm tra PreCondition
Gọi hàm kiểm tra Invariant
Gọi hàm gốc (hàm đã được đổi tên @origin_*)
Gọi hàm kiểm tra PostCondition
Gọi hàm kiểm tra Invariant
Trang 6[Hàm kiểm tra PreCondition]
{
Các câu lệnh kiểm tra các mệnh đề và xuất thông báo tương ứng của
PreCondition
}
[Hàm kiểm tra Invariant]
{
Các câu lệnh kiểm tra các mệnh đề và xuất thông báo tương ứng của
Invariant
}
[Hàm kiểm tra PostCondition]
{
Các câu lệnh kiểm tra các mệnh đề và xuất thông báo tương ứng của
PostCondition
}
Ví dụ: Hàm và PreCondition, PostCondition, Invariant:
/*
@#$Require:
@#$Ensure:
!IsEmpty()
count == OLD_count + 1 $int # New count = Old count + 1
*/
public void put(int obj)
Trang 7{
}
/*
@#$Invariant:
*/
Trang 8Code phát sinh:
public void put(int obj)
{
int OLD_count = count;
if(put_PreCondition(obj)!="")
throw new Exception("PreCondition Violated at
[MyStack - public void put(int obj)]:" +put_PreCondition(obj));
if(put_Invariant(obj)!="")
throw new Exception("Invariant Violated at
[MyStack]:" +put_Invariant(obj));
@origin_put(obj);
if(put_PostCondition(obj,OLD_count)!="")
throw new Exception("PostCondition Violated at
[MyStack - public void put(int obj)]:" +put_PostCondition(obj,OLD_count));
if(put_Invariant(obj)!="")
throw new Exception("Invariant Violated at
[MyStack]:" +put_Invariant(obj));
}
private string put_PreCondition(int obj)
{
if (!(!IsFull() ))
return " Stack Full";
return "";
}
Trang 9private string put_Invariant(int obj)
{
if (!(count >= 0))
return " ";
if (!(count <= capacity))
return " ";
if (!(current >= 0))
return " ";
return "";
}
private string put_PostCondition(int obj,int OLD_count) {
if (!(!IsEmpty()))
return " ";
if (!((int)representation[count-1] == obj))
return " ";
if (!(count == OLD_count + 1 ))
return " New count = Old count + 1";
return "";
}
Project được biên dịch theo source code mới
Bắt sự kiện OnBuildDone của project, thực hiện việc trả lại source code như
cũ cho project
Trang 1016.2 Thiết kế
16.2.1 Tổng thể
Hình 16-1: Sơ đồ thiết kế tổng thể
Danh sách các lớp đối tượng:
1 Configuration
Màn hình cho phép người dùng enable hoặc disable chức năng kiểm tra của PreCondition,
PostCondition, Invariant
2 Connect Lớp chính của chương trình, đây là lớp quản lý mọi
thao tác của Add-In với project
Trang 113 ProjectInfo Lớp đối tượng để lưu trữ thông tin của project hiện
hành
4 ClassInfo Lớp đối tượng để lưu trữ thông tin của một lớp trong
project
5 FunctionInfo Lớp đối tượng để lưu trữ thông tin của một phương
thức trong class
6 Assertion Lớp đối tượng để lưu trữ thông tin của một Assertion
(precondition, postcondition, invariant)
7 Extra Lớp đối tượng chứa những hàm riêng, không thuộc
trách nhiệm của những lớp trên
16.2.2 Chi tiết các lớp đối tượng
16.2.2.1 Màn hình Configuration
Hình 16-2: Màn hình Configuration
Trang 12Hình 16-3: Chi tiết màn hình Configuration
Danh sách các đối tượng thể hiện:
1 chkPreCondition checkbox Xác định có sử dụng PreCondition
hay không
2 chkPostCondition checkbox Xác định có sử dụng PostCondition
hay không
3 chkInvariant checkbox Xác định có sử dụng Invariant hay
không
4 chkBasePre checkbox Xác định có sử dụng PreCondition của
những lớp dẫn xuất hay không
5 chkBasePost checkbox Xác định có sử dụng PostCondition
của những lớp dẫn xuất hay không
6 chkBaseInv checkbox Xác định có sử dụng Invariant của
những lớp dẫn xuất hay không
và thoát khỏi màn hình