关于复杂度的一些想法

标签: 复杂度 想法 | 发表时间:2021-09-15 21:31 | 作者:Xargin
出处:https://xargin.com/

之前陶师傅推荐过这么一篇文章, Complexity has to live somewhere,大致意思是系统的复杂度是没法凭空消失的,只能从一个地方转移到另一个地方,因为现实世界的逻辑就是那么多,边边角角的 case 就是那么多,你必须要处理,这必然会给系统引入复杂度。

尽管这些复杂度你可以转移给你的同事,或者外包给第三方系统,但复杂度是不灭的。

设计系统时,我们要注意到这一点,同时要管理好复杂度问题。

在《a philosophy of software design》这本书中,作者也提出了一个不一样的,比较有意思的系统复杂度理论,

可以和上面那篇文章结合在一起来看。

C 代表 Complexity,T 代表在该模块上开发投入的时间 Time。系统的整体复杂度= “每个模块的复杂度 Ⅹ 在该模块上投入的开发时间”,再对结果求和。

如果我们日常工作中主动或被动地去设计并实现过一些逻辑比较复杂的系统,这个简单的公式应该是一看就懂。这个公式里的 C 其实也可以认为是 Cognitive Load,即认知负担。你写的代码你同事很难看懂,那也要认为这些代码是很复杂的。

提高研发效率,本质上应该是降低这里定义的系统整体复杂度。

将公式与我们日常的开发和系统设计相结合,这篇文章简单列一些暴论,希望大家一起探讨。

系统可以设计得复杂,只要复杂的部分不常修改就可以了

举个例子,我们的 API 服务基本都部署在 linux 上,linux 当前有千万行级的代码,但我们并不需要阅读 linux 的源代码,也不需要关注 linux 的复杂度。只需要将精力聚焦在上层业务。即使是做系统编程,也只需要熟读 man7.org,并不需要把 syscall 底层的实现机制搞明白(现在很多人是自己太卷了)。

如果碰到了系统相关的性能问题,大多数情况下也不需要我们去内核里做优化,根据业务情况调整少量的系统暴露配置参数就可以了,比如 somaxconn,tcp_tw_reuse 等。

如果是设计一套业务系统,为了适配尽可能多的情况,不常修改的部分对复杂度也不必畏之如虎,只要你的抽象足够通用,并且能够在无法适配的时候给用户提供好扩展的后门,也不会有什么大问题。

与 linux kernel 场景类似,如果我们面对的是只需要解决一次的复杂问题,通过一个不频繁修改的复杂系统来解决它,也是合理的。

对于极复杂的这一部分系统,哪怕修改一次需要一个月,两年修改一次也并不是太高的成本。

经常修改的部分与不经常修改的部分可以进行拆分

无论是业务系统还是基础设施,随着时间的推移都会变得越来越复杂,具体可能体现在:冗长复杂的逻辑,场景化的代码分支,繁多的协议适配,奇怪的功能组合。

在“看起来很复杂”的系统上做开发并不见得就一定会很痛苦,因为我们常修改的并不总是系统的流程,可能只是经常变化的业务策略:触发拉新的推送频率,用户使用的业务指标,当前功能开启的城市,用户违规的判罚标准。

上面的这些策略也是业务复杂性的一部分,不过它们跟流程没有什么关系。设计糟糕的系统,面对巨大的 code base,不知道该去哪里修改,需要反复阅读整个流程代码才能确认在哪里进行修改更为合适。如果工作任务压迫严重,排期缩水,工程师也有神技,所有的需求都可以在入参处理后,结果返回之前的两个位置进行无限累加。经过经年累月的迭代,这样的系统基本是没法维护的。

我们可以将这些易变常变的内容从系统中拆分出来成为配置,总结为模式。通过配置来控制系统的行为。

即使做不到配置化,将 不常修改的部分与常修改的部分隔离开,也可以大幅降低工程师维护整体系统时的心智负担,开发只需要关注自己系统的功能就好。系统与系统之间是解耦的。

重复的工作一定可以配置化

