0. 引子

本文是一篇强调实践、注重实效、轻量级、面向开发者的软件架构指南。你将从中学到:

  1. 软件架构的本质;
  2. 为什么软件架构角色应当包含编码、指导与合作;
  3. 如何用简单的草图让你的软件架构可视化;
  4. 软技能。
1. 软件架构的本质软件架构词汇图谱

在不同的人眼里“架构”一词的意思大相径庭,互联网上对架构的定义也多如牛毛。过去几年里我问过上百人同一个问题,在他们看来“架构”意味着什么。得到的答案概括如下(排名不分先后):

模块、连接、依赖和接口;大局观;改变成本很高的事情;难以改变的事情;更加兼顾全局的设计;接口而非实现;审美(比如:艺术般的整洁代码);概念模型;满足非功能需求/质量属性;每件事都有“架构”;沟通能力(抽象、语言、词汇);计划;一定程度的严格和可靠性;蓝图;系统、子系统、交互和接口;管理;战略决策的产出;必要的约束;结构(组件和交互);技术方向;战略和愿景;结构单元;实现目标的过程;标准和准则;整个系统;工具和方法;从需求到最终产品的道路;指导原则;技术领导力;构成产品的元素之间的关系;对环境约束和限制的意识;“基础;抽象的观点;把问题化整为零的过程;产品的骨架、支柱;...

还可能包括:

系统的形态(例如,客户端-服务器、基于Web、原生移动客户端、分布式、异步,等等);软件系统的结构(例如,组件、层、交互,等等);技术选择(即编程语言、部署平台,等等);框架选择(例如,Web MVC 框架、持久性/ORM 框架,等等);设计方法/模式选择(例如,针对性能、可伸缩性、可用性等的方法);...

难怪找不到一个合适的定义!好在还可以分为名词和动词两大类。无论我们谈论的是建造一个物理建筑或一个软件系统,都适用。

作为名词

架构作为名词来解释时,概括起来都与“结构”有关:将产品分解为一系列组件、模块和交互。这需要考虑整个产品,包括:

  1. 处理(建筑物的)供电、供水、空调各个业务领域知识,
  2. 还有处理(软件的)安全、配置、错误处理等横切关注点的基础设施服务。
作为动词

架构作为动词来解释时,包括了:

  1. 理解你需要构建什么;
  2. 设定愿景以便于进行构建和做出恰当的设计决策。

所有这些都要以需求为基础,因为需求驱动架构 。

关键在于,架构是关于交流愿景以及引入技术领导力的,这样参与构建产品的每个人都能理解这个愿景,并为产品的成功做出积极贡献。

小结

不管你是构建软件系统、网络还是数据库,任何成功的方案都需要你:

  1. 理解问题;
  2. 并设定一个愿景;
  3. 可以和每个参与构建最终产品的人沟通。

不论何种领域的架构,其实主要就是结构和愿景 。

软件架构需要考虑诸如:面向对象的原则、类、接口、控制反转、重构、自动化单元测试、代码整洁和其他不胜枚举的技术实践:

  1. 横切关注点,比如登录和异常处理;
  2. 安全性,包括认证、授权和敏感数据保密;
  3. 性能、可伸缩性、可用性和其他质量属性;
  4. 审计及其他监管需求;
  5. 客观环境的约束;
  6. 互操作性、与其他软件系统的集成;
  7. 运维需求;
  8. 结构和整个代码库解决问题、实现特性的方法的一致性;
  9. 评估正在构建的基础有助于交付按计划进行。

有时你需要退一步,远离代码和你的开发工具。这并不意味着低层次的细节不重要,因为可用的软件最终还是要靠交付可运行的代码。细节同样重要,但就大局而言,对软件的整体视角可以确保你的代码符合整体愿景而非背道而驰。

2. 软件架构角色:编码、指导与合作软件架构角色

下面是我认为构成软件架构角色应有的内容。注意,我这里说的是“角色”;它可以是一个人,也可以由团队共同扮演。

