jke*_*eys 6 c++ defensive-programming dry
免责声明:我是一名正在学习编程的非专业人士.从未参与过项目,也没有写过超过500行的文章.
我的问题是:防御性编程是否违反了"不要重复自己"的原则?假设我对防御性编程的定义是正确的(让调用函数验证输入而不是相反),这对你的代码不会有害吗?
例如,这很糟糕:
int foo(int bar)
{
if (bar != /*condition*/)
{
//code, assert, return, etc.
}
}
int main()
{
int input = 10;
foo(input); //doesn't the extra logic
foo(input); //and potentially extra calls
foo(input); //work against you?
}
Run Code Online (Sandbox Code Playgroud)
与此相比:
int main()
{
if (input == /*condition*/)
{
foo(input);
foo(input);
foo(input);
}
}
Run Code Online (Sandbox Code Playgroud)
再说一次,作为一个外行人,我不知道有多少简单的逻辑陈述对你来说就性能而言是多少,但对于程序或灵魂而言,防御性编程肯定不好.
违反DRY原则看起来像这样:
int foo(int bar)
{
if (bar != /*condition*/)
{
//code, assert, return, etc.
}
}
int main()
{
int input = 10;
if (input == /*condition*/)
{
foo(input);
foo(input);
foo(input);
}
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,问题是我们在程序中有两次相同的检查,所以如果条件改变,我们必须在两个地方修改它,很可能我们忘记了其中一个,导致奇怪的行为.DRY并不意味着"不要两次执行相同的代码",而是"不要两次写相同的代码"
这一切都归结为界面提供的合同.有两种不同的情况:输入和输出.
输入 - 我基本上是指函数的参数 - 应作为一般规则由实现检查.
输出 - 返回结果 - 应该基本上由调用者信任,至少在我看来.
所有这一切都受到这个问题的影响:如果一方违约,会发生什么?例如,假设您有一个界面:
class A {
public:
const char *get_stuff();
}
Run Code Online (Sandbox Code Playgroud)
并且该合约指定永远不会返回空字符串(最坏的情况下它将是一个空字符串)然后执行此操作是安全的:
A a = ...
char buf[1000];
strcpy(buf, a.get_stuff());
Run Code Online (Sandbox Code Playgroud)
为什么?好吧,如果你错了,并且被调用者返回null,那么程序将崩溃.那真的很好.如果某个对象违反了合同,那么一般来说结果应该是灾难性的.
你过度防守所面临的风险是你写了很多不必要的代码(可能会引入更多的错误),或者你可能通过吞下一个你真的不应该的异常来掩盖一个严重的问题.
当然情况可以改变这一点.