《代码整洁之道》部分笔记

1、命名

  • 名副其实:让读者看名字就明白它的作用
  • 避免误导:不要用有歧义的词语,例如不是List就不要带有List
  • 有意义的区分:不要加一些废话,例如NameString,例如ProductData和ProductInfo,不能区别它们的作用。
  • 使用读得出来的名称:使用英语单词
  • 使用可搜索的名称:不要使用a、b、c这种变量名,使用便于搜索的名字
  • 避免使用编码:不要加一些无意义的前后缀
  • 避免思维映射:不要使用l、O这种名字(与1,0相近),尽量少的引起歧义。
  • 类名:应该命名为名词或名词短语
  • 方法名:应该命名问动词或动词短语
  • 每个概念对应一个词:同样的功能对应一个名字,不要出现一会用manager,一会用controller的情况
  • 别用双关词:遵循一语一意的原则,如果连接用了add,那么添加就别再用add,可以用append或insert
  • 使用专业名称:例如使用JobQueue等,带有含义与数据结构的词语,让程序员一看就明白它的意思
  • 添加有意义的语境:state,很难之道它的含义,如果它代表的是地址的state,可以加上前缀语境addrState
  • 不要加无意义的语境

2、函数

  • 短小:函数尽可能的短
  • 只做一件事:只做一件事,完成在同一抽象层次下的一些步骤完成一项工作。例如人是一个层级,四肢是更低的层级,手指又是更低的层级。
  • 每个函数一个抽象层级:1、不要在一个函数内混杂不同层级的操作,2、自顶向下的规则,顺着抽象层级结构写函数。
  • Switch语句:违反了单一权责原则、开放闭合原则,解决方法:放在工厂类用,利用接口多态派遣。
    • 单一权责原则:一个类负责一个功能
    • 开放闭合原则:对扩展开放,对修改关闭,通过扩展来修改,而不是修改原代码
  • 使用描述性名称:名字要表达函数的功能,不用怕长,长而清晰的名称,比短而费解的名称好。
  • 函数参数:函数的参数应该越少越好,而且应该让人看到名称和参数,就大概清楚函数的作用,几种参数的情况:
    • 一元函数:有三种情况,一二种比较普遍
      • 询问该参数一些问题:例如 boolean fileExists(“MyFile”)
      • 将参数进行转换:例如 InputStream fileOpen(“MyFile”)
      • 事件,通过参数修改系统状态:例如 void passwordAttemptFailedNtimes(int attempts)
    • 不要传入标识参数:例如render(Boolean isSuite),有这种情况,将函数拆分成两个renderForSuite() 和 renderForSingleTest()
    • 二元函数:
      • 两个值有自然顺序,组成一个整体,例如笛卡尔座标的x,y值
      • 尽量写成一元函数,例如writeField(outputStream, name),尽量写成 outputStream.writeField(name)
      • 需要两个参数时,利用函数名减少记忆参数顺序负担,例如assertExpectedEqualsActual(expected, actual)
    • 三元函数:尽量少用,可以将多个参数封装成类,通过名字提示内容,减少记忆参数顺序的负担。
  • 无副作用:不要在函数中加别的操作,遵循只做一件事的原则,也不要把参数用作输出
  • 分割指令与询问:例如需要一个参数决定是否执行,不要在一个函数内既做询问,又做设置,应分开它:
if(attributeExists("username")){
	setAttribute("username", "unchebob");
}
  • 使用异常替代返回错误码:当指令函数返回错误码时,不要用太多if-else嵌套,放在一个try-catch模块中
  • 抽离try-catch代码块:尽量将try-catch代码抽离为单独一个方法,与正常流程区分开来。错误处理就是一件事,错误处理的函数应该遵循只做一件事的原则,只处理错误函数
  • 减少重复:不要重复算法,公有相同的操作应该抽离出来。

3、注释

尽量不要写注释,用代码来解释意图

4、格式

  • 垂直格式:
    • 整体的顺序应该是先给出高层次的概念和算法,细节逐渐展开
    • 垂直方向上,概念相近的靠近
    • 垂直上的顺序是,调用者尽可能放在被调用者上面
    • 垂直上封包声明、倒入声明、每个函数之间用空行隔开
  • 横向格式:
    • 空格用于加强分割作用,等号的两边是不同的要素,加空格起到分割的作用,而函数名和括号之间是一个整体,不加空格。
    • 空格另一种用法是强调运算顺序,b*b - 4*a*c 这样就会比较清晰,看出左右部分,遵循先乘除后加减的运算顺序。

5、对象和数据结构

  • 类应该暴露抽象接口。用户无需了解数据实现就能操作数据本体。
  • 过程式编程和面向对象式编程:
    • 过程式:类与方法分开,一个方法针对不同的类实现不同的逻辑,添加新的方法不需要修改类,但是添加新的类就要修改所有现有的方法。
    • 面向对象:类中继承接口,实现抽象方法,优点是添加新的类不需要修改现有的方法,但是添加新的方法就要修改所有的类。
    • 小结:处理问题时需要分情况讨论,过程式的编程添加新的方法比较方便,而面向对象的编程添加新的类比较方法
  • 得墨忒耳律:类C的方法f只应该调用以下对象的方法:
    • C
    • 由f创造的对象
    • 作为参数传递给f的对象
    • 由C实体变量持有的对象
  • 数据传送对象:
    • DTO是只有公共变量(包括私有变量+公共getter/setter)、没有函数的类,是最精炼的数据结构。
    • Active Record是一种特殊的DTO形式,同时也会拥有save、find方法,通常是对数据库或其他数据源的之间翻译(就是我们项目中的Domain Object,一个类对应数据库一张表)。Active Record往往被塞进业务规则方法,导致数据结构和对象的混杂体。
    • 应该把Active Record当成数据结构,另外创建包含业务规则、隐藏内部数据的独立对象。

6、类

  • 类的组织:
    • 变量顺序:公共静态、私有静态、私有实例变量
    • 公共函数跟在变量之后,把公共函数调用的私有函数放在公共函数后面,满足自顶向下的原则,读起来像一张报纸
  • 类应该短小:遵循单一权责的原则,一个类负责一个权责
  • 内聚:把大的方法进行拆分,如果一些方法只被少数的变量用到,就应该拆分处一个类。保证类的内聚性,类的变量被类中的方法所使用。
  • 为修改而组织:需要添加功能时,可以通过子类实现这项功能,满足开放闭合原则,对修改关闭,对扩展开放。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章