函数《代码整洁之道》
函数
1. 短小
- 函数在保证完整性的情况下,越短越好
- 每个函数都应该一目了然
- 长度为 20 行最佳
2. 只做一件事
- 每个函数应该保证只做一件事
- 要判断函数是否只做了一件事,可以看是否还能再拆出一个函数
- 一件事是指在同一抽象层次上完成的动作
3. 每个函数一个抽象层级
- 抽象层级类似于动作的抽象程度,例如
getData
和data.push(item)
就属于不同的层次,getData
属于高层级别,而data.push(item)
已经是属于比较低级别,因为它深入到了数据操作的底层 - 函数调用一般是高级别调用低级别,这样一层一层深入,是一种自顶向下的规则
- 如果出现同级别的函数调用,那可能是还有隐含的低层次还未抽象出来
4. switch 语句
- switch 天生是做多件事的,因此无法满足只做一件事的要求
- switch 难以写出较为短小的语句
- 可以利用抽象工厂的方式,将 switch 抽象到父类中,利用多态来隐藏 switch 语句
5. 使用描述性的名称
- 好的函数名称可以清晰地说明函数的作用
- 不要害怕长名称,长而具有描述性的名称,比短而令人费解的名称要好
- 长而具有描述性的名称,也比描述性的长注释要好
- 命名应该保持一致,使用与模块名一致的短语、名词或动词
6. 函数参数
- 函数参数不要多,0个最好,1个比较好,2个还行,3个以上基本不考虑
- 不要使用输出参数(不是输出值),而应该使用返回值,输出参数已经是以前旧代码的写法了。例如有返回值
StringBuffer transform(StringBuffer in)
会比输出参数void transform(StringBuffer in)
更好一些 - 不建议使用标识参数(即 bool 参数),因为违反了一个函数只做一件事的原则,解决方法是拆分成两个函数
- 3个及以上的参数,应该考虑将其封装成类,从而减少参数数量
7. 分隔指令与查询
- 函数要么做修改对象的状态,要么返回对象的有关信息,二者不可兼得。例如
boolean set(String attr, String value)
就属于既修改来对象的状态,又返回了有关信息 - 正确的做法是将指令与查询分开,即利用
set
和get
来实现
8. 使用异常替代返回错误码
- 返回错误码轻微违反了指令与查询分隔的规则
- 返回错误码容易导致多层次的嵌套,因为主流程代码需要根据不同的返回错误码进行不同的错误处理
- 使用异常替代返回错误码,可以将错误处理代码和主流程代码分离开来
- 将 try/catch 块抽取出来,单独作为一个函数,因为它容易导致函数结构混乱
- 使用异常替代错误码,可以使用新异常类从基本异常类中派生出来
9. 消除重复代码
- 重复代码是影响代码整洁性的罪魁祸首之一
- 要尽量清除掉代码中的重复代码
10. 反复调整
- 不要想着一开始就把函数写好,都是反复重构的
- 将函数的功能实现后,再根据基本原则对代码,对代码进行修改调整
- 最好给函数加上测试用例,调整完成后要保证函数都能通过测试