Lập trình hợp đồng

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ệ

Chặn 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");

Hợp đồng hàm

inout để 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).

Kiểm tra bất biến

invariant() là hàm đặc biệt của các kiểu structclass, đượ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

  • Hàm invariant() được gọi sau khi đối tượng được khởi tạo, và trước khi đối tượng bị hủy;
  • Hàm đó cũng được gọi trước các hàm thành phần của đối tượng được gọi, và nó cũng được gọi sau khi hàm đó kết thúc.

Kiểm tra đầu vào từ người dùng

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.

Nâng cao

rdmd playground.d