我目前正在阅读更多有关Design by Contract / code contract的信息。
据我所知,它是编写合同(不变量,前置和后置条件)以确保代码可以有序维护。它还将保证基于检查和平衡的明确机制可以防止错误
但这不会暗示软件性能吗?因为每个方法调用之间都有额外的检查。
我真的很感谢人们与我分享他们对契约设计的看法和经验。欢迎缺点或优点。
答案 0 :(得分:3)
通常,此类框架支持运行时检查和静态分析。后者在编译时(或之前)执行;它根本不会减慢您的代码速度。前者可能会影响绩效。
Microsoft Research Code Contracts项目就是一个很好的例子。您可以配置系统:
静态分析在编译时应用可能的合同执行的子集,甚至在deigner环境中应用;
为在调试模式下编译的所有代码启用运行时检查;以及
为在发布模式下编译的代码的公共API启用了运行时检查的子集(非公共代码没有运行时检查)。
这通常是性能和稳健性之间的良好折衷。
答案 1 :(得分:1)
应用按合同设计理念的一种方法纯粹是静态的。
考虑函数max_element()
的合同:
/*@
requires IsValidRange(a, n);
assigns \nothing;
behavior empty:
assumes n == 0; ensures \result == 0;
behavior not_empty:
assumes 0 < n;
ensures 0 <= \result < n;
ensures \forall integer i; 0 <= i < n ==> a[i] <= a[\result]; ensures \forall integer i; 0 <= i < \result ==> a[i] < a[\result];
complete behaviors;
disjoint behaviors;
*/
size_type max_element(const value_type* a, size_type n);
如果能够在编译时验证实现总是保证满足ensures
子句中的后置条件,前提是使用满足{中的前置条件的参数调用函数{1}}条款,没有必要为后置条件生成检查。
类似地,如果验证所有调用者,当满足他们自己的前置条件时,仅使用满足其前置条件的参数调用requires
,则在函数入口处不需要检查。
以上示例来自ACSL by Example。该库在ACSL中提供了许多函数契约。为合同提供了C语言的实现。这些实现已经静态正式验证,以保证后置条件适用于具有满足前置条件的参数的所有调用。因此,后期条件不需要运行时检查。编译器可以将注释视为注释(使用max_element()
语法)。
答案 2 :(得分:0)
按合同设计旨在确保正确实施 - 代码是针对调用者和被调用者之间的预期API正确编写的。理想情况下,您可以使用开发和alpha测试环境中的静态分析工具和运行时检查来验证合同是否得到维护。希望到那时你已经发现了关于API错误的任何实现错误。除非您尝试追踪错误,否则您可能不会将运行时检查用于测试和生产。