为什么我们的系统复杂度这么高了?

我曾多次听到灵魂拷问:

  1. 为什么你们程序员不能一个人负责所有服务呢?
  2. 为什么开发这么简单的需求还需要这么多人?
  3. 为什么服务需要分给不同的人,不能一个人可以了解所有服务功能?
  4. 一个项目为什么还需要这么多人?

答案在一个古老的传说中,上帝在混沌中创造了天堂和人间,而程序员创造了混沌。

软件系统复杂度的由来

我们先看看大家是否遇到过这样的场景:

  1. 这是2017年遗留下来的系统了,问题是非常多的,还能跑起来,就是与现在格格不入,哪哪都有问题,到处都需要改,无从下手。
  2. 这个技术升级要不要去做呢?不知如何衡量成本与收益,从价值大小入手,更多的是哪些故事更好听,哪些优先级更高。
  3. 技术架构优化通常都是底层优化,牵一发而动全身,测试不全面,急于上线引出更大的问题,被各方指责,直接回退,后续的优化动作被迫停止,无疾而终。
  4. 我们第一期先做一个简单的系统MVP跑起来。两周后,老大说了,功能需要加这些那些,还有这这的功能。还是得按照原计划上线。

上面的场景隐含了软件的复杂度主要两个来源:需求功能的复杂度和技术设计的复杂度。而这两个复杂度就是系统演进的产物。

建筑师不会轻易给100层的高楼增加一个地下室,但是软件工程师会,不但增加了1层地下室还是多盖了5层楼,额外再加上外挂阳台。

建筑师一般只在设计阶段修改图纸,而软件工程师在任何时候都在修改,设计时候修改,在测试时候修改,还在上线后继续修改。这肯定会带来复杂度的,但是最大的复杂度来自于——规模

大家熟知的朋友圈功能上主要点:发动态、评论和点赞。业务功能不复杂,但是人群规模复杂度很高。是典型的质量复杂度高,业务复杂度低的业务。

程序员有一个笑话:

  小李跟小王抱怨,说这段代码实在是太恶心了,花了很长时间才看懂,并且代码非常僵硬,而正好这个需求需要改动到这里,代码真的就像一坨乱麻。
  小王问他最后是怎么处理的。小李说,我给它又加了一坨。

有一个需求,需要小王到土里埋个地雷,这确实不复杂,但小王往往面临的真实场景其实是:“在这片雷区里加一个雷”,而雷区里哪里有雷,没有人说得清楚。

在开始地里还没有很多地雷的时候,风险是很小的。随着经常埋地雷,风吹雨晒,没有人指导之前埋下的地雷在哪里了,这时候就是复杂度高危的时刻。

大家会想到,在软件系统的设计前期,我们研发人员做好设计如层次、模块划分等,那不是解决系统复杂度的问题了吗?

有道理!实际情况是——

  系统的复杂性与能量守恒定律是相匹配的。能量不会凭空消失,只能从一种形式转化为另一种形式。软件的复杂性不会凭空消失,只会转移到另一个地方。

我们使用微服务架构,我们尽可能复用服务,只是将复杂度从开发阶段转移到了维护治理阶段

我们花费大量时间分析需求,产品设计等,那么复杂度变成需求功能的复杂度。

整体的复杂度在外力的作用下,可以变得有序,复杂度看着是降低了,也的确降低了。但是宇宙第一定律(自封的)--熵增定律告诉我们:在孤立系统中,系统的熵在自发过程中不会减少,通常会增加

复杂度还是会增加,我们投入了人力打破了这个『自发过程』,降低了复杂度。我们投入人力,就是把复杂度分担给了不同的人,让每个人可以接受的复杂度属于合理范围。这个外力还可以通过删减下线服务,打破『自发过程』也可以降低复杂度。

同时也需要注意到,组织规模带来的复杂度。《人月神话》告诉我们通过增加人力资源,可以在较短时间内完成一个软件项目的错误观念。

软件系统复杂度的分类

软件系统复杂度的分类有很多中分类方式,《人月神话》将软件复杂度分为本质复杂度偶然复杂度。本质属性是一个物体必然拥有的属性,偶然属性是一个物体可以拥有的属性(也可以不拥有)。比如我们需要做一个电商系统,必然包含商品,交易和用户等业务复杂度,这就是本质复杂度。但是我们开发过程中引入了一个新的技术和第三方而带来的复杂度,则为偶然复杂度。

