任何在 IT 公司工作的人,对于“架构”这个词应该都不陌生。但你去问“架构”这个词是什么意思,似乎又有点只可意会不可言传的意思。那么
- “架构”这个词,它应该如何定义呢?
- 架构设计对于软件系统和软件开发而言起到的作用是什么呢?
- 软件系统或软件产品的架构应该用什么样的方式表达呢?
这篇文章,会尝试讨论一下上面这些问题。
如何定义架构设计?
我们先来看一个古老的的思想实验:
忒休斯之船(The Ship of Theseus)最早出自罗马帝国时代普鲁塔克的记载。它描述的是一艘可以在海上航行几百年的船,归功于不间断的维修和替换部件。只要一块木板腐烂了,它就会被替换掉,以此类推,直到所有的功能部件都不是最开始的那些了。问题是,最终产生的这艘船是原来的那艘忒休斯之船,还是一艘完全不同的船?如果不是原来的船,那么在什么时候它不再是原来的船了?
(摘自百度百科)
哲学家们为了这个问题争论不休,而它也被称为“忒休斯悖论”。“忒休斯悖论”实际上问的是,一个物体是不是等于组成它的各个部分的总和?如果答案是肯定的,那么当船上所有木板都被更新了,那么这条船当然是一艘完全不同的船了。但是,直觉告诉我们,这条船还是原来的那条船啊。如果不是这样,一所学校,学生几年就全换一遍,老师几十年全换一遍,难道这所学校就是一所新的学校了?一条河,河里的水奔流不息,难道这条河就不是原来那条河了?也就是说,我们凭直觉知道,一个物体并不等于组成他的各个部分的简单加总。那么,它到底等于什么呢?
要回答这个问题,就需要引入系统论的观点了。科学研究的主要方法,是把复杂事物拆解成一个个简单模块来分析,这种思维模式叫做“还原论”。然而,人们发现,还原论可以很好地解决单个事物的问题,却很难解决系统性、结构性的问题。想要解决这些复杂问题,必须重新回到“整体论”,而系统论正是研究这一领域的学科。
在《系统之美》这本书中,“系统”不是一堆事物的简单集合,而是由一组相互连接的要素构成的、能够实现某个目标的整体。任何一个系统都由要素、连接和功能(目标)构成。譬如对于忒休斯之船,其要素是一堆木板,连接是这些木板的位置和铆合关系即结构,而功能就是航行。系统论讲的是广义上的系统,房间的温度、公司的经营、国家的经济,都可以用系统论的模型去进行描述。
软件系统,也是一种系统,因此也可以用系统论的方法进行描述。架构就是构成软件系统的要素、连接和目标。架构设计就是找到软件系统中的要素,并将要素之间的连接描绘清楚,从而实现软件系统目标的过程。
为什么架构这么重要?
架构清晰,才能理解问题
《系统之美》的作者说,当我们看一个系统时,往往只会注意到系统的要素,而忽略掉系统的连接和目标。但对于一个系统而言,要素往往不是最重要、随时可以替换的。如果改变了系统的连接,那么系统就会发生巨大的变化。譬如在大学里,如果不是教授给学生打分,而是学生给教授打分,那么大学就不再是大学而是商业培训机构。而比连接更重要的是目标,譬如大学的目标如果不是教书育人,而是赚钱盈利,大学也会成为另外一种系统。
软件系统是一种非常抽象和复杂的系统,软件系统的构造是一个非常复杂的问题。普通人去理解软件系统往往只能看到其中的要素(功能模块),而看不到要素之间的连接(模块之间的关系),但如果不能确定功能模块之间的关系而直接进入到开发状态,由多人或多个组织单元从事的软件系统的开发就会陷入混乱,在耗费大量的人力物力和时间成本后,发现难以达成想要的目标,只留了一堆需要继续投入人力成本维护的代码。
架构合理,才能应对变化
《人月神话》中有一句名言:软件开发过程中,唯一不变的就是变化本身。变化就会带来软件系统的熵增,即软件的生命力从最初的理想状态,逐步趋向于复杂、混乱和无序的状态发展,直到软件不可维护而被迫下线或重构。显而易见,对于从事软件系统开发的商业组织而言,熵增的后果就是无法满足客户需求导致的收入减少和成本居高不下。而业界多年成功和失败的经验已经证明,软件系统熵增的根本导因就是架构设计被忽视。
例如大多数软件项目都采用了快速迭代的开发方法,即从软件的一小部分重要功能模块开始开发,逐步增加新的功能模块。这种方法带来好处的同时也带来了问题,系统开发过程中会不断引入新的要素(功能模块),这些新的要素的引入很可能会打破原本已经存在的要素之间的连接(功能模块之间的关系)。如果在开始开发之前没有进行架构设计,将所有重要的要素都找出来、理清要素之间的连接并证明其可以支持系统达成最终的目标,那么在开发过程中就会需要不断进行重构,或者因为“技术无法实现”而放弃某些功能。
架构稳定,才能积累能力
得到App《启发俱乐部》第29期《能力如何增长?》中有这样一段话:
能力增长,不是兵来将挡水来土掩,遇到问题解决问题的结果。而是一开始就有一个初始架构,这个架构不提供答案,但它提供了一组永恒的问题,同时屏蔽了那些不指向能力积累的解决方案。
玩儿过 Linux 的程序员应该都听说过“神的编辑器" Emacs,这是一款 1975 年开始开发并至今仍有用户使用文本编辑器,而它居然还能支持多种 1990 年代后出现的编程语言的开发与调试。相似的例子还有 Eclipse,它除了作为最初的 Java IDE,还被改造为多种其它用途。
为什么这些软件能够经过数十年的发展依然经久不衰,支撑了在当年不可能预见的需求;而有很多软件产品每隔三五年就要进行一次完全的翻新、不能在最初的版本上进行向前兼容的演进,不断积累能力?因为在进行软件产品开发前没有进行必要的架构设计,这样就根本找不到那“一组永恒的问题”。于是面对客户的“定制需求”时,就只能“真的定制”,给出无数不能指向能力积累的解决方案。
这种状态不仅导致软件系统的交付周期延长、质量下降,也会导致提供软件产品或服务的商业组织大量收入变为成本而无法成为利润。
软件系统的架构如何描述
关于软件系统的架构如何表达方法,在行业里争论就比较多了,由于所处的环境和工作背景的不同,每个人的理解都不太一样。但目前在行业中,有一些共识是架构的表达需要分层分类,不可能简单的用一张 PPT 就描绘清楚软件系统架构的所有问题。
行业中比较常见的关于架构分层分类的方法是:业务架构、应用架构、数据架构、技术架构。这些词被放到不同的环境中时,其具体含义也会发生一些变化,但其底层逻辑是一致的。
业务架构:对于软件系统开发者而言,其最终的目的是为了实现客户的概念目标(战略目标),而概念目标往往是一些比较含糊的描述,并没有给出具体的实现方法;因此概念目标必须被拆解为具体的业务目标,即通过开展哪些业务,怎么开展来把概念目标实现;在业务目标出现后,能推导出系统的功能目标,即系统应该具有哪些功能模块。概念目标,往往是客户的高层领导关注的,业务目标则是具体的业务负责部门领导关注的,而功能目标则是软件系统的操作者关注的。业务架构的核心是把要实现软件系统业务目标所需要的业务有哪些(要素),这些业务之间的关系(连接)是什么讲清楚。把业务搞清楚,不仅仅是架构的问题,也是真正理解用户需求,并且给出明确的问题解决方法的过程,而这也是业务专业性的体现。
应用架构:业务架构设计是在不考虑软件实现方式的前提下进行的,如何实现业务设计以及如何体现信息化给业务带来的价值提升则是应用设计阶段要解决的问题,在这个阶段就要进行应用架构的设计。应用架构为子系统划分了明确的边界,深刻影响系统功能组织、代码开发、部署和运维等各方面。应用架构定义系统有哪些模块或子系统、以及它们之间如何分工和合作。同时,系统的可扩展性、可配置性问题,往往也需要在应用架构设计阶段给出答案。可以看出,做业务架构设计的人,不一定要懂技术知识,但做应用架构设计则是要同时拥有业务知识和一定的技术知识。
数据架构:数据架构要回答的是软件系统重数据的来源、数据模型、数据存储或其分布、数据流向以及数据管理的相关内容。
技术架构:技术架构关注的是软件系统的实现问题,其中包含了从技术选型、代码开发、测试到最终部署的各种问题。
在上述四类架构设计工作中,应用架构通常是最为薄弱的环节,因为业务架构可以由不特别懂技术的人做,技术架构可以由不特别懂业务的人做,而应用架构需要能深刻理解业务又懂技术的人做,这样的能力往往需要多个工种的工作经验和长时间的积累才能获得。当然,应用架构做的越好,也越容易给商业组织带来竞争力。
结语
如前文所述,如果在软件系统开发前,没有将架构问题解决,那么会给开发工作带来无尽的麻烦。而对于从事 TO B 软件产品或服务开发的商业组织而言,因其所提供的产品或服务要面对不同客户,也一定会面对不同客户的不同需求所带来的定制化问题,架构设计的重要性就更加不言而喻。
因此在产品或服务的立项阶段和研发过程中的设计阶段,就必须将业务架构、应用架构、数据架构和技术架构中的关键问题描述清晰,并且该产品或服务的功能越多、部署方式越复杂就越需要认真完成这一工作,不可绕过。如果只是把 UI/UE 设计完成就开展相关的研发工作,一定会在熵增的路上越陷越深。