软件设计原则失效了?神文《认知负荷才是关键》引来Karpathy、马斯克点赞


最近,Artem Zakirullin的一篇名为《 Cognitive load is what matters 》的文章引起了广泛关注,文章散获得Karpathy的转载和马斯克认同。我们来一起看看这篇散发着“KISS”味道的文章讲了什么?

什么是认知负荷?

认知负荷说白了就是"开发人员需要动多少脑子才能完成一项任务"。人的工作记忆有限,一般只能同时记住约4个信息块。当你阅读代码时,需要记住变量值、控制流逻辑、调用顺序等信息,一旦超过这个限度,理解代码就会变得困难。
两种认知负荷
文章将认知负荷分为两类:
内在认知负荷: 由任务本身的难度造成,无法减少
外在认知负荷: 由信息呈现方式造成,可以通过优化大幅减少

内在 vs 外在认知负荷
几个典型的认知负荷案例
1. 复杂的条件判断
if val > someConstant     && (condition2 || condition3)    && (condition4 && !condition5) {    ...}
这样的代码会快速占满你的工作记忆。更好的方式是引入有意义的中间变量:
isValid = val > someConstantisAllowed = condition2 || condition3isSecure = condition4 && !condition5if isValid && isAllowed && isSecure {    ...}
2. 继承地狱
当你需要修改一个类时,发现它继承自多个层级:
AdminController extends UserController extends GuestController extends BaseController
你不得不追踪每一层的实现,最后大脑就会过载。文章建议使用组合而不是继承。
3. 过度微服务化
文章举了一个真实案例:一个 5人的创业团队建了 17 个微服务,结果每个新需求都要改 4个以上的服务,最终导致项目严重延期。这就是典型的认知负荷过高的例子。
如何降低认知负荷?
不要盲目应用一些软件架构和设计原则,而是从直觉出发,文中给出了DDD、分层、DRY,函数的长度不应过大等等我们曾奉为圣经的反模式,文章给出了几个实用建议:
避免过度抽象 - 不要为了复用而复用,有时候适当重复比创建复杂抽象更好
使用描述性的命名 - 好的命名可以减轻理解负担
保持代码线性 - 跳来跳去的代码更难理解
控制模块大小 - 不要追求过小的模块,适当的大模块反而更容易理解
深度模块 vs 浅层模块

深度模块示意图
文章特别强调了"深度模块"的概念:
深度模块:接口简单,功能强大
浅层模块:接口复杂,功能有限
Unix 的I/O 接口就是典型的深度模块 - 仅有 5个基本调用,但实现了数十万行代码的功能。
总结启示
总的来说,文章告诉我们在软件开发中,不要一味追求所谓的"最佳实践",而要从认知负荷的角度去思考代码质量。好的代码应该是容易理解的代码,符合直觉的、而不是看起来很酷,或者故弄玄虚的代码。
甚至,最近笔者借助一些AI工具编程的体会来讲,过去那些面向人类程序员而诞生的设计原则,对于AI来讲也并不一定适用,比如,重复代码这个例子,对于人类来讲,为了避免漏改,最好能够抽成一个函数复用,这样修改方便,但对于AI来讲,与其理解代码的依赖关系和影响面,直接按需修改具体功能的代码更为容易。

后台回复“进群”一起入群讨论
我们可以通过将一个复杂问题拆分,再利用AI生成大量独立的简单服务来组合解决,远比让AI直接生成一个看似方便人类维护的复杂服务或是对人类有效的复杂模式来解决容易且可靠得多。也就是说,我们需要充分理解AI的长处和不足,避免生搬硬套、刻舟求剑。
文章最后用一张图片形象地总结道:不要做那个"聪明的作者",编写让人头疼的代码。

聪明的作者
这篇文章的观点可能会改变你写代码的方式。下次编码时,不妨问问自己:这段代码会给阅读者带来多少认知负担?
想看原文:https://minds.md/zakirullin/cognitive
后台回复“进群”入群讨论
到顶部