《程序员必读之软件架构》读书笔记

架构师真正要学会的东西

1. 要学会去看,然后忘掉(所见即所得(WYSIWYG))
2. 要学会去听,然后忘掉
3. 要学会去做,然后忘掉
4. 要学会超越

每个开发者都应该知道软件架构的五件事:

1. 软件架构不是大型预先设计
2. 每个软件团队都需要考虑软件架构
3. 软件架构的角色关乎编码、指导和合作
4. 无需使用UML
5. 好的软件架构是支持敏捷开发的

什么是软件架构

1、 什么是架构

作为名词:和结构有关。将产品分解为一系列组件、模块和交互。

作为动词:以需求为基础的,对产品进行的构建、设计、设定愿景以及决策。

2、 架构的种类

“技术架构”通常指软件、硬件,或者两者兼有。

不管你是构建软件系统、网络还是数据库,任何成功的方案都需要你理解问题,并设定一个愿景可以和每个参与构建最终产品的人沟通。不论任何领域的架构,其实最主要就是结构和愿景。

3、 软件架构是什么

应用程序架构

应用程序架构的关注点是应用程序,通常包括将应用程序解构为类和组件,确保设计模式的正确应用,构建或使用框架等等。本质上,应用程序架构谈论的是软件设计的低级切面,通常只考虑单一的技术栈。

应用程序架构着重考虑软件和代码组织。

系统架构

系统架构描述为从组件和服务到子系统等更高层次的抽象。系统架构的定义大多数都包括了软件和硬件。

系统架构是更大规模的应用程序架构。

软件架构

软件架构就是应用程序和系统架构的结合。

从代码结构和基础到将代码成功部署到生产环境,与一个软件系统重要元素相关的所有东西就是软件架构。
包括:

  • 开发技术(面向对象、重构、单元测试、代码整洁和技术实践);
  • 安全性;
  • 性能、可伸缩性、可用性和其他质量属性;
  • 监控;
  • 客观环境的约束;互操作性、与其他软件系统的集成;
  • 运营、支持和维护的需求…

企业架构:战略而非代码

企业架构一般是指整个组织的中心工作,着眼于如何组织和利用人员、流程和技术来使企业有效和高效地工作。

4、 敏捷软件架构是什么

敏捷是什么

快速行动,拥抱变化,持续交互,接受反馈,不一而足;

团队动态、系统思维、心理学以及其他可能会跟创建高效团队联系在一起的事情。

好的架构带来敏捷

5、 架构对上设计

架构和设计的区别:

格雷迪▪布奇(Grady Booch)的观点:

  • “作为名词,设计是指一个系统内命名的(尽管有时无法命名)结构或行为,解决或有助于解决该系统的一个或多个问题。因而设计代表了潜在的决策空间的一个点。
  • 所有的架构都是设计,但并非所有的设计都是架构。
  • 架构反映了使一个系统成型的重要设计决策,而重要性则通过改变的成本来衡量。

以上的观点本质上是:重要决策即“架构”,其他的都是“设计”。

我们的软件系统中哪些可能是重要的(或者说“架构的”):

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

6、软件架构重要吗

缺乏软件架构将引发的问题

软件架构的好处

  • 让团队跟随一个清晰的愿景和路线图,无论这个愿景是一人的还是整个团队的;
  • 技术领导力和更好的协调;
  • 与人交流的刺激因素,以便回答与重要决策、非功能需求、限制和其他横切关注点相关的问题;
  • 识别和减轻风险的框架;
  • 方法和标准的一致性,随之而来的结构良好的代码库;
  • 正在构建的产品的坚实基础;
  • 对不同的听众,以不同的抽象来交流解决方案的结构。

软件架构的角色

软件架构角色
1 、架构驱动力

这个角色首先要理解业务目标和管理架构驱动力,其中包括需求(功能性需求和非功能性需求)和环境的限制。

2 、设计软件

设计软件的过程是软件架构角色的一部分。涉及到要理解如何解决架构驱动力带来的问题,创建系统的整体结构,并为交付设定一个愿景。

软件设计的一个关键部分是技术选择。

3、技术风险

就是主动发现、减轻和承担高优先级的技术风险,这样才能保住你的项目和工作。

4、架构演变

在整个交付过程中依据不断变化的需求和团队反馈来对其演化。

5、编写代码

编码为架构师提供了一种与团队分享软件开发经验的方式,从而帮助他们更好地理解如何从开发的角度看待架构。

6、质量保证

