关于我们
![]() ![]() |
软件架构决策之道:软件架构决策的原则和方法 [美]斯里纳特·佩雷拉
本书阐述了在构建软件系统时不可或缺的技术与非技术原则和方法,并详尽展示了如何运用这些原则和方法有效管理项目中的不确定性,从而构建稳固的决策框架。同时,它深刻探讨了领导力与软件架构设计洞察力之间的微妙联系,细致阐述了用户体验设计、宏观架构规划及服务架构部署等关键领域的核心理念与实用技术。通过引用莱特兄弟与凯利·约翰逊等杰出技术领导者的生动案例,来帮助读者理解制订强大决策的重要性。对于软件行业的技术领导者和软件架构决策者来说,本书是一本优秀的参考书。
技术为骨、领导为魂、产品为心 驾驭软件架构不确定性的破局之道; 软件架构决策的完整指南 帮助领导者管理不确定性并做出正确的判断; 为所有软件架构师、技术决策者 提供一套系统的软件架构原则和方法。
开发软件系统的目标往往是构建符合质量标准的系统,并在长期或预定时间内获得最高的投资回报率(ROI)。同时,这也是软件架构的目标。软件架构本质上是在构建软件系统的设计蓝图。如果在产品上增加投入能够带来更多的收益,那么这将被视为具有良好的投资回报率。在这里,投资回报率不仅仅是指经济效益。相反,粗劣的软件架构设计则会导致后期频繁的修改,最终耗费更多的成本。优秀的软件架构设计能够平衡成本与收益,并最大化投资回报率。软件架构设计涉及诸多方面,比如找到恰当的抽象概念、决定包含哪些功能、确定每项功能的深度、设定服务质量(QOS)参数、确定灵活性程度,以及时间安排和用户体验等。判断力的作用软件架构师会学习抽象概念、架构风格和模式,并研究它们的优缺点、在特定情况下的适用性,以及如何在了解潜在陷阱、失败案例和用例的基础上组合它们。然而,大多数的设计错误都是由于缺乏判断力而不是缺乏知识造成的。在这里,判断力指的是经过深思熟虑后做出决策或得出合理结论的能力,以优化最重要的结果。我在20多年的软件架构设计中,发现了以下常见错误:过多纳入用户旅程所需的功能。设计过于灵活或过于一致,从而影响未来的变化。限制功能深度,从而严重影响用户体验(UX)。为最终用户解决无关紧要的问题。对用户旅程和体验关注不足。错过交付时间。之所以会犯下这些错误,主要是因为我们不了解未来的趋势,不了解使用系统的用户,也不了解系统是如何运作的。这说明了判断力的必要性,也使我们面临的不仅仅是技术方面的挑战,更是领导力方面的挑战。这里是领导力是指管理不确定性、将混乱变为有序、为更美好的未来提供希望,并朝着这个未来前进。拿破仑·波拿巴曾说过,领导者是希望的传递者。也就是说,领导者并不总是知道未来会发生什么,也并不是全知全能的。领导者应该有一个关于未来的愿景;他们应该以一种最小化风险的方式管理不确定性。领导者应该将他们的愿景和实施方案传达给他人,并带领众人实现愿景。让我们从软件架构师的角度重申一下此观点。也就是说软件架构师并不是无所不知的,也不是总知道系统应该具备哪些功能以及将被如何使用。他们应该有一个愿景以及整体解决方案。领导者应该将他们的愿景和实施方案传达给团队,并指导团队构建软件系统,然后运行这个系统。我并不认为知识对于架构师来说不重要。知识的确重要,但是判断力起着关键性的作用。但遗憾的是,知识是普遍的,判断力却很稀缺。我读过很多软件架构方面的好书和文章,仅举几例:鲍勃·马丁(Bob Martin)的著作、格雷戈·霍普(Gregor Hohpe)的著作以及马丁·福勒(Martin Fowler)的博客。然而,他们的作品主要关注的是知识,较少涉及判断力方面的话题。我还读过很多关于领导力的好书:本·霍洛维茨(Ben Horowitz)的The Hard Things About Hard Things、埃里克·施密特(Eric Schmidt)等人的Trillion Dollar Coach、斯坦利·麦克里斯特尔(Stanley McChrystal)的Team of Teams: New Rules of Engagement for a Complex World、理查德·鲁梅尔特(Richard Rumelt)的Good Strategy, Bad Strategy,以及乔科·威林克(Jocko Willink)等人的其他著作。这些作品讨论了判断力,但只是停留在一般层面上,而不涉及技术层面。显然,在优秀的领导力和优秀的软件架构判断力之间存在着不小的认知鸿沟。内容导读本书讨论了领导力和软件架构判断力之间的差距,重点阐述了何为软件领导力,以及我们在构建软件系统时如何将其发挥至极致。如前所述,许多在软件架构上犯的错误都源于知识与判断力之间的差距。本书不是关于如何管理团队的书,也不是关于工程管理或人力资源管理(HR)以及如何组建团队的书,更不是关于企业战略的书。此外,本书也不涉及如何创造愿景。可以说,本书是一本关于技术领导力的书,也可以说本书是一本关于技术判断力的书。本书解释了高级架构师必须深入理解的原则和概念,并讨论了技术领导者或架构师如何利用这些原则来管理不确定性。例如,本书的一个论点是:深思熟虑,慢慢实施。另一个论点是,领导者必须确定事务的界限,承担起不确定性的责任,而不是将责任转嫁给同事。本书讨论的问题和原则可以帮助我们管理不确定性,并提供了一种有效的决策框架。如果你不是负责人,那还需要读本书吗?我认为是需要的。人们总是会跟随那些提出并处理不确定性问题并取得进展的人。优秀的架构师在被授予“负责人”的头衔之前的许多年就已经开始扮演这个角色了。知识越渊博,成为领导者的机会就越大。主动出击,帮助你的领导一起完成任务,你就会发现你得到的机会越来越多,声誉和头衔也将随之而来。如果你认为有人比你更适合扮演这个角色,那就要向他学习、提出问题,并向他请教!在这种情况下,你可以使用我们在书中讨论的内容协助领导者。你成长的机会也将随之而来。本书引用了许多技术领导力方面的范例,并特别提到了两个故事:众所周知的莱特兄弟——奥维尔和威尔伯,以及设计了U-2和黑鸟SR-71等飞机的凯利·约翰逊的故事。这些领导者具备一种强大的技术控制力,他们利用有限的资源,使看似不可能实现的系统成为现实。当然,还有许多像Google的杰夫·迪恩这样的软件领导者,我对他们同样推崇备至。众所周知,莱特兄弟制造了第一架可持续和控制飞行的具有动力的飞行器。但事实上,他们并没有受过大学教育,他们只不过经营着一家自行车店而已。他们与资金充足的专业人士竞争,并最终获得了成功。的确,在莱特兄弟之前有许多飞行器的设计,但他们是第一个正确设计所有参数的团队。莱特兄弟先是制造了滑翔机并学习如何控制和调整它,然后增加了螺旋桨和发动机,逐渐将滑翔机改造为一架飞机,展示了极佳的判断力。凯利·约翰逊是洛克希德U-2、SR-71黑鸟和其他40多种飞机的设计师。“黑鸟”飞机对雷达隐身,飞行速度能够超过导弹,并且在20多年的服役期间从未被击落过。它是第一架飞行速度超过3倍音速的量产飞机。凯利还制造了第一架速度达到2倍音速的战斗机和第一架速度超过400mile/h的战斗机(1mile=1609.344m)。洛克希德U-2飞机达到并保持了70000ft(1ft=0.3048m)的飞行高度。他能够将一个不可实现的目标分解为若干可执行的任务,精益求精地要求自己,然后让系统运转起来。凯利以在预算范围内提前完成项目而闻名,而且还将节省的资金返还给了政府。据说他的上司曾经感慨:“那个瑞典人真的能看到空气”。这指的就是凯利对设计的强大直觉。“架构”和“设计”这两个术语通常可互换使用。“设计”是指完整详细的蓝图(例如,软件架构中的类图和序列图);而“架构”则是高层次的概念视图(例如,组件视图和组件级的序列图)。在本书中,我们将重点落在高层次视图上,因此全书都将使用“架构”这个术语。本书使用TOGAF的三层架构来确定以下重点关注的主题:在业务架构层勾勒出业务运营的概貌,并展示各种组件如何协同工作以推动业务运营。信息系统架构层分为数据架构和应用架构。数据架构的核心是对不同的数据类型进行分类,并突出它们之间的连接。应用架构识别系统中的独特组件(如服务),并阐明它们在系统中的交互作用。技术架构层描述了具体的特定技术。包括软件标准、使用的软件包、硬件、网络以及安全细节等要素。本书侧重于信息系统架构。业务架构与信息系统架构之间的联系较为错综复杂。信息系统架构的设计在很大程度上取决于各种业务要素。这些要素不仅包括业务架构,还包括诸如项目进度、团队技能和竞争对手的挑战等业务环境要素。尽管这些业务环境要素通常不包括在TOGAF等业务架构中,但它们确实影响了业务架构的实施和组织的战略方向。系统架构面临的一个主要挑战是:领导层要基于业务环境做出技术决策。本书第1章讨论的五个问题的一个关键目标就是确保我们的架构始终符合业务环境。系统架构有两种主要的方法:瀑布式(Waterfall)方法。敏捷(Agile)方法。瀑布式方法基于这样的前提:事先确定系统需求的全部细节是可行的。因此,这种方法需要进行全面的规划,然后再执行。TOGAF的架构设计模型(ADM)就是这种方法的一个例子。它演示了如何准确捕捉需求并基于需求进行开发。此外,像对象管理组织(OMG)和国际标准化组织(ISO)这样的机构也提供了支持类似概念模型的标准。敏捷方法(也是一种迭代方法)则专注于快速推出一个版本,并与用户合作完善需求,构建一个能让用户真正受益的系统。比较这两种方法,我更倾向于敏捷方法。虽然人们一直努力将迭代特性与ADM等模型结合起来,但在实践中,这往往过于复杂,且无法保持迭代模型所需的快速节奏(通常是1~2周进行一次迭代)。对于大型组织和复杂项目来说,更加集中的规划或许是合理的。许多软件流程(如TOGAF ADM等标准和参考架构)都以瀑布模型为基础,旨在精确捕捉需求。虽然我们可以从TOGAF、OMG和ISO中汲取宝贵的经验,但前提是可以在事先确定需求,并且只会进行渐进式的改变。因此,本书重点介绍一种敏捷方法,使得需求更加简单和易操作,并通过短期迭代不断改进,同时向用户学习。在更广泛的设计层面上,运用敏捷方法可将整个系统分解为松散连接的子系统(每个子系统都可能与用户互动并提供价值),定义它们之间的应用程序接口(API),然后将各个子系统连接起来,在高层监督下独立运作。在我们深入探讨敏捷方法之前,有必要了解一下软件项目中的各个典型角色。产品经理在业务利益相关者、用户体验(UX)设计师和架构师的帮助下决定要构建什么产品。架构师与工程经理和团队合作构建产品。然后,产品经理与所有人合作以确保达到产品的质量要求(精益求精)。根据工作地点的不同,架构师的职责也会发生变化。例如,在初创公司,架构师负责产品管理,决定要构建的产品功能;而在大型公司,架构师可能与需求规范无关。当今时代,业界正从瀑布式方法转向迭代的、敏捷的软件开发方法,责任正在共担,职业角色也在融合。例如,在决定包含哪些功能、何时包含这些功能以及如何定义用户体验时,架构师应该与产品经理密切合作,并要求团队精益求精。本书共12章。第1章讨论了软件架构、不确定性和判断力,提出了处理不确定性的五个问题和七项原则。第2~3章深入探讨了系统性能和用户体验(UX)。系统性能决定了架构中什么是可行的,什么是不可行的。用户体验(UX)决定了用户对系统的采用与否。与其他章节相比,第2章讲述的内容更为详细、技术性也更强。这些细节至关重要,然而在其他书籍中并未被广泛提及。如果你最初是为了寻求更宽泛的理解,可以简要浏览第2章,但我建议最终回过头重读第2章,以便掌握更细微的要点。第3章强调了用户体验(UX)原则的重要性,并建议你尽早将用户体验专家纳入团队中,并听取这些专家的建议。此外,我还想强调用户体验对于应用程序接口(API)、配置和扩展的重要性。第4~11章从宏观和微观层面讨论了如何构建系统或应用程序。在宏观层面将服务组合成一个连贯的架构;在微观层面学习如何构建良好的服务。在这部分中,我们会尽可能解释一种默认的架构选择,这种选择大多数时间都是行之有效的,我们还会讨论如何选择更复杂的架构,并讨论如何为你的公司选择合适的架构方案。这些讨论包括了反模式和一些常见错误。此外,还将讨论一些至关重要的技术思想。第10章阐述了微服务的注意事项,并没有将它们分散在第5~7章中。这种阐述方式更容易将相关概念作为一个整体来掌握,而不是将各个部分分开来理解。随后,本书将根据适用的五个问题和七项原则来解释每一个技术决策。第12章将讨论如何将全书内容整合在一起。这一章的重点是建立一个快速反馈循环,以消除任何阻碍开发人员完成迭代、接收反馈和学习的因素。本章敦促领导者确保开发人员能够高效地完成工作,同时也要亲自参与解决阻碍开发人员工作进程的问题。
斯里纳特·佩雷拉(Srinath Perera)拥有超过20年的软件架构和编程经验。Apache Axis2项目的联合创始人和Apache软件基金会成员,参与设计了多个分布式系统,如Apache Axis2、Apache Airvatha、WSO2 CEP(Siddhi)和WSO2 Choreo。此外,还参与了10多个项目、100多个版本的架构评审工作。斯里纳特于2009年获得美国印第安纳大学博士学位,并担任非营利组织Lanka软件基金会的研究科学家,致力于为斯里兰卡软件工程师提供创建开源软件技术的平台。同时,他还是斯里兰卡莫拉图瓦大学计算机科学与工程系的客座教授。目前,斯里纳特负责带领研究团队,制定和实施产品与业务战略,推动公司在开源软件和系统架构领域的持续创新与发展。
译者序序前言第1章 软件系统、设计和架构 11.1 软件架构简介 11.2 软件系统设计 31.3 五个问题 51.3.1 问题1:何时是最佳的发布时机 51.3.2 问题2:团队的技能水平如何 51.3.3 问题3:系统的性能敏感度如何 61.3.4 问题4:何时可以重写系统 71.3.5 问题5:有哪些难点 81.4 七项原则:总体概念 91.4.1 原则1:一切从用户的旅程出发 91.4.2 原则2:使用迭代薄切片策略 101.4.3 原则3:在每次迭代中,以最小的投入获得最大的价值,以支持更多用户 121.4.4 原则4:做出决策并承担风险 141.4.5 原则5:深入设计难以改变的事物,但要慢慢地实施 151.4.6 原则6:尽早并行处理棘手的难题,消除未知因素,并从实证中学习 161.4.7 原则7:理解软件架构中内聚性和灵活性之间的权衡 171.5 为在线书店进行设计 191.6 为云计算进行设计 221.7 总结 24第2章 系统性能的思维模型 262.1 计算机系统 282.2 性能模型 282.2.1 模型1:从用户模式切换到内核模式的成本 292.2.2 模型2:操作层级 292.2.3 模型3:上下文切换开销 302.2.4 模型4:阿姆达尔定律 312.2.5 模型5:通用可扩展性定律 322.2.6 模型6:延迟和利用率的权衡 332.2.7 模型7:以最大有效利用率模型设计吞吐量 332.2.8 模型8:添加延迟限制 342.3 优化技术 372.3.1 CPU优化技术 382.3.2 I/O优化技术 392.3.3 内存优化技术 412.3.4 延迟优化技术 422.4 对性能的直观感受 432.5 领导力的考量 432.6 总结 44第3章 用户体验 463.1 架构师所需的用户体验概念 463.1.1 原则1:了解用户 473.1.2 原则2:必要功能 483.1.3 原则3:好产品不需要说明书,其用途不言自明 483.1.4 原则4:从信息交换的角度思考 493.1.5 原则5:保持简单 493.1.6 原则6:在实施前设计用户体验 503.2 配置的用户体验设计 503.3 API的用户体验设计 523.4 扩展性的用户体验设计 543.5 领导力的考量 553.6 总结 56第4章 宏观架构:简介 574.1 宏观架构的历史 584.2 现代架构 614.3 宏观架构下的构建模块 624.4 领导力的考量 654.5 总结 67第5章 宏观架构:协调 685.1 方法1:从客户端驱动流程 685.2 方法2:使用另一个服务 695.3 方法3:使用集中式中间件 705.4 方法4:实施编排 715.5 领导力的考量 725.6 总结 72第6章 宏观架构:保持状态的一致性 746.1 使用事务 746.2 超越事务 756.2.1 方法1:重新定义问题以减少保证要求 776.2.2 方法2:使用补偿 786.3 最佳实践 806.4 领导力的考量 816.5 总结 83第7章 宏观架构:安全问题 857.1 用户管理 867.2 交互安全 897.2.1 认证技术 907.2.2 授权技术 927.2.3 应用程序的常见安全交互场景 947.3 存储、GDPR和其他法规 987.4 安全策略和建议 1007.4.1 性能和延迟 1017.4.2 零信任方法 1027.4.3 运行用户提供的代码时要小心 1037.4.4 区块链 1037.4.5 其他话题 1037.5 领导力的考量 1047.6 总结 106第8章 宏观架构:处理高可用性和扩展 1078.1 加入高可用性 1078.1.1 复制 1078.1.2 快速恢复 1108.2 理解可扩展性 1128.3 现代架构的扩展:基本解决方案 1138.4 扩展:领域中的工具 1148.4.1 扩展策略1:无共享 1168.4.2 扩展策略2:分布 1168.4.3 扩展策略3:缓存 1168.4.4 扩展策略4:异步处理 1168.5 构建可扩展的系统 1178.5.1 方法1:连续消除瓶颈 1178.5.2 方法2:无共享设计 1198.6 领导力的考量 1218.7 总结 122第9章 宏观架构:微服务的注意事项 1239.1 决策1:处理共享数据库 1249.1.1 解决方案1:使用一个微服务更新数据库 1259.1.2 解决方案2:使用两个微服务更新数据库 1269.2 决策2:确保微服务的安全 1269.3 决策3:微服务的协调 1269.4 决策4:避免依赖地狱 1279.4.1 向后兼容 1279.4.2 向前兼容 1279.4.3 依赖关系图 1299.5 微服务的替代方案:松耦合的基于代码库的团队 1299.6 领导力的考量 1319.7 总结 132第10章 服务架构 13310.1 编写服务 13310.2 理解编写服务的最佳实践 13410.3 微服务中的高级技术 13610.3.1 使用替代的I/O和线程模型 13610.3.2 理解协调开销 14210.3.3 高效保存本地状态 14310.3.4 选择传输系统 14510.3.5 处理延迟 14610.3.6 读写操作分离 14610.3.7 在应用程序中使用锁 14710.3.8 使用队列和池 14810.3.9 处理服务调用 14910.4 在实践中使用这些技术 14910.4.1 CPU密集型应用(CPU使用远大于内存且无I/O) 14910.4.2 内存密集型应用(CPU + 内存密集且无I/O) 15010.4.3 平衡型应用(CPU + 内存 +I/O) 15010.4.4 I/O密集型应用(I/O + 内存 > CPU) 15110.4.5 其他应用分类 15110.5 领导力的考量 15310.6 总结 154第11章 构建稳定的系统 15511.1 系统失效的原因及应对方法 15511.2 处理已知错误 15711.2.1 处理意外负载 15711.2.2 处理资源故障 16111.2.3 处理依赖关系 16511.2.4 处理人为变更 16611.3 常见故障 16711.3.1 资源泄漏 16711.3.2 死锁和慢操作 16811.4 处理未知错误 16911.4.1 可观测性 16911.4.2 错误和测试 17011.5 优雅地降级 17211.6 领导力的考量 17211.7 总结 173第12章 系统的构建和发展 17412.1 亲自动手 17412.1.1 打好基础 17412.1.2 了解设计过程 17712.1.3 做出决策并承担风险 18012.1.4 追求卓越 18112.2 沟通设计 18312.3 系统的发展:向用户学习并改进系统 18412.4 领导力的考量 18712.5 总结 189
你还可能感兴趣
我要评论
|