代码整洁之道-读书笔记

Code Clean

Posted by Monk on July 5, 2019

爱上了代码的艺术,却偏偏痴迷于计算机的运算魅力

第一章 整洁代码

  1. 糟糕的代码如果从一开始就不去管理,那么只会越来越糟糕。不应该对糟糕的代码弃而不顾。
  2. 代码逻辑应该直截了当,叫缺陷难以隐藏,每个模块都应该只负责一件事情,尽量少的依赖关系,需要明确定义和提供清晰、尽量少的API
  3. 整洁的代码应该有单元测试和验收测试,整洁的代码看起来像是某位特别在意它的人写的,几乎没有改进的余地
  4. 简单代码:消除重复和提高表达力,提早构建简单抽象
    • 能通过所有测试
    • 没有重复代码
    • 体现系统中的全部设计理念
    • 包括尽量少的实体,比如类,方法等。

第二章 有意义的命名

  1. 名副其实:它为什么存在,它做什么事,应该怎么用。应该做到命名,命名,再命名
  2. 避免误导:不应该有相似的名称,不应该用关键字命名
  3. 名称定义:
  4. 使用读得出来的名称
    • 使用可搜索的名称:长名称胜于短名称
    • 类名和对象名应该是名词或名词短语
    • 方法名应当是动词或动词短语
    • 拒绝双关语,需要遵循“一词一义”

第九章 单元测试

TDD三定律

  • 在编写不能通过的单元测试前不可编写生产代码
  • 只可编写刚好无法通过的单元测试,不能编译也算通不过(不太理解)
  • 只可编写刚好足以通过当前失败测试的生产代码(不太理解)
    1. 脏测试等同于没测试,所以要写测试,并且要写好测试(因为测试代码和生产代码一样重要,需要被思考,设计和整洁)
    2. 整洁的测试应该具备可读性(明确,简洁,足够的表达力),以尽可能少的文字表达大量内容
    3. 写测试应该拆分为三个环节(构造-操作-检验):
      • 第一个环节构造测试数据 编写Given时,“驱动”我们思考被测对象的创建,以及它与其他对象的协作;
      • 第二个环节操作测试数据 编写When时,“驱动”我们思考被测接口的方法命名,以及它需要接收的传入参数;考虑行为方式,究竟是命令式还是查询式方法(CQS原则);
      • 第三个环节检验操作是否得到期望的结果 编写Then时,“驱动”我们分析被测接口的返回值;
    4. CQS原则,即命令-查询分离原则(Command-Query Separation),是指一个函数要么是一个命令来执行动作,要么是一个查询来给调用者返回数据。但是不能两者都是。
    5. 对于任务“判断每次的猜测结果”,我们首先要考虑由谁来执行此任务。从面向对象设计的角度来讲,这里的任务即“职责”,我们要找到职责的承担者。从拟人化的角度去思考所谓“对象”,就是要找到能够彻底理解(Understand)该职责的对象。遵循信息专家模式,大多数情况下,承担职责的对象常常是拥有与该职责相关信息的信息持有者,即所谓“信息专家”。
    6. 信息专家模式(Information Expert)是GRASP模式中解决类的职责分配问题的最基本的模式。职责的执行需要某些信息(information),把职责分配给该信息的拥有者。换句话说,某项职责的执行需要某些资源,只有拥有这些资源的对象才有资格执行职责。
    7. 可以进行封装一套API的函数和工具代码,这样更能方便的写出测试,也更便于阅读。

      每个测试应该有一个断言

      1. 利用模板方法,将given/when放到基类中,将then放到派生类中,消除代码重复问题。
      2. 利用@Before注解,将given/when放到该方法中,when方法@Test中
      3. 每个测试一个概念:每个测试函数只测试一个概念

F.I.R.S.T 规则

  1. 快速(Fast):测试应该够快,能快速运行
  2. 独立(Independent):测试应该相互独立
  3. 可重复(Repeatable):在任何环境中都可以重复通过
  4. 自足验证(Self-Validating):测试该有boolean值输出 (*)
  5. 及时(Timely):测试应该及时编写

第十章 类

  1. 类的组织:从一组变量列表开始
    • 如果有公共静态常量,应该先出现
    • 然后是私有静态变量
    • 私有实体变量
    • 很少有公共变量
  2. 单一权责原则:类或模块应有且只有一条加以修改的理由
    系统应该由许多短小的类而不是少量巨大的类组成。每个小类封装了一个权责,只有一个修改的原因,并与少数其他类一起协同达成期望的系统行为。
  3. 开放-闭合原则:类应当对扩展开放,对修改封闭
  4. 内聚
    • 类中有少量的实体变量,每个方法都应该操作一个或多个这种变量。如果一个方法使用了所有的变量,那么该方法具有最大的内聚
    • 拆分较小的类和函数,并取一个好的名字