合同设计对我们有用吗?
我们是否专业使用按合同设计?是从项目开始就要做的事情,还是可以改变方式并开始将其纳入软件开发生命周期中?我们发现设计方法的优点/缺点是什么?
我在一个研究生学校课程中遇到了"按合同设计"方法。在学术环境中,这似乎是一种非常有用的技术。但是我目前还没有专业地使用按合同设计,也不知道其他正在使用它的开发人员。最好能从SO人群那里得知它的实际用法。
解决方案
回答
我不能高度推荐它。如果我们有一个采用内联文档合同规范的套件,那就特别好,例如:
// @returns null iff x = 0 public foo(int x) { ... }
并将它们转换为生成的单元测试,如下所示:
public test_foo_returns_null_iff_x_equals_0() { assertNull foo(0); }
这样,我们实际上可以看到正在运行的测试,但是它们是自动生成的。顺便说一下,不应将生成的测试签入源代码管理。
回答
在SOA领域中进行任何工作时不按合同进行设计是绝对愚蠢的,如果我们正在从事任何模块化工作,这在以后可能会被一点点地换掉,尤其是在涉及到任何黑盒子的情况下,这总是有帮助的。
回答
代替更具表现力的类型系统,我绝对会在军事级项目中按合同使用设计。
对于弱类型语言或者具有动态作用域的语言(PHP,JavaScript),功能协定也非常方便。
对于其他所有方面,我都会抛弃对Beta测试人员和单元测试的依赖。
Gaius:运行时会自动为我们抛出Null Pointer异常,因此在函数序言中测试这些东西没有任何好处。如果我们对文档更感兴趣,那么我将使用可与静态分析器等配合使用的注释(例如,确保代码不会破坏注释)。
一个更强大的类型系统,再加上按合同设计,似乎是必经之路。看一下Specfor的例子:
The Spec# programming language. Spec# is an extension of the object-oriented language C#. It extends the type system to include non-null types and checked exceptions. It provides method contracts in the form of pre- and postconditions as well as object invariants.
回答
我实际上并不是每天都使用"按合同设计"。但是,我的确知道它已经被纳入D语言中,作为D语言的一部分。
回答
如果我们研究STL,boost,MFC,ATL和许多开源项目,则可以看到有太多ASSERTION语句,这使项目可以更安全地进行下去。
按合同设计!它确实适用于实际产品。
回答
弗兰克·克鲁格(Frank Krueger)写道:
Gaius: A Null Pointer exception gets thrown for you automatically by the runtime, there is no benefit to testing that stuff in the function prologue.
我对此有两个回应:
- 空只是一个例子。对于square(x),我想测试结果的平方根(大约)是参数的值。对于设置员,我想测试该值是否实际更改。对于原子操作,我想检查所有组件操作是否成功或者全部失败(确实是一次测试是否成功,而n次测试失败)。对于弱类型语言的工厂方法,我想检查是否返回了正确的对象。清单一直在继续。基本上,可以在一行代码中进行测试的任何东西都是序言注释中代码合同的很好的候选者。
- 我不同意我们不应该测试事物,因为它们会生成运行时异常。如果有的话,我们应该测试可能会生成运行时异常的事物。我喜欢运行时异常,因为它们会使系统快速故障,这有助于调试。但是示例中的" null"是某些可能输入的结果值。有一个关于永不返回null的论点,但是如果要这样做,则应该对其进行测试。
回答
当我们在必须相互通信的应用程序之间建立接口时,我们真的会真正欣赏按合同进行的设计。
没有合同,这种情况很快就变成了责备网球运动。团队不断来回敲控指控,浪费了大量时间。
有了合同,责任就很明显了。
来电者是否满足前提条件?如果不是这样,客户团队需要修复它。
收到有效请求后,接收方是否满足发布条件?如果不是,服务器团队需要修复该问题。
双方都遵守合同,但结果不令人满意吗?合同不足,需要升级该问题。
为此,我们不需要以断言的形式实施合同,我们只需要确保各方都记录了文件并达成协议即可。
回答
根据我的经验,单元测试和按合同设计都是有价值的测试方法。
我曾尝试在系统自动测试框架中使用按合同设计,而我的经验是,这种灵活性和灵活性不易通过单元测试获得。例如,可以运行更长的序列并验证
每次执行动作时,响应时间都在限制范围内。
查看InfoQ上的演示,看来按合同设计是组件集成阶段中常规单元测试的宝贵补充。
例如,可以先创建一个模拟接口,然后再使用该组件
或者发布新版本的组件时。
我还没有找到能够满足通过合同测试进行设计的所有设计要求的工具包
在.Net / Microsoft平台中。
回答
是的,它确实!实际上,几年前,我设计了一个用于参数验证的小框架。我当时在做一个SOA项目,其中不同的后端系统进行了各种验证和检查。但是为了增加响应时间(在输入无效的情况下,并减少加载这些后端系统的时间),我们开始验证所提供服务的输入参数。不仅适用于Not Null,而且适用于String模式。或者集合中的值。以及参数之间具有依赖性的情况。
现在我意识到我们当时通过合同框架实施了一个小设计:)
对于那些对小型Java参数验证框架感兴趣的人,这里是链接。这是作为纯Java解决方案实现的。
回答
我发现这表明Go编程语言没有使按合同设计成为可能的结构。 panic / defer / recover并不完全一样,因为defer和restore逻辑可以忽略恐慌,而IOW可以忽略违约。至少需要某种形式的无法恢复的恐慌,这确实可以断言。或者,最好是通过合同结构(前提条件和条件后,实现和类不变式)直接为设计提供语言支持。但是,鉴于语言纯粹主义者在Go船长的领导下坚毅不拔,因此我所做的任何改动都没有改变。
通过在恐慌函数中的最后一个defer函数中检查特殊的断言错误并调用runtime.Breakpoint()以在恢复期间转储堆栈,可以实现类似断言的行为。要断言,行为必须是有条件的。当然,当在执行断言之后添加新的延迟函数时,这种方法就会瓦解。在大型项目中,这恰恰会在错误的时间发生,从而导致错误遗漏。
我的观点是,断言在很多方面都非常有用,以至于不得不跳动它可能会让人头疼。