架构之美

【声明】本文为AdamsLee原创,转载请注明出自围炉网并保留本文有效链接:架构之美, 转载请保留本声明!

概念完整性是架构最重要的特征:“最好是让系统⋯⋯反映一组设计思

想,而不是让系统包含许多好的思想,而这些思想却彼此独立而不协调”(1995)。正是

这种概念完整性,让开发者在知道了系统的一部分之后,能够迅速理解系统的另一部分。

概念完整性来自于处理问题的一致性,如分解的判据、设计模式的应用和数据模式。这

让开发者运用在系统中的一部分工作的经验,来开发和维护系统的其他部分。同样的规

则应用于整个系统各处。当我们转向“众系统之系统”时,在集成了这些系统的架构中

也必须保持概念完整性。例如,可以选择发布/订阅消息总线这样的架构风格,然后将

这种风格统一地应用于“众系统之系统”的系统集成中。

每个关注点都以问题的方式表述,架构师在项目过程中可能需要考虑它。当然,

具体系统会有其他关键的关注点。

功能性( Functionality

产品向它的用户提供哪些功能?

可变性( Changeability

软件将来可能需要哪些改变?哪些改变不太可能发生,不需要特别容易进行这些改变?

性能( Performance

产品将达到怎样的性能?

容量( Capacity

多少用户将并发使用该系统?该系统将为用户保存多少数据?

生态系统( Ecosystem

在部署的生态环境中,该系统将与其他系统进行哪些交互?

模块化( Modularity

如何将编写软件的任务分解为工作指派(模块),特别是这些模块可以独立地开发,

并能够准确而容易地满足彼此的需要?

可构建性( Buildability

如何将软件构建为一组组件,并能够独立实现和验证这些组件?哪些组件应该复用

其他的产品,哪些应该从外部供应商处获得?

产品化( Producibility

如果产品将以几种变体的形式存在,如何开发一个产品线,并利用这些变体的共

性?产品线中的产品以怎样的步骤开发(Weiss和Lai 1999)?在创建一条软件产品

线时,要进行哪些投资?开发产品线中不同变体的选择,预期会得到怎样的回报?

特别是,是否可能先开发最小的有用产品,然后再添加(扩展)组件,在不改变以

前编写的代码的情况下,开发产品线的其他成员?

安全性( Security

产品是否需要用户认证,或者必须限制对数据的访问?数据的安全性如何得到保

证?如何抵挡“拒绝服务”攻击或其他攻击?

最后,一个好的架构师会认识到,架构会影响组织机构。Conway指出,系统的结构会

反映构建它的组织机构的结构(1968)。架构师可能会认识到,Conway法则可以反过来

应用。换言之,一个好的架构可能对组织机构产生影响,让组织机构发生改变,从而更

有效地从该架构构建出系统。

延迟设计决定

有一项XP原则确实提高了“设计之城”的架构品质,这就是YAGNI(如果你不是马上

需要,就不要去做)。这促使我们在早期只设计了重要的部分,将所有余下的决定推迟,

直到我们对实际的需求有了更清晰的理解并知道如何放到系统中最好时,再做出这些决

定。这是一种非常强大的设计方法,在很大的程度上解放了我们的思想。

• 当你还不理解问题时就开始设计,这是一件糟糕的事。YAGNI迫使你等待,直到

你知道真正的问题是什么,它应该怎样由设计来体现为止。这消除了猜测的工作,

确保设计是正确的。

• 当你开始创建软件设计时就加入所有可能需要的东西(包括厨房水槽)是危险的。

你的大部分设计工作会变成无用功,得到的只是额外的负担,你不得不在软件的

整个变更生命周期中支持这些设计。它一开始就增加了成本,而且在项目的生命

周期中不断增加成本。

注意:延迟设计决定,直到你必须做出这些决定为止。不要在你还不知道需求的时候就做出架构

决定。不要猜测。

保持品质

从一开始,“设计之城”就准备好了一些品质控制过程:

• 结对编程。

• 对没有结对编程的工作进行代码/设计复审。

• 对每一段代码进行单元测试。

这些过程确保了系统中从未加入不正确的、不合适的变更。所有不符合软件设计的内容

都被拒之门外。这可能听起来有点过于严厉,但这些是开发者们坚信的过程。

这种信念凸显了一个重要的态度:开发者们相信设计,认为设计对项目相当重要。他们

拥有设计,对设计负责。

注意:必须保持架构品质。只有当开发者们相信它并对它负责时,才能做到这一点。

管理技术债务

除了这些品质管理方法之外,“设计之城”的开发是相当注重实效的。随着最后期限的临近,

一些不太重要的功能被砍掉,让产品能够准时推出。小的代码“瑕疵”或设计问题允许存在

于代码集中,要么是为了让功能快一点实现,要么是为了在接近发布时避免高风险的改动。

但是,与“混乱大都市”项目不同的是,这些逃避职责的地方被标记为技术债务,并安

排在后续的版本发布中修正。这些问题很清楚,开发者对它们不满意,直到将它们处理

掉为止。同样,我们看到了开发者对设计的品质负责。

单元测试打造了设计

关于代码集的一项核心决定就是所有代码都要有单元测试(这也是在XP开发中强制要求做

到的)。单元测试带来了许多好处,其中一点就是能够修改软件的一些部分,而不必担心在

修改的过程中破坏其他的东西。我们对“设计之城”内部结构的某些部分进行了相当激进的

返工,单元测试给了我们信心,让我们相信系统的其他部分没有被破坏。例如,线程模型和

音频管道的内部连接接口都进行了彻底的改变。这是在子系统开发较晚的时候发生的严重设

计变更,但与音频通道接口的其他代码仍然执行得很好。单元测试让我们能够改变设计。

随着“设计之城”的逐渐成熟,这种类型的“主要”设计变更越来越少了。在经过一些

设计返工之后,情况稳定下来,此后只有一些不重要的设计变更。系统开发得很快:以

迭代的方式进行,每一次迭代都改进了设计,直到它达到了相对稳定的状态。

注意:你的系统应该有一组不错的自动化测试,它们让你在进行根本的架构变更时风险最小。这

为你提供了工作的空间。

单元测试的另一个主要好处在于,它们在很大程度上定型了代码设计:它们实际上迫使

我们实现好的结构。每个小的代码组件都被定型成定义良好的实体,可以独立存在,因

为它必须能够在单元测试中构造出来,不需要围绕它构造系统的其他部分。编写单元测

试确保了每个代码模块的内聚性,也确保了与系统其他部分之间的松耦合。单元测试迫

使我们仔细考虑每个单元的接口,确保该单元的API是有意义的,内部是一致的。

注意:对你的代码进行单元测试将带来更好的软件设计,所以设计时要考虑可测试性。

设计时间

“设计之城”成功的另一个因素是分配的开发时间段,它既不长也不短(就像金发歌蒂

的粥,既不热也不冷,刚刚好)。项目需要一个有利的环境才能获得成功。

如果时间太多,程序员常常会想创建他们的巨作(那种总是快要好了,但永远不会实现

的东西)。有一点压力是好事,紧迫感有助于完成事情。但是,如果时间太少,就不可

能得到任何有价值的设计,你只会得到半生不熟的解决方案,就像“大都市”那样。

注意:好的项目计划将带来优质的设计。分配足够的时间来创建架构杰作,它们不会立即出现。

与设计同行

尽管代码集很大,但它是一致而易于理解的。新的程序员可以比较容易地拿起代码并开

始工作。不需要去理解不必要的复杂内部关系,也不需要面对奇怪的遗留代码。

由于代码中产生的问题比较少,工作起来有乐趣,所以团队人员的流失率很低。这是因

为开发者们负责设计,并不断希望改进它。

看着开发团队动态地遵守架构设计是一件有趣的事情。“设计之城”的项目原则规定没有

人“拥有”哪一部分设计,这意味着任何开发者都可以改动系统的所有地方。每个人都应

该写出高品质的代码。“大都市”是许多不协作的、互相争斗的程序创造的一团混乱,而

“设计之城”则是由密切合作的同事创建的一组干净、一致、密切合作的软件组件。在很

大程度上,Conway法则(注)反过来也生效,团队的组织方式就像软件的组织方式一样。

注意:团队的组织方式必然对它产生的代码有影响。随着时间的推移,架构也会影响到团队协作

的好坏。当团队瓦解时,代码的交互就很糟糕。当团队协作时,架构就集成得很好。

此条目发表在未分类分类目录,贴了标签。将固定链接加入收藏夹。