学点架构师思维和技能总是有益的。
架构是关于软件系统的一系列重大设计决策的有机整体,实现期望的质量属性和业务目标。
架构是站在系统全局视角思考和构建软件,解决问题。系统全局,包括系统和与系统相关的所有人员。
《架构师修炼之道》清晰简明地阐述了架构师的职责、思维、技能和工具箱。全书内容更侧重沟通维度的技能,适合作为手册,放在桌边边读边学边练边用,一个小技能一个小技能地落实。
职责与影响力
软件架构师做什么
从系统全局出发,指导开发团队一起实现系统的短中长期业务目标,推进项目成功。
- 挖掘和确定关键架构需求。需要与主要利益相关方、最终用户深入交谈。
- 从工程角度定义问题。关注软件的上下文语境,定义质量属性。
- 分解系统,分配职责。确定构成软件的主要模块(子系统)及模块(子系统)之间的关联。
- 确定系统关键质量属性。需要在质量属性之间权衡取舍。
- 关注核心功能实现。确定系统所面临的核心技术难题,并推进确定对应的技术决策和方案。
- 展示和评估系统的关键决策。通过各种视图、图表从多个视角展示软件的全景图和主要组成部分。
- 管理技术债务。
- 提升团队成员的设计技能。
针对每个项目提问
- 利益相关方是谁,主要业务目标是什么?
- 整体解决方案是什么?
- 涉及哪些技术?
- 最大风险是什么?如何克服?
- 有机会重做,如何改进?
架构之于软件开发
架构在软件开发中的作用
- 将大问题分解为容易处理的小问题。
- 为协同工作提供总体指导和方向。
- 为讨论复杂设计提供基本词汇。
- 重点解决系统质量属性。
- 兼顾考虑成本、约束、进度、风险、交付。
- 避免犯重大错误。
- 让软件更加灵活。
架构不做什么:有所为有所不为
- 不做过于细节的具体决策,除非细节与系统关键质量属性相关。
- 不涉及非核心功能的实现,除非影响系统核心功能。
- 不关注功能需求的实现,但关注关键架构需求。
架构目标与衡量
从“质量-效率-成本”铁三角维度来说,架构的目标就是站在系统整体看待和解决问题,提升研发效率和关键质量,降低长期维护成本。
架构思维
基本思维
- 系统全局:始终坚持站在系统和全局的视角看待和解决问题。
- 以人为本:理解利益方需求,关心最终用户,考虑程序员、测试人员、项目经理、运维等。
- 推迟决策:不到成熟一刻,不着急做出最终决策;低优先级的事情,推迟决策。
- 善于借鉴:研究和借鉴已有的设计成果和设计模式。
- 化虚为实:让想法具体化形象化,将架构展现出来。
- 极简主义: 只关注高优先级的质量属性,提升这些质量属性同时降低风险。
基本方法
- 思考循环:分解问题 => 理解问题 => 澄清问题 => 清晰描述问题 => 探索设计 => 展示设计 => 评估设计可行性和适用性 => 实施设计 => 反馈效果
- TDC循环:思考、动手、检查。
知识与技能
架构师的知识体系是建构在组件级别和团队的级别上的。
- 深入理解各种软件设计原则和工程思想;
- 善于系统需求分析,擅长沟通,能够挖掘出关键架构需求;
- 熟悉领域建模,能够为业务建立合适的架构模型;
- 熟悉各种技术架构模式,确立系统关键质量属性;
- 能够推演系统可能面临的技术难题并设法解决;
- 熟悉各种组件模块之间的依赖、复用、解耦关系和方法;
- 熟悉开发架构、业务架构、部署架构、数据架构等多种架构视图;
- 熟悉如何引导、探索、展示、评估设计的各类方法和工具箱;
- 有能力在团队里提倡架构思维,提升团队成员的架构设计能力。
架构师在关于质量和目标的权衡取舍、判断力和直觉上有很强的敏锐度和丰富的经验。
架构技能
确定关键架构需求(ASR)
关键架构需求,是指显著影响架构设计的需求。主要有:约束、影响大的功能需求、系统质量属性。
用约束限制设计选择
约束有业务约束、技术约束和法律政策文化上的约束等。约束确定后不能讨价还价,因此接受约束要慎重。适当约束可以简化问题,过度约束会增加设计难度。
影响大的功能需求分类
将系统功能需求分类为少数有代表性的类别,筛选出影响力大的功能需求,针对每一类影响力大功能需求,确立质量属性需求。
影响力较大的功能需求具有如下特征:
- 高优先级的
- 有难度的
- 反映一种类别的架构问题
比如入侵检测系统的影响较大的功能需求分类:
- 入侵行为检测流程:准确度、及时性、稳定性、可扩展性;
- 告警列表和详情:查询性能;信息的丰富度;
- 规则管理:大量规则下发的性能与稳定性;
- 检测配置:检测和响应行为的灵活度控制;
- 威胁情报: 性能与稳定性;威胁情报的准确度、及时性、丰富度。
需要着重考虑这些功能需求所需要的架构特征、质量属性。
定义系统质量属性
系统质量属性是架构需求中最主要要满足的需求,用来指导技术、结构、模式以及评估设计决策合理性。用场景描述质量属性,定义量化目标。
质量属性有全局质量属性和模块质量属性。全局质量属性通常指系统的稳定性、可用性、可移植性;模块质量属性通常指性能、可扩展性、可维护性等。系统质量属性其实可以归结为高优先级的模块的质量属性。
对于某些质量属性的量化,业界已经有比较成熟的实践。性能衡量有量化的目标,比如 RT, QPS, TPS; 可用性也有量化的目标,比如 x% 的可用性代表多少分钟不可用。
谨防“方案型需求”的陷阱
你或许听过方案型需求及其弊端。何为方案型需求?如何区分方案型需求和真实需求?从词汇用语上辨别。方案型需求的词汇是 do what,比如“我要一个XXX”;真实需求是 for what or problem in scene,比如“我在XXX场景下遇到了一个问题,无法或很难达成XXX的目的”。
产品经理给到开发人员的大部分都是方案型需求,即将客户真实需求经过仔细思考、过滤、转换后的产品化方案需求。好的产品经理能够尽可能让产品化方案需求实现真实需求,但普通的产品经理则可能误解客户的真实需求,或者直接把业界的方案搬来用。
谨防“方案型需求”,就要多问几个为什么:为什么客户需要这个功能?在什么场景用来做什么达成什么目的?使用频繁度如何?功能缺失的影响程度如何?一步步接近客户遇到的真实场景、问题和需求。
需求分析,可以阅读徐峰老师的《有效需求分析》一书,掌握基本的需求分析方法。
建立架构模型
架构模型确定了系统的整体结构特征。架构模型应当包含两部分:
- 技术角度:架构模式
- 业务角度:领域模型
建立良好架构模型的优点有:
- 丰富设计词汇。架构模型为架构师向开发人员及管理人员、利益相关者阐述架构及业务影响提供了丰富有效的词汇和表达能力。
- 关注重要细节。架构模型能够让关乎质量属性和业务目标的重要细节凸显出来。
- 推演质量属性。架构模型的特征能够展示出其能够支持的质量属性,提供有信服力的依据。
- 展示架构构思。架构模型能够为开发人员提供整体设计指导,便于开发人员将其实施落地。
技术架构模式
常用的技术架构模式有:
- 分层模式:应用通常分为多层(控制层、服务层、领域层、数据层、基础设施层),是最常见的技术架构模式。
- MVC模式:“模型-视图-控制”, 经典的 WebUI 架构,控制处理请求从而更新模型和返回视图,模型更新驱动视图更新,视图请求控制处理。
- 端口适配模式:系统通过各种端口适配器将输入转换为系统能够处理的输入,或者将系统输出转换为外部能够接收的输出。通常也称为接口模式,用于子系统交互或消息适配。
- 插件模式:系统支持加载不同的插件来完善自身功能。微内核是一种插件模式,其自身只包含最核心的模块,其它模块通过插件机制动态加载进来。
- 管道过滤器模式:由一系列过滤器通过管道连接,构成一个处理流水线。linux 管道就是典范。
- SOA:应用分解为多个分布式的服务组件,通过消息总线和标准服务对象格式来通信。
- 微服务模式:应用分解为多个分布式的微服务组件,通过 RPC 或消息队列来通信。
- 事件驱动模式:组件的变化会产生事件,任何组件都可以发布和监听事件。当事件发布时,监听者获得通知并进行处理,从而又会创建事件,推动进一步的监听和处理,往复循环。
- 订阅推送模式:订阅者订阅消息发布者的某类消息。当消息发送后,订阅者将接收消息进行处理。通常用于解耦多个生产者和消费者。
- 共享数据模式:多个应用通过共享数据库来访问数据。通常是有一个中心数据库,只有少量组件有写权限,而其它组件具备读权限。
- AKF立方体:从功能职责、数据、服务实例三个维度来分解架构职责。
- 单体应用模式:构建一个单体应用,包含了所有的模块和功能组件。通常是为了尽快交付一次性使用系统,不考虑长远维护。
不同的技术架构模式具备不同的整体结构特征,对于不同质量属性的支持程度也是不同的,引入的系统复杂度也是不同的。各个架构模式的详细讲解及所能达成的质量属性,可参阅: 《软件架构基础(影印版)》。
实际工程中,通常是可以多种结合使用的。比如采用微服务模式来构建完整应用的整体通信结构并使各子系统分开独立发展、使用分层模式来控制数据在系统中的有序流转、使用 MVC 模式实现前端与后端的交互、采用管道过滤器模式来处理上报数据、采用事件驱动机制来处理系统内的事件产生和关联、级联处理、采用插件模式来增强系统的功能和可定制性、使用订阅-推送模式来实现业务流程之间的通信和处理、使用端口适配模式来处理来自前端和第三方开发者的请求、使用 AKF 立方体来增强系统的服务能力。
建立领域模型的方法
建议结合阅读 《领域驱动设计》。虽然例子有点难懂,但很有启发性。当初第一次读时,就感觉:有一个稳定的持续演进的领域模型,来指导软件设计与开发,就像增加了一层高屋建瓴的视角。
建立领域模型的基本方法就是:识别业务实体,建立概念及概念的关联。比如云主机入侵领域,可以画一张草图。这张草图基本概括了云主机入侵的基本概念及概念的关联。基于这张图,可以推演各种主机入侵行为。
建立概念的基本方法就是给出概念的名词解释。对每个名词进行清晰的定义和阐释,辅以必要的示例。整个系统围绕这几个名词展开,不乱增概念,不一词多义,也不多词一义混用。名词需要用代码仔细对应和实现。
在获得基本概念及关联之后,可以结合实际场景,持续提炼新的概念。书中给出了一个“墙-门-有锁的门”的例子。还给出了一个提炼新概念的方法:提问-检验(无法回答问题)-分离新概念-完善模型-检验(通过)
将架构模型转为代码
- 统一使用架构词汇:比如领域模型的概念,就需要好的类命名来与之对应。好命名的演进过程:空白-凑合-沾边-反映功能-反映角色-反映意图-领域抽象。
- 组织代码突出架构:比如采用组件编排来实现入侵检测流程,那么就有 components 的包结构,将所有检测相关组件都放在这个包下。
- 贯彻元素关系:用代码表达元素关系(模块结构、组件连接器结构、分配结构)。
- 用代码生成模型:用代码来生成模型,逆向实现代码与模型的一致性。可以了解下 PlantUML,通过代码生成UML图。
- 必要时添加代码注释。
探索设计
够用的设计
- 将解决方案看成实验,通过实验的方式去探索更佳的解决方案。
- 简化问题。努力思考问题的本质,提炼出问题的要素和关联,从基本面去着手解决。
- 快速迭代学习。
- 同时考虑问题和解决方案。
设计策略
- 决定做多少前期设计。 1000w 大系统 37% ,1w 小系统 5%
- 风险作为导航。风险: 条件-影响-范围。
- 主动选择架构、根据系统监控被动设计。
- 制订设计计划:结束设计的条件、必要的设计成果、时间节点、重大风险、概念架构设计。
沟通与交谈
- 利益相关方关系图。
- 记录业务目标: 主体-业务目标-背景。
- 换位思考。
探索方案的方法
【书中有实操指南,需要团队集体创作,还没怎么实践】
- 分而治之
- 概念图
- 组件-功能-协作者卡片
- 架构演变记录
- 白板涂鸦
- 循环设计
- 事件风暴
- 团队海报
构建基本可用的方案
要构建一个基本可用的方案,可以从三方面着手:存储设计、流程设计、规则约束。
- 存储设计:类似程序的“数据结构”,是数据建模、组织和存储;
- 流程设计:类似程序的“算法”,构造闭环流程来实现业务流程;
- 规则约束:提炼数据与流程所要满足的规则和约束,校验规则和约束。
在构建出一个基本可用的方案之后,就可以持续完善。从工程层面来考量,考虑系统的异常处理、性能、稳定性、可用性、可维护性、可扩展性等质量属性。
展示设计
展示总体设计
- 用不同的视图展示展现架构:开发架构、业务架构、部署架构、数据架构等。
- 元素功能视图、粗略视图、精细视图、质量属性视图、映射视图、自定义视图
- 绘制出色的图表:使用图例、突出模式、简洁一致、描述性文字
展示总体设计常用的图
- 系统全景图。采用分层视图,展示系统的基础组件层、业务底座层、核心业务能力层、系统模块与依赖模块层、具体产品层。
- 系统模块图。展示了构成系统的各个模块及模块之间的关联关系。比如数据依赖(信息、配置等)、控制依赖(开关下发等)、服务依赖(文件服务、引擎检测等)等。
- 数据流图。 展示一个核心功能里,数据如何从源端流转到各个模块或组件,最终抵达目的端。
- 系统部署图。展示了构成系统的各个组件的服务器部署、通信端口及连接方式(别人画的)。这里的组件通常指微服务、存储组件与中间件。
- C4 图。主要包括:系统与用户上下文交互、技术选型图、开发导航图、组件图、某个组件的具体内部图。
重在实践!网络上有很多优秀开源系统的架构图,可以仔细揣摩研究哈。
展示设计决策的常用方法
- 架构主旨:用一页文档将系统的所有架构决策精华全部囊括在内。相当于系统架构首页。
- 架构决策记录(ADR):用多页文档或卡片记录关于系统的一系列主要决策及背景、依据、状态等。
- 精选阅读列表:用一个表格展示关于系统的一系列重要技术问题及方案文档。
- 系统模块交互图:见上述系统模块图。
- 制作原型:在构建一个中大型系统之前,先做一个原型,验证基本想法是可行的。比如在大规模迁移老的入侵检测能力到公司新技术架构上之前,先做一个原型,验证一个主要功能是可以迁移并成功运行的。
- 时序图: 开发常用,用于技术方案文档中。
- 系统隐喻: 用一个易懂的故事或寓言来讲解系统的架构设计及影响。需要会讲故事。主要是讲给非技术人员听的。
- 未采纳的决策:记录未采纳的决策及缘由,避免后续维护的人做重复无用功。
评估设计
评估设计方案的常用方法
- 架构简报:关于架构整体设计及架构设计变更的阐述及及时更新到关注人。
- 决策矩阵:类似技术选型的对比表格,说明各个方案的利弊,是否切合当前项目需求,最终决策及考量和依据。
- 场景走查:用实际场景走查,看看技术方案是否满足。在中型系统重构时,尤其要用此法来检验新方案能否解决所有已有的业务场景。
- 测量和监控:关于性能、稳定性相关的问题,需要通过测量和监控来论证可行性。
- 问题、评论、关注事项:团队成员对技术设计方案进行评论、指出问题、讨论问题。
- 风险风暴:团队成员一起来进行风险风暴,一起讨论设计方案在应对需求时存在的潜在风险及应对方案。
- 合理性检查:检查技术方案在满足需求、约束、规范方面的合理性。
- 代码审查: 通过代码审查,确定设计方案落实到系统实现中。
架构实施
架构实施往往涉及到多个团队的协作,因此需要考虑如何将架构职责分配到多个团队里。
现代企业里,一般会分为前端团队、客户端团队、服务端团队、大数据团队、DBA(如果有的话)、测试团队、产品团队、运维团队。某一领域比较专业化的话,还会细分,比如存储团队、网络团队、虚拟化团队等。每个团队在内部又会根据具体业务来划分成不同的小组。比如 A 小组负责容器业务,B 小组负责主机业务等。
团队协作模式主要有:
- 专业协作模式:由不同的专业团队组成和协作,每个专业团队负责自己所负责技术领域的服务、工具、支持等。互联网企业里最常见的团队架构模式。比如开发、测试、产品、DBA、运维团队等。
- 开源贡献模式:从质量和完整性角度审核其它人提交的组件和更改。开源的开发者不负责所有功能模块的实现。
- 能力中心模式:CoC团队,或者称“架构小组”,为公司业务提供整体架构构建、技术、最佳用例、开发支持工具、培训等。
根据地域的特征,可以分为本地模式和远程模式、集中模式和分布式模式。架构实施需要考虑远程模式和分布式模式的实际情况。
架构师与团队
架构师与团队是相互依存相互成就的关系。架构师指导团队开发系统,提升团队成员的设计技能;团队成员在架构师的授权下独立完成模块的设计,帮助架构师一起实现完整的系统架构和业务目标。
提升团队架构技能
- 提倡架构思维
- 传授技能、辅助决策
- 创建实践机会(结对设计、搭建支架、引入架构导轨、交流会)
- 设计授权
- 共同设计架构
设计授权的七个层次
- 告知。自己做设计决策,告诉团队结果。
- 贯彻。自己做设计决策,说明设计依据缘由。
- 咨询。 咨询团队意见,自己做设计决策。
- 商定。 与团队合作,达成共识。平等话语权。
- 建议。 通过观点、见解影响团队,由团队成员做设计决策。
- 审查。 由团队做决策,并由他们解释为什么这么做。
- 委托。 委托团队成员做决策,并由他负全责。作为辅助,帮助收集信息。
小结
即使未必成为架构师,学习架构师思维和技能总是有益的。 也许我们未必需要“成为”什么,而是应当“具备”什么。不一定成为架构师,但可以具备架构思维;不一定成为经济学家,但可以具备经济思维;不一定成为艺术家,但可以具备艺术思维;不一定成为谈判专家,但可以具备谈判思维。具备多元化思维,个人觉得,总是大有裨益的。
重在实践,有一进一。一个小技能一个小技能地练习和掌握。