《系统架构》读书笔记:架构到底是什么?

引子

这个月读了一本书,《系统架构》。然而这本书讲的不仅仅是软件系统的架构,而是更高一个层面,它讲的是复杂系统的架构。这本书的三位作者,有两位是航空航天专业的教授和副教授,所以书里用了不少 NASA 的项目为案例,比如人类有史以来最复杂的工程——阿波罗计划。读完这本书,让我对架构的认识提升了一个高度,原先各种离散的关于架构的知识和理解,在这个框架下,终于可以融会贯通了。

系统和系统思维

首先,系统是什么?按本书的定义,系统是由一组实体和这些实体之间的关系所构成的集合,而其功能要大于这些实体各自的功能之和。后半句很重要,如果一个系统的功能,等于其部件的功能之和,那么这个系统就没有存在的意义。因为我们单独使用那些部件,也可以得到需要的功能。只有当这些部件组合时,能够涌现出新的功能,那才算是组成了一个系统。

要理解系统架构,首先要有系统思维。所谓系统思维,就是把某个疑问、某种状况或某个难题明确地视为一个系统,也即是视为一组相互关联的实体,而不是孤立的一个对象。

系统思维要有四个步骤是:
1. 确定系统整体的形式与功能。
2. 确定系统中包含的组件,组件的形式与功能。
3. 确定系统中各个组件之间的关系,并且定这些关系的形式及其功能。
4. 根据组件的功能及功能性的互动来确定系统的涌现属性。

系统思维的初级目标是理解系统是什么,更进一层的目标是为了预测系统在发生某些变化之后的情况。而最高级的目标,则是用部件来合成一个系统,这个过程也就是所谓的系统架构。

系统架构的分析

形式与功能

形式是系统的物理体现或信息体现,它有助于功能的执行。形式可以分为形式对象,以及这些形式对象之间具有的形式关系(也就是结构)。例如,汽车作为一个系统,它的形式对象就是汽车部件,而软件系统的形式对象则是模块、过程、代码和指令,而这些形式对象则通过不同的结构组装成一个系统。

系统的另一个属性就是功能。功能由过程和操作对象组成,过程在操作对象上执行之后,会改变操作对象的状态。当系统对外展现的功能对系统的外部的对象进行操作时,系统的价值就体现出来了。例如,离心泵中的电动机可以带动叶轮旋转,这是它内部的一个功能。而离心泵作为一个系统,它可以给外部对象(例如某种液体)加压,从而移动液体。这也就是它的功能和价值所在。

屏幕快照_2018-10-11_上午11.28.19

形式和功能的区别就是,形式决定了系统是什么,而功能决定了系统能做什么。架构其实就是形式与功能之间的映射。形式结构对功能起着承载作用,或者能够促进相关的性能。在复杂系统里,形式与功能的映射会非常复杂,包含很多不确定的问题,或者非理想的因素。因此架构师需要使用抽象等方法来简化架构,以便能够更好的理解和交流架构。

另外,还有一种特殊的功能,叫做解决方案无关的功能。例如,我要从上海出差去北京,那么“将旅客从上海快速、安全的运送到北京”就是解决方案无关的功能,而“使用高铁/飞机将旅客从上海运送到北京”则不是。好的系统规范书,应该是使用与特定解决方案无关的功能来描述的。如果系统规范书将人引导向某种具体的解决方案,可能会令架构师的视野变窄,从而不去探索更多的潜在选项。

从概念到架构

前面说过,架构就是功能与形式之间的映射,但对于复杂系统,这种映射往往非常复杂。架构师常常需要创造一些概念,来简单明了的解释功能是如何映射到形式的。例如前面离心泵的例子,它的解决方案无关的功能则是“移动液体”,而离心泵本身其实就是一个概念,一提到离心泵,熟悉的人一定会想到电动机、叶轮等等。其他的概念包括油电混动、高速铁路、发光二极管、快速排序、分布式缓存等等。软件开发中的各种设计模式,其实也是概念。

对于一个解决方案无关的功能,往往能提出多个不同的概念。架构师需要创造性地提出这些概念,对它们进行整理,并选定其中一个概念,将其转化为一套架构。

复杂系统的架构往往是分层的,同时我们还需要对架构进行模块化。需要注意的是,如果要对某一层的架构进行模块化,我们必须将其分解到下一层。因为只有检查各个实体在更下一层的关系,才能更好的对当前层级进行模块化。

