контракт

Контракт

Контракт - правило, обеспечивающее соблюдение программой формальных требований. Является центральным понятием контрактного программирования.

Основная идея контрактного программирования - заменить неформальные соглашения в коде формальными. Например, в языках без поддержки контрактов автор некой функции может указать в документации условия для входных данных этой функции - такой подход не дает гарантии, что пользователь прочитает документацию и будет использовать функцию правильно. И наоборот - программист может давать неформальные гарантии о поведении функции или о ее результатах, но де-факто нарушать их вследствие ошибки. Контрактное программирование позволяет уменьшить риск подобных недоразумений путем введения формальных спецификаций для компонентов программы непосредственно в коде.

Использование контрактов позволяет сделать программу более надежной без необходимости постоянного регрессионного тестирования - иными словами, избежать ошибок, когда после внесения изменений в программу перестает работать то, что работало ранее. В этом смысле контрактное программирование является альтернативой разработке через тестирование (test-driven development), но ничто не мешает использовать обе парадигмы одновременно - в некоторых языках (например, в D) они дополняют друг друга. Однако некоторые виды контрактов позволяют верифицировать то, что невозможно верифицировать при помощи тестов.

В основе парадигмы контрактного программирования лежит логика Хоара - способ формального доказательства корректности алгоритма. Она оперирует такими понятиями, как предусловие, постусловие и инвариант.

  • Предусловие (precondition) - контракт, который должен быть исполнен перед выполнением функции. Применяется к параметрам функции
  • Постусловие (postcondition) - контракт, который должен быть исполнен после завершения функции. Применяется к возвращаемому значению функции
  • Инвариант (invariant) - контракт, который должен быть исполнен после изменения некоего состояния. Используется для проверки соответствия состояния условию.

К контрактам также можно отнести следующие языковые конструкции:

  • Утверждение корректности (assertion) - условие, которое должно быть выполнено до перехода к следующему утверждению в потоке
  • Интерфейс (interface) - контракт, гарантирующий доступ к определенным методам класса
  • Атрибуты (attributes) - правила семантического анализатора, гарантирующие соблюдение определенных условий на этапе компиляции. Например, в языке D есть следующие атрибуты:
    • pure - чистая функция. Такие функции не имеют доступа к внешнему контексту и внешним функциям и могут вызывать только другие чистые функции, что гарантирует отсутствие побочных эффектов. Возвращаемое значение чистой функции зависит только от ее параметров
    • nothrow - функция, которая не выбрасывает исключение
    • @safe - безопасная функция. Безопасные функции обязаны соблюдать ряд требований: например, в них не разрешается приведение и арифметика указателей, использование системных вызовов, приведение неизменяемого типа к изменяемому и др.
    • @trusted - доверенная функция. Является функцией, которая может быть вызвана из безопасной функции, но безопасность которой не проверяется компилятором. Атрибут служит своеобразным компромиссом между формальным и неформальным контрактом
    • @nogc - функция, не использующая сборщик мусора. В таких функциях запрещены некоторые операции языка, связанные с динамическим выделением памяти
    • const - атрибут-спецификатор типа, обеспечивающий доступ к данным только для чтения
    • immutable - атрибут-спецификатор типа, обеспечивающий неизменяемость данных.
  • контракт.txt
  • Последнее изменение: 2021/03/15 09:24
  • (внешнее изменение)