程序可修改性非常重要,毕竟世界总是动态变化的,以前写的程序在新条件下可能不满足需求,也有可能程序需求在初始阶段并没有搞明白,后来就越来越清楚了。总之,程序需要被修改或者直接重写。如果总是重写,从零开始,成本是很大的。如果有之前的积累,至少和别人相比,起点也会高些。但是,如果程序可修改性太差,也有可能会让我们陷入泥潭,还真不如轻装上阵来的自在!
首先,怎么才算可修改性高呢?我觉得有两个指标:
一、修改本身实现起来容易
二、修改不影响程序其他部分
下面,我们看看为了实现这些目标,都有什么策略。修改本身容易,我觉得分为两种情况:
(1) 任务量减少了
(2) 任务量不变,但效率提高了
减少任务量
怎么让一个修改的任务量减少呢?可能是一个好的主意让任务量减少,比如说《五军之战》,目标是矮人要击败半兽人,怎么办,可以硬抗,但是任务量大,还不一定抗得住;电影里面,是擒賊先擒王,任务量不知道少了多少个等级,结果还胜了。还有一个办法就是复用,利用以前的工作,使得本次任务量降低。总结起来就是:
a) 一个好主意,使得任务量变低
b) 复用,总任务量不变,但本次任务量降低了
一个好主意,可遇而不可求,我们也不做苛求,所以减少任务量的主要办法就是复用。复用说起来容易,实现起来实际上很难的,并且要克服自己的直觉习惯,每次实现的时候,要想想哪些可以复用。可以参考设计模式来获得更多复用的灵感。
提高效率
任务量不变情况下,提高效率,我觉得有两种办法:
a) 自动化
b) 并发
自动化,是利用工具或者脚本来代替我们工作,从而提高效率。甚至有一些更高级的,比如说一些uml工具可以自动生成代码等等。要支持并发,其实也离不开自动化工具,多个自动化工具同时进行,效率会大幅提升。只不过需要任务的基础架构支持并发。
依赖稳定
第二个指标是修改不影响程序其他部分,可以把它分为三种情况:
(1) 修改和其他部分独立
(2) 就是不独立,想连部分保持不变
(3) 实在要变,把影响降到最小
我们先来说第一个,修改和其他部分独立,换种说法就是其他部分不依赖修改部分。这里有一些基本原则,可以遵守:高层模块不应该依赖底层模块,抽象不应该依赖细节,细节应该依赖抽象。简单来说就是容易变的应该依赖不怎么变的。比如说有两个不同对象a,b。它们如果要互相通讯,有三种办法:
a) a 调用b,b调用a
b) a 调用b,a 监听b事件,收到b的信息
c) b 调用a, b监听a事件,收到a的信息
如果图简单方便的话,a)是首选,也是直觉上的自然选择。如果稍加考虑,看看依赖关系,比如说b是容易变的,此时不应该让a依赖b发生,所以最后就应该选c)。
接口编程
如果实在要依赖,那么就要依赖接口,并且保持修改的时候,接口保持不变。在设计模式中,实现了变化,但是接口却保持不变的有几个相关模式,比如:适配器、装饰器、代理等等。
影响最小化
最后,实在没办法,接口也要变。一种办法是把变化封装到一个模块内,这就涉及到基本功,类设计的时候,按照职责分配,提高内聚性,并把模块粒度控制在一个合理的大小范围内。第二个办法是基于外部的,利用中介把外部几个都依赖修改的转换成都依赖中介,然后让中介一个依赖修改。不过,这个设计需要前期判断,觉得哪个地方出现变化的概率大,不然会出现很多无用功。