创建系统架构

架构师

很多人常常会问,架构师的职责到底是做什么?这本书给出了很明确的回答,架构师的职责主要是以下三个方面:
- 减少歧义,确定系统的边界、目标和功能
- 发挥创造力,创建概念
- 管理复杂度,为系统选定一种分解方案

而架构师的交付成果,应该包括:
- 一套清晰、完整、连贯的目标,并且是可行的(80% 以上概率)。
- 系统所在的大环境(法律法规、行业规范等等)以及整个产品环境的描述。
- 系统的概念以及操作方式。
- 系统的功能描述(至少两层分解),除了系统对外界展现的功能,也包括系统的内部功能。
- 系统的形式(至少两层分解)和形式结构,以及功能和形式之间的映射。
- 所有的外部接口以及接口控制过程的详细描述。
- 开发成本、工期、风险、实现计划等。

消除歧义,确定目标

为了消除歧义,架构师必须首先理解上游和下游的相关因素对系统架构的影响。上有因素包括:公司策略、营销、法律法规、行业标准、技术成熟度等,下游因素包括实现(编码、制造、供应链管理)、操作、产品与系统的演化。

复杂的系统一般会涉及多个的利益相关者,他们会有不同的诉求和目标,架构师需排定各项目标之间的优先次序。首先,可以把价值视为一种交换,在交换过程中,我方的成果用来满足对方的需求,而对方的成果也同样用来满足我方的需求。其次,可以根据利益相关者对本产品的重要程度,来排列其优先次序。最后,则可以把系统的目标,展示在系统问题描述中(System Problem Statement, SPS)。

发挥创造力,创建概念

接下来,架构师就需要发挥创造性、创建概念了。创造概念,主要有两种方式,一种是无结构的方式,一种是结构化的方式;无结构的创新包括头脑风暴法、自由联想法等方法。对于一些包含多个功能的丰富概念,我们可以对其进行扩展和分解,提出对应的概念片段,而这些概念片段组合后,又会形成新的整体概念。最后通过定量和定性分析,筛选出 2~3 个作为候选概念。

管理复杂度,为系统选定一种分解方案

架构师另外一项工作,就是分解系统,管理复杂度。系统的表面复杂度就是系统的难懂程度,表面复杂度高的系统理解起来会比较困难。架构师可以通过抽象、层级化、分解及递归等手段来减少表面复杂度,但这样做可能会提升实际复杂度。其中架构师最重要的一项决策,就是对系统进行的分解。要判断一种分解方式好不好,必须先向下分解两层,并根据第二层的分解情况,来检查第一层的分解方式是否合适。另外,架构师也要选择合适的分解平面,例如可以按功能分解、按形式分解、按模块变化程度分解、按供应商分解等等。

架构决策

其实架构方面的决策也可以用一些程序化的方法进行计算,以帮助架构师进行决策,这部分比较枯燥就不细说了。不过书中提到架构决策的模式,还有点意思,一共有六个模式:
1. Decision-Option(决策-选项):一组决策,每个决策都有一套离散选项。例如,开始一个系统需要做一下两个决策,决定数据库和 API 接口的使用何种技术:数据库是用 MySQL、MongoDB 还是 Cassandra,API 接口是用 HTTP 还是 Protobuf。这就是一个 Decision-Option 决策。
2. Down-Selecting(筛选):一组二选一的决策,代表选择实体中的某个子集。例如,我要从全国各地的 候选 IDC 机房中,选择合适的机房来部署 CDN,就是一个 Down-Selecting 决策。
3. Assiging(指派):把一个实体集中的元素,指派给另一个实体集中的某个或某些元素。
4. Partitioning(分区):把一个实体集的元素划分为多个互斥的子集,并且覆盖所有元素。这是模块分解的典型决策模式。
5. Permuting(排列):在一个实体集和一个位置集之间建立一一对应关系。
6. Connecting(连接):给定一个用图中节点表示的实体集,用一组连线展示这些节点之间的关系。网络拓扑结构的决策就是一个 Connecting 问题,即选择星形拓扑、环形拓扑或者总线拓扑等等。

书里用了一个很牛逼的例子——阿波罗计划,来说明架构决策的方案。

屏幕快照_2018-10-11_上午11.30.41

总结

看完这本书,你会发现,其实所有的架构,软件也好、汽车飞机等各种机器的架构也好,都是相通的。甚至我各种生物组织、团队组织的架构,也是一样的道理。只要我们能掌握系统架构的思维,再加上各个领域的专业知识,我们就能做出一套优秀的架构。