如果我们反复修改的是一些判断条件,那么把这些条件抽象为规则,放在配置管理系统中就好。

如果我们反复修改的外部数据源,那么把数据本身进行抽象,并使用 xpath,jpath 之类的工具来进行查询就好。再复杂的数据获取可以直接使用 apijson,GraphQL 或 falcor 之类的开源项目,自己设计一套方案也不难。

如果我们反复修改的是计算逻辑,那么我们在系统内支持表达式引擎就可以。

如果我们反复修改的是业务流程,那么将流程本身使用 bpm 类框架实现即可。

如果我们反复修改的是各种协议的支持,那么设计一套按照 IDL 来生成协议处理代码的工具即可。

配置化是将重复的工作内容模板化,在上面的公式中,是 通过直接减少 T 来降低了系统整体的复杂度

工程师不应该抗拒复杂度

现在的 CRUD 工程师都不太喜欢复杂的东西,很多时候会以“这个需求会让系统变复杂”为由,拒绝接受新的需求或对系统进行大的修改。

但简单的项目无非逻辑堆砌,应届生就可以做得很好,很多人又为了涨工资跳槽跳得飞快,对于经历过的公司业务理解有限。将所有公司的业务都总结为 CRUD,实在有点简单暴力。

前几年中台大热,几乎所有公司都在推中台,尽管本人对中台有一些批评意见,但并没有否定中台提升工程师能力的效用。由于业务中台项目往往有一定复杂度,对于参与的工程师来说是很好的视野开阔和能力锻炼机会,因为太复杂,没收益(年终奖)的理由,放弃了这些机会,对个人来说是比较大的损失(当然,收益还是要考虑的)。

当初在某司设计某平台,按照部门内的惯例,这样的平台并不会得到太多部门的支持与收益,但可以消灭组内大量的重复无聊的开发工作。我们从过往的开发经验中总结了 90% 的需求和日常工作,结合了公司本身阶段考量和业界先进系统的调研才设计出了这套系统。

落地之后,我们这些参与者,也通过这个过程看到了这种数据相关的系统向更大范围延伸,能够发展出什么样的未来。比如,可以是一个数据中台,搭上国内中台的热流,成为一线互联网公司的数据中台实践案例;也可以是类似 Google F1 那样的超级查询系统,成为先进工程理念落地的典范;也可以进化为专门服务机器学习业务的特征、模型生命周期管理平台。

这些是之后的可能性,向哪一个方向继续进化并不是一线的开发者与架构师所能决定的,去除政治因素,整个系统的研发与迭代还是给我们提供了非常宝贵的经验,至今依然受用。

设计系统类似算命

尽管我们可以从过往的开发中汲取经验,但在做系统设计时还是要对未来做一些预测。

这些预测并不一定准确,技术上的判断和业务未来的发展并不一定能匹配。比如电商公司们也没想到异军突起的是一家类似游戏厂商的新型电商,在很长一段时间内被打得措手不及。原来的系统和机制设计就没法实现类似对手的游戏化电商,在宣传标语里神通广大的中台也是不行的。

我们对架构师有个调侃,架构师本身就是数据驱动的算命师傅,要对未来做预测,预测对了是神,预测错了是🐶。

不过也只是个调侃,大家都是人,没有谁能突破人类的上限。

有时间单独写写 《a philosophy of software design》这本书的读书笔记。

相关 [复杂度 想法] 推荐:

关于复杂度的一些想法

- - No Headback
之前陶师傅推荐过这么一篇文章, Complexity has to live somewhere,大致意思是系统的复杂度是没法凭空消失的,只能从一个地方转移到另一个地方,因为现实世界的逻辑就是那么多,边边角角的 case 就是那么多,你必须要处理,这必然会给系统引入复杂度. 尽管这些复杂度你可以转移给你的同事,或者外包给第三方系统,但复杂度是不灭的.

Eclipse:使用Metrics 测量复杂度

