- Published on
我的架构设计思考
一,开始之前的几个活动
- 确定和决定要使用的开发技术和平台。
- 定义开发标准:比如,编码标准,工具,代码review流程,测试方法等。
- ** 协助识别和理清业务需求。 设计系统和基于需求做出决策。**
- 记录和沟通架构定义、设计和决策(Document and communicate architectural definitions, design and decisions)。
- 检查和review架构和代码,比如,检查确定的模式和编码标准的实现是否合理。
- 与其他 的架构师和利益相关者协作。
- ** 开发人员的教练和顾问。**
- 细化并把high level的设计具体到low level设计。
⚠️ 注意: 注 架构是一个持续的活动,尤其是在敏捷开发团队中。因此,这些活动得一遍一遍的重复迭代,over and over again。
二,10个重要技能:设计,决策,简化,代码,文档,沟通,评估,权衡,顾问,营销。
(1)设计
知道基础的设计模式: 知 模式是一个非常重要的工具,是架构师开发可维护系统的重要工具之一。记住,你要想开发出可 维护维 的系统,请记得适当地运用设计模式。通过模式你可以重用那些已经被证明可以解决常见问题的设计思路。去看看 GoF(Gang of Four)写的有关设计模式的书吧,尽管这些模式已经20多年了,但依然是现代软件架构的基础。比如 Model-View-Controller (MVC) 模式就可以用于多个领域,甚至是一些更新的模式的基础,比如MVVM。
对模式和反模式进一步钻研: 对 如果你已经知道了所有基础的GoF设计模式,接下来可以扩展自己的知识储备去学习更多 的软件设计模式,或对你感兴趣的领域进行垂直钻研。我个人比较喜欢Gregor Hohpe写的一本书叫:Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions。这本书主要的内容是系统之 间的数据交换(应用集成方面)。
(2)决策
知道什么是重要的: 知 不要浪费时间在那些不重要的决定或活动上,学会认识什么是重要的。目前看来也没什么书籍教你认识别这些。我个人有个原则,每当我要评价一件事是否重要我就会考虑这两个方面:
- 概念完整性(Conceptional Integrity): 如果你决定以某种方式去做,那么就干,即使有时候会有更优的方案。 通常来说,这会使得你有一个直接的全局的概念,使得更容易理解和更容易维护。
- 统一性(Uniformity):比如如果你有名称的一些约定,当然无论是小写还是大写,至少让每个地方都是用同样的方 式,比较统一。 优先级: 优 有关这方面建议去看一下Weighted Shortest Job First (WSJF) 模型,这个模型被广泛用于敏捷软件开发中尤其是时间紧迫性( time criticality)和降低风险(risk reduction)对于评估架构决策优先级至关重要。
评估多个选项: 评 应该总是给出多种方案,这样才能进行做出决策和决定。不要只给一个方案,听着感觉就是你没有认真 工作一样。另外只有一个方案的时候,也没法做出一个合理的选择,因为只有一个方案。另外就是要定义一些指标和标 准,通过这个来衡量哪个方案好,哪个方案不好,最好不要去凭感觉。比如:license花费或成熟度(本文有讲到成熟 度模型)。这样才能做出一个更好的决策。
(3)简化
记住一个解决问题的原则Occam’s Razor。 这个原则告诉你解决问题要简单。这个原则里有一句话叫:最简单的那个 solution往往是最好的。我总结这个原则的核心是:如果你对某个问题有多个假定解决方案,这很有可能就是错的,或 者导致没必要的复杂的解决方案。多个假定 方案应该被简化到只有一个好的解决方案。别提出来一大堆解决方案,说这 个也可以,那个也可以,说明是有问题的。
矫正解决方案: 矫 通过对解决方案的矫正,有助于你发现最简单的那个方案,通过从不同的角度和位置去看,往往会得到 不错的效果。你可以从上到下的想一遍,然后再从下到上的想一遍。如果你有一个数据流(data flow)或流程,那么 你可以先从左往右想一遍,然后从右往左想一遍。与此同时问自己一个问题:“在理想的世界里,你的解决方案会发生 什么?” 或:“公司或指定人员会做什么?” 这两个问题会强迫你把解决方案减少到如Occam’s Razor建议的那样。
分解成一个个小问题( 分 Divide and Conquer): 简化问题的一个好办法就是把问题切分成多个小问题然后挨个解 决。这让我想起了自己小时候打扫院落的场景,看着偌大一个院子,看着就烦,于是我决定把院子划分成三个小块,然 后一个个去打扫,这让我的心理负担减轻了不少。一个个小块打扫完了,最后再整体查看下整个院子还有没有边边角角 的地方需要打扫。总览一下全局,然后整个院子就打扫完了。再枯燥的生活,都可以发现一些乐趣。 重构并不可耻 重 : 有时候,你可能一时半会想不到更简单的方案,你不妨就从一个复杂的方案开始做起,先做着,等到之 后再进行重构,这时候再去重新思考解决方案。
重构并不可耻,但重构之前要注意一件事情:足够的自动化测试以确保 你所重构的地方的功能正确和满足利益相关者的需求。学习更多重构的知识,我建议你可以读读《重构、改善既有代码 的设计》 “Refactoring. Improving the Design of Existing Code” ,这本书是 Martin Fowler写的。
(4)代码
只有当你自己尝试去做事情本身,然后你感受到情感和发生情绪,然后有了对事物好坏的判断。你使 用技术的时间越长越能做出正确的评判。这有助于你在日常的工作中做出正确的判断。当前有大量的语言和框架,只有 你对这些有一定的经验和了解后才能做出正确的决策,从而引导开发人员朝着正确的方向迈进。还是那句话,记住经验 的定义:所见、情感和假设。要想有经验就要去动手!
找到正确的事去尝试: 找 你不可能去尝试所有事情。这是不可能的。你需要一个更加结构化的方法。有一个来自 ThoughtWorks不错的方法是技术雷达(Technology Radar)。他们把技术、工具、平台、语言和框架分为四类: Adopt,Trial,Assess 和 Hold。Adopt(采用) ( 意思是 “强烈的感觉到已经可投入到生产中使用了”,Trial(试( 用)用 意思是 “可以先在某个项目中做尝试,在这个项目中做到风险可控”, Assess(调研) ( 意思是“可以探索下对公 司有哪些影响”, Hold(保留) ( 意思是 “谨慎使用”。通过这种分类,更容易获得新技术的整体情况及其准备情况,以 更好地评估下一步要干什么。
(5)文档
架构文档有时候很重要,但有时候又不重要。重要的文档比如架构决策或编码指导手册。编码开始之前通常需要初始文 档,并且需要不断完善。其他文档可以自动生成,因为代码也可以是文档,例如UML类图。
Clean Code:代码是最好的文档,如果你写得足够好。一个好的架构师要有能力分辨出好代码和烂代码。著名的 书:“Clean Code”。
如果可能的话,尽可能自动生成文档: 如 手动写文档的坏处不 多说,把 Swagger 和 RAML 或者公司内部开发的文档系 统快点用起来吧。
文档尽可能少( 文 As much as necessary, as little as possible ):) 文档尽量少。无论您需要写什么文档(例如 决策文档),都应尝试一次只关注一件事,并且仅包含关于这件事的必要信息。大量的文档很难阅读和理解。附加信息 应放在附录中。特别是对于决策文件,讲一个有说服力的故事更为重要而不是仅仅发表大量的论证。而且,这可以为你 和你的同事节省很多时间,因为他们要阅读你的文档。看看你过去输出过的一些文档(源代码,模型,决策文件等), 然后问自己以下问题:“是否包含所有必要的信息才能理解它?”,“确实需要哪些信息?可以省略吗?”和“文档中是否 有红线?”。一句话,不要废话。
(6)沟通
沟通很重要。
经常沟通:一个再好的架构没人知道它的价值依然为零。分发对应级别的架构,然后安排会议与开发者、架构师和管理 者分享未来的和已经在践行的架构。
要透明: 定期的沟通只能部分缓解透明度问题。你需要把决策的原因透明化。特别有的人可能没有参加决策过程的情况 下会很难理解决策以及其背后的原因。
随时准备演讲: 随 把常见问题放在一个显眼(易找到)的地方,随时应对人们提出的问题,这样有时候会保护你。
(7)评估
(1) 设计实践 :
这个架构用了哪个模式?有没有被正确的使用?
这个设计遵循红线(red line)了吗?这个设计有没有能够可持续(uncontrolled growth)?
有没有一个清晰的结构和各自领域 的单独关注有没有分布合理?
(2) 开发实践 :
代码指引手册有没有到位?遵循了吗?
代码版本管理怎么做的?有没有版本化? 部署是怎么分布的?
(3) 质量保障 :
自动化测试覆盖率怎么样?
静态代码分析有没有做?分析结果怎么样?交叉检查有没有做?
(4) 安全:
有哪些安全概念到位?
内置安全? 渗透测试或自动安全分析工具是否到位,经常在用吗?
(8)权衡
解决矛盾目标: 解 一个典型的矛盾目标的例子就是短期和长期目标。项目往往趋向于构建一个最简单的方案来解决问题而 架构师则具有长期的眼光和愿景。一般情况下,最简单的方案往往都不能满足长期目标和愿景。为了避免技术实现步入 错误的方向,有两件事情需要考虑: (1) 开发人员和业务需要明白长期愿景和目标,知道调整成新的解决方案可以带来好处。 (2) 负责预算的管理人员需要知道对财务的影响,没有必要100%站在长期愿景一边。
冲突管理: 冲 架构师经常是多个不同背景的团队的粘合剂(胶水)。有时候在不同的level之间的交流会发生冲突,需要你 去找到一个平衡的解决方案,这可能会对长期战略的目标造成影响。我的解决之道是Schulze von Thun的四眼模型 ( “Four-Ears Model” of Schulze von Thun)。基于这个模型,可以帮你搞定一些事情。但这个理论需要多实践几 次才能熟练掌握,可以在交流研讨会上多用几次。
(9)顾问
主动询问,而不是被动等待,而且你需要有预见,预见接下来的几周内会发生什么,然后规划相应的步骤。有远见和 构建实践社区。
(10)营销
- 激励并说服
- 原型
- 小短片
- 为你的 为 idea坚持到底。
三,关注点
- 延迟延:表示获得响应之前经过的时间,这里指的是一段时间。我们有最小延迟(开始时间)和 截止日期 截 (结束时间)。衡量延迟的其他因素包括 优先级 优 (我们在其中查看响应的顺序)和 抖动抖 (随时间观察到的延迟波动)。
- 吞吐量:是指在固定时间间隔内获得的响应数。但为了提高精度,我们应该度量多个时间间隔。
- 可用容量:以上度量的结合体。在不超出延迟要求的情况下可实现的最大吞吐量。
- 可调度的利用率:利用率是资源繁忙时间的百分比,而可调度的利用率是满足一定时间要求的最大利用率。
- 数据丢失:如果使用缓存来提高性能,那么缓存未命中将成为性能指标。
提高可用性的技术
监控项 | 描述 |
---|---|
CPU | 监视系统的 CPU 使用情况。 |
内存 | 监视系统的内存使用情况。 |
心跳 | 定期检查系统以确保一切正常。 |
时间戳 | 事件应具有关联的时间戳,以便重现不同的场景。 |
异常 | 我们无法预见的异常情况。 |
超时 | 我们设置了生成响应的最大允许时间限制。 |
检测到异常情况后,我们可以进行干预。
概念 | 描述 |
---|---|
热冗余 | 这意味着我们面对 的是集群环境,当一个组件出现故障时,集群将介入并继续工作。 |
暖冗余 | 这里涉及一个主从关系。冗余组件会一直待命,出问题时立刻接收来自主组件的所有更改,并且可以在几毫秒内取代它。 |
冷冗余 | 满足某些条件时,将生成组件的新实例。但这意味着会存在停机时间,因此不建议在高可用性系统中使用它。 |
异常处理 | 我们可以使用重试机制和缓存。 |
重试机制 | 我们应该假设系统在重试后变得可用。 |
回滚 | 使系统恢复到先前工作状态的能力。 |
增强安全性的技术
检测方法 | 描述 |
---|---|
基于签名的检测 | 使用先前存储的一组签名或已知的恶意行为模式来检查服务请求模式。 |
基于异常的检测 | 通过存储客户的行为,我们可以检测出异常情况何时发生。此任务并非易事,因为它需要大量数据。 |
验证消息完整性 | 使用校验和或哈希对消息签名。这些值出现变化就意味着存在问题。 |
检测中间人 | 在消息中使用时间戳可以检测到异常行为(例如消息到达时间比平时要长)。 |
可测试性
在所有系统中它都是一个重要特征。我们必须确保构建的系统尊重了客户的需求。复杂的系统很难测试。以微服务架构为例,我们有 很多独立开发的活动部件。这个特征经常会让步给其他特征。为了使系统可测试,我们需要能控制每个组件的输入和输出。