防御性编码实践

时间:2008-11-06 06:18:55

标签: coding-style

自从我第一次写作

if ($a = 5) {
   #  do something with $a, e.g.
   print "$a";
}

并经历了正常的令人费解的会议

  • 为什么结果总是如此
  • 为什么$ a总是5

直到我意识到,我已经分配了5到$ a,而不是进行比较。

所以我决定将上述那种情况写成

 if (5 == $a)
换句话说,

始终将常量值放在比较运算符的左侧,如果您忘记添加第二个“=”符号,则会导致编译错误。

我倾向于称之为防御性编码并且倾向于认为它是表现为防御性编程,而不是算法规模,而是关键词。

您开发了哪些防御性编码实践?


一周后:

对所有回答或可能在将来添加其他答案的人表示“谢谢”。

不幸的是(或者说幸运的是!)没有一个正确的答案。为此,我的问题是广泛的,要求更多的意见或经验的学习,而不是事实。

15 个答案:

答案 0 :(得分:16)

始终使用大括号:

if(boolean)
    oneliner();
nextLineOfCode();

与:

不同
if(boolean)
{
    oneliner();
}
nextLineOfCode();

如果oneliner()是#defined函数,并且未定义,则下一行代码突然变为if()。同样的事情适用于for循环等。使用大括号,下一段代码永远不会无意中成为if / for etc的条件。

答案 1 :(得分:14)

我采用的前三种防御性编码方法是

  1. 单元测试
  2. 单元测试
  3. 单元测试
  4. 没有更好的防御代码质量,而不是一个好的单元测试来支持你。

答案 2 :(得分:13)

这是一个简单而明显的一个,但我永远不会在我的代码中重复两次相同的字符串常量,因为我知道如果我这样做,我将拼写其中一个错误:)使用常量,人!

答案 3 :(得分:8)

总是在if / for / while之后加上花括号......即使之后只有一个单句。 BTW D. Crockford认为它也更好:Required blocks

答案 4 :(得分:8)

将字符串与常量进行比较时,请写

if ("blah".equals(value)){}

而不是

if (value.equals("blah")){}

防止NullPointerException。但这是我唯一一次使用建议的编码风格(原因是“if(a = 1)...”在Java中是不可能的)。

答案 5 :(得分:7)

我在Javascript世界中总是试图记住的一件事就是始终在与返回关键字相同的行上启动函数的返回值。

function one(){
    return {
        result:"result"
    };
}

function two(){
    return 
    {
        result:"result"
    };
}

这两个函数不会返回相同的值。第一个函数将返回一个Object,其属性结果设置为“result”。第二个函数将返回undefined。这是一个非常简单的错误,它的发生是因为Javascript过于热心的半结肠插入策略。在Javascript中,半冒号是半可选的,因此Javascript引擎会添加它认为应该是的半库存。因为return实际上是一个有效的语句,所以在return语句之后会插入一个分号,并且该函数的其余部分将基本上被忽略。

答案 6 :(得分:6)

来自我的博客:

  1. 积极思考并尽早回归并避免深度筑巢。而不是

    if(value!= null){     ......做有价值的事...... } 返回

    if(value == null){     返回 } ......做有价值的事......

  2. 避免使用“字符串常量”(即多个位置的引号中的相同文本)。始终定义一个实常数(使用名称和可选注释意味着什么)并使用它。

答案 7 :(得分:5)

  • 始终初始化变量
  • 尽可能使用const(不使用mutable
  • 避免动态分配内存或其他资源
  • 始终使用花括号
  • 编码实施前的任何类的代码用例和测试
  • 尽可能多地打开有用的警告(至少-Wall -Wextra -ansi -pedantic -Werror
  • 使用解决问题的最简单工具(在我目前的环境中,即bash - > grep - > awk - > Python - > C ++)。

答案 8 :(得分:5)

就个人而言,我不喜欢这种防御方式,它使代码难以阅读。

VC编译器警告级别4将发现此(可能)错误 “警告C4706:条件表达式中的赋值”

您可以在任何级别启用此特定编译器警告:

#pragma warning(3,4706)

答案 9 :(得分:4)

我停止使用你可以做的语言

if a = 5: print a

这为我节省了大量头痛=)。

更严肃的说明......我现在总是在写完iffor循环后立即编写花括号,然后填写它们。这样可以确保我的括号始终对齐。

答案 10 :(得分:3)

返回可变对象的副本,即数组的副本,而不是可变对象本身。

答案 11 :(得分:2)

避免不必要的测试。 示例

  1. if(bool == true)
  2. 指针检查是否(指针)
  3. 编辑: 如果(指针)不可读,那么现在我更喜欢if(NULL!= pointer)

答案 12 :(得分:2)

夫妻俩:

  • 是的,1行块。使用大括号......哎呀,最好的IDE会为你制作它们。
  • 在您编写代码后对其进行注释,或者如果提前完成,请重新阅读您的注释。确保您的代码仍然符合评论所说的内容。
  • 单元测试是重新阅读代码的重要后果。
  • 始终记录异常...或者,不要在不这样说的情况下捕获异常,至少在调试中。

答案 13 :(得分:2)

嵌入式C编程的几点建议来自embedded.com的文章Rules for Defensive C Programming

答案 14 :(得分:1)

已安装的Resharper;) 然后,如果我做错了,我不需要写“5 == a”来警告:)