Menu

Контрактне програмування

Контрактне програмування D включає у себе набір мовних конструкцій, які дозволяють підвищити якість коду шляхом впровадження перевірок програми на відсутність очевидних помилок, що дає змогу переконатися, що код поводить себе, як передбачалося. Контракти доступні тільки у режимах відлагодження чи тестування та не будуть працювати у режимі релізу. Саме тому вони не повинні використовуватися для перевірки введених користувачем даних або як альтернативу обробки винятків.

assert

Найпростіша форма контрактного програмування у D - це вираз assert(...), який перевіряє, чи певна умова виконана, а також перериває програму за допомогою AssertionError, якщо умова не вірна.

assert(sqrt(4) == 2);
// опціонально можна вказати власну помилку для користувача
assert(sqrt(16) == 4, "sqrt не працює!");

Функціональні контракти

in та out дозволяють оформити контракти для перевірки вхідних параметрів і результату функцій.

long square_root(long x)
in {
    assert(x >= 0);
} out (result) {
    assert((result * result) <= x
        && (result+1) * (result+1) > x);
} body {
    return cast(long)std.math.sqrt(cast(real)x);
}

Зміст блоку in також можна перенести у тіло функції, але втрачається очевидність. У блоці out повернення значення функції можна перехопити за допомогою out(result) і перевірити коректність результату.

Інваріантна перевірка

invariant() - це спеціальна функція struct та class, що дозволяє контролювати стан об'єкта напротязі всього часу його життя:

  • Вона викликається після виклику конструктора і перед викликом деструктора.
  • Вона викликається перед виконанням функції
  • invariant() викликається після завершення функції-члена.

Перевірка даних, введених користувачем

Оскільки усі контракти будуть видалені у релізній збірці, дані, введені користувачем, не повинні перевірятися за допомогою контрактів. При цьому, assert-и можуть бути використані у nothrow-функціях, тому що вони породжують фатальні помилки (Error). Аналогом часу виконання для assert-ів є std.exception.enforce, який буде видавати виключення (Exception), які дозволяється перехоплювати.

Поглиблення

rdmd playground.d