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()
我从软件工程广播(software engineering radio)上的一集“按合同设计”(design by contract)中得到了按合同设计(design by contract)的一般示例平方根。他们还提到了语言支持的必要性,因为断言在确保Liskov替换原则方面没有帮助,尽管我上面的例子旨在证明另一点。我还应该提到C++ PIPML(私有实现)习语作为灵感来源,尽管它有完全不同的目的。
根据我的经验,合同设计是值得做的,即使没有语言支持。对于未重写断言的方法,连同docstring对于前置和后置条件都足够了。对于被重写的方法,我们将该方法分为两部分:一个检查前置和后置条件的公共方法,一个提供实现的受保护方法,并且可以由子类重写。下面是后者的一个例子:
我从软件工程广播(software engineering radio)上的一集“按合同设计”(design by contract)中得到了按合同设计(design by contract)的一般示例平方根。他们还提到了语言支持的必要性,因为断言在确保Liskov替换原则方面没有帮助,尽管我上面的例子旨在证明另一点。我还应该提到C++ PIPML(私有实现)习语作为灵感来源,尽管它有完全不同的目的。
在我的工作中,我最近将这种契约检查重构为一个更大的类层次结构(契约已经被记录,但没有系统地测试)。现有的单元测试显示,这些契约被多次违反。我只能得出这样的结论:这应该在很久以前就完成了,而且一旦按合同设计得到应用,单元测试覆盖率就会得到更大的回报。我希望任何尝试这种技术组合的人都能做出同样的观察。
更好的工具支持可能会在未来为我们提供更多的力量,我对此表示欢迎。
我没有在python中使用按合同设计,所以我不能回答您的所有问题。不过,我花了一些时间查看了contracts库,它的最新版本最近已经发布,看起来非常不错。
在reddit中有一些关于这个库的讨论。
你发现的PEP还没有被接受,所以没有一个标准或者被接受的方法来实现它(但是——你可以自己实现它!)。然而,正如您所发现的,有几种不同的方法。
可能最轻量级的方法就是简单地使用Python装饰器。在Python Decorator Library中有一组用于前/后条件的装饰器,可以直接使用。下面是该页的一个示例:
现在,你提到类不变量。这有点困难,但我要做的是定义一个检查不变量的调用,然后在每个方法调用结束时让post condition decorator检查该不变量。作为第一个切入点,您可能只需要使用postcondition decorator就可以了。
相关问题 更多 >
编程相关推荐