它的内容不只是代码评审,还可以是引入一些标准和工作实践,如编码标准、设计原则和工具等。质量保证也包括确保团队对架构实现的一致。

合作或失败

一个软件系统需要很多人做出贡献。这包括了从需要理解和认同架构的直接开发团队、一直到那些对安全性、数据库、运营、维护或支持感兴趣的人组成的扩展团队。任何担任架构角色的人都需要与这些人合作,以确保架构能与周围环境成功整合。

技术领导是一个角色而非级别

提出你自己对这个角色的定义

对于对软件架构角色的期望,要跟你的团队达成共识;

如果看到益处,就在你的组织里对其标准;

架构师应该编码

  • 不放弃编码但也不把时间都用于编码
  • 构建原型、框架和基础
  • 进行代码评审
  • 实验并与时俱进

从开发者到架构师

经验是一个好的评价标准,但你需要看得更深。

架构驱动力:捕捉和挑战一套复杂的非功能需求,还是简单地假设它们的存在。

设计软件:从零开始设计一个软件系统,还是扩展已有的。

技术风险:证明你的架构能够工作,还是盲目乐观。

架构演变:持续参与和演化你的架构,还是把它交给“实现团队”。

编写代码:参与交互的实践部分,还是袖手旁观。

质量保证:保证质量并选择标准,还是反其道而行之或无所作为。

以上的大部分可以归结为是承担寻找方案的责任还是推诿问题

拓展T

进一步的技术能力

“T”指的是技术,这也正是优秀的软件架构师应该懂得的。作为软件开发者,我们需要知道编程语法、API、框架、设计模式、自动化单元测试和其他日常的底层技术。而这些对于架构师来说使基础。因为扮演软件架构角色的人要懂技术,他们才能回答:

  • 该方案是否有效?
  • 我们要这样去构建吗?

知识面宽

软件架构师要能够回答以下类型的问题:

  • 和其他可选技术相比,我们所选的是否最合适?
  • 对该系统的设计和构建,还有哪些选择?
  • 是否应该采用一种通用的架构模式?
  • 我们是否明白所做决策的利弊?
  • 我们照顾到了品质属性的需求吗?
  • 如何证明这种架构行之有效?

软件架构师是通才型专家

虽然一般性的设计知识、技巧、模式和方法通常适用于许多不同的技术,但不明白如何将其成功应用在底层细节上可能会导致问题。找到那些知你不知的人,与他们紧密合作。

软件架构是技术活

软技能

软技能包括:

  • 领导力:创造共有的愿景并带领人民向着共同目标前行的能力
  • 沟通
  • 影响力
  • 信心
  • 合作
  • 指导:对他人进行角色、技能上的指导
  • 辅导:对他人学习方面的指引
  • 动力:保持团队愉快、开朗和积极
  • 润滑剂:特别是在团队有不同的意见时,需要探索、客观、帮助团队达成共识
  • 政治:至少要明白周围发生了什么
  • 责任感:如果软件架构不能满足业务目标,无法交付非功能性需求或技术品质很差,都是你的问题
  • 授权:授权的不是责任
  • 保持积极

软件架构不是接力运动

软件架构不需要“解决方案架构师”,需要负责大局的人。

软件架构需要引入控制

从部分控制开始,倾听反馈,以便随着项目的推进再微调。如果团队老是问“为什么”和“怎么办”,那可能就需要更多指导。如果团队好像总是在和你对着干,可能你就是把操作杆推得太多。这没有一个标准的答案,但有一些控制是好事,因此很值得花些时间看看你的团队适合引入多少控制。

如果你是软件架构师:

  • 包容与合作:让开发团队参与软件架构的过程,帮助他们了解大局,认同你所做的决策。
  • 动手:参与项目的日常开发工作来提高你对架构交付的理解。

如果你是软件开发者:

  • 了解大局:花些时间去了解大局将帮助你了解架构决策的语境,增强你对系统整体的理解。

  • 挑战架构决策:有了对大局的了解,就有机会挑战眼前的架构决策了。

  • 申请参与:申请参与架构工作。

敏捷软件项目仍然需要架构,因为那些围绕复杂非功能需求和约束的棘手问题不会消失,只是对架构角色的执行不同。集体代码所有制,每个人都要能在架构的层次上工作,因此每个人某种程度上都是架构师。

设计软件

架构驱动力

一套常见的驱动、影响和塑造最终软件架构的东西:

  1. 功能需求
  2. 质量属性
  3. 约束
  4. 原则
  5. 理解影响

