对抗软件复杂度的战争(2)

简介: 对抗软件复杂度的战争

07

软件道德观


在微观层面控制软件复杂度,认真编写单元测试以保障代码编写的质量反馈,对于研发效率来说是至关重要的,但同时也是耗时耗力的。而且由于这种投入对商业的价值需要很长时间才能体现出来,因此容易被研发主管所忽视。


开发者都是在生产代码、文档、API 服务等软件中间产物,这些中间产物被逐渐组装起来成为产品,产生商业价值。软件中间产物的质量对于研发组织的整体效率是至关重要的,而复杂度得到很好控制的代码和系统,就是高质量的软件中间产物;良好的软件研发道德,或者有时候也会认为这是良好的工程师文化,就是大家形成一种以交付高质量软件中间产物为荣,以交付低质量软件中间产物为耻的共识文化。


软件研发的核心职责之一是关注软件复杂度,通过开放代码、文档,Code Review 等方式让软件复杂度的信息透明,并且让所有在增加/降低复杂度的行为透明,并且持续激励那些消除复杂度的行为。唯有如此,在微观层面的控制复杂度的方法才能得到落实。


08

系统架构对复杂度的影响


介于宏观的技术战略和微观的工程师文化之间,存在着一块重要的决策区域,也对软件复杂度有着关键的影响,我称之为系统架构。在面对需求的时候,缺乏经验的工程师会直接想着在自己熟悉的模块中直接解决,而经验丰富的工程师会先思考一下系统上下文。在《Design Docs at Google》这篇优秀的技术文档写作指导中,就重点提到了,设计文档应当写清楚系统上下文图(sysmte-context-diagram),这背后的原因是什么呢?


我近期对一个遗留系统做了一个依赖链路的梳理分析,这个系统是负责生产环境中各类资源的管理的,包括资源的规格,版本,依赖关系等等,梳理完成后,整体的结构吓了我一跳,这个图大致是这样的:

图中蓝色的部分是控制和执行的子系统(System X,Y,Z),例如控制容器的调度,控制镜像变更的执行等等,是比较清晰的。但是其余部分就不是这样了(A1, A2, A3, C1, C2, S, E),它们都是在管理一个资源的运行态版本,包括镜像的版本,容器的规格,是否有 GPU,容器的数量,关联的网络资源等等,但却演进出了七个子系统,这实际上是非常高的偶然复杂度。当一个领域的概念被分散到这么多子系统之后,就会产生一系列问题:


  • 不同子系统对于同一个概念有不同的名称,交互的时候会涉及各种翻译。

  • 不同子系统承担了同一个实体的部分概念,导致修改的时候需要大范围一起修改,且容易出错。

  • 更高的运维成本。


仔细去分析这一复杂度形成的因素,我发现这既不是技术战略的问题,也不是微观层面工程师生产低质量代码导致,而是有其他更深层次的问题。其中的最核心的因素是,这些子系统在不同时期是归属于不同的团队的,有的甚至是不同部门的,具体来说,当各个部门各个团队目标不一致的时候,而这个系统又不幸地被拆到各个团队,那么就不会有人会对系统整体的复杂度控制负责。当有的团队在负责把这套系统商业化对外输出,有的团队在负责把这套系统从虚拟机模式演进到容器模式,有的团队在负责资源的成本控制,有的团队在思考全局高可用架构,而没有一个全局的架构师从整体控制概念,控制边界的时候,系统就自然而然地腐化成这样的一个状态了。


当一个问题域没有系统架构,或者其系统架构是错误的时候,你就会发现不同的人在发明不同的语言,这就好比相隔几十公里的两个村子,常常对同一个概念有不同的用词或者发音。日常生活中语言的不精确不是问题,因为日常的沟通是充满上下文的(表情,气氛,环境等),但在计算机的世界,语言的不精确就意味着需要写代码翻译,一旦翻译错误软件就会执行出错。这也就是为什么领域驱动设计那么强调统一语言,强调限定上下文。但领域驱动设计是方法论,而知道方法并不能取代系统架构角色的缺位。


这个复杂系统是康威定律的绝佳例证,康威定律说:“任何系统设计的系统,其系统结构会复制组织的沟通结构。”这句话其实还是有些抽象的,更具体的一些阐述是:


“康威定律 … 是一个合理的社会学观察。… 除非模块 A 和模块 B 的设计及实现者能有效沟通,否则这两个软件模块是无法正确对接的。因此软件系统的接口结构,就必然会和生产软件系统的社会结构及组织相对应。”


康威定律所揭示的事实,就是软件架构在很大程度上是由组织的结构和协作模式决定的,这实际上已经不再是一个软件技术问题了,而是一个组织管理问题。因此,解决系统架构层面的软件复杂度问题,就必须面对组织管理的挑战。关键问题域是否有唯一的负责人?当不同的团队在同一个问题域重复建设系统的时候,如何整合团队?当已有团队为了自己的生存,不断夸大其负责系统的重要性和特殊性,如何识别这种问题?组织如何给予大家充分的安全感,让工程师愿意为了架构的合理性,放弃自己辛苦耕作的系统模块?


