文章目录
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子句正常情况下不太可能发生,那就作为诊断信息来检查错误
3、表驱动法
这种方法感觉java上面不太实用,实践效果不佳,开阔眼界为主
4、一般控制问题
4.1 布尔表达式
-
在布尔表达式中应该用 true 和 false,而不要用 0 和 1 等数值
-
复杂的布尔表示式应该用括号来提高可读性
-
与其写一个具有多项的复杂布尔判断,不如将中间结果赋给变量,然后执行一个简单判断进行处理
-
将需要重复使用的复杂布尔表达式提取成一个布尔函数
-
在
if语句中判断条件优先使用肯定形式 -
用狄摩根定理简化否定的布尔判断
-
注意短路判断
-
理解
==和equals()的差异
4.2 空语句
尽量不要写空语句,如果有,最好用一组空的括号来强调该空语句
4.3 深度嵌套
4.3.1 重复判断一部分条件
必须容忍使用一个更复杂的判断
源代码:
改进后的代码:
4.3.2 使用break块简化嵌套if
源代码:
改进后的代码:
4.3.3 转换成if-then-else
源代码:
改进后的代码:
4.3.4 转换成case语句
可以用case语句重写一些判断,尤其是那些含有整数的判断
4.3.5 把深层嵌套的代码提取成单独的子程序
如果深层嵌套出现在循环里,通常可以通过把循环体提取成子程序来加以改善
4.3.6 使用工厂和策略模式
个人觉得,这种方式在可读性和维护性上最好。但是可能会多处很多类,要视具体情况而定。
4.3.7 重新设计深层嵌套的代码
5、程序复杂度
将复杂度降低到最低水平是编写高质量代码的关键。
复杂度在超过5说明子程序需要优化了,超过10,通常最好将子程序的某一部分拆分成另一个部分。虽然这不会降低整个程序的复杂度,但是会降低程序员的管理复杂度。
目前的静态代码走查工具(如fixbug)可自动判断子程序的复杂度。当然这些数据只能作为警告和参考,比如一天情况很多的case语句可能会包含超过10个复杂度。