
3.3 架构的目标
模块化不仅有助于解决软件架构中社会性方面的问题,还会帮助我们设计更加灵活的软件系统,也就是,具备弹性、高适应性以及可维护性架构的系统。查看一下之前关于架构的定义,就会得到架构的目标。Fowler所引用的由Johnson给出的架构定义表明架构就是关于重要的事情的。在以下表述中,Booch明确说明如果有的事情很难改变,那么在架构上它就是重要的:
所有的架构都是设计,但并不是所有的设计都是架构。架构表现为重要的设计决策,这些决策会形成系统,在这里重要性是通过变化的成本衡量的。
基于以上表述,可以得到这样的结论:软件架构的目标必须是减少变化的影响和成本,从而消除架构上的重要性。通过创建灵活易变化的方案,我们试图使得一些事情在架构上不那么重要,如图3.3所示。但是这里存在一个悖论。
图3.3 架构的目标
3.3.1 悖论
消除架构并不是新的理念。实际上,Fowler在他的文章“谁需要架构师?”(Who Needs an Architect?,2003)中提到了“丢掉软件架构”(getting rid of software architecture)。通过减少变化的影响和成本来消除架构的必由之路就是灵活性。系统越灵活,就越能按需进行适应和进化。但是这里有一个悖论,Ralph Johnson的表述支持了这个观点(Fowler 2003):
……让每件事都易于变化会使得整个系统非常复杂……
随着灵活性的增长,复杂度(参见4.1节)也会随之增加。复杂性是我们要试图驯服的怪兽,因为复杂的事情比简单的事情更难以处理。可以肯定的是,没有明确的道路通往胜利。但是,如果既能驯服复杂性又能增加灵活性,如图3.4所示,那又会怎么样呢?现在探讨一下设计灵活的软件系统同时又不增加复杂度的可能性。可能吗?换句话说,怎样消除架构?
图3.4 最大化灵活性,管理复杂度
3.3.2 消除架构
正如对Johnson的引用中所明确指出的,设计无限灵活的系统是不可行的。因此,我们很有必要识别出在什么地方保证灵活性从而减少变化的影响和成本。但挑战在于,我们并不是总能在项目的初期就知道最终哪里会发生变化,所以对于我们不知道的事情无法创建一个灵活的方案。这就是预先设计的大架构(Big Architecture Up Front,BAUF)所面临的问题,这也是我们需要根据当时的情况做出架构决策的原因。换句话说,在有充足的知识保证我们能够做出最明智的决策之前,我们应当尽可能地延迟做出具体的架构决策,因为那样会使我们局限在一个具体的解决方案中。
当面临不确定时,对问题进行隔离并做出决策前我们要十分慎重并要确保当未知问题的答案出现时,初始决策能够灵活变化,我们这样做也是基于以上的原因。为此,模块化是被忽略的一个部分,它能够帮助我们尽可能地减少变化带来的影响和成本,这是我们使用模块化架构设计软件系统的驱动力。在《UML User Guide》 [1]中,Booch提到了“为系统中的接缝(seam)建模”。他说(1999):
识别系统中的接缝涉及识别在系统体系架构中明确的分界线。在这些分界线的每一侧,都会发现可独立变化的组件,只要在分界线两侧的组件遵循由接口描述的契约,在一侧变化的组件就不会影响另一侧的组件。 [2]
Booch称为组件的地方,我们称为模块。Booch称为接缝的地方,我们称为结合点(joint,参见4.5节)。模块化以及设计模式和SOLID原则(参见附录),代表了我们尽可能减少变化的影响和成本的最好愿望,同时它也会消除变化所带来的架构重要性。