系统架构原则

书中最后总结了系统架构的二十六个原则,我摘录在这里供大家参考:

涌现原则:当各实体拼合成一个系统时,实体之间的交互会把功能、行为、性能和其他内在属性现出来。

整体原则:每个系统都作为某一个或某些个大系统的一小部分而运作,同时,每个系统中也都包含着更小的一些系统。

聚焦原则:在任何一个点上都能发现很多影响系统的问题,而其数量已经超出了人们的理解能力。因此,我们必须找出其中最关键、最重要的那些问题,并集中精力思考它们。

二元原则:所有由人类构建而成的系统,其本身都同时存在于物理领城和信息领域中。

受益原则:好的架构必须使人受益,要想把架构做好,就要专注于功能的涌现,使得系统能够把它的主要功能通过跨越系统边界的接口对外展示出来。

价值与架构原则:价值是有着一定成本的利益。架构是由形式所承载的功能。由于利益要通过功能而体现,同时形式又与成本相关,因此,这两个论述之间形成一种特别紧密的联系。

与特定解决方案无关的功能原则:糟糕的系统规范书总是把人引向预先定好的某一套具体解决方案、功能或形式中,这可能会令系统架构师的视野变窄,从而不去探素更多的潜在选项。

架构师角色原则:架构师的角色是解决歧义、专注创新,并简化复杂度。

歧义原则:系统架构的早期阶段充满了歧义。架构师必须解决这种歧义,以便给架构团队定出目标,并持续更新该目标。

现代实践压力原则:现代产品开发过程是由同时工作着的多个分布式团队来进行的,而且还有供应参与,因此,它更加需要有优秀的架构。

架构决策原则:我们要把架构决策与其他决策分开,并且要提前花一些时间来道慎地决定这些问题,因为以后如果想变更会付出很高的代价。

遗留元素复用原则:要透相地理解遗留系统及其现属性,并在新的架构中把必要的遗留元素包据进来。

产品进化原则:系统必须进化,否则就会失去竟争力。在进行架构时,应该把系统中较为稳固的部分定义为接口,以便给元素的进化提供便利。

开端原则:在产品定义的早期阶段列出的(企业内部和企业外部的)利益相关者会对架构产生极其重大的影响。

平衡原则:有很多因素会影响并作用于系统的构想、设计、实现及操作,架构师必须在这些因素中寻求一个平衡点,使大多数重要的利益相关者得到满足。

系统问题陈述原则:对问题所做的陈述会确定系统的高层目标,并划定系统的边界。就问题陈述的正确性进行反复的辩论和完善,直到你认为满意为止。

歧议与目标原则:架构师必须解决这些歧义。以便提出几条有代表性的目标并持续地更新它们。这些目标要完备且一致,要兼具挑战性和可达成性,同时又要能够为人类所解决。

创新原则:在架构中进行创新,就是要追求一种能够解决矛盾的好架构。

表面复杂度原则:我们要对系统进行分解、抽象及分层,将其表面复杂度控制在人类所能理解的范围。

必备复杂度原则:系统的必备复杂度取决于它的功能,把系统必须实现的功能仔细描述出来。然后选择一个复杂度最低的概念。

第二定律原则:系统的实际复杂度总是会超过必备复杂度。架构师要令实际复杂度尽量接近必备复杂度。

分解原则:分解是由架构师主动做出的选择。分解会影响性能的衡量标准,会影响组织的运作了式及供应商的价值捕获潜力。

二下一上原则:要想判断出对 Level1 所做的分解是否合适,必须再向下分解一层,以确定 Level2 的各种关系。

优雅原则:对于身处其中的架构师来说。如果系统的必备复杂度较低,而且其分解方式能够同与多个分解平面相匹配,那么该系统就是优雅的。

架构健壮程度原则:好的架构要能够应对各种各样的变化。能够应对变化的那种架构,要么是比较健壮架构。要么是适应能力比较强的架构。前者能够处理环境中的变化,而后者则能够适环境中的变化。

架构决策的耦合与整理原则:可以按照指标对决策的敏感度以及决策之间的连接度来排定架构决策之间的先后顺序。

0

我们正在招聘Java工程师,欢迎有兴趣的同学投递简历到 rd-hr@xingren.com

发表评论

电子邮件地址不会被公开。 必填项已用*标注