每个业务系统的开发者都应该具备一定的架构师素养,架构师的重要职责不仅仅是做决策,更重要的是提升团队的整体能力。一个好的架构师应该聚焦于业务和系统,定义问题和结果,设计系统、模块和代码,同时也需要解决跨域问题,确定团队间的边界,制定规范,统一语言,并创建一个让每个人都能成长为架构师的环境,以促进团队的敏捷性。本文旨在探讨如何培养架构思维,并阐述了架构师的职责、能力模型、方法论,以及如何成为架构师。
前言
对于架构师的职责,最近感慨颇深;很认同知名工程师Martin Fowler说的,
Improving the development team’s ability gives an architect much greater leverage than being the sole decision maker.
Martin Fowler
大意就是提高团队整体能力的架构师比只做决策的架构师更牛逼。
因为对于每个业务系统,我们都需要从这个业务的架构视角进行代码开发/优化和迭代,所以每个业务系统的开发者,都应该要有架构师属性,这里我将其定义为纵向架构师;对于目标在提高整个团队水平、确定多业务边界的,则定义为横向架构师。
纵向架构师需要聚焦业务和系统,做问题和结果的定义,做系统、模块、代码设计;横向架构师需要解决跨域问题,确定跨团队边界,定义规范,统一语言,定义纵向架构能力基础/标准的成长路径和方法论,让人人都成为架构师,让团队更加敏捷;简而言之,其核心过程是探讨如何完成架构设计,如何拥有架构思维。
什么是架构师
▐ 2.1 什么是架构师
引用维基百科的定义:
软件架构师定义和设计软件的模块化,模块之间的交互,用户界面风格,对外接口方法,创新的设计特性,以及高层事物的对象操作、逻辑和流程。 软件架构师与客户商谈概念上的事情,与经理商谈广泛的设计问题,与软件工程师商谈创新的结构特性,与程序员商谈实现技巧,外观和风格。
总结一下,架构师需要提炼需求方关于项目的概念并和需求方有统一的沟通语言;需要基于利益相关方总结关键质量属性,给出满足质量属性的软件系统架构设计;需要与开发工程师共同进行软件系统的落地。
这里的质量属性指的是评估系统性能的非功能性需求,如可扩展性,可用性,一致性等;wiki中的定义如下:
Within systems engineering, quality attributes are realized non-functional requirements used to evaluate the performance of a system.
基于wiki对架构师的定义我们可以看出,架构师的能力模型需要包含:
- 挖掘/提炼需求描述的能力:客户/产品的prd往往描述得比较局部,会缺少一些上下文或者产品上认为不重要的部分 ,相信很多同学还经常收到一句话需求,更有甚者就简单地说和XXX产品一样。这时候就需要架构师将需求的迷雾层层拨开,了解需求详情、业务目标,了解不同的利益相关方动机、关注点;
- 架构设计能力:关键架构需求中,有一个点就是架构师及团队的经验和特长,比如我们用lindorm更多,那么我们在选型中就会更青睐于lindorm,因为这对项目的开发、运维成本以及进度风险会更低;但与此同时,我们也要承担这个选型带来的一些缺点;所以架构设计方法除了本文讲到的方法论,还很依赖于架构师的技术前沿性。就像一位前辈所说的,“每时每刻都在发生技术的升级和变革,只有持续不断的学习,才能对老的架构有新的认识,对于老的问题产生新的解法,要了解业界最近在发生什么变化,这个领域最关键的项目和人在做什么,学习他们的技术,学习他们的论文”;
- 代码落地能力:架构师要能够和开发工程师一起完成代码编写落地,这块本文不过多赘述;
总而言之,架构师是需要在日常中,多维且持续去坚持锻炼的,包括业务抽象能力、代码能力、复杂问题的解决能力、计算机基础、sql调优,项目管理推进能力等。
▐ 2.2 方法论
这里把方法论单独拎出来,一是因为要聊如何成为架构师,就要聊成为架构师的方法论和实践的故事;二是在刚参加工作的时候,我应该和大多数同学一样,认为方法论很虚头巴脑;原因也很简单,因为那个时候没有足够的经验对方法论感同身受,也没有接纳方法论的那份心情。现在回过头来看,学习方法论->实践->基于方法论对实践进行反思 的循环,正正是我们自身能力螺旋上升的典型模式。
再讲一个更亲切地能说明其重要性的例子。我们都知道关于路程/时间/加速度有两条非常容易通过实验得出的公式:s = 1/2 * (V0 + Vt) * t、a = (V0 - Vt) / t;基于这两个公式,我们一顿推导,将时间t消掉,可以得到 Vt^2 - V0^2 = 2as的公式,应用非常的广;经过我们多次的刷题实践和思考,这个公式在我们心里已经是一条基础公式,做题的时候,我们完全不需要再耗费精力去将它推导得出。
Vt^2 - V0^2 = 2as 这条公式,就是一个【方法论】。初看这条公式的时候,觉得也不过如此,静下来推导一番,也能够得出,然后再用它去解决问题。但是推导它是需要耗费精力的,人最宝贵的资源之一就是精力;当你将这个公式作为一个方法论铭刻于心后,在解决关于这个公式的相关问题时,就可以释放出推导它的这部分精力,用来解决更有挑战性的部分。
可见,我们还在读书的时候,已经深刻且频繁地在使用方法论了。
纵向架构师思维
这篇文章的标题是人人都是架构师,这里最重要的其实是希望人人都具备架构师思维;忘了之前看的哪篇文章里面有写到,“不一定人人都能够是经济学家,但可以人人都具备经济思维;不一定人人都能够是历史学家,但可以人人都具有鉴往知来的思维”;写得很精辟。
要完成这一章的探讨和编写,需要回答好这么几个问题。架构是什么?架构师要解决的问题有哪些?解决这些问题的方法论是什么?
▐ 3.1 架构是什么
在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.
这个定义对架构的描述高屋建瓴;它描述了架构是由组成模块、特定上下文环境下模块间的关系、指导模块和关系发展的原则。
就像代码中的基类一样,越顶层的抽象描述事物的范围越广,对于软件系统架构,我们其实可以从一个软件系统最终落地的结果来看,得到软件系统架构关于架构的具体实现:
- 系统模块架构
- 模块:系统分层模块,应用模块,外部服务模块;
- 关系:模块依赖关系,模块数据流转方式;
- 原则:模块划分方案。
- 对象架构
- 模块:类,有哪些核心类,类职责是什么;
- 关系:类继承关系,类与类之间的依赖关系;
- 原则:类设计指导思想和关注点;
- 数据存储架构
- 模块:库表模块,描述有哪些数据库、有哪些表,如何做分库分表,数据库如何选型;
- 关系:表关联关系,不同数据表之间的一对多/一对一等依赖关系;
- 原则:数据存储选型/设计方案和关注点,设计考虑的核心质量属性;
▐ 3.2 架构师要解决什么问题
在上文中我们讲到软件系统架构有哪些,这些也正是架构师要产出以及要落地的内容,即输出;对于业务系统而言,我们的输入往往是业务需求/技术需求的描述集合。如下图所示,其中的长方形就是架构师要解决的问题:如何将业务/技术需求描述加工成落地的软件系统架构。
从上文中讲到的数据存储架构/对象架构/系统模块架构向上推导,我们需要有业务领域模型,才能够设计软件系统的领域模型;而要得到业务领域模型,我们需要对需求充分了解,充分挖掘,并评估各个利益相关方关注的核心质量属性和业务目标。因此,架构师要解决的问题如下图所示:
从上往下,我们首先需要了解需求,包括利益相关方的业务目标/动机、关键架构需求和用例集;其中利益相关方的业务目标和动机会影响质量属性的优先级以及架构的设计选型;关键架构需求一般包含以下四块:
- 约束:给定的不可更改的设计决策;
- 质量属性:评估系统性能的非功能性需求,是利益相关方判断软件系统是否好用的一切外部可见特性,包括响应耗时、sla、可伸缩性、可用性、可维护性、可测试性等;其表征系统在特定环境下的运行情况,设计决策一般都会提高或者抑制一个质量属性,比如性能和可读性等。这点非常重要,在模式选择的时候,需要基于质量属性进行抉择;
- 影响较大的功能需求:需要特别注意的特性和功能;
- 其他影响因素:架构师/团队的经验、特长等;
最后是用例集,它是一组相关的成功和失败的场景集合,用来描述参与者如何使用系统来实现目标;优秀的产品的prd文档,应该要无限接近于标准的格式化用例描述集合,它是原始产品方案通过多轮沟通对焦,得出来的标准化语言,一个用例应该要包含 参与者(可以是系统或者用户)+前置条件(在什么场景下)+如何使用系统+经过什么规则+产生什么结果;而这样的用例集合,应该要能够描述出产品系统的功能全貌。
当能够从业务目标、关键架构需求和用例集将需求描述清晰了之后,就可以开始用业务模型来描述项目产品,这一层设计的是问题空间中的领域模型,它是对客观物理世界中概念、规则、关系的分析和描述,与软件系统无关。引用前辈的总结,“这个层次上的实体我们称之为概念实体,这部分内容是用在需求和业务分析上的,讨论业务概念模型时完全不需要考虑软件的实现,这个过程是一个分析过程,即使不做软件研发,做其他的研发,类似的分析过程也应该是有的”。《实现领域模型驱动》这本书也对问题空间做了定义,“问题空间是顶级域和其他域的组合,以及域之间的关联关系,即使没有软件的存在,这些域还是存在的,域之间的关系也还是存在的,领域模型之间的关系也还是存在的”。
最后我们要把问题空间的领域模型映射到解决问题空间,《实现领域模型驱动》中对解决问题空间的定义是“一组特定的软件模型,它通过软件的方式来实现解决方案”,这一组特定的软件模型,也就是我们要产出的软件系统架构(系统模块架构、对象架构、存储架构)。现在有很多讲架构的文章,大多是讲的这一层的故事,甚至于讲的是这一层中系统模块架构的故事。比如mvc架构,六边形架构,洋葱架构,整洁架构等。《领域驱动设计,软件核心复杂性应对之道》 中则花了非常大的篇幅,讲实体、值对象、服务、聚合根、工厂、仓库、界限上下文等,这是一套将问题空间领域模型映射到解决空间对象架构的设计模式。
▐ 3.3 怎么解决架构师要解决的问题
- 3.3.1 了解需求
千里之行,始于足下。只有了解了需求,了解了利益相关方关注点,了解了业务目标,我们才能制定设计策略。
3.3.1.1 利益相关方
首先我们要梳理需求的利益相关方关注点图表:
优先级 |
相关方 |
关注点 |
1 |
消费者 |
xx |
2 |
业务方1 |
xx |
3 |
业务方2 |
xx |
4 |
产品经理 |
xx |
5 |
上游1 |
xx |
6 |
下游1 |
xx |
7 |
测试 |
xx |
. . . |
这里将相关方进行排序,优先级越高的,他的关注点就更能影响后续决策。
与利益相关方进行沟通之后,我们要与他们明确业务目标:背景(原因)+ 主体 + 结果。业务目标是架构的主要驱动因素,多个利益相关方冲突时,以业务目标进行排序抉择。
3.3.1.2 关键架构需求
关键架构需求指的是能够显著影响架构中的结构选择的需求,一般有四类:约束、质量属性、影响较大的功能需求、其他影响因素。具体的定义已有讲到,这里不做赘述。
- 约束:约束是架构中不能被打破的原则性前提;如果描述的语法类似于“要尽可能地xxx”、“如果能xxx那就更好了”,这种就不属于约束,约束的语法应该是“必须xxx”。由于约束的不可变性,我们要尽可能减少约束性需求。可能是产品链路还没有思考清楚,可能是业务模型还没有理清,水平不高的产品往往并不知道新增约束会带来的后果,由于新增约束通常会带来架构设计上的便利,加速项目功能上线,这些产品在前期会给出很多并不恰当的约束,导致后续技术债难还,这就需要架构师慧眼识珠了。
- 质量属性:质量属性与功能性需求无关,所以很容易被忽略。但是在模式选择和方案设计的时候,通常需要基于质量属性做设计决策。因此要有一个质量属性优先级的排名,比如说数据一致性、事务性、可测性、数据准确性等,我们可以通过质量属性网格或图表,对利益相关方关注的事项和原始质量属性场景进行提取、分类、完善、排定优先级,可视化头脑风暴和与利益相关方的沟通结果。如下图,是我摘自《List of Quality Attributes for Grid Monitoring Tools》的一个示例。
- 影响较大的功能需求:需要特别注意的特性和功能;
- 其他影响因素:虽然它叫“其他影响因素”,但是它对最终架构选型至关重要;架构师和团队的经验会大大影响我们对技术框架的使用和对基础存储的选择,因为熟悉的事物对项目的进度风险,对后续的运维成本,都会小很多。所以架构师要不断学习新的知识,了解技术升级和变革。