0.缘起
最近在和同事以及相关领域的人沟通时,大家都在强调架构、架构图,于是兴起了一片关于架构的方法论介绍。
本文对内容的组织按照顶层设计思路,先对架构本身进行剖析:什么是架构?为什么架构很重要?这些是对架构方法论理解的前提。在对概念有明确理解后,得需要有一个好的架构设计,这部分也是架构真正的内容来源。有了架构内容后,还需要很好的呈现出来,正所谓酒香也怕巷子深。因此,本位后段会从如何通过图去描述和传达架构设计。值得注意的是,本文不会侧重单一的工具和方法论,更希望的是关注优秀方法论背后的通用方法,找到架构的本质、共性和最佳实践。
本篇内容结构:
什么是软件架构
架构有什么用?为什么重要
如何设计一个好的架构
怎么描述架构设计
架构制图方法论和工具
1.什么是软件架构
Linus 03 年在聊到拆分和集成时有一个很好的描述:
I claim that you want to start communicating between independent modules no sooner than you absolutely HAVE to, and that you should avoid splitting things up until you really need to, because that communication complexity often swamps the complexity of the actual pieces involved in it.
我们意识到:把复杂系统拆分成独立的模块,似乎并不能降低系统的复杂度,而整个系统的复杂度反而会因为拆分的模块,以及模块之间的交互变得更加复杂。
从上面的文字理解,架构来源于系统的拆分,而系统拆分最基本的出发点是为了效率,通过推系统合理拆分,最终目的是效率最大化。虽然这里延伸出了架构的概念,但并没有仔细说明什么是架构。
百度百科:
软件架构为软件系统提供了一个结构、行为和属性的高级抽象,由构件的描述、构件的相互作用、指导构件集成的模式以及这些模式的约束组成。
在 Wikipedia 上的定义:
Architecture is both the process and the product of planning, designing, and constructing buildings or any other structures.
ISO/IEC 42010:20072 中对架构有如下定义:
The fundamental organization of a system, embodied in its components, their relationships to each other and the environment, and the principles governing its design and evolution.
从上面对架构的定义,作者自己的理解:架构是系统的一种描述,由元素、元素之间的关系、以及设计与演进的基本原则构成。
2.架构有什么用?为什么架构重要
从linus的描述中,我们找到架构最本质的要点:管理系统复杂性、效率最大化。而导致架构发生变化的主要原因有两个:一个是以改善软件质量为目的的内在结构性变化;另一个是以满足客户需求为目的的外在功能性变化。但不论何种变化,架构的最终形态都是不断取舍和判断后的结果,在业务需求和系统之间实现权衡。
2.1 架构是系统实现的蓝图
在房屋建造时,我们最开始看到的一定是架构设计,设计为我们呈现了房屋的外观、轮廓、结构、功能等一系列说明,也正是基于对这些说明的理解和认可,才会有根据架构进行施工,也才让成千上百人的分工合作和验收标准有了依据。映射到软件工程领域,因为架构,我们能了解到系统的组成构成,有了系统的全盖面貌,也才有了系统实现的依据。
2.2 架构是沟通协作的基础
大型软件系统的实现,是多人、多团队协作的结果。有统一的架构设计后,才能做到:
理解对齐:架构包含系统所有早期的决策,这些决策和判断通过架构描述被记录和同步,使得项目参与成员对架构的理解对齐,形成共识。
标准术语:程序员对于造概念情有独钟,所以在软件实现过程中,可以看到各种各样的概念名称。架构的一个重要目的,就是定义和解释清楚系统中涉及的概念元素,并在整个实现中使用统一的标准术语,避免沟通过程中理解歧义;
工作量化:项目管理最重要的一环是工时评估,通过架构的理解拆分,将绝大部分的工作可以做到可见、可预测和可拆解,自然而然也就做到了可量化评估。
言之有物:每个人的记忆和抽象都不一样,在讨论高纬度的技术实现方案时,需要有具体的承载物,这也是架构的一部分;
2.3 架构决定了产品质量
软件产品质量模型最新的是GB/T 25000.10—2016,该国标对应的国际标准为ISO/IEC 25010—2011。软件产品质量模型将一个软件产品需要满足的质量要求总结为8个属性(功能性、兼容性、安全性、可靠性、易用性、效率、可维护性和可移植性),每个属性又可细分出了很多子属性。
2.4 架构的复用价值
因为同一组织内的产品之间肯定会具备很多共性(需要、限度、环境等),很适宜在架构层面进行最大化复用,防止反复解决类似的问题;
3.如何设计一个好的架构
在EA(企业架构)领域,常见的架构方法有Zachman和TOGAF。
TOGAF: 开放组体系结构框架,是英文 The Open Group Architecture Framework 的头一个字母的缩写。它是一个企业架构框架,为企业管理信息架构提供了一种设计,规划的方法。TOGAF 是国际开放组织于 1995 年开发的。
TOGAF 是一种高层设计方法,提供了 4 种建模级别:业务,应用程序,数据,技术。
Zachman:John Zachman早在1987年就提出了这种思想,它全称为企业架构和企业信息系统结构架构。Zachman框架提炼和吸收了传统方法中的一些精髓,它是一款独立于信息企业所使用的工具的平台。它可以根据抽象规则定义企业信息的一个方面.一个框架采用了一种六行,每行中包含36个子单元的格式,这六行包括了范围,商业模式,系统模式,技术模式,组件和工作系统)其中有六列分别为谁,什么,什么时间,什么地点,为什么和如何做。Zachman框架被很多企业管理者认为是一种发展IT企业和进行复杂管理的规则集合。
对个人来讲,TOGAF使用更多,再结合我们日常的业务开发,架构设计中更偏重于业务架构和应用架构,所以在如何架构这块我们重点关注业务架构和系统架构,讨论清楚如何进行业务架构和系统架构。
3.1 架构的过程就是建模的过程
从现实世界到软件世界,是一个不断抽象的过程,抽象的表现是建立模型,所以架构设计的过程也可以理解为建模的过程。首先,我们要了解什么是建模。
百度百科:建模,就是建立模型,就是为了理解事物而对事物做出的一种抽象,是对事物的一种无歧义的书面描述。
提取几个关键信息:建模是一种抽象,而抽象是基于事物本身特征对其理解的描述。把这些理解概念组织起来,构成一种对所观察的对象的内部结构和工作原理的便于理解的表达。
百度百科:从具体事物抽出、概括出它们共同的方面、本质属性与关系等,而将个别的、非本质的方面、属性与关系舍弃,这种思维过程,称为抽象。
换句话说,抽象就是做减法和做除法。通过舍弃非本质和无关紧要的部分,着眼于问题的本质,去粗取精;通过透过现象看本质,发现不同事物之间的共同之处,异中求同,同类归并,也就是做除法。
3.1.1 业务建模
业务建模的前提是对业务的理解和认识,从业务本身的价值出发,梳理业务核心流程。业务建模可以参考
业务建模一定抓住两个关键点:客户是谁?核心诉求是什么
3.1.2 系统建模
从研发实现的角度,这个阶段会产出各种各样的模型图,比如实体模型图、时序图、状态图、各个层次的架构图等等,但是无论何种角度,何种层次,系统建模一定是在业务建模的基础上,完成业务需求到系统模型之间的映射;这其中涉及业务功能到系统能力、业务流程到数据流程的映射;系统建模更强调职责、依赖、约束关系,用于指导研发的落地实现。
常用的系统建模方式:
顶层设计推演:从最上层业务问题,一层一层的剥开拆解,然后到最原子的问题。这里没有一个明确的标准到什么粒度就是原子级别,而是从问题域和解法域看。比如:做电商系统,主要核心的流程包括:商品、商家、订单等,拆解到订单维度的设计又会包括:商品订单、支付订单、物流订单等等,是否还需要进一步拆解,可根据实际情况来看;
核心实体抽取:包括对象分析法、用例分析法、问题分析法等;
3.1.3 抽象的评估
抽象由角度、层次和边界共同决定。
抽象角度:抽象角度也是分类的角度,角度不同,会导致完全不同建模方向和结果。角度的选取来源业务和目的,正所谓屁股决定脑袋。
抽象层次:抽象层次越高,细节越少,普适性越强;反之,抽象越具体,细节越多,则个性化越多;几个通用的原则有:个性化的往上抽象、通用的往下沉淀,下层可以独立于上层存在,但是上层控制着下层。
抽象边界:边界的划分来源职责和分工,这一块可结合业务领域进行梳理。
抽象最终想要达到的结果是高内聚和低耦合。
3.2 好架构的设计原则
SOLID准则是一套比拟经典且风行的架构准则。
单一职责:与 Unix 哲学所提倡的“Do one thing and do it well”不约而同;
开闭准则:用新增(扩大)来取代批改(毁坏现有封装),这与函数式的 immutable 思维也有殊途同归之妙;
里式替换:父类可能呈现的中央子类肯定可能呈现,这样它们之间才算是具备继承的“Is-A”关系;
接口隔离:不要让一个类依赖另一个类中用不到的接口,简略说就是最小化组件之间的接口依赖和耦合;
依赖反转:依赖抽象类与接口,而不是具体实现;让低层次模块依赖高层次模块的稳固形象,实现解耦。
此外,设计时也会尽量遵循如下一些准则:
正交性:架构同一档次拆分出的各组件之间,应该尽量放弃正交,即彼此职责独立,边界清晰,没有重叠;
高内聚:同一组件外部应该是高度内聚的(cohesive),像是一个不可分割的整体(否则就应该拆开);
低耦合:不同组件之间应该尽量减少耦合(coupling),既升高互相的变动影响,也能加强组件可复用性;
隔离变动:许多架构准则与模式的实质都是在隔离变动 —— 将预期可能变动的局部都隔离到一块,缩小发生变化时受影响(须要批改代码、从新测试或产生故障隐患)的其余稳固局部。
4.怎么描述架构
架构的描述主要有文字和图两种方式,但从ROI来讲,一般通过图的方式呈现架构。而好的架构图
解决沟通障碍:达成共识、减少歧义。
提升协作效率:团队内部和团队之间的协作、沟通、愿景和指导。
画架构图的时候,一定要考虑到面向对象,不同的对象诉求不同,也没有办法通过一张图就能满足所有对象的需求。架构图的目标客户至少有几类:
参与项目的团队,主要包括业务、产品、开发、测试、安全、运维;
项目之外的客户,如外部客户,评审专家;
各层次TL,用于汇报,跨 BU、跨团队协作沟通
5.架构制图方法论和工具
5.1制图方法论
架构制图本质上是从不同的视角,不同的抽象角度去描述系统。较低层次的抽象包括:应用内部包、类图,某个领域,实体图、时序图、状态图、用例图等等。较高层次的抽象包括:如微服务架构,系统间的交互图,领域/子领域架构图,整个系统架构图等等。
单从实践的角度,个人觉得何种分类不是最重要的,最重要的是想清楚面向谁和解决什么诉求,然后思考架构图到底从哪个角度、哪个层次去抽象。这也回到了我们架构图最基本的原则。
借鉴他人对制图方法论的总结,可以概括有5个方面:
理解制图指标:正所谓“以始为终”,有了指标我们才能清晰地前行。对指标的总结有:
准确:图的描述一定要准确,不能形成歧义;
完整:需要覆盖架构的核心要素和关键信息;
清晰:图的呈现内容应当清晰,流程具有逻辑自洽性;
一致:图的风格和形状统一,降低受众的理解成本;
简洁:在满足上述情况下,还有尽量保证图的简洁性,方便受众理解;
找准受众和关注点:不同受众需要接收的信息是不同的,关注点也会不一样,比如产品关注的是业务流程是否很好实现,运维关注的是资源可用性等等。
自顶向下分层描述:
多种架构试图配合:
遵循标准和最佳实际:
5.2 架构图评判
架构图的好坏,可以从两个方向,一个是需要跳出图本身去看,业务领域的抽象设计合理性,是否符合“高内聚,低耦合”的要求,这个需要回到前文的业务建模、系统建模和抽象过程去寻找答案。另外一个方向是图本身,以下几个点供参考:
内容术语一致、信息粒度大小一致,图例清晰,颜色类型统一,美观
图中的信息与相应的抽象级别相关,且满足利益相关者(合作方)的需求
一张好的架构图不需要多余的文字解释!受众有没有准确接收到想传递的信息;如果它所导致的疑问比它能解释的问题还要多,那么它就不是一张好的架构图
架构图应该帮助每个人看到大局,了解周围的环境,适当的上下文信息
架构图应该避免“只见树木,不见森林”
5.3 制图工具
本人比较常用的制图工具主要有
UML
draw.io
以上内容均来自作者对已有文献的参考,加之自身理解。若有不当之处,可指正讨论,共同进步。
参考文献:
https://blog.csdn.net/alienttech/article/details/106995406
https://lequ7.com/guan-yu-jia-gou-jia-gou-zhi-tu-gong-ju-yu-fang-fa-lun.html
https://www.cnblogs.com/jiujuan/p/16871889.html
https://www.likecs.com/show-204962729.html#sc=183
http://blog.itpub.net/14441101/viewspace-598251/