0%
短小
- 函数的第一规则是要短小,每个函数依序把你带到下一个函数
- 函数的缩进层不该多于一层或两层
只做一件事
每个函数一个抽象层级
- 要确保函数只做一件事,函数中的语句都要在同一抽象层级上
- 自顶向下的阅读顺序,让每个函数后面都跟着位于下一抽象层级的函数
switch语句
- 无法完全避开
switch语句,但是能够确保每个switch都埋藏在较低的抽象层级,而且永不重复
- 对于
switch语句,如果只出现一次,用于创建多态对象,而且隐藏在某个继承关系中,在系统其他部分看不到,就还能容忍
使用描述性的名称
- 函数越短小,功能越集中,就越便于取个好名字
- 长而具有描述性的名称,要比短而令人费解的名称好;长而具有描述性的名称,要比描述性的长注释好
- 命名方式要保持一致,使用与模块名一脉相承的短语、名词和动词给函数命名
函数参数
- 最理想的是零参数函数,其次是单参数函数,再次是双参数函数,尽量避免三参数函数
- 参数与函数名处于相同的抽象层级
单参数的普遍形式
- 向函数传入单参数的理由
- 问关于该参数的问题,如
boolean isFileExists("MyFile")
- 操作该参数,将其转换为其他东西,再输出之,如
InputStream fileOpen("MyFile")
- 事件(event),有输入参数而无输出参数,程序将函数看做一个事件,使用该参数修改系统状态,如
void passwordAttemptFailedNtimes(int attempts)
flag参数
- 不要向函数传入布尔值,否则会使函数不止做一件事
- 对于试图向函数传入布尔值,应该将函数一分为二,如
renderForSuite()和renderForTest()
双参数函数
- 使用双参数函数会付出理解的代价,应该尽量利用一些机制将其转换成单参数函数,如将
writeField(outputStream, name)修改为outputStream.writeField(name),或者分离出类似FieldWriter的新类,在其构造器中采用outputStream并包含一个write方法
动词与关键字
- 对于单参数函数,函数和参数应当形成一个非常良好的动词/名词对形式
- 函数名称的关键字(keyword)形式,把名称编码成函数名,如
assertEqual改成assertExpertedEqualsActual(expected, actual),可以大大减轻记忆参数顺序的负担
分隔指令和询问
- 函数要么做什么事,要么回答什么事,两件事都干会导致混乱
异常处理
- 用异常代替错误码,当返回错误码时,就是在要求调用者立刻处理错误
- 用异常代替返回错误码,错误处理代码就能在主路径代码中分离出来
- 最好把 try 和 catch 代码块的主体部分抽离出来,另外形成函数
- 处理错误的函数不该做其他事,如果 try 在某个函数中存在,它就该是这个函数的第一个单词,而且 catch/finally 代码块后面不该有其他内容
如何写出这样的函数