抽象的层次

从最终用户来看,

软件是一个整体,

所有的代码提供一个功能。


从工程师的角度来看,

软件由多个互相联系的模块组成,

每个模块提供一部分功能。


然而,这些都是静态的观点,

是在软件发布的那一瞬间观察到的。


实际上呢?


实际上,软件是一个动态的事物,

像一个生命体一样活着,

软件发布,只是它的一次快照。


这就提醒了我们,

不能像设计建筑一样设计软件。


更要考虑到它的成长。


模块间的接口

我们永远不能假定,

软件提供的功能只被人来使用。


其实,更多的是,

被其他软件系统来调用。


这就要求我们,

首先提供程序可调用的接口,

而不是人机交互界面。


这其实是测试驱动开发的直接结果,

我们首先要有自动化的用例,

才能保证功能的稳定。


变化的接口

当我们确定了模块的调用接口后,

目的性就更加明确了。


似乎,无论内部怎样设计,

只需要实现功能就行了。


其实不然。


根本原因就在于,

模块的调用接口是变化的。


模块内的设计,

要有能力快速响应这种变化。


不同的意见

有人认为,

接口设计的初衷,就是为了把变化隔离开,

接口发生变化了,设计本身就是不对的。


诚然。


但是,回想一下我们做过的项目,

有哪一个功能是稳定的?

又有哪一个设计能预判未来呢?


因此,

接口是隔离变化的手段之一,

它只能尽量把变化压缩到模块内部。


可扩展的设计

对于功能变更,不要埋怨,

否则,说起来好像我们一开始不知道似的。


精巧的设计,

在设计之初就考虑到了这些,

留有扩展的余地。


什么样的设计才是可扩展的呢?


那就要求我们提取模式,

只对抽象进行编程。


使得接口需要的功能,

作为抽象设计的特定情形。


这样的话,

任何改变,都是抽象设计的不同应用。


层次性

何必要这么麻烦呢?

直接提供功能不行吗?


为什么还要先写一个抽象,

然后再具体化呢?


这是因为抽象隔离了变化。

具体功能易变,而功能的模式更稳定。


甚至,随着软件的日益复杂,

功能模式已经不再适用时。


我们还要进一步抽象,

让现在的抽象层变成更高层的实例。


友好的外观

优雅的设计,

内部的抽象层次是分明的,

外观同样也是简易的。


这就像人一样,

越是有好的修养,

越是内心华丽,外表朴实。


把精妙藏于简易的接口内部,

是一种艺术。


这需要我们做很多努力,

不要把复杂开放给别人。


不要炫耀。


结语

与其说,设计是一种创造性的活动,

不如说,设计是一种心智的锻炼活动。


我们在努力学习软件的时候,

也不能忘记磨练自己的品行。


没有藏锋内敛的修养,

就难以完成大巧若拙的设计。