爱上了代码的艺术,却偏偏痴迷于计算机的运算魅力
第一章 整洁代码
- 糟糕的代码如果从一开始就不去管理,那么只会越来越糟糕。不应该对糟糕的代码弃而不顾。
- 代码逻辑应该直截了当,叫缺陷难以隐藏,每个模块都应该只负责一件事情,尽量少的依赖关系,需要明确定义和提供清晰、尽量少的API
- 整洁的代码应该有单元测试和验收测试,整洁的代码看起来像是某位特别在意它的人写的,几乎没有改进的余地
- 简单代码:消除重复和提高表达力,提早构建简单抽象
- 能通过所有测试
- 没有重复代码
- 体现系统中的全部设计理念
- 包括尽量少的实体,比如类,方法等。
第二章 有意义的命名
- 名副其实:它为什么存在,它做什么事,应该怎么用。应该做到命名,命名,再命名
- 避免误导:不应该有相似的名称,不应该用关键字命名
- 名称定义:
- 使用读得出来的名称
- 使用可搜索的名称:长名称胜于短名称
- 类名和对象名应该是名词或名词短语
- 方法名应当是动词或动词短语
- 拒绝双关语,需要遵循“一词一义”
第九章 单元测试
TDD三定律
- 在编写不能通过的单元测试前不可编写生产代码
- 只可编写刚好无法通过的单元测试,不能编译也算通不过(不太理解)
- 只可编写刚好足以通过当前失败测试的生产代码(不太理解)
- 脏测试等同于没测试,所以要写测试,并且要写好测试(因为测试代码和生产代码一样重要,需要被思考,设计和整洁)
- 整洁的测试应该具备可读性(明确,简洁,足够的表达力),以尽可能少的文字表达大量内容
- 写测试应该拆分为三个环节(构造-操作-检验):
- 第一个环节构造测试数据 编写Given时,“驱动”我们思考被测对象的创建,以及它与其他对象的协作;
- 第二个环节操作测试数据 编写When时,“驱动”我们思考被测接口的方法命名,以及它需要接收的传入参数;考虑行为方式,究竟是命令式还是查询式方法(CQS原则);
- 第三个环节检验操作是否得到期望的结果 编写Then时,“驱动”我们分析被测接口的返回值;
- CQS原则,即命令-查询分离原则(Command-Query Separation),是指一个函数要么是一个命令来执行动作,要么是一个查询来给调用者返回数据。但是不能两者都是。
- 对于任务“判断每次的猜测结果”,我们首先要考虑由谁来执行此任务。从面向对象设计的角度来讲,这里的任务即“职责”,我们要找到职责的承担者。从拟人化的角度去思考所谓“对象”,就是要找到能够彻底理解(Understand)该职责的对象。遵循信息专家模式,大多数情况下,承担职责的对象常常是拥有与该职责相关信息的信息持有者,即所谓“信息专家”。
- 信息专家模式(Information Expert)是GRASP模式中解决类的职责分配问题的最基本的模式。职责的执行需要某些信息(information),把职责分配给该信息的拥有者。换句话说,某项职责的执行需要某些资源,只有拥有这些资源的对象才有资格执行职责。
-
可以进行封装一套API的函数和工具代码,这样更能方便的写出测试,也更便于阅读。
每个测试应该有一个断言
- 利用模板方法,将given/when放到基类中,将then放到派生类中,消除代码重复问题。
- 利用@Before注解,将given/when放到该方法中,when方法@Test中
- 每个测试一个概念:每个测试函数只测试一个概念
F.I.R.S.T 规则
- 快速(Fast):测试应该够快,能快速运行
- 独立(Independent):测试应该相互独立
- 可重复(Repeatable):在任何环境中都可以重复通过
- 自足验证(Self-Validating):测试该有boolean值输出 (*)
- 及时(Timely):测试应该及时编写
第十章 类
- 类的组织:从一组变量列表开始
- 如果有公共静态常量,应该先出现
- 然后是私有静态变量
- 私有实体变量
- 很少有公共变量
- 单一权责原则:类或模块应有且只有一条加以修改的理由
系统应该由许多短小的类而不是少量巨大的类组成。每个小类封装了一个权责,只有一个修改的原因,并与少数其他类一起协同达成期望的系统行为。 - 开放-闭合原则:类应当对扩展开放,对修改封闭
- 内聚
- 类中有少量的实体变量,每个方法都应该操作一个或多个这种变量。如果一个方法使用了所有的变量,那么该方法具有最大的内聚
- 拆分较小的类和函数,并取一个好的名字