讨论管理工作似乎已经超出了这篇论述软件复杂度的文章的范畴,但很多工程师或者隐隐感觉,或者思来想去最终领悟,这是我们的软件系统或优雅健壮或千疮百孔的根本因素。


小结


我曾经的大老板郭东白曾在一次 QCon 的演讲中讨论优秀架构师的特质,除了大家都很好理解的有眼光、善于思考、能感召等几个特质外,还特别强调了“有良知”,他说:

有良知,这是一个架构师随着时间的流逝,沉淀在身上最重要的品质。什么是有良知?为人正直,选择做正确的事情。很多人是非常聪明的,业务理解能力强,技术实践丰富,但他不一定为公司或为组织做最正确的事情。有良知是非常重要的一个事情,如果架构师没有素质,他会让一家公司的损失很惨重。


软件复杂度是人的行为引起的,无论是微观层面的重视质量和工程师文化,在系统架构层面让组织结构和沟通符合客观问题域,还是在技术战略层面做符合公司利益的决策,这里都存在客观无法改变的规律。如何认识到这些规律,并基于这些规律制定决策(可改变可影响),努力为公司创造价值,努力让每个工程师被尊重,是每个工程师、架构师、技术管理者所应当秉承的基本态度。本文讨论软件复杂度的初衷,就是尽量去揭示复杂度背后的客观规律,希望帮助大家认清现实,用更务实的态度去思考和决策,创造更有价值,也更让自己满足的软件系统。


参考阅读

  1. Why choose Domain-Driven Design?  这篇文章清晰地解释了本质复杂度和领域驱动设计的关系。
  2. 《人月神话》-「没有银弹」一篇阐述了本质复杂度和偶然复杂度的概念。
  3. 《The Lean Product Playbook》- 本书的第2章清晰地解释了 Problem Space 和 Solution Space。
  4. Wardley Map  - 分析技术战略的绝佳工具,合理地选取商业产品可以帮助降低系统复杂度。
  5. Grokking Simplicity  - 在微观层面,使用函数式的思维降低软件复杂度。
  6. Design Docs at Google
  7. Conway’s Law
  8. 警惕复杂度困局:关于软件复杂度的思考
相关文章
|
6月前
|
搜索推荐 程序员 测试技术
研究思考|关于软件复杂度的困局
本文重点围绕软件复杂度进行剖析,希望能够帮助读者对软件复杂度成因和度量方式有所了解。
|
6月前
|
架构师 Java 测试技术
对抗软件复杂度的战争
对抗软件复杂度的战争
49 0
|
搜索推荐 程序员 测试技术
研究思考丨关于软件复杂度的困局
研究思考丨关于软件复杂度的困局
1300 8
研究思考丨关于软件复杂度的困局
|
决策智能
博弈论第十一集总结(进化稳定—合作,突变,与平衡 “ 观后感)
博弈论第十一集总结(进化稳定—合作,突变,与平衡 “ 观后感)
72 0
|
JavaScript 前端开发 Java
对抗软件复杂度的战争(1)
对抗软件复杂度的战争
453 0
|
架构师 JavaScript Java
对抗软件规模与复杂度的战争:救命、治病、养生
对抗软件规模与复杂度的战争:救命、治病、养生
502 0
|
SQL 存储 安全
红蓝对抗-基础学习
安全是一个整体,正如木桶定律,最短的木板是评估木桶品质的标准,安全最薄弱环节也是决定系统好坏的关键。而网络红蓝军对抗的目的就是用来评估企业安全性,有助于找出企业安全中最脆弱的环节,提升企业安全能力的建设。
|
人工智能
降低损失挽救生命,用人工智能对抗自然灾害
人们长久以来一直将称之视为纯粹突发的极端事件。但实际上,成千上万条微妙且缓慢推进的线索,早已指明了自然灾害发生的可能性与严重程度。
135 0
降低损失挽救生命,用人工智能对抗自然灾害
|
安全 算法
新冠病毒的演化的进化算法推演
自从新冠病毒爆发以来,疫情的发展就一直牵动着全国人民的心。但随着近两个月疫情的飞速发展,可以说新冠病毒的传播速度已经超出了所有人的预料! 而年前因工作需要,刚研究过进化算法,所以新冠病毒是如何快速进化出来的,引起了我的兴趣。
2688 0
新冠病毒的演化的进化算法推演
为抵抗病毒感染,国内研究团队找到新型调控因子EGCG
据李涛表示,国际上许多大的制药集团和研究团队都在倾力寻找cGAS抑制剂。
889 0