了解以上东西可以帮助你减少摆在你面前的可选项,特别是如果你发现驱动力包括了复杂的非功能性需求或者像部署平台的限制之类的主要约束。然后根据特定的目标和语境,做出“明智”的设计决策。

质量属性(非功能性需求)

非功能性需求通常被看作“能力”,主要更服务质量有关。

  1. 性能:响应时间和延迟
  2. 可伸缩性
  3. 可用性
  4. 安全性
  5. 容灾恢复
  6. 可访问性
  7. 监测
  8. 管理(对监测管理)
  9. 审计(日志)
  10. 灵活性
  11. 可扩展性
  12. 可维护性
  13. 法律法规
  14. 国际化
  15. 本地化

约束

约束也是可以驱动、塑造和影响你的架构。常见的约束有:

  1. 时间和预算的约束
  2. 技术约束
  3. 人员约束
  4. 组织约束

每个软件系统都要屈从于一个或者多个约束,软件架构角色的一部分就是找出这些约束,搞清楚它们为什么会被强加进来,让它们帮助你塑造软件架构。

原则

原则是你为了将标准方法和一致性引入构建软件的方式而想采用的。

开发原则

例如:编码标准和规范、自动化单元测试、静态分析工具等等。

架构原则

例如:分层策略;业务逻辑位置;高内聚、低耦合、SOLID等;无状态组件;存储过程;域模型;HTTP会话使用;始终一致和最终一致等等。

在构建软件系统的时候,要担心“最佳实践”。即使是最善意的原则,有的时候也会产生意想不到的负面影响。如果只是构建一个快速的技术方案,为确保完整的关注点分离而采用复杂的分层策略,也能耗费大量的时间。原则通常是因为好的理由才引入,但它们并不是任何时候都有好处。

技术不是实现细节

架构图应该包括技术的选择。技术不只是一个“实现细节”,你做出的技术决策跟你分解、安排和设计系统的方式同等重要。

更多的分层等于更高复杂度

协同设计是一把双刃剑

采用白板来设计软件的一个主要原因是它鼓励更加合作的方式,而不是大家都对着自己电脑上最喜欢的建模工具,各自为政。合作,也就是相互沟通和挑战。

软件架构是对话的平台

可视化软件

沟通障碍

ps:关于这一点,我不觉得应该抛弃UML或者怎么样,团队有一个共同的语言就OK。

对草图的需要

画草图不是艺术

画草图不是综合模型

画草图可以协作活动

无效的草图

草图是捕捉和呈现软件架构的好方法,它们通常会缺少UML图的正规和严谨。图表应该需要被理解。

C4:语境、容器、组件和类

软件系统由多个容器构成,容器又由多个组件构成,组件由一个或多个类实现。

  • 类:在一个面向对象的世界里,类是软件系统的最小结构单元。
  • 组件:组件可以想象成一个或多个类组成的逻辑群组。组件通常由多个类在更高层次的约束下组合而成。
  • 容器:容器是指一个在其内部可以执行组件或驻留数据的东西。它可以是从网络或应用服务器直到富客户端应用或数据库的任何东西。
  • 系统:系统是最高的抽象层次,代表了能够提供价值的东西。
架构结构的简单模型

总结软件的静态视图

  • 语境:设定场景的高层次图,包括关键的系统依赖和参与者。(应该也叫用例图)
  • 容器:容器图显示了高层次的技术选择,容器如何分担责任、如何通信。
  • 组件:组件图可以让你看到每个容器的关键逻辑组件及之间的关系。
  • 类:这是一个可选的层次。如果想解析某个模式或组件将(或已经)被怎样实现,画少量高层次UML类的图。

明确技术选择

技术选择不应该是实现细节。

技术选择有助于把其他理想化和概念化的软件设计带回现实,再次脚踏实地。

图应该反映现实

图应该表达反映现实的抽象,而不是对不存在的进行概念化表现。你应该能看到图的元素反映在代码库中,反之亦然。如果你能明白自己要如何编写代码,就能知道如何可视化。

软件架构和编码

组件最简单的方式就是,它是接口背后的一组相关行为,可以用一个或多个协作类实现(当然,假设是面向对象的语言)。好的组件和好的类有一些共性,应该高内聚、低耦合,有良好定义的公共接口、良好的封装等。

  • 用层封装代码
  • 用特性封装
  • 用组件封装

有效的草图

包括:标题、标签、形状、职责、线条、颜色、边框、布局、方向、要点、图表的评审清单、倾听问题。

为软件生成文档

代码不会讲述完整的故事

需要使用更多的信息来描述一个系统。

