在Python中使用契约式设计

2024-06-16 09:03:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我希望在大量工作中的基于Python的项目中开始使用DBC,我想知道其他人在使用DBC方面有什么经验。到目前为止,我的研究结果如下:

我的问题是:您是否将DBC与Python一起用于成熟的生产代码?它做得怎么样/值得这么做吗?你推荐哪些工具?


Tags: 项目orgdevhttpnetwww经验建议
3条回答

根据我的经验,合同设计是值得做的,即使没有语言支持。对于未重写断言的方法,连同docstring对于前置和后置条件都足够了。对于被重写的方法,我们将该方法分为两部分:一个检查前置和后置条件的公共方法,一个提供实现的受保护方法,并且可以由子类重写。下面是后者的一个例子:

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(私有实现)习语作为灵感来源,尽管它有完全不同的目的。

在我的工作中,我最近将这种契约检查重构为一个更大的类层次结构(契约已经被记录,但没有系统地测试)。现有的单元测试显示,这些契约被多次违反。我只能得出这样的结论:这应该在很久以前就完成了,而且一旦按合同设计得到应用,单元测试覆盖率就会得到更大的回报。我希望任何尝试这种技术组合的人都能做出同样的观察。

更好的工具支持可能会在未来为我们提供更多的力量,我对此表示欢迎。

我没有在python中使用按合同设计,所以我不能回答您的所有问题。不过,我花了一些时间查看了contracts库,它的最新版本最近已经发布,看起来非常不错。

reddit中有一些关于这个库的讨论。

你发现的PEP还没有被接受,所以没有一个标准或者被接受的方法来实现它(但是——你可以自己实现它!)。然而,正如您所发现的,有几种不同的方法。

可能最轻量级的方法就是简单地使用Python装饰器。在Python Decorator Library中有一组用于前/后条件的装饰器,可以直接使用。下面是该页的一个示例:

  >>> def in_ge20(inval):
  ...    assert inval >= 20, 'Input value < 20'
  ...
  >>> def out_lt30(retval, inval):
  ...    assert retval < 30, 'Return value >= 30'
  ...
  >>> @precondition(in_ge20)
  ... @postcondition(out_lt30)
  ... def inc(value):
  ...   return value + 1
  ...
  >>> inc(5)
  Traceback (most recent call last):
    ...
  AssertionError: Input value < 20

现在,你提到类不变量。这有点困难,但我要做的是定义一个检查不变量的调用,然后在每个方法调用结束时让post condition decorator检查该不变量。作为第一个切入点,您可能只需要使用postcondition decorator就可以了。

相关问题 更多 >