- - CSDN博客推荐文章
Metrics可以进行许多有用的代码度量,包括圈复杂度度量,它用于测量方法中惟一路径的数目. 在Eclipse中安装和使用Metrics步骤 . Elipse中安装Metrics插件 . 打开Help->Install new Software,点击Add,添加Repository. 选择相应的版本插件,继续随后的安装 .

MySQL源码:JOIN顺序选择的复杂度

- - OurMySQL
   在看MySQL优化器代码过程中,这应该是相对较简单/代码较清晰的部分了. MySQL优化器有两个自由度:单表访问方式,多表顺序选择. 前文已经介绍过MySQL单表访问的一些考量(ref/range等),本文将介绍JOIN在顺序选择上的复杂度分析.    当有多个表需要JOIN的时候,MySQL首先会处理两类特殊情况,一个是常数表,一个是由于外连接导致顺序依赖关系.

复杂度的指数曲线,以及敏捷原则的根本

- diaoxsh - 透明思考 - Thoughts
想象我正在往一个已有的代码库中添加新的功能. 假如我一次只添加一个小修改,这个小修改是如此简单以至于它只有两种状态——写完代码之后只要看一看,我要么是改对了要么是改错了;如果改错了,我就用另一种方式来修改,后者一定是正确的. 如果我一次不是添加一个小修改,而是添加两个,然后把两个修改放在一起来验证.

那些想法

- plume - 岁月如歌
hax 的文章很不错:关于国内前端和 JS 技术发展的乱想. 愚公贴出了四个月前的聊天记录,如今再读,别有一番滋味:我们需要什么样的“技术”. 我当时也留存了一些感想,索性也贴出来:. 这是一篇改变我很多想法的文章:大教堂和集市. 老文章,很耐读,最近放在 iPhone 上,没事就看看,烂熟. 世界上有很多聪明人,很多事情已经做得非常棒.

对BITCOIN的几点想法

- wuwu - 郭凯经济笔记
有人问我对BITCOIN有什么看法,我还没时间仔细想这个东西,但是粗略的了解了一下之后,有以下初步的想法,总结起来就是:神奇的技术,但优点可能被夸大,缺点可能很致命. 技术的部分我就不评价了,不懂更没资格评价. BITCOIN的优点中最被强调的就是:这是一个不需要中央银行的P2P的货币体系,因此不会有滥发钞票的风险.

今年,换个想法吧!

- 兰诺 - 译言-每日精品译文推荐
来源Don’t leave learning to the young Older brains can grow, too - NYTimescom. 发表于2011年12月31日. NEW Year’s resolutions often have to do with eating more healthfully, going to the gym more, giving up sweets, losing weight — all admirable goals aimed at improving one’s physical health.

不要强调这是“你的”想法

- binforever - 蔡康永的博客
当你跟他的想法很不同,但你又很想说服他时,你最好不要强调这是“你的”想法,. 你可以在措词上转个弯,让他感觉,你是“被他启发”,才产生这个想法的. 这麽做最省力,因为所有人,都不会反对自己的想法. 这类有点贱的招式,最适合以下犯上时使用. (  和這篇味道類似的 , 還有另一篇 : 你是盆栽型的工作者嗎 ).

做一个有想法的程序员

- chenhua - 涂雅
涂雅导读:程序员有很多种,有些人是鼠标,你拽一下动一下,有些人还是一只烂鼠标,拽都拽不动. 有些人是病毒,喜欢四处出击,他会在程序中加入自己的想法. 有些人会考虑用户的感受,有些人认为程序员只管业务逻辑,把数据插入数据库里面就OK了. 相比之下,我更喜欢有自己想法的程序员,你是哪一种. 先做一个实验,假如我们要开发一个小项目,需求很简单,就是一个保存用户基本信息的页面,要求用户可以输入姓名、电话、联系地址、邮箱、手机号码、备注,其中姓名与邮箱是必输项目,我们把这个项目分给三个程序员做(当然这三个人都是虚拟的,其实都是我做的),三个程序员交来的作品都没有逻辑错误,数据保存正常,让我们看看做出来的效果有什么不一样.