代码整洁之道-读书简记

编程

Posted by baiyf on March 1, 2019

一、有意义的命名

  1. 名副其实

    让变量、函数、参数、类和封装的命名具有实际意义,好的命名具有自注释性

  2. 避免误导

    • 避免使用与本意相悖的词,例如accountList,除非它真的是个list
    • 避免使用差异较小的名称,例如XYZControllerForEfficientHandlingOfStringsXYZControllerForEfficientStroageOfStrings就很难辨别
    • 单纯的字母l和o具有误导性,例如”lo”容易被误人为是”10”
  3. 做有意义的区分

    • 避免使用数字字母序列:A1,A2,A3…
    • 少说废话,例如已经有了一个Product类,再添加ProductInfoProductData就很有混淆性,因为InfoData在这里意义不大
  4. 使用读的出来的名称

    易读的名称便于讨论,例如generationTimestamp就比genymdhms要好

  5. 使用可搜索的的名称

    • 使用有意义的宏变量名代替阿拉伯数字,便于搜索和维护,例如MAX_CLASSES_PER_STUDENT就比数字7好搜索很多
    • 名称长短与作用域大小相对应,作用域越大名称应该越长
  6. 类名

    类名和对象名应该是用名词或名词短语,不应当是动词

  7. 方法名

    方法名应该是动词或动词短语

  8. 给每个抽象概念选一个词,并且一以贯之。

    例如fetch,retrive和get只需要选一个词来表示这个概念即可

  9. 别用双关语

    避免使用一个有多重意思的词作为名称

  10. 起其他程序员看得懂的名称

    尽量在程序员的知识背景中选择名称,而不是其他领域的专业名词,毕竟你的代码是给程序员看的

  11. 为名称添加语境

    使用前后缀或者类把相关的名称关联起来,便于理解

  12. 取名称最难的是需要良好描述技巧和共有文化背景

二、函数

  1. 函数应该尽量短小

  2. 代码块与缩进

    函数的缩进层级不宜多于一层或两层

  3. 函数只做一件事

    函数应该做一件事,做好这件事,只做这一件事

  4. 每个函数一个抽象层级

    • 每个函数内应该只包含一个抽象层级的代码,混有多个抽象层级代码的函数容易使人迷惑
    • 函数与函数之间应该抽象层级逐步降低,每个函数后跟着更低抽象层级的函数,这样便于自上而下的阅读
  5. 使用具有描述性的名称

    • 名称应该较好的描述函数所做的事,长而具有描述性的文章比短而令人费解的名称好

    • 命名方式要保持一致,函数名应与模块名一脉相承

  6. 函数参数

    函数参数数量越少越好,零参数函数最好,单参数函数次之。较多的函数参数会增大测试工作的复杂性

    • 尽量避免使用表示参数,向函数传入布尔值不是一种好做法。可以将函数一分为二来替代
    • 对于一元函数,函数名和参数名组成动词/名词对有助于理解,例如write(name)
  7. 分隔指令与询问

    将指令与询问放在一起不利于提高程序的可读性,为了避免这个问题可以将指令与询问分割开来

  8. 使用异常替代返回错误码

    善用异常,有利于指令与询问的分离

    • 抽离Try/Catch代码块,将其从主体函数中抽离出来
    • 错误处理只做一件事,处理错误的函数不该做其他数
  9. 避免代码块的重复

    重复就会带来问题,许多原则与实践规则都是为了控制与消除重复而创建的,例如面向对象编程、面向方面编程和面向组件编程等等

  10. 避免使用goto语句

  11. 先写出来再慢慢打磨

    先实现函数功能,并辅以单元测试。后期再打磨代码、分解函数、修改名称、消除重复

    没有人可以一开始就按照规则写函数,好的代码需要反复打磨

    三、注释

不准确的注释比没注释坏的多,应该时刻记得尽量减少注释

  1. 注释救不了烂代码

  2. 好的名称可以起到注释的效果

  3. 值得写的注释

    • 法律信息,包括版权和著作声明
    • 提供信息的注释,帮助程序员理解代码
    • 对意图的解释,解释代码的设计思想
    • 阐释,把某些晦涩难懂的参数和返回值翻译成可读形式
    • 警示,用于警告其他程序员会出现某种后果
    • TODO注释,用于记录待办事项,所以要定期查看定期处理
    • 放大,放大某些看似不合理之物的重要性
  4. 不值得写的注释

    • 喃喃自语,写出来只能给自己看的注释

    • 多余的注释,如果代码本身比较简单,写出冗长的注释显然是不值得的

    • 误导性注释

    • 循规式注释

    • 日志式注释,记录代码修改的每次记录是完全不需要的,不然要git干嘛

    • 废话式注释,用整理代码的决心替代创造废话的冲动吧

    • 能用函数或变量就别用注释

    • 少用位置标记,减少背景噪音

    • 括号右边的注释

      例如:

      while(step==END){
          ...
      } //while
      

      正确的做法应该是减少函数的行数,而非添加括号注释

    • 归属与署名注释,同样可以被git完美替代

    • 注释掉的代码,注释掉的代码没人敢动,最终会越积越多。尽量减少注释掉太多的代码

    • HTML注释

    • 非本地信息,描述远在他方的其他函数往往让人不知所云

    • 与代码没有明显联系的代码,注释的作用是解释未能自行解释的代码,如果注释本身还需要解释那就太遗憾了

    • 函数头注释,写函数头注释不如为一系列短函数起好名字

四、格式

  1. 格式的意义

    代码格式关乎沟通,而沟通是专业开发者的头等大事

  2. 简洁有条理

    源文件名称应该简洁且一目了然,源文件顶部给出高层次概念和算法。细节往下渐次展开,知道找到源文件中最底层的细节和函数

  3. 垂直方向上的区隔

    在封包声明、导入声明和每个函数之间,都有空白行隔开,标识出新的独立概念的出现

  4. 垂直方向上的靠近

    紧密相关的代码应该相互靠近

  5. 横向格式

    一行保持在80个字符以内,至多不能超过120

    • 赋值操作在”=”两段加空格,起到强调赋值操作效果的作用

    • 在函数名和左圆括号之间不加空格,因为函数名与函数参数有着强相关,加了空格就会显得两者毫无关系。

    • 用空格把函数调用参数相互隔开,强调逗号,表示函数的各个参数是互相分离的

    • 空格还可以用来强调前面的运算符

      例如:

      double determinant(double a, double b, double c){
          return b*b - 4*a*c;
      }
      

      这种灵活的空格用法强调了较低优先级的加减法运算,使之不易被忽略

  6. 遵守团队规则

五、对象和数据结构

  1. 得墨忒耳律

    模块不应该了解它所操作对象的内部情形

六、错误处理

  1. 使用异常而非返回码

  2. 先写try-catch-finally语句

    先搭建好异常捕获的框架在向其中补充具体的异常处理方法

  3. 使用不可控异常