По моему опыту стоит заниматься дизайном по контракту даже без языковой поддержки.Для методов, которые не являются переопределенными утверждениями, вместе со строкой документации достаточно как предварительных, так и постусловий.Для переопределенных методов мы разделяем метод на два: открытый метод, который проверяет предварительные и постусловия, и защищенный метод, который обеспечивает реализацию и может быть переопределен подклассами.Вот пример последнего:
class Math:
def square_root(self, number)
"""
Calculate the square-root of C{number}
@precondition: C{number >= 0}
@postcondition: C{abs(result * result - number) < 0.01}
"""
assert number >= 0
result = self._square_root(number)
assert abs(result * result - number) < 0.01
return result
def _square_root(self, number):
"""
Abstract method for implementing L{square_root()}
"""
raise NotImplementedError()
Я получил квадратный корень в качестве общего примера разработки по контракту из эпизода о разработке по контракту на радиоинженерии программного обеспечения (http://www.se -radio.net / 2007/03 / эпизод-51-дизайн по-контракта / ).Они также упомянули о необходимости языковой поддержки, потому что утверждения не помогли в обеспечении принципа подстановки Лискова, хотя мой пример выше демонстрирует обратное.Я должен также упомянуть идиому C ++ pimpl (частная реализация) в качестве источника вдохновения, хотя это имеет совершенно иное назначение.
В своей работе я недавно реорганизовал этот вид проверки контрактов в большую иерархию классов(договор уже был задокументирован, но систематически не проверялся).Существующие юнит-тесты показали, что контракты были нарушены несколько раз.Я могу только заключить, что это должно было быть сделано давным-давно, и что покрытие модульных испытаний окупается еще больше, когда применяется проектирование по контракту.Я ожидаю, что любой, кто попробует эту комбинацию техник, сделает те же наблюдения.
Лучшая поддержка инструментов может предложить нам еще больше возможностей в будущем, я приветствую это.