我正在阅读B. Stroustrup的关于C++ 17的思考合同,并协助一个小小的演讲,谈论他们,但我不确定我是否真的理解它们.
所以我有一些问题,如果有可能用一些例子来说明它们:
合同是否是经典的更好替代品,assert()它们应该一起使用吗?对于软件开发人员来说,简单的合同是什么?
合同会对我们处理异常的方式产生影响吗?如果是,我们应该如何使用例外和合同?
使用合同是否意味着执行时的开销?我们是否允许在发布代码上停用它们?
从提案N4415编辑:
可以编写Vector类的索引操作符的前置条件合约:
T& operator[](size_t i) [[expects: i < size()]];类似地,ArrayView类的构造函数上的条件后约定可表示为:
ArrayView(const vector<T>& v) [[ensures: data() == v.data()]];
我正在努力改进我们小组的开发过程,我正在考虑如何最好地实现与测试驱动开发合同设计.看来这两种技术有很多重叠,我想知道是否有人对以下(相关)问题有所了解:
这些问题的主要问题是这个更普遍的问题:如果我们已经正确地进行了TDD,如果我们也使用DbC,我们是否会从开销中获得显着的好处?
一些细节,虽然我认为这个问题主要与语言无关:
在探讨问题时,我最近assert在Java中发现了关键字.起初,我很兴奋.我还不知道有用的东西!一种更有效的方法来检查输入参数的有效性!耶老师!
但后来我仔细研究了一下,我的热情并没有像一个简单的事实那样"完全被扼杀"而"温和":你可以关闭断言.*
这听起来像是一场噩梦.如果我断言我不希望代码继续输入,如果输入listOfStuff是null,为什么我想要忽略该断言?听起来好像我正在调试一段生产代码,并怀疑listOfStuff可能错误地传递了一个,null但没有看到任何触发该断言的日志文件证据,我不相信listOfStuff实际上已经发送了一个有效值; 我还必须考虑断言可能完全被关闭的可能性.
这假设我是调试代码的人.不熟悉断言的人可能会看到并且(非常合理地)假设如果断言消息没有出现在日志中,则不会出现listOfStuff问题.如果你的第一次遭遇assert是在野外,你甚至会发现它可以完全关闭吗?毕竟,它不像是一个允许你禁用try/catch块的命令行选项.
所有这些都让我想到了我的问题(这是一个问题,而不是一个咆哮的借口!我保证!):
我错过了什么?
是否有一些细微差别使得Java的实现assert比我给它的功劳更有用?在某些情况下,从命令行启用/禁用它的能力实际上是非常有价值的吗?当我设想在生产代码中使用它代替语句时,我是否误解了它if (listOfStuff == null) barf();?
我觉得这里有一些重要的东西,我没有得到.
*好的,从技术上讲,它们实际上是默认关闭的; 你必须不遗余力地打开它们.但是,你仍然可以完全击败他们.
这assert首先是一个调试工具的概念需要很长的路要走,才能使它对我有意义.
我仍然认为应该在生产环境中禁用输入检查非平凡私有方法的概念,因为开发人员认为不可能输入错误.根据我的经验,成熟的生产代码是一种疯狂的,庞大的东西,多年来由具有不同技能的人们开发,其目标是快速变化的不同程度的理智要求.即使糟糕的输入确实是不可能的,从现在起六个月后的一段邋maintenance维护编码也可以改变这一点. 提供的链接gustafc(谢谢!)包括这个例子:
assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval;
禁用如此简单的生产检查让我感到愚蠢乐观.然而,这是编码哲学的差异,而不是破碎的特征.
另外,我绝对可以看到这样的价值:
assert reallyExpensiveSanityCheck(someObject) : someObject;
感谢所有花时间帮助我理解这个功能的人; 这是非常赞赏.
您是否专业使用Design by Contract?这是您从项目一开始就要做的事情,还是可以改变方向并开始将其融入您的软件开发生命周期?您发现什么是设计方法的优缺点?
我在研究生课程中遇到了" 按合同设计"的方法.在学术环境中,它似乎是一种非常有用的技术.但我目前不专业地使用Design by Contract,而且我不知道任何其他开发人员正在使用它.听听SO群众的实际使用情况会很好.
Java中的方法签名:
public List<String> getFilesIn(List<File> directories)
Run Code Online (Sandbox Code Playgroud)
类似的红宝石
def get_files_in(directories)
Run Code Online (Sandbox Code Playgroud)
对于Java,类型系统为我提供了有关该方法所期望和提供的信息.在Ruby的情况下,我不知道我应该传递什么,或者我期望收到什么.
在Java中,该对象必须正式实现该接口.在Ruby中,传入的对象必须响应此处定义的方法中调用的任何方法.
这似乎很成问题:
不打算讨论静态打字与鸭子打字,而是希望了解如何维护一个几乎没有能力按合同设计的生产系统.
没有人真正通过这种方法所需的文档来解决方法内部实现的暴露问题.由于没有接口,如果我不期望某个特定类型,我不必逐条列出我可能调用的每个方法,以便调用者知道可以传入什么内容吗?或者这只是一个没有真正出现的边缘情况?
是否有任何库有助于在C++应用程序中通过契约原则实现设计?
特别是,我正在寻找一个可以使用原理的库,就像这样.
这些天我习惯于检查每个函数的每个前提条件,因为我从大学的一个OS编程课程中习惯了这个习惯.
另一方面,在软件工程课程中,我们被告知只应检查一个共同的前提条件,例如,如果一个函数委托给另一个函数,第一个函数应检查它们,但在第二个函数中再次检查它们是多余的.
我确实看到了冗余点,但我确实觉得总是检查它们更安全,而且你不必跟踪它们之前检查的位置.
这里的最佳做法是什么?
我最近阅读了一篇文章,将"按合同设计"与"测试驱动开发"进行了比较.似乎有很多重叠,一些冗余,以及DbC和TDD之间的一点协同作用.例如,有一些系统可以根据合同自动生成测试.
DbC以什么方式与现代类型系统重叠(例如在haskell中,或者是那些依赖类型的语言之一)并且有两点使用两者都比哪一方更好?
haskell types type-systems design-by-contract code-contracts
Swift是否提供本地设计合同支持?我知道它可以在运行时通过断言完成,但它可以在编译期间完成吗?或者,有没有外部插件/库这样做?
编辑
通过说"在编译期间按合同设计",我并不是说库是C#所有功能强大的静态分析器.如果它类似于iContract为Java提供的东西,那对我来说已经足够了.我们来看一个例子:
使用iContract在Java中进行平方根评估的DBC代码可以写成:
/**
* @pre f >= 0.0
* @post Math.abs((return * return) - f) < 0.001
*/
public float sqrt(float f) { ... }
Run Code Online (Sandbox Code Playgroud)
现在,这使我的合同成为我的API规范的一部分而不是其实现的一部分,我认为这是一种更清洁的方式.呼叫者将知道他的职责是什么,被呼叫者正在设定其期望,所有这些都是更清晰的方式.我们在Swift中有这样的东西吗?
这个问题涉及编码约定,最佳实践和生产风格,关键任务Common-Lisp代码.我仔细阅读了Google的Common-Lisp样式指南(http://tinyurl.com/qfvnqcx),但没有找到任何明确解决我特定问题的内容,我通过示例表达,与C/C++,Java等形成对比.我还快速浏览了Github上的Common-Lisp代码库,我没有看到很多参数检查和中间值检查,我在C/C++,Java等中看到过.
在我的商店里,我们非常习惯于检查论点和其他价值观,并在论证不符合合同/先决条件等时提前退出.例如,考虑以下(设计,不完美,典型,但请 - 不要' t-waste-time-criticizing,micro-example,它预示着CL的例子):
ErrorCode o_symb_to_g_symb (char * symb, uint len)
{ if (len < 2) { return ERROR_LENGTH; }
if (symb[0] != 'O' || symb[1] != '!') { return ERROR_SYNTAX; }
char * result = (char *) malloc (len + 1);
if (NULL == result) { return ERROR_MALLOC; }
if (result != strncpy (result, symb, len + 1))
{ return ERROR_STRNCPY; }
result[0] = 'G';
return result; }
Run Code Online (Sandbox Code Playgroud)
这与Doug Hoyte的第67页"Let Over Lambda"的代码大致相同,只是在整个过程中尽可能地检查(http://letoverlambda.com/).
(defun o!-symbol-to-g!-symbol …Run Code Online (Sandbox Code Playgroud)