当我们讲软件架构的时候,到底在说什么

架构这个词,是软件从建筑学借鉴来的。在建筑学中指的一个建筑设施中承受各种力的核心框架,最常见的,就是住房建筑中的承重墙和承重梁了。承重墙和梁的关键特征是,装修的时候是不能动的,房间的大布局是被承重墙和梁所限制的。因此很多人讲软件架构就是说软件系统的子系统/组件/服务的拆分与定义。在讨论架构的时候,往往会拿出一个非常漂亮的图来,里面画满了小框框,并且包含了不同的颜色,更漂亮的还会有横向的分层以及纵向的领域区分,最高级的还会加上虚线框标注的所谓平台、后台、中台、前台等各种台。

这个诠释,当然是对的。但是,还不太够。我们的软件不是学校时的课后练习题,算个斐波那契数列就结束了。真正的商用系统必须要面对的一个问题是变化,所以系统的架构除了要明确当前的划分外,还有很关键的一项内容是要明确对变化的应对原则。也即,除了当前的空间上的静态架构,还应该包含时间上的架构演进动态原则。而软件的演进,是很难在设计的当下去做出足够的预测的,尤其是贴近用户的应用类软件,能规划半年算高手,预测准一年以上要做什么而能提前布局的,绝对是专家级别了。

那我们怎么办的是换个思路,守住变化的边界,不做什么。举个例子,一个 交系统通常会有关系链的部件。那在架构设计中除了明确这个部件负责关系链外,还应该包括“关系链数据禁止不通过API直接访问”,“不提供三度以上关系链数据”等等的原则。这些原则就是在后续添加新需求,培养新成员时确保初始架构的设计目的不会被破坏的关键。至于新增的短视频也好,LBS也好,可能认识的人也好,都不会破坏关系链部件的稳定性。这些不做什么的边界原则,往往是存在于架构师的脑中,缺少明确化的显式表达与传递,才会导致在具体实现时有所偏离,尤其是在一些大型团队中,从总架构师到具体的编码开发人员之间存在了多次的信息传递,一些细小的变化对边界的破坏就会逐渐积累,埋下巨大的变化成本。

对于变化的应对原则,一个不算很恰当,但是在软件工程领域必然会了解到的著名案例就是瓦萨 悲剧了。瓦萨 作为可能是史上最有名的瑞典战舰(避免争议还是加个)之一,在设计之初,核心主架构还算靠谱,但是在国王的一再要求下,舰上的重炮数量不断增加。于是在1628年8月10日,瓦萨 建成后的第一天处女航,斯德哥尔摩港外大约离岸几百米的地方,伴随着几声礼炮鸣放,海水飞快地从炮孔和裂隙中灌入船舱,几十名船员在水下30米深处和瓦萨 一起结束了航行。事后的分析,人们提出了各种猜测和质疑,最后达成的共识是,对于不断增加的要求和变化没有坚持初始的原则。妥协葬送了瓦萨 与它的船员们。(题图就是在瓦萨 博物馆所拍的战舰实物,黑卡的广角根本在馆内找不到能拍下巨舰全身的角度与位置)

其次,用框框图来表示架构是远远不够的。软件的各个部件之间是需要交互的,他们之间的关系就是由这些交互所承载和体现。具体而言,就是对外的API与数据,以及相互之间如何利用这些API和数据。但是框图所能承载的,除了名称外一无所有。所以我们会看到太多的系统,看框图貌似各部件分工明确,职责十分清晰。但是实际代码一塌糊涂,不同的部件之间密切耦合,牵一发动全身。要么是API对外直接暴露细节数据,甚至于数据库都直接对外暴露,导致其他部件必须与本部件同步修改;要么是大而全的万能接口,使用成本极高。这些都会导致落地的代码与看似清晰的框图相差千里。

所以一名优秀的架构师,在框图之外都会直接负责,至少是参与各部件之间接口的设计工作。而接口的好坏,是与建模能力直接相关的。但这在中国目前的各企业软件团队中还属于一个稀缺能力。很多架构师,是对业务非常熟悉但是软件建模却不甚了解。因此在做架构设计的时候,往往是习惯于按照过程性的各个阶段来划分部件,推导出的接口API也是鲜明的过程化的非常具体的接口,缺少适当粒度的抽象。这样的结果就是,在新需求提出时,一连串的部件与对应接口都需要修改,俗称的烧烤签子一插到底。

总结一下,软件系统的架构,主要体现在系统的子部件划分、边界定义/演进原则、接口API三者。很多人在讲架构时候拿出来的框图,是无法涵盖架构的关键要素的。

彩蛋时间,前段时间华为公司曾经有一份关于车BU的业务的公告被广为流传。我认为那份公告充分表现出了任老板的架构水平。公告里主要就三条内容:一,车的业务划入CBG,这是讲部件划分;二,车的相关决策由xxx决定,这是在讲职责接口;三,不做整车,这是讲的边界定义与演进原则。非常清晰:)

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年1月25日
下一篇 2021年1月25日

相关推荐