软件架构形成的原理(软件架构的本质)(1)

架构师也要写代码

在古代和中世纪的历史中,大多数建筑设计和建设都是工匠完成的:下至石匠和木匠,上至建造大师。尽管石匠大师受人尊敬、通常也很富有,然而在达到行业顶峰之前,他必须经历石匠、监督的历练来证明自己的价值。石匠大师为将要建造的东西设计结构、美学和象征等方面的特性,组织后勤,还要评定工作的优先级并决定它们的顺序。

优秀架构师的重要特征是抽象思维能力,也可以理解成不把所有时间都耗在细节里的能力。这没错,但你画的那些框框线线终归要形成代码。

软件架构形成的原理(软件架构的本质)(2)

编码为架构师提供了一种与团队分享软件开发经验的方式,从而帮助他们更好地理解如何从开发的角度看待架构。一个写代码的软件架构师会更有成效也更快乐。你不应该因为“我是架构师”,就把自己排除在编码之外。

3. 用简单的草图让你的软件架构可视化

让建筑行业的人直观地传达建筑物的架构,您将看到场地平面图、平面图、立面图、横截面图和详细图。相反,如果让软件开发人员使用图表来传达软件系统的软件架构,您可能会得到一团乱麻的方框和线条……不一致的符号(颜色编码、形状、线条样式等)、模棱两可的命名、未标记的关系、通用术语、缺少技术选择、混合抽象等。

软件架构形成的原理(软件架构的本质)(3)

作为一个行业,我们确实有统一建模语言 (UML)、ArchiMate 和 SysML,但询问这些是否提供了一种有效的软件架构交流方式通常是无关紧要的,因为许多团队已经将它们抛弃,转而支持更简单的“盒子和线”图。放弃这些建模语言是一回事,但也许在敏捷性的竞赛中,许多软件开发团队已经失去了视觉交流的能力。

Maps of your code:用于可视化软件架构的 C4 模型: 上下文、容器、组件和代码

C4 模型是绘制软件架构图的“抽象优先”方法,基于反映软件架构师和开发人员如何思考和构建软件的抽象。

软件架构形成的原理(软件架构的本质)(4)

在 C4 模型中,软件系统由一个或多个容器( Web 应用程序、移动应用程序、桌面应用程序、数据库、文件系统等)组成,每个容器包含一个或多个组件,而这些组件又由一个或多个代码元素实现(例如类、接口、对象、函数等)。

C4 模型中的角色

软件架构形成的原理(软件架构的本质)(5)

一个人代表您的软件系统的人类用户之一(例如演员、角色、角色等)。

软件系统

软件系统是最高级别的抽象,它描述了为用户提供价值的东西,无论他们是不是人类。这包括您正在建模的软件系统,以及您的软件系统所依赖的其他软件系统(反之亦然)。

软件架构形成的原理(软件架构的本质)(6)

在许多情况下,软件系统由单个软件开发团队“拥有”。

容器(应用程序和数据存储)

不是码头工人!在 C4 模型中,容器代表应用程序或数据存储。容器是为了使整个软件系统工作而需要运行的东西。实际上,容器类似于:

服务器端 Web 应用程序:在 Apache Tomcat 上运行的 Java EE Web 应用程序、在 Microsoft IIS 上运行的 ASP.NET MVC 应用程序、在 WEBrick 上运行的 Ruby on Rails 应用程序、Node.js 应用程序等。客户端 Web 应用程序:使用 Angular、Backbone.JS、jQuery 等在 Web 浏览器中运行的 JavaScript 应用程序。客户端桌面应用程序:使用 WPF 编写的 Windows 桌面应用程序、使用 Objective-C 编写的 OS X 桌面应用程序、使用 JavaFX 编写的跨平台桌面应用程序等。移动应用程序:Apple iOS 应用程序、Android 应用程序、Microsoft Windows Phone 应用程序等。服务器端控制台应用程序:独立(例如“public static void main”)应用程序、批处理等。无服务器函数:单个无服务器函数(例如 Amazon Lambda、Azure 函数等)。数据库:关系数据库管理系统、文档存储、图形数据库等中的模式或数据库,例如 MySQL、Microsoft SQL Server、Oracle 数据库、MongoDB、Riak、Cassandra、Neo4j 等。Blob 或内容存储:Blob 存储(例如 Amazon S3、Microsoft Azure Blob Storage 等)或内容交付网络(例如 Akamai、Amazon CloudFront 等)。文件系统:完整的本地文件系统或较大网络文件系统的一部分(例如 SAN、NAS 等)。Shell 脚本:用 Bash 等编写的单个 shell 脚本。ETC

