在 我的简单设计价值观 一文中,我分享了我在实践中形成对简单设计的理解。而提到价值观,平时跟同事讨论某个技术实践的时候,一旦触碰到价值观,我就会很谨慎,因为在两个人价值观不同的前提下,去讨论一项实践的好坏,很可能在面红耳赤之后不欢而散。
如果你压根都不认同简单设计价值观,我不建议你阅读此文。如果你跟我刚开始类似,并不是不认同简单设计的价值观,只是觉得它很抽象,没法落地,本文我会基于Kent Beck提出的简单设计原则,结合今天的软件开发,对这几个原则做一个全面的解读。
设计的问题
在使用某项实践之前我们一定要去思考一个问题:我们为什么要使用它? 我从代码设计所面临的问题为起点来回答为什么要遵循简单设计。
在代码设计中,我们会面临设计不足和过度设计的问题,比如不假思索过程式编写代码,以及不择手段套用设计模式,在实际中通常位于这两极端之间。设计不足主要表现为冗余、耦合、注释覆盖率高,过度设计主要表现为复杂、臃肿、代码闲置率高。这些现象通常会引发几大问题:难以修改、难以测试、难以阅读。
设计决策
针对上述常见的代码设计问题,我们可以通过引入提前设计来规避。值得一提的是,极限编程中也提倡提前做少量的设计。那么怎么把控这个度,我们在设计决策的时候就需要警惕了。
在设计决策中我们应该关注需求、可理解性、易修改性 和复杂度 这四个主要的维度,针对这四个维度,尝试问自己四个问题:
- 测试都通过了吗?
- 代码理解起来困难吗?
- 代码存在重复逻辑吗?
- 能够减少代码元素吗?
针对这四个问题,Kent Beck给出了四条参考原则 [1]:
- 通过测试
- 揭示意图
- 消除重复
- 最少元素
原则解读
通过测试
通过测试 通常会被一概地理解为通过所编写的测试,这个点成立的两个前提条件是:
- 测试覆盖率达到100%
- 所有测试都是有效的
如果你的项目中没有满足这两点,就需要换一个角度去理解 通过测试。我们编写测试始终应该聚焦在业务价值上,测试测的是业务价值,所以通过测试 广义理解为要满足业务需求,通过客户的验收,不管是自动化测试还是手工测试,只要测试是业务价值驱动的,都可以理解为通过测试。
消除重复
重复乃万恶之源 – SJ
重复意味着低内聚、高耦合,导致的后果是难以修改,对变化的响应力降低。响应力降低势必会造成维护工作量的提升,[我的简单设计价值观]({ { site.url }}{ { ‘/value-of-simple-design/’ }}) 一文中的懒惰 将驱使我尽我所能消除这些重复,从而减少修改时的工作量,提升软件的响应力。
揭示意图
在代码设计层面,我们可从一增一减两个方向同时去努力,从而达到揭示意图:
- 增强代码的自身可理解性,让代码自解释
- 减弱代码的其他干扰因素,让代码更纯净
增强方面,比如在变量、方法以及类的命名等,我们都竭尽全力去赋予它们一个更加表露意图的名字,让它们能够自解释,从而让读者能够在深入细节之前就能够在较高层次上快速理解代码的意图。减弱方面,比如在注释、方法的组织、类的交互设计等,可以去除不必要的注释,控制方法体的大小、降低类交互复杂度来让代码更纯净,从而让读者更好地聚焦在核心代码上。
最少元素
Kent Beck以类和方法来代表最少元素 中的元素。我们可以把元素的覆盖面扩大,比如,变量、常量、注释、注解、关键字、包等都属于代码元素。
最少元素 的核心思想是:在不必要的时候,尽可能减少代码元素来降低代码复杂度