Lập trình hợp đồng (Contract programming
) là việc dùng một số cú pháp
để tăng chất lượng mã nguồn, đảm bảo mã tuân theo các hợp đồng đã ước định.
Các hợp đồng được kiểm tra khi chương trình chạy ở chế độ kiểm thử hoặc dò lỗi,
nhưng chúng bị bỏ qua hoàn toàn trong chế độ biên dịch ra sản phẩm cuối (-release).
Vì vậy, các hợp đồng không nên được dùng để kiểm soát dữ liệu đầu vào
hoặc kiểm soát lỗi ngoại lệ
assert
Phiên bản đơn giản nhất của lập trình hợp đồng là dùng các chặn
assert(...)
để ước định một số điều kiện được thỏa mãn, hoặc thoát và
dừng chương trình với mã AssertionError
trong các trường hợp khác.
assert(sqrt(4) == 2);
// có thể thêm thông báo lỗi vào cho dễ dò
assert(sqrt(16) == 4, "không tính đúng căn bậc hai");
in
và out
để kiểm soát đầu vào và đầu ra của hàm bất kỳ:
long square_root(long x)
in {
assert(x >= 0);
} out (result) {
assert((result * result) <= x
&& (result+1) * (result+1) > x);
} do {
return cast(long)std.math.sqrt(cast(real)x);
}
Khối mã in
cũng có thể đặt bên trong thân hàm, nhưng ý nghĩa của nó
sẽ rõ ràng khi đặt bên ngoài như trong ví dụ trên. Trong khi đó, khối
mã out
có thể sử dụng giá trị trả về của hàm bằng cách chỉ ra biến, ví dụ
out(result)
.
invariant()
là hàm đặc biệt của các kiểu struct
và class
, được dùng
để kiểm tra trạng thái đối tượng của kiểu trong suốt quá trình tồn tại
của đối tượng
invariant()
được gọi sau khi đối tượng được khởi tạo,
và trước khi đối tượng bị hủy;
Mọi hợp đồng được bỏ qua khi chương trình biên dịch với cờ release
.
Vì thế, đầu vào từ người dùng không được kiểm tra bằng các hợp đồng.
Hơn nữa, chặn assert
vẫn có thể được dùng trong các hàm nothrow
bởi chúng sẽ quăng lỗi Error
.
Lúc chạy chương trình, thay vì dùng assert
bạn có thể dùng
std.exception.enforce
,
để quăng ra các lỗi ngoại lệ (Exception
) có thể bắt được.