主页

索引

模块索引

搜索页面

架构设计原则

备注

架构设计领域并没有一套通用的规范来指导架构师进行架构设计,更多是依赖架构师的经验和直觉,因此架构设计有时候也会被看作一项比较神秘的工作。优秀程序员和架构师之间还有一个明显的鸿沟需要跨越,这个鸿沟就是 “不确定性”。

重要

架构设计的几个共性的原则隐含其中:合适原则、简单原则、演化原则

合适原则第一考虑,优先满足业务需求;
简单原则第二考虑,挑选简单方案快速落地验证;
演进原则第三考虑,适当预测业务发展,感觉预测不准就不预测,等真的出现问题的时候演进即可

常让架构师陷入两难的境地的示例:

1. 是要选择业界最先进的技术,还是选择团队目前最熟悉的技术?
    如果选了最先进的技术后出了问题怎么办?如果选了目前最熟悉的技术,后续技术演进怎么办?
2. 是要选择 Google 的 Angular 的方案来做,还是选择 Facebook 的 React 来做?
    Angular 看起来更强大,但 React 看起来更灵活?
3. 是要选 MySQL 还是 MongoDB?
    团队对 MySQL 很熟悉,但是 MongoDB 更加适合业务场景?
4. 淘宝的电商网站架构很完善,我们新做一个电商网站,是否简单地照搬淘宝就可以了?

合适原则

重要

合适原则宣言:“合适优于业界领先”。具体怎么算合适,例如性能要求等

“脚踏实地”:

1. 将军难打无兵之仗
    没那么多人,却想干那么多活,是失败的第一个主要原因。
2. 罗马不是一天建成的
    没有那么多积累,却想一步登天,是失败的第二个主要原因。
3. 冰山下面才是关键
    没有那么卓越的业务场景,却幻想灵光一闪成为天才,是失败的第三个主要原因。

真正优秀的架构都是在企业当前人力、条件、业务等各种约束下设计出来的,能够合理地将资源整合在一起并发挥出最大功效,并且能够快速落地。

简单原则

重要

简单原则宣言:“简单优于复杂”。

软件领域的复杂性体现在两个方面:

1. 结构的复杂性
    a. 组成复杂系统的组件数量更多;
    b. 这些组件之间的关系也更加复杂。
2. 逻辑的复杂性
    逻辑复杂的组件,一个典型特征就是单个组件承担了太多的功能。
    把太多功能全部在一个组件中实现,就是典型的逻辑复杂性。

结构的复杂性:

1. 组件越多,就越有可能其中某个组件出现故障,从而导致系统故障
假设组件的故障率是 10%(有 10% 的时间不可用),那么:
  有 3 个组件的系统可用性是(1-10%)×(1-10%)×(1-10%)= 72.9%,
  有 5 个组件的系统可用性是(1-10%)×(1-10%)×(1-10%)×(1-10%)×(1-10%)=59%
  两者的可用性相差 13%。

2. 某个组件改动,会影响关联的所有组件
这个问题会影响整个系统的开发效率,
因为一旦变更涉及外部系统,需要协调各方统一进行方案评估、资源协调、上线配合。

3. 定位一个复杂系统中的问题总是比简单系统更加困难
首先是组件多,每个组件都有嫌疑,因此要逐一排查;
其次组件间的关系复杂,有可能表现故障的组件并不是真正问题的根源。

逻辑的复杂性:

逻辑复杂几乎会导致软件工程的每个环节都有问题

假设现在淘宝将这些功能全部在单一的组件中实现:
  1. 系统会很庞大,可能是上百万、上千万的代码规模,“clone” 一次代码要 30 分钟。
  2. 几十、上百人维护这一套代码,某个 “菜鸟” 不小心改了一行代码,导致整站崩溃。
  3. 需求像雪片般飞来,为了应对,开几十个代码分支,然后各种分支合并、各种分支覆盖。
  4. 产品、研发、测试、项目管理不停地开会讨论版本计划,协调资源,解决冲突。
  5. 版本太多,每天都要上线几十个版本,系统每隔 1 个小时重启一次。
  6. 线上运行出现故障,几十个人扑上去定位和处理,一间小黑屋都装不下所有人,整个办公区闹翻天。
  7. ……

备注

为什么复杂的电路就意味更强大的功能,而复杂的架构却有很多问题呢?根本原因在于电路一旦设计好后进入生产,就不会再变,复杂性只是在设计时带来影响;而一个软件系统在投入使用后,后续还有源源不断的需求要实现,因此要不断地修改系统,复杂性在整个系统生命周期中都有很大影响。

备注

功能复杂的组件,另外一个典型特征就是采用了复杂的算法。复杂算法导致的问题主要是难以理解,进而导致难以实现、难以修改,并且出了问题难以快速解决。

备注

无论是结构的复杂性,还是逻辑的复杂性,都会存在各种问题,所以架构设计时如果简单的方案和复杂的方案都可以满足需求,最好选择简单的方案。《UNIX 编程艺术》总结的 KISS(Keep It Simple, Stupid!)原则一样适应于架构设计。

演化原则

重要

演化原则宣言:“演化优于一步到位”。

备注

软件架构与建筑的架构的区别在于:建筑一旦完成(甚至一旦开建)就不可再变,而软件却需要根据业务的发展不断地变化!对于建筑来说,永恒是主题;而对于软件来说,变化才是主题。

生物演化:

首先,生物要适应当时的环境。
其次,生物需要不断地繁殖,将有利的基因传递下去,将不利的基因剔除或者修复。
第三,当环境变化时,
    生物要能够快速改变以适应环境变化;
    如果生物无法调整就被自然淘汰;
    新的生物会保留一部分原来被淘汰生物的基因。

软件架构设计演化:

首先,设计出来的架构要满足当时的业务需要。
其次,架构要不断地在实际应用过程中迭代
    保留优秀的设计,修复有缺陷的设计,改正错误的设计,去掉无用的设计,使得架构逐渐完善。
第三,当业务发生变化时,
    架构要扩展、重构,甚至重写;
    代码也许会重写,但有价值的经验、教训、逻辑、设计等却可以在新架构中延续。
https://img.zhaoweiguo.com/knowledge/images/architectures/designs/design_principle1.png

Windows 系统的发展历史

https://img.zhaoweiguo.com/knowledge/images/architectures/designs/design_principle1.png

Android 的发展历史

其他原则

架构设计原则:

1. 适合优于业务领先: 可参照淘宝,但不要照搬
2. 演化优于过度设计: 不要设计过于超前的方案,演化也不要推倒重来
3. 简单优于复杂: 轮询大部分时间很好,不确定就穷举,不明确就轮询
4. 重构优于重写: 风险控制、经验传承、成本分散
5. 硬件优于人工: 能用硬件解决的就不要用人工解决
6. 专注优于全面: SRP 原则,一个系统只关注一件事
7. 开放优于封闭: SOA&微服务
8. 能用优于完美
9. 重用优于自研
10. 业务优于技术
11. 存储优于计算: 存储设计是架构设计的关键
12. 技术优于流程: 不要试图提升人的能力来保证质量,不要试图投入大量测试来保证质量,尽量做到出问题能快速发现和处理
13. 分布优于集中
14. 优化优于重构

其他

预测部分在整个架构设计里占百分比多少:

不同行业不同公司都不同,一般来说,互联网 2C 行业预测时间不超过 2 年,但是 2B、政府事业单位这些,预测 5 年也是可能的

约书亚:

我平时工作中更多提醒自己压抑一下想预测各种需求变化的欲望。因为之前总是过度设计。压抑并不是说不去考虑各种变化,而恰恰需要把可能性大的变化点一一罗列出来,分维度打分,维度包括 可能性大小?长期还是短期会变化?如果发生变化,目前的组织和系统要花多大成本适应变化。这些变化正是李老师之前说过的各种复杂度上的变化,比如用户量激增带来的性能要求。此外还包括一个业务功能逻辑上的变化。 在经过上面分析后往往会给出 “上中下” 策的设计方案,下策一般考虑的变化少,短视,但迅速,修改小,立竿见影。上策一般看重远期,但成本高很高,也很可能预测不中。 最后还要分析,如果决定采用下中策,如果预测的变化发生了,系统修改为中上策的代价有多大,有些代价几乎是无穷大的,比如必须中断服务进行升级。如果代价小,那可以放心采用下策或中策。如果答案是否,可上策当前的代价又真的不可接受,那又要返回头重新分析了 实践发现这个方法挺好用,尤其当有人来咨询架构方案时,往往对给出的结果比较满意

参考

  • 实例参考:《淘宝技术发展》

  • 实例参考: 《QQ 1.4 亿在线背后的故事》

主页

索引

模块索引

搜索页面