有没有一个库可以帮助在C++应用程序中实现契约设计原则?
特别是,我正在寻找一种能够方便地使用该原则的库,类似于这个。
有没有一个库可以帮助在C++应用程序中实现契约设计原则?
特别是,我正在寻找一种能够方便地使用该原则的库,类似于这个。
我遵循以下文章的教导:
最终,我采用了Samek的方法。只需创建REQUIRE、ENSURE、CHECK和INVARIANT宏(基于现有的assert
宏)就非常有用。当然,这并不像本地语言支持那样好,但无论如何,它都允许您从该技术中获得最大的实际价值。
至于库的选择,我认为不必使用一个库,因为断言机制的一个重要价值在于其简单性。
关于调试和生产代码之间的区别,请参见When should assertions stay in production code?。
一些设计模式,例如非虚拟接口,使得为给定方法编写前/后置条件变得更加自然:
#include <cassert>
class Car {
virtual bool engine_running_impl() = 0;
virtual void stop_impl() = 0;
virtual void start_impl() = 0;
public:
bool engine_running() {
return engine_running_impl();
}
void stop() {
assert(engine_running());
stop_impl();
assert(! engine_running());
}
void start()
{
assert(! engine_running());
start_impl();
assert(engine_running());
}
}
class CarImpl : public Car {
bool engine_running_impl() {
/* ... */
}
void stop_impl() {
/* ... */
}
void start_impl() {
/* ... */
}
}
最简单的方法?
在函数开头添加Assert语句以测试您的要求。 在函数结尾添加Assert语句以测试您的结果。
是的,它很粗糙,不是一个大系统,但它的简单性使其具有通用性和可移植性。
#include <dbc.hpp>
class InvarTest {
public:
int a = 0;
int b = 9;
INVARIANT_BEGIN
Inv(RN(0,a,32));
Inv(RN(0,b,10));
INVARIANT_END
inline void changeMethod() {
Invariant(); // this runs the invariant block at the beginning and end of the method
a = 33;
}
};
int testFunc(int a, double d, int* ip) {
// RN = a in range 0 to 10, NaN = not a number, NN = not null
Rqr(RN(0,a,10), NaN(d), RN(0.0,d,1.0), NN(ip));
// Enr return the passed value
return Esr(RN(0.0,a+d,20.3));
}
void testFunc2(std::vector<int>& a, std::shared_ptr<int> sp) {
Rqr( SB(a,0), TE(a.size() % 12 == 0), NN(sp));
}
使用标准的ASSERT/Q_ASSERT,但要注意“无效”的断言,特别是如果您在外部测试中保留这样的诊断(使用没有NDEBUG的构建)。
关于在C++项目中实现DBC(使用断言)和“始终启用调试”策略的小故事。
我们一直在使用相当标准的工具(ASSERT()/Q_ASSERT())作为DBC实现,直到我们在集成测试中遇到了以下情况:我们的最新构建总是在启动后立即失败。发布这样的版本并不是很专业(经过了一周的内部QA努力)。
问题是如何引入的?
结果,可怜的开发人员被指责犯了这个错误(显然,如果没有这个ASSERT,就不会崩溃),我们不得不发布热修复程序来允许继续进行集成测试。
首先,我需要在集成测试中启用断言以跟踪失败的条件(断言越多越好)。另一方面,我不希望开发人员担心某些“额外”的ASSERT会导致整个软件堆栈崩溃。