1、直线型代码

有明确顺序的语句

  • 对于一些有前后依赖关系的操作和运算,在写代码的时候一定要注意流程。方法、变量名要能体现出这种相互的依赖关系
  • 设法组织代码,使得依赖关系变得很明显
  • 子程序的命名要能凸显依赖关系
  • 利用子程序参数明确显示依赖关系
  • 用注释对不清楚的依赖关系进行说明(最好是用代码,除非实在是没有办法)
  • 用断言或者错误处理来检查依赖关系

顺序无关的语句:

  • 使代码易于自上而下的阅读(跳来跳去的代码很糟糕)
  • 把相关的语句组织在一起。相对独立的语句组放进各自的子程序。这一点很重要,便于重构

2、条件语句

2.1 if-else 语句

  • 首先写代码的正常路径,再处理不常见的情况
  • 确保对于等量的分支是正确的(不要用“>”代替“>=”)
  • 把正常情况的处理放在if后面而不是放在else的后面
  • 让if子句后面跟随一个有意义的子句(有的人直接在if子句后面加一个空子句,这样的代码很傻)
  • 考虑else子句(大部分情况下,if语句后面应该配一个else子句,哪怕写一个空的else子句,也表明这种情况你考虑到了)
  • 测试代码的时候,要测试else子句的正确性

2.2 if-else if 语句

  • 利用布尔函数简化复杂的检测
    • 对于非常复杂的条件检测,可以考虑将这些条件重构成一个布尔函数,这样的话代码看起来会非常的简单
  • 把最常见的情况放在最前面
    • 这样写有两大好处:一是提高代码执行效率;二是调试时阅读代码很顺畅
  • 确保所有的情况都考虑到了
    • 可以在最后的else子句中用断言或者出错消息来捕捉不曾考虑到的情况
  • 尽量可以case语句来代替具有很多情况的长的if-else语句

2.3 case语句

  • 为case子句选择最有效的排列顺序
    • 把正常情况放在前面
    • 把最经常执行的情况放在前面。如果都相同,可以按字母顺序排列
  • 简化每种情况对应的操作(复杂的操作封装到子程序中,使代码短小精悍)
  • 不要为了使用case子句而刻意创造一个变量
  • 把default子句只用于检查真正的默认情况
  • 如果default子句正常情况下不太可能发生,那就作为诊断信息来检查错误

读书笔记:《代码大全第2版》 08.语句

3、表驱动法

这种方法感觉java上面不太实用,实践效果不佳,开阔眼界为主

4、一般控制问题

4.1 布尔表达式

  • 在布尔表达式中应该用 true 和 false,而不要用 0 和 1 等数值

  • 复杂的布尔表示式应该用括号来提高可读性

  • 与其写一个具有多项的复杂布尔判断,不如将中间结果赋给变量,然后执行一个简单判断进行处理

  • 将需要重复使用的复杂布尔表达式提取成一个布尔函数

  • if 语句中判断条件优先使用肯定形式

  • 用狄摩根定理简化否定的布尔判断

  • 注意短路判断

  • 理解==equals()的差异

4.2 空语句

尽量不要写空语句,如果有,最好用一组空的括号来强调该空语句

4.3 深度嵌套

4.3.1 重复判断一部分条件

必须容忍使用一个更复杂的判断

源代码:
读书笔记:《代码大全第2版》 08.语句

改进后的代码:
读书笔记:《代码大全第2版》 08.语句

4.3.2 使用break块简化嵌套if

源代码:
读书笔记:《代码大全第2版》 08.语句

改进后的代码:
读书笔记:《代码大全第2版》 08.语句

4.3.3 转换成if-then-else

源代码:
读书笔记:《代码大全第2版》 08.语句

改进后的代码:
读书笔记:《代码大全第2版》 08.语句

4.3.4 转换成case语句

可以用case语句重写一些判断,尤其是那些含有整数的判断

4.3.5 把深层嵌套的代码提取成单独的子程序

如果深层嵌套出现在循环里,通常可以通过把循环体提取成子程序来加以改善

4.3.6 使用工厂和策略模式

个人觉得,这种方式在可读性和维护性上最好。但是可能会多处很多类,要视具体情况而定。

4.3.7 重新设计深层嵌套的代码

5、程序复杂度

将复杂度降低到最低水平是编写高质量代码的关键。

读书笔记:《代码大全第2版》 08.语句
复杂度在超过5说明子程序需要优化了,超过10,通常最好将子程序的某一部分拆分成另一个部分。虽然这不会降低整个程序的复杂度,但是会降低程序员的管理复杂度。

目前的静态代码走查工具(如fixbug)可自动判断子程序的复杂度。当然这些数据只能作为警告和参考,比如一天情况很多的case语句可能会包含超过10个复杂度。

相关文章: