问题标签 [design-by-contract]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
design-by-contract - 合同设计对您有用吗?
您是否专业地使用按合同设计?这是您从项目一开始就必须做的事情,还是您可以换档并开始将其纳入您的软件开发生命周期?您发现设计方法的优点/缺点是什么?
我在研究生院课程中遇到了合同设计方法。在学术环境中,这似乎是一种非常有用的技术。但是我目前没有专业地使用按合同设计,而且我不知道有任何其他开发人员在使用它。很高兴从 SO 人群中听到它的实际用法。
language-agnostic - api 文档和“价值限制”:它们匹配吗?
您是否经常在 API 文档(例如“公共函数的 javadoc”)中看到“值限制”的描述以及经典文档?
注意:我不是在谈论代码中的注释
通过“价值限制”,我的意思是:
- 参数是否可以支持空值(或空字符串,或...)?
- '返回值'可以为空还是保证永远不会为空(或者可以是“空”,或者......)?
样本:
我经常看到的(无法访问源代码)是:
我希望看到的是:
我的观点是:
当我使用带有 getReaderNames() 函数的库时,我通常甚至不需要阅读 API 文档来猜测它的作用。但我需要确定如何使用它。
当我想使用这个函数时,我唯一关心的是:在参数和返回值方面我应该期待什么?这就是我安全设置参数和安全测试返回值所需要知道的全部内容,但我几乎从未在 API 文档中看到此类信息......
编辑:
这可能会影响已检查或未检查异常的使用或不使用。
你怎么看 ?值限制和 API,它们是否属于一起?
exception - 使用断言或异常按合同设计?
当通过契约编程时,函数或方法首先检查其先决条件是否得到满足,然后再开始履行其职责,对吧?进行这些检查的两种最突出的方法是 byassert
和 by exception
。
- 断言仅在调试模式下失败。为了确保(单元)测试所有单独的合同先决条件以查看它们是否真的失败是至关重要的。
- 异常在调试和发布模式下失败。这样做的好处是测试的调试行为与发布行为相同,但会导致运行时性能损失。
你觉得哪一个更可取?
在此处查看相关问题
.net - 在 .NET 中断言参数和值的前置条件和后置条件的最佳方法?
我最近一直在考虑按合同设计,我想知道人们认为在 .NET 中断言值的前置条件和后置条件的最佳方式是什么?即验证方法的参数值。
有些人推荐 Debug.Assert,而其他人则谈论使用 if 语句加上抛出异常。各自的优缺点是什么?
您推荐了哪些可用的框架?
java - 红宝石和鸭子打字:合同设计不可能?
Java中的方法签名:
红宝石中的类似
在 Java 的情况下,类型系统为我提供了有关该方法期望和交付什么的信息。就 Ruby 而言,我不知道我应该传递什么,或者我期望收到什么。
在 Java 中,对象必须正式实现接口。在 Ruby 中,传入的对象必须响应此处定义的方法中调用的任何方法。
这似乎很有问题:
- 即使有 100% 准确的最新文档,Ruby 代码也必须从本质上公开其实现,从而破坏封装。撇开“OO 纯度”不谈,这似乎是一场维护噩梦。
- Ruby 代码让我不知道返回了什么;我必须进行实验,或阅读代码以找出返回的对象会响应哪些方法。
不是要讨论静态类型与鸭子类型,而是要了解如何维护一个几乎没有合同设计能力的生产系统。
更新
没有人真正通过这种方法所需的文档来解决方法内部实现的暴露问题。由于没有接口,如果我不期待特定类型,我是否不必逐项列出我可能调用的每个方法,以便调用者知道可以传入什么?或者这只是一个没有真正出现的边缘案例?
c# - C# 中的“按合同设计”
我想在我最新的 C# 应用程序中尝试一些按合同约定的设计,并希望语法类似于:
我知道我可以从单元测试框架中获得这样的静态方法,但我想知道这样的东西是否已经内置到语言中,或者是否已经存在某种框架。我可以编写自己的 Assert 函数,只是不想重新发明轮子。
c# - 多少空检查就足够了?
当不需要检查空值时,有哪些指导方针?
我最近一直在处理的许多继承代码都带有令人作呕的空检查。对琐碎函数进行空检查,对声明非空返回的 API 调用进行空检查等。在某些情况下,空检查是合理的,但在许多地方,空值并不是一个合理的期望。
我听过很多论点,从“你不能相信其他代码”到“总是防御性地编程”再到“在语言保证给我一个非空值之前,我总是会检查”。在某种程度上,我当然同意其中的许多原则,但我发现过多的空值检查会导致其他通常违反这些原则的问题。顽强的空值检查真的值得吗?
我经常观察到带有过多空值检查的代码实际上质量较差,而不是质量较高。许多代码似乎过于关注空值检查,以至于开发人员忽略了其他重要品质,例如可读性、正确性或异常处理。特别是,我看到很多代码忽略了 std::bad_alloc 异常,但对new
.
在 C++ 中,由于取消引用空指针的不可预测的行为,我在某种程度上理解了这一点;在 Java、C#、Python 等中,null 取消引用的处理更加优雅。我是否刚刚看到了警惕的 null 检查的不良示例,或者这真的有什么问题吗?
这个问题旨在与语言无关,尽管我主要对 C++、Java 和 C# 感兴趣。
我见过的一些似乎过度的空值检查示例包括以下内容:
这个示例似乎考虑了非标准编译器,因为 C++ 规范说失败的新编译器会引发异常。除非您明确支持不兼容的编译器,否则这有意义吗?这在 Java 或 C#(甚至 C++/CLR)等托管语言中是否有意义?
另一个例子是在处理内部代码时。特别是,如果是一个可以定义自己的开发实践的小团队,这似乎是不必要的。在某些项目或遗留代码中,信任文档可能不合理……但是对于您或您的团队控制的新代码,这真的有必要吗?
如果您可以看到并可以更新(或可以对负责的开发人员大喊大叫)的方法有合同,是否仍然需要检查空值?
在开发私有或其他内部函数时,当合约仅调用非空值时,是否真的需要显式处理空值?为什么空检查比断言更可取?
(显然,在您的公共 API 上,空值检查至关重要,因为向您的用户大喊不正确使用 API 被认为是不礼貌的)
相比:
language-agnostic - 合同设计和测试驱动开发
我正在努力改进我们团队的开发过程,并且我正在考虑如何最好地通过测试驱动开发来实现按合同设计。似乎这两种技术有很多重叠,我想知道是否有人对以下(相关)问题有所了解:
- 除非您使用某种代码生成器来生成基于合约的单元测试,否则拥有 TDD 和 DbC 是否违反 DRY 原则?否则,您必须在两个地方(测试和合同本身)维护合同,还是我遗漏了什么?
- TDD 在多大程度上使 DbC 变得多余?如果我写的测试足够好,它们不等于写合同吗?如果我在运行时以及通过测试执行合同,我是否只会获得额外的好处?
- 仅使用 TDD 而不是 TDD 和 DbC 是否更容易/更灵活?
这些问题的重点是这个更普遍的问题:如果我们已经在正确地进行 TDD,如果我们还使用 DbC,我们是否会从开销中获得显着的收益?
一些细节,虽然我认为这个问题很大程度上与语言无关:
- 我们的团队非常小,<10 个程序员。
- 我们主要使用 Perl。
java - 如何显示方法是否可能返回 null
在发布了这个问题并阅读了这个问题之后,我意识到知道一个方法是否应该返回 null 或者这是否被认为是错误条件并且应该抛出异常是非常重要的。还有一个很好的讨论何时返回 'null' 或抛出异常。
我正在编写一个方法,并且我已经知道是否要返回 null 或抛出异常,表达我的决定的最佳方式是什么,换句话说,记录我的合同?
我能想到的一些方法:
- 把它写在规格/文档中(有人会读吗?)
- 使其成为方法名称的一部分(正如我在这里建议的那样)
- 假设每个抛出异常的方法都不会返回 null,而每个“不”抛出的方法都可能返回 null。
我主要是在谈论 java,但它也可能适用于其他语言:为什么有一种正式的方式来表达是否会抛出异常(throws
关键字),但没有正式的方式来表达是否可能返回 null?
为什么没有这样的东西:
总结与结论
合同的表达方式有很多种:
- 如果您的 IDE 支持它(如 IntelliJ),最好使用注释,
@NotNull
因为它对程序员可见并且可用于自动编译时检查。Eclipse有一个插件可以添加对这些的支持,但它对我不起作用。 - 如果这些不是一个选项,请使用类似
Option<T>
or的自定义类型NotNull<T>
,这可以增加清晰度并至少进行运行时检查。 - 无论如何,在 JavaDoc 中记录合同永远不会有害,有时甚至会有所帮助。
- 使用方法名称来记录返回值的可空性不是由我以外的任何人提出的,尽管它可能非常冗长且并不总是有用,但我仍然相信有时它也有其优点。
design-by-contract - 合同设计中的编译时间检查?
我读到编译器可以在编译时强制执行 dbc .. 它是如何做到的?