当然还可以根据对象分为系统复杂度、代码复杂度、业务复杂度和组织复杂度等。

在《软件研发行业创新实战案例解析》书中内容:

最上层是问题域本身的复杂度,也称为业务复杂度,该复杂度和软件系统本身无关,在没有软件的时候就已经存在了,代表业务本身。

第二层是解决方案的复杂度,指业务问题映射到软件领域之后的解决方案,描述软件系统处理业务领域问题的具体方法,领域驱动设计(Domain-Driven Design,DDD)就工作在这一层。

第三层是软件的复杂度,分为本质复杂度和随机复杂度。

本质复杂度是软件必须拥有的,继承自问题域本身的复杂度,除非缩小问题域的范围,否则无法消除本质复杂度,本质复杂度是系统复杂度的下限。

随机复杂度是软件可以拥有也可以没有的属性,由解决方案的实现过程附加产生,主要表现为短视效应、认知负荷和协同成本,是我们需要尽力规避的部分,也是需要关注的重点。

可以看出来,这本书复杂度也是来源于《人月神话》,经典永不变!

软件系统复杂度的度量

软件系统的运行远不及人体那么复杂,哪怕是google的系统也是如此。但随着系统规模的增大,系统的运行会变得非常复杂,远超出一个人所能认知的范围,在这种情况下,它们的复杂度对于人类的认知是一样的,软件系统和人体都可以看做是非常复杂的系统。

认知之外就是答案。

医学领域经过多年的探索,医生可以通过各种维度的“指标”数据来判断真实的病因,甚至有的指标可以直接判定疾病。

那么系统的复杂度如何度量?这目前还是没有答案的,系统的复杂度不能像算法和程序控制流一样使用分别时间空间和McCabe 度量法计算。

John Ousterhout(约翰-欧斯特霍特),在他的著作《A Philosophy of Software Design》中提出,软件设计的核心在于降低复杂性。他选择从认知的负担和开发工作量的角度来定义软件的复杂性,并且给出了一个复杂度量公式: 子模块的复杂度乘以该模块对应的开发时间权重值,累加后得到系统的整体复杂度 C。系统整体的复杂度并不简单等于所有子模块复杂度的累加,还要考虑开发维护该模块所花费的时间在整体时间中的占比(对应权重值)。也就是说,即使某个模块非常复杂,如果很少使用或修改,也不会对系统的整体复杂度造成大的影响。

我认为复杂度就是认知度的体现,那么可以归属到信息领域,那么就可以熵这个概念来度量。已经有科学家做了类似的研究了:《Measures of complexity:A non-exhaustive list》。

论文提出用计算能力度量复杂性一种观点认为,系统的计算能力如果等价于通用图灵机的计算能力,就是复杂系统。不过,班尼特等人则认为,具有执行通用计算的能力并不意味着系统本身就是复杂的;应当测量的是系统处理输入时的行为的复杂性

当然目前也没有看到更好的方法,熵增定律会是一个解决复杂度的好思路。

软件系统复杂度与我们的关系

之前使用过医学领域对复杂度的处理,在中国古代还有一个传说,扁鹊三兄弟的故事。这个故事从管理者角度来看,应该是一个长期主义的故事,扁鹊大哥的治疗方法旨在预防疾病爆发,具有长远的健康视野,但也没有积极传播自己的成就,以建立声誉。

我们追求短期交付效率,使用DDD(期限驱动开发)方式,在新的创新项目上是可行的。加上对验证失败的项目果断放弃放弃会更好。在这点上,我最欣佩的公司是抖音集团,可以做到快速验证业务,而又果断关闭业务。比如近期关闭了时光相册、幸福里、酒旅类电商和Shopify店面等。

《凤凰架构》也说过:复杂性本身不是洪水猛兽,无法处理的复杂性才是。

对复杂系统我们可以采用分而治之,对组织结构也是如此。

先进的生产力都伴随着更高的复杂性,需要有与生产力符合的生产关系来匹配,敏锐地捕捉到生产力的变化,随时调整生产关系。系统复杂度也是类似的,问题在技术,根子在组织

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章