标签: design-by-contract

使用断言或例外通过合同设计?

通过合同编程时,函数或方法首先检查其前提是否已满足,然后才开始履行其职责,对吗?两个最重要的方式做这些检查是通过assertexception.

  1. 断言仅在调试模式下失败.确保(单元)测试所有单独的合同前提条件以确定它们是否确实失败是至关重要的.
  2. 在调试和释放模式下异常失败.这样做的好处是,测试的调试行为与发布行为相同,但它会导致运行时性能下降.

你觉得哪一个更好?

请参阅此处的相关问题

assert design-by-contract exception

121
推荐指数
5
解决办法
2万
查看次数

多少空检查就足够了?

什么是什么时候没有必要检查空?

我最近一直在研究的许多继承代码都有空检查令人作呕.Null检查普通函数,对表示非空返回的API调用进行空检查等.在某些情况下,空检查是合理的,但在许多地方,null不是合理的期望.

我听过很多论点,从"你不能相信其他代码"到"总是防守程序"到"直到语言保证我的非空值,我总会检查." 我当然同意这些原则中的许多原则,但我发现过多的空值检查会导致其他通常违反这些原则的问题.顽强的空检查真的值得吗?

通常,我观察到过多的空检查代码实际上质量较差,而不是质量较高.许多代码似乎都专注于空检查,开发人员已经忽略了其他重要的特性,例如可读性,正确性或异常处理.特别是,我看到很多代码忽略了std :: bad_alloc异常,但对a进行了空检查new.

在C++中,由于解除引用空指针的不可预测行为,我在某种程度上理解这一点; 在Java,C#,Python等中更优雅地处理null dereference.我刚刚看到了警惕的空检查的不良例子,还是真的有什么东西可以解决这个问题?

这个问题旨在与语言无关,尽管我主要对C++,Java和C#感兴趣.


我见过的一些空检查的例子似乎过多,包括:


这个例子似乎是非标准编译器的原因,因为C++规范说失败的新抛出异常.除非您明确支持不合规的编译器,否则这有意义吗?这确实让任何意义的,如Java或C#(甚至C++/CLR)托管语言?

try {
   MyObject* obj = new MyObject(); 
   if(obj!=NULL) {
      //do something
   } else {
      //??? most code I see has log-it and move on
      //or it repeats what's in the exception handler
   }
} catch(std::bad_alloc) {
   //Do something? normally--this code is wrong as it allocates
   //more memory and will likely fail, such as writing to a log file.
} …
Run Code Online (Sandbox Code Playgroud)

c# c++ java design-by-contract

66
推荐指数
5
解决办法
1万
查看次数

ReSharper - 使用Microsoft.Contracts时可能的空值分配

有没有办法向ReSharper表明由于按合同设计需要检查,不会出现空引用?例如,以下代码将Possible 'null' assignment to entity marked with 'NotNull' attribute在第7行和第8行的ReSharper中引发warning():

private Dictionary<string, string> _Lookup = new Dictionary<string, string>();

public void Foo(string s)
{
    Contract.Requires(!String.IsNullOrEmpty(s));

    if (_Lookup.ContainsKey(s))
        _Lookup.Remove(s);
}
Run Code Online (Sandbox Code Playgroud)

真正奇怪的是,如果删除该Contract.Requires(...)行,ReSharper消息就会消失.

更新

我通过ExternalAnnotations找到了解决方案,Mike也在下面提到过.以下是如何在Microsoft.Contracts中为函数执行此操作的示例:

  • 创建一个Microsoft.ContractsExternalAnnotationsReSharper目录下调用的目录.
  • 接下来,创建一个名为的文件Microsoft.Contracts.xml并填充如下:

<assembly name="Microsoft.Contracts">
    <member name="M:System.Diagnostics.Contracts.Contract.Requires(System.Boolean)">
        <attribute ctor="M:JetBrains.Annotations.AssertionMethodAttribute.#ctor"/>
        <parameter name="condition">
            <attribute ctor="M:JetBrains.Annotations.AssertionConditionAttribute.#ctor(JetBrains.Annotations.AssertionConditionType)">
                <argument>0</argument>
            </attribute>
        </parameter>
    </member>
</assembly>
Run Code Online (Sandbox Code Playgroud)

  • 重新启动Visual Studio,消息就消失了!

c# resharper design-by-contract code-contracts microsoft-contracts

52
推荐指数
3
解决办法
9640
查看次数

单元测试 - 合同变更的单元测试的好处?

最近我与一位同事就单元测试进行了一次有趣的讨论.当合同发生变化时,我们正在讨论何时维持单元测试的效率降低.

也许任何人都可以告诉我如何解决这个问题.让我详细说明:

所以我们假设有一个类可以做一些漂亮的计算.合同说它应该计算一个数字,或者当它由于某种原因失败时返回-1.

我有合同测试谁测试.在我所有的其他测试中,我将这个漂亮的计算器存在.

所以现在我改变了契约,只要它无法计算就会抛出一个CannotCalculateException.

我的合同测试将失败,我将相应地修复它们.但是,我所有的模拟/存根对象仍将使用旧的合同规则.这些测试将成功,而他们不应该!

提出的问题是,凭借对单元测试的这种信念,可以对这些变化有多少信心......单元测试成功,但在测试应用程序时会出现错误.使用这个计算器的测试需要修复,这需要花费时间,甚至可能很多时候被抄袭/嘲笑......

你觉得这个案子怎么样?我从来没有想过它.在我看来,单元测试的这些变化是可以接受的.如果我不使用单元测试,我也会在测试阶段(测试人员)看到这样的错误.然而,我没有足够的信心指出什么会花费更多的时间(或更少).