软件架构形成的原理(软件架构的本质)(7)

容器本质上是一个上下文或边界,在其中执行一些代码或存储一些数据。每个容器都是可单独部署/可运行的事物或运行时环境,通常(但不总是)在其自己的进程空间中运行。因此,容器之间的通信通常采用进程间通信的形式。

组件

软件架构形成的原理(软件架构的本质)(8)

“组件”一词在软件开发行业中是一个非常重的术语,但在这种情况下,组件是封装在定义良好的接口后面的一组相关功能。如果您使用 Java 或 C# 之类的语言,考虑组件的最简单方法是它是接口后面的实现类的集合。诸如这些组件如何打包(例如,一个组件与每个 JAR 文件、DLL、共享库等多个组件)等方面是一个独立且正交的问题。

软件架构形成的原理(软件架构的本质)(9)

这里需要注意的重要一点是,容器内的所有组件通常都在同一个进程空间中执行。 在 C4 模型中,组件不是可单独部署的单元。

4. 软技能

软件架构角色同时也是技术领导的角色,“软技能”或“交际能力”也极其重要。

  • 领导力 :简单来说,领导力就是创造共有的愿景,并带领人们向着共同目标前行的能力。
  • 沟通 :你有世界上最好的想法和愿景,但如果不能有效地传达给其他人,也是死路一条。这包括了软件开发团队内外的人,要使用适合受众的语言和细节水平。
  • 影响力 :这是重要的领导技能,从毫不掩饰的劝说到神经语言编程1 或绝地控心术2 ,它能够以多种途径实现。通过妥协和谈判也可以达到这样的目的。每个人都有自己的想法和计划,你在处理时还得让他们都不反感,并主动地去追求你需要的结果。好的影响力也要求好的倾听和探索能力。
  • 信心 :信心很重要,是有效的领导力、影响力和沟通的基础。但信心不代表傲慢。
  • 合作 :软件架构角色不应该被孤立,(与其他人)合作想出更好的方案是一项值得实践的技能。这意味着倾听、谦虚和响应反馈。
  • 指导 :不是每个人都对你正尝试做的事情有经验,你需要对他们进行角色、技术等方面的指导。
  • 辅导 :辅导是对人进行学习方面的指引,而非告诉他们怎么做一件事。作为领导,你可能会被要求去辅导团队中的其他人。
  • 动力 :这说的是保持团队愉快、开朗和积极。团队要有积极性,才会跟随你这个软件架构师所创建的任何愿景。你还要面对团队中一些人不买账的局面。
  • 润滑剂 :你经常需要退后一步,促进讨论,特别是团队内有不同意见时。这需要探索、客观,帮助团队达成共识。
  • 政治 :每个组织都少不了政治。我的咒语是,离得越远越好,但你至少应该明白周围发生了什么,这样才能做出更可靠的决策。
  • 责任感 :你不能因为失败就责备软件开发团队中的其他人,有责任感对你而言很重要。如果软件架构不能满足业务目标,无法交付非功能性需求或技术品质很差,那都是你的问题。
  • 授权 :授权对任何领导角色来说都是一个重要部分,作壁上观和事必躬亲之间有一条模糊的界线。你应该学会在适当的时候授权,但请记住,你授权的可不是责任。
参考资料

Simon Brown. “程序员必读之软件架构。”关于 C4 model:https://c4model.com/

,