0%

Functions

短小

  • 函数的第一规则是要短小,每个函数依序把你带到下一个函数
  • 函数的缩进层不该多于一层或两层

只做一件事

  • 函数应该只做一件事

每个函数一个抽象层级

  • 要确保函数只做一件事,函数中的语句都要在同一抽象层级上
  • 自顶向下的阅读顺序,让每个函数后面都跟着位于下一抽象层级的函数

switch语句

  • 无法完全避开switch语句,但是能够确保每个switch都埋藏在较低的抽象层级,而且永不重复
  • 对于switch语句,如果只出现一次,用于创建多态对象,而且隐藏在某个继承关系中,在系统其他部分看不到,就还能容忍

使用描述性的名称

  • 函数越短小,功能越集中,就越便于取个好名字
  • 长而具有描述性的名称,要比短而令人费解的名称好;长而具有描述性的名称,要比描述性的长注释好
  • 命名方式要保持一致,使用与模块名一脉相承的短语、名词和动词给函数命名

函数参数

  • 最理想的是零参数函数,其次是单参数函数,再次是双参数函数,尽量避免三参数函数
  • 参数与函数名处于相同的抽象层级

单参数的普遍形式

  • 向函数传入单参数的理由
    1. 问关于该参数的问题,如boolean isFileExists("MyFile")
    2. 操作该参数,将其转换为其他东西,再输出之,如InputStream fileOpen("MyFile")
    3. 事件(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 代码块后面不该有其他内容

如何写出这样的函数

  • 先实现,再打磨