有什么想法吗?

unit-testing design-by-contract

51
推荐指数
3
解决办法
2408
查看次数

如何显示方法是否可以返回null

在发布这个问题并阅读那个问题,我意识到知道一个方法是否应该返回null是非常重要的,或者如果这被认为是错误条件并且应该抛出异常.还有一个很好的讨论,何时返回'null'或抛出异常.

我正在写一个方法,我已经知道如果我想返回null或抛出异常,表达我的决定的最佳方式是什么,换句话说,记录我的合同?

我能想到的一些方法:

  • 在规格/文档中写下来(任何人都会阅读它吗?)
  • 使它成为方法名称的一部分(正如我在这里建议的那样)
  • 假设抛出异常的每个方法都不会返回null,并且每个执行'not'抛出的方法都可能返回null.

我主要讨论java,但它也可能适用于其他语言:为什么有一种正式的方式来表达是否会抛出异常(throws关键字)但是没有正式的方式来表达是否可能返回null?

为什么没有这样的东西:

public notnull Object methodWhichCannotReturnNull(int i) throws Exception
{
    return null; // this would lead to a compiler error!
}
Run Code Online (Sandbox Code Playgroud)

总结和结论

表达合同的方式有很多种:

  • 如果您的IDE支持它(作为IntelliJ),最好使用注释,@NotNull因为它对程序员可见,并且可用于自动编译时检查.Eclipse有一个插件可以添加对这些的支持,但它对我不起作用.
  • 如果这些不是一个选项,请使用类似Option<T>或的自定义类型NotNull<T>,这样可以增加清晰度并至少提高运行时检查.
  • 无论如何,在JavaDoc中记录合同永远不会伤害,有时甚至会有所帮助.
  • 除了我之外,没有人提出使用方法名来记录返回值的可空性,虽然它可能非常详细而且并不总是有用,但我仍然认为它有时也有其优点.

java null design-by-contract

45
推荐指数
2
解决办法
3万
查看次数

一个很好的Java合同设计库?

几年前,我做了一个关于Java的DbC包的调查,我对它们中的任何一个都不满意.不幸的是,我没有对我的发现做好记录,我认为事情已经发生了变化.有人会关心比较和对比不同的Java DbC包吗?

java design-by-contract

45
推荐指数
2
解决办法
2万
查看次数

在Python中使用契约式设计

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

我的问题是:您是否将DBC与Python一起用于成熟的生产代码?它的效果如何/值得努力?你会推荐哪些工具?

python design-by-contract

42
推荐指数
5
解决办法
9771
查看次数

合同要求使用

这是我的问题.我是契约设计的忠实粉丝,我正在使用这个概念,特别是在开发可供其他开发人员使用的库时.我刚刚发现了一种新的方法,即:Contract.Requires而不是Exception:所以不要:

public void SomeMethod(string name){
   if(name==null) throw new NullArgumentException("Null values not supported");
} 
Run Code Online (Sandbox Code Playgroud)

我现在有:

public void SomeMethod(string name){
   Contract.Requires(name != null);
}
Run Code Online (Sandbox Code Playgroud)

编辑:我在调试模式下在VS2010下工作.

问题:Contract.Requires什么都不做,即使name是什么时候null!

MSDN文档说:

为封闭方法或属性指定前置条件协定.

但是如果条件不满足则没有指定任何内容!

我还注意到还有其他 Contract.Requires重载会抛出异常,显示消息......但是接下来是什么Contract.Requires(Boolean)

EDIT下面的答案强调必须安装一个插件才能充分发挥ContractAPI的作用,那么那些希望他们的代码在不同平台上表现相同的Mono用户呢?

c# design-by-contract

41
推荐指数
2
解决办法
2万
查看次数

C#中的"按合同设计"

我想在我最新的C#应用​​程序中通过契约尝试一点设计,并希望语法类似于:

public string Foo()
{
    set {
        Assert.IsNotNull(value);
        Assert.IsTrue(value.Contains("bar"));
        _foo = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以从单元测试框架中获取这样的静态方法,但是我想知道这样的东西是否已经内置于该语言中,或者是否已经存在某种类型的框架.我可以编写自己的Assert函数,只是不想重新发明轮子.

c# design-by-contract

37
推荐指数
4
解决办法
2万
查看次数

与测试驱动开发相比,为什么按合同设计不那么受欢迎?

你可能会觉得这个问题是像这样的问题在计算器上问早.但我试图以不同的方式看待事物.

在TDD中,我们编写包含不同条件,标准,验证码的测试.如果一个班级通过了所有这些测试,我们很高兴.这是一种确保班级实际上做了它应该做的事情而不是别的事情的方法.

如果你按照Bertrand Meyers的书中逐字逐句地介绍面向对象的软件构建,那么这个类本身就有内部和外部的契约,所以它只能做它应该做的事情,而不是别的.不需要进行外部测试,因为确保合同的代码是类的一部分.

快速举例说明事情

TDD

  1. 创建测试以确保在所有情况下的值范围为(0-100)

  2. 创建一个包含传递测试的方法的类.

DBC

  1. 创建一个类,为该成员创建一个合同var范围从(0-100),设置合同违约合同,定义一个方法.

我个人喜欢DBC方法.


有没有理由说纯DBC不那么受欢迎?它是语言或工具还是敏捷,还是我喜欢让代码对自己负责?

如果你认为我思考不对,我会更愿意学习.

tdd unit-testing design-by-contract

37
推荐指数
9
解决办法
1万
查看次数