优秀设计的精髓
优秀的设计比糟糕的设计更容易变更,也叫ETC原则(Easier To Change,更容易变更)。
每个人遇到的情况不一样,设计的方式方法也不一样。但”容易变更”的原则是通用的。变更是没办法避免的,不仅仅需求在变,用户习惯和数量也在变。可以说变化是常态。
如果系统比较复杂,耦合性高,改动一个会前影响另一个,这就不那么容易变更。改起来会很痛苦。
ETC原则假定了我们知道未来什么更容易变更,就把未来可能变更的场景考虑到设计里。这对能力要求有点高。但我们可以简单点操作,让每一个方法只做一件事情,如果需求变更,变更这个方法即可。
你也可以参考书中的两个方法
然而有时你找不到设计的线索。这也没关系。这种情况下,我们觉得你可以做两件事。
第一件事,假设不确定什么形式的改变会发生,你也总是可以回到终极的“容易变更”的道路上:试着让你写的东西可替换。这样,无论未来发生什么,这块代码都不会成为路障。这似乎有点极端,但不管怎样,实际上你一直应该这样做。做起来并不难,想着一直保持代码的解耦和内聚就够了。
第二件事,把它当作培养直觉的一种方式。在工程日志中记下你面临的处境:你有哪些选择,以及关于改变的一些猜测。在源码中留个标签,以便之后必须修改这块代码时,进行回顾并给自己留下反馈记录。下一次在行进的道路上再碰到类似的分岔口时,这会有所帮助
DRY—— 不要重复自己
不要在两个或者更多的地方使用相同的东西,如果变更了其中一个,还需要变更其他的。
DRY不仅仅只针对编码,即不要在多个地方复制粘贴代码。而是这种思维,在编写的时候就要考虑到,如果其中一个变了,其他地方是不是还要变动?这种变动是手动的,还是自动的?能用程序自动执行的,就不要手动去操作。人会犯错,机器不会。
最难检测到且最难处理的重复类型,可能发生在同一项目的不同的开发人员之间。整块的功能集可能会在不经意间重复,而这种重复或许好几年都未被发现。除了制定统一的编码规范外(方便新同事查找已经写好的方法),我们认为解决这个问题的最好方法是鼓励开发人员之间积极频繁的交流。
正交性
在计算科学中,这个术语象征着独立性或解耦性。对于两个或多个事物,其中一个的改变不影响其他任何一个,则这些事物是正交的。在良好设计的系统中,数据库相关代码应该和用户界面保持正交:你可以变更界面但不应影响数据库,切换数据库而不必更换界面。
但凡编写正交的系统,就能获得两个主要的收益:提高生产力及降低风险。
提高生产力
· 将变更限制在局部后,开发时间和测试时间都会减少。编写相对较小的、独立自主的组件比编写完整一大块代码要容易。简单的组件可以在设计、编码、单元测试之后遗弃——加点新代码就行的时候没必要一直改变已有的代码。
· 正交的方法同时促进了重用。如果组件有一个职责定义清晰的规范,就能以原作者预想不到的方式与新组件组合使用。系统耦合越松散,重新配置系统和再加工就越容易。
· 组合正交组件能获得相当微妙的生产力提升。假设一个组件能做M
件独特的事情,另一个能做N件。如果它们是正交的,组合起来就能做M×N件事。如果两个组件不正交,有重叠之处,结果就少一些。在正交组件的组合过程中,单个单元的性价比提高了。
减少风险
正交的方法减少了开发中内在的风险。
· 代码中病变的部分被隔离开。如果一个模块生病了,不太可能将症状传播到系统的其他部分。把它切下来并移植一个新的健康器官进去,也更加容易。
· 这样获得的系统不那么脆弱。对特定区域进行小的变更和修复后,因此而产生的任何问题都将局限于该区域。
· 正交系统可能更利于测试,因为为其组件设计和运行测试更加容易。
· 你不会被特定的供应商、产品或平台紧紧束缚。因为这些第三方组件的接口所关联的,仅仅是整个开发中相对很小的一部分。
可以用一个简单的方法来测试设计的正交性。当你规划好组件后,问问自己:如一个特别功能背后的需求发生显著改变,有多少模块会受影响?对于一个正交系统,答案应该是“一个”
有几种技术可以用来保持正交性:
保持代码解耦
编写害羞的代码——模块不会向其他模块透露任何不必要的信息,也不依赖于其他模块的实现。
避免全局数据
只要代码引用全局数据,就会将自己绑定到共享该数据的其他组件上。即使只打算对全局数据进行读操作,也可能引发问题(例如突然需要将代码改为多线程的情形)。一般来说,如果总是显式地将任何需要的上下文传递给模块,那么代码会更容易理解和维护。在面向对象的应用程序中,上下文通常作为参数传给对象的构造函数。在其他代码中,也可以创建一个包含上下文的数据结构,并将结构的引用传出去。
避免相似的函数
我们经常会遇到一组看起来很相似的函数——或许在开头和结尾的地方共享了公共代码,但是每个函数都有不同的中心算法。重复代码是结构问题的症状。想要更好的实现,可以看看《设计模式》中的策略模式。
如果你加入一个公司,发现他们的项目每次改动都会导致系统中的其他问题,这说明项目并没有做好正交性设计和编码,那么这时候你应该考虑重构。