几乎所有团队都会说:
“我们这个系统,是慢慢复杂起来的。”
但这是一个非常危险的错觉。
真实情况是:
系统复杂度并不是线性增长的,而是长期被压缩、突然释放的。
一、复杂度在前期其实“看不见”
在系统早期,你会觉得一切都还好:
- 一个需求加一个 if
- 一个新流程加一个状态
- 一个补偿逻辑加一个定时任务
- 一个例外情况写在代码角落
每一次改动都很小,小到:
“这不算什么复杂度。”
但问题是:
复杂度并不会因为你“感觉不明显”而不存在。
它只是被你分摊到了很多地方。
二、复杂度真正的形态不是“代码行数”,而是“耦合密度”
很多人以为复杂度来自:
- 代码多
- 类多
- 服务多
但真实世界里,系统崩溃前往往是这样:
- 代码不算多
- 服务数量也合理
- 性能也没明显问题
真正的问题是:
你已经无法单独理解任何一个模块,而不去考虑其它模块。
这才是复杂度的本体:
耦合密度过高。
三、复杂度失控前,一定会出现这三个征兆
1️⃣ 修改成本开始“不可预测”
你改一个小点,却不知道:
- 会不会影响老流程
- 会不会触发补偿
- 会不会被定时任务覆盖
- 会不会被异步回放
于是你开始说:
“这个改动我得多测几轮。”
但“多测几轮”其实是:
对系统行为已经失去确定性的表现。
2️⃣ 系统开始依赖“时间顺序”才能正确运行
例如:
- A 一定要先调
- B 只能在 C 之后
- D 如果失败必须等下一个周期
- 某些逻辑“只在凌晨是安全的”
当系统正确性开始依赖时间顺序时,
复杂度已经接近临界点。
3️⃣ 新人不再问“为什么”,而是问“能不能别让我改这块”
这是最危险的信号。
当团队开始用“绕开复杂区域”来维持效率,
系统已经在内部塌陷。
四、复杂度为什么总是“突然爆炸”?
因为复杂度是可压缩的,但不可消除的。
你可以:
- 把它压进配置
- 压进约定
- 压进历史数据
- 压进异步逻辑
- 压进“大家都知道的规则”
但总有一天:
一个需求,会同时触发这些被压缩的复杂度。
那一天你会发现:
- 状态互相打架
- 补偿互相覆盖
- 异步互相踩踏
- 回滚无法完成
系统不是“变复杂了”,
而是复杂度一次性释放了。
五、真正成熟的系统,反而“拒绝压缩复杂度”
它们会刻意做一些“看起来很浪费”的事:
- 拆流程
- 拆状态
- 拆数据
- 拆责任
- 拆执行路径
不是因为闲,而是因为:
复杂度不拆开,就一定会在某个时刻一起爆。
六、一个非常实用的自检问题
你可以问自己:
如果现在让我删除一个功能,
我是否能明确说出:
哪些地方一定要一起删,
哪些地方绝对不能动?
如果你答不上来,
说明复杂度已经不再“可理解”。