(翻译) 不要尝试消灭复杂性

25 Sep 2021

翻译

原文地址

和复杂性的斗争是软件开发领域永恒的话题, 各种场合都能见到相关的讨论: 应该写多少注释? 什么情况下会觉得一个框架过于复杂? 一个组织里面应该允许多少种开发语言?

我们总是追求简洁, 尝试避免或者控制复杂性. 这是不正确的思路, 因为复杂性是无法被消灭的.

控制论的弹性工程(Resilience Engineering)的一个概念就是”必要多样性原则”: 只有通过提高复杂性才能对抗复杂性.

构建工具开发过程中遇到的一些问题:

  1. 简单的工具不能处理实际的各种场景
  2. 想支持各类场景, 则不能建立一些固有规则
  3. 想通过合理的默认配置项简化默认场景规则, 则这个默认场景规则必须被广泛接受和实施
  4. 允许配置, 等于提供用户制造规则的能力以匹配既有系统, 固有规则无法建立
  5. 工具做简单, 必须限制可配置的选项
  6. 最终, 如果你的工具不能满足需求, 用户会再包一层”胶水层”以达到目的

这些问题都是无法避免的, 因为复杂性是人们尝试解决问题的本质不可分割的一部分.

如果我们总是允许胶水层, 胶水层内部的逻辑复杂性就是我们要维护的的东西. 至此, 复杂性不再”冬眠”, 而是游走在对接的边界, 每个人都得花费精力学习并适应它.

人们看到两个不融洽的概念, 总是想办法绕过. 这个必要的复杂性可以通过匹配工具迁移掉, 或者通过重整彻底消灭. 重整需要大量的投入, 引入很多调整调整点. 为了确保成功, 在实施重整过程中, 需要让人们认识理解并处理各调整点的复杂性. 有时候, 重整因为产生了新的和人们固有预期不一致, 故不得不妥协又包一层, 最终并不能让事情变得简单. 本质复杂性(essential complexity)不过是历史悠久的偶发复杂性(accidental complexity)的累积. 只要一直在做事, 偶发复杂性就无法避免, 且不断变化.

“脑海中的知识”和”世界上的知识”: 你知道这个东西是可以按的, 因为它看上去长得像一个按钮. 对现实的解释是基于文化以及具体场景的, 并且依赖脑海中的先验知识 (你脑海里得现有按钮这个概念). 专业能力就是利用脑海中的知识帮你更好的解读世界.

软件开发一个常见陷阱就是由于过于追求代码的简单易读, 在简化过程中, 将代码里的复杂性”迁徙”到了其它地方.

作者设计rebar3 (Erlang项目构建工具) 时, 觉得这个工具可以做的很简单. 其前提是大家对于Erlang/OTP项目规范有基本的了解, 只要你熟悉这些规范, 工作可以很顺利. 这里, 复杂性外化到Erlang这个技术生态里. 这些规范rebar3的潜在用户一定要学的, 否则无法理解这个工具. 这样做虽然方便了既有成熟用户的使用, 但是牺牲了新用户的学习成本. 其它技术生态下, 为不同目的开发的工具, 设计上也会做类似的折衷取舍.

这个问题是在软件架构中的慢性病. 当我们采用了如微服务之类的技术, 我们尝试将每个独立服务变得简单. 但是除非这个每个独立服务解决的问题本质上都很简单独立, 否则复杂性还是在那里. 如果复杂性不在每个独立服务中, 那它去那儿了?

复杂性总是存在的. 幸运的时候, 复杂性存在于明确定义的位置: 在代码中, 在解释代码的文档中, 或是在新人手把手培训的过程中. 给复杂性一个位置, 不要尝试隐藏它, 想办法管理好它, 从而需要的时候知道从哪里找出来.

如果很不幸, 你假装认为复杂性是可以整体被避免的, 想去去碾碎它, 没地儿去的复杂性, 只能碎裂四散开来, 一些藏在在代码里, 一些在相关维护人员的口口相传里, 并随着人员的变动, 逐渐消逝.

复杂性不可被避免. 接受它, 给它一个应得的位置, 设计系统以及人员结构的时候, 承认复杂性的存在, 专注并适应之, 你的复杂性可能会变成你的优势.

个人想法

没有银弹, 软件工程就是和复杂性做斗争的工作.

识别不必要的复杂性

应对本质复杂性

惯性是强大的, 变革是困难的, 不要尝试修改用户习惯. 不要图新鲜追逐潮流的浪花尖, 深入学习理解以及迁移的成本, 或者换言之过程复杂性, 是巨大的.

要学会说不, 要认识到所有工具都是有其使用场景和局限的. 不要为了多上车, 尽可能广泛的使用落地, 而把工具做的很复杂. 要有接受世界是多元的, 不能用一种工具解决所有的问题. 同样的, 不要试图讨好所有人.

从既有工具/流程思考问题, 会思维僵化, 拒绝新事物, 导致严重的不匹配. 手里只有个锤子, 于是什么问题都是钉子, 哪怕它其实是个螺丝, 应该用螺丝刀 (工具错配), 或者是个可以直接摁下去的大头钉 (不必要的工具引入).

从零开始的项目, 就像个新生儿, 一开始可以策马奔腾, 快速发展; 但受限于自身重量 (不断累积的复杂性), 越长越慢, 除非注重日常”锻炼”(维护改善, 局部重构), 否则最终都会停留在一个苟延残喘的阶段, 或者慢慢消亡.

HOME