代码之上的辅助信息图

软件文档即指南

把辅助文档作为一个指南,它应该给人们上手提供足够的信息,帮助他们加快探索的过程。
以下的标题描述了你可能想要包含在软件指南中的事情:

  1. 语境;
  2. 功能性概览;
  3. 质量属性;
  4. 约束;
  5. 原则;
  6. 软件架构;
  7. 外部接口;
  8. 代码;
  9. 数据;
  10. 基础设施架构;
  11. 部署;
  12. 运营和支持;
  13. 决策日志;

开发生命周期中的软件架构

敏捷和架构的冲突

冲突1:团队结构

冲突2:流程和产出

软件架构提供了TDD、BDD、DDD、RDD和代码整洁的分界线

(TDD:测试驱动设计;BDD:行为驱动设计;DDD:领域驱动设计;RDD:责任驱动设计)

你需要思考架构的驱动力(影响最终软件架构的主要事情),包括以下:

  • 功能需求:需求驱动架构。
  • 质量属性:非功能需求(比如:性能、可扩展性、安全等)通常是技术方面的,也很难改造。
  • 约束:约束普遍存在于现实世界,包括批准的技术清单、规定的集成标准、目标部署环境、团队规模等。
  • 原则:是在试图为软件提供一致性和清晰度时你想要采用的东西。

架构是改变起来很困难或者成本很高的东西,跟那些你不能用一个下午就轻松完成重构的、大的或者“主要”的决策有关。它包括核心技术选择,全面的高层次结构(全局)以及对如何解决各种复杂、高风险、关键问题的理解,等等。软件架构很重要。

恰如其分的预先设计

软件的一个主要分歧是要做多少预先设计。

多少预先设计是太少

  • 不了解系统边界是什么,在哪里。
  • 团队中对“大局”没有形成共识。
  • 无法交流整体愿景。
  • 团队成员对需要做的事情不清楚或感到不适。
  • 没有考虑非功能需求/质量属性。
  • 没有考虑(现实的)环境约束如何影响软件(比如部署环境)。
  • 没有考虑主要的风险,比如非功能需求、外部接口等。
  • 尚未确认重大问题及其答案。
  • 没有考虑关注点分离、适当的抽象层次、分层、可修改性,拐点等。
  • 对架构师要扮演的角色没有共识。
  • 解决问题的方法不一致。
  • 团队缺乏控制和指导。
  • 项目生命周期中本应预先考虑到的重大架构变化。
  • 过多的设计选择和选项,往往伴以团队成员对解决方案或前进方向的反对。
  • 对于设计是否管用的不确定(比如,设计过程中没有执行原型的部分)。
  • 缺乏技术选择(即不必要的延迟)。

多少预先设计是太多

  • 太多信息(即很长的文档或信息超载)。
  • 在太多抽象层次都过于详细。
  • 太多图表。
  • 在文档中编写代码或伪代码。
  • 过于死板,缺乏灵活性的架构。
  • 所有抽象层次的所有决策都已做出。
  • 有众多展示了所有可能交互的序列图的类层次设计。
  • 详细的实体关系模型和数据库的设计(比如,表、视图、存储过程和索引)。
  • 分析瘫痪和纠缠于次要细节的团队。
  • 编码成了对团队来说无聊而消极的设计文物到代码的简单交换。
  • 一个无节制的“设计阶段”(即时间和预算)。
  • 还未进行任何编码就已达到最后期限。

多少是“恰如其分”

如果需要做到“恰如其分”,以下几点不管软件架构角色由一个人扮演还是团队内共享都适用。

  • 结构
    • 是什么:理解主要的结构元素,以及它们如何基于架构驱动力组合在一起。
    • 怎么做:设计并分解为容器和组件。
  • 风险
    • 是什么:识别和缓解最高优先级的风险。
    • 怎么做:风险风暴和具体的实验。
  • 愿景
    • 是什么:创建并交流团队展开工作的愿景。
    • 怎么做:语境、容器和组件图。

把恰如其分的预先设计置于适当的语境

对每个解决方案提出以下类型的问题:

  • 架构会管用吗?如果不管用,为什么?
  • 所有关键的风险都已被识别了吗?
  • 架构是否过于简单?是否过于复杂?
  • 架构是否有效地交流过?
  • 图的哪些地方是受人喜欢的?哪些可以改进?
  • 细节是否太多?细节是否足够?
  • 你能把这作为七点交给你的团队吗?
  • 控制是否太多?指导是否不足?
  • 你对已做出或推迟的技术决策的程度满意吗?