写点什么

软件设计原则失效了?怎么把代码写得更实在,最新神文让 AI 大神卡帕西和马斯克都点赞

  • 2024-12-30
    北京
  • 本文字数:2723 字

    阅读完需:约 9 分钟

软件设计原则失效了?怎么把代码写得更实在,最新神文让 AI 大神卡帕西和马斯克都点赞

最近,技术圈掀起了一波关于“怎么减少代码认知负荷”的热烈讨论。“导火索”是这样一篇文章:《Cognitive load is what matters》(《认知负荷才是关键》),阐述了为什么写代码最重要的事,不是用什么高级架构,不是追逐酷炫技术,而是别让人看了你的代码后“想骂人”。文章在 Hacker News 上迅速占据热榜,引发了技术社区的广泛共鸣。


作者 Artem Zakirullin 是一位经验丰富的软件架构师,拥有超过 13 年的软件开发和工程经验。他目前担任软件开发公司 Inktech 的 CTO 一职。


OpenAI 创始成员之一、前特斯拉 AI 主管 Andrej Karpathy 在 X 平台上转发了这篇文章,发出感慨评价:“这大概是最真实却最少被实践的观点。”



并且,埃隆·马斯克也在 Karpathy 的帖子下评论道:“确实。”


认知负荷为什么如此重要

文章提出了一个人人都能感受到但少有人正视的问题:写代码时的“认知负荷”(Cognitive Load)。


所谓认知负荷,是指开发人员为了完成一项任务所需要承担的思考量。也可以简单理解为:为了完成一项任务,需要动多少脑子、占用多少注意力。


特别是当我们阅读代码时,需要将变量值、控制流逻辑和调用序列等内容塞进自己的脑袋。普通人能够支配的记忆力大约可以容纳 4 个这样的构建块,而一旦认知负荷达到了这个阈值,对于事物的理解难度就会开始陡然上升。



想象一下,你需要接手一个完全陌生的项目并进行修复。当你打开代码,迎面而来的是前一位“天才开发者”留下的大量酷炫的架构设计、花哨的库以及时下流行的技术方案。这种情况下,你不仅要理解项目本身的逻辑,还得费力去消化这些复杂的设计决策——这就是典型的高认知负荷


Artem Zakirullin 进一步将认知负荷分为两种:


  • 内在负荷:源自任务固有的难度,这种没法避免,也是软件开发工作的核心所在。

  • 外在负荷:由信息的呈现方式导致,与任务本身无关,例如聪明作者们的个人习惯。这方面负荷是可以大大降低的。



因此, Zakirullin 在文章中的核心主张就是,尽量减少项目中的外在认知负荷

“减负秘笈”


那么,如何减少外在认知负荷?结合开发中常见的“认知雷区”例子,Zakirullin 给了一些接地气的建议:

1.复杂条件语句:拜托别玩脑筋急转弯

这类代码你可能见过:


if val > someConstant // 🧠+    && (condition2 || condition3) // 🧠+++,上一条件应当为真,c2或c3之一必须为真    && (condition4 && !condition5) { // 🤯,到这一步我们的脑袋就快爆炸了……    ...}
复制代码


解决办法?引入清晰的中间变量:


isValid = val > someConstantisAllowed = condition2 || condition3isSecure = condition4 && !condition5// 🧠,有了描述性变量,我们就不再需要记住条件if isValid && isAllowed && isSecure {    ...}
复制代码

2. 继承噩梦:少用继承,多用组合

“继承链”是认知负荷的天花板。你改 AdminController 的代码,发现它继承了 UserController,后者又继承了 GuestController,还不止这些——改着改着,突然冒出来个 SuperuserController,让你意识到一处改动可能引发蝴蝶效应。


解决办法?别玩继承了,多试试组合吧。

3. 小模块≠简单:浅模块问题

开发界流传着一种迷思,像“方法应该少于 15 行代码”或者“类不能太大”之类的常规习惯实际上是错的。


事实证明,结果一不小心,你的项目里塞满了多个小模块,那维护起来比修一张蜘蛛网还难。


  • 深模块——接口简单,但功能复杂;

  • 浅模块——相对于所提供的小功能,其接口相对复杂。



Zakirullin 认为更好的方法是设计深模块:隐藏内部复杂性,只暴露一个简单的接口。比如 UNIX 的 I/O 接口就非常简单,只有五个基本调用:

open(path, flags, permissions)read(fd, buffer, count)write(fd, buffer, count)lseek(fd, offset, referencePosition)close(fd)
复制代码


“信息隐藏非常重要,而浅模块中无法隐藏太多的复杂性。”Zakirullin 在文章中说道。

4. 语言功能越多越好吗

当遇到喜欢的编程语言发布新功能时,谁能不感到兴奋并迫不及待想用起来。然而,文章还提醒说,这种一时热情的背后藏着一个巨大的认知负荷陷阱。


Zakirullin 引用了 Rob Pike(Go 语言的主要设计者之一)的一句话:要通过限制选项的数量来降低认知负荷。


举个例子,当你用了一些新特性写了代码,可能当时觉得很“优雅”。但几个月后,当你回头看这些代码时,你不仅需要重新理解代码逻辑,还得想起“我当时为啥要用这个特性来解决这个问题?”


这无疑增加了外在认知负荷。简言之,丰富的语言功能肯定不是坏事,但前提这些功能要彼此关联。

5.别滥用分层架构

有人说,架构设计要“优雅”,于是各种抽象层、接口层、适配器层层叠叠。等到真要查 Bug 时,开发者得顺着 5 层调用链一路追溯问题来源,头发掉得比写论文还快。


分层架构的初衷是通过抽象隐藏复杂性。有些人可能以为这样的分层有助于快速替换数据库或者其他依赖项,但事实并非如此。存储方面的变更会导致很多问题。


Zakirullin 强调,开发过程中最不需要担心的就是数据访问层上的抽象机制。充其量,这些抽象能够节约 10%的迁移时间(这还是在比较乐观的情况下),而真正的麻烦永远来自数据模型不兼容、通信协议、分布式系统挑战以及隐式接口。


所以,既然后续根本没有回报,又何必要为这种分层架构付出高昂的认知负荷成本呢?


总之,分层架构只有在需要明确扩展点时才有意义。否则,这些层次带来的额外认知负荷远高于它能提供的好处。

6.领域驱动设计(DDD):用对了是神器,用错了是灾难

文章还提到另一个开发者热衷但经常误解的概念:领域驱动设计(DDD)。DDD 本质是关于问题空间的思考,而不是解决方案空间的代码设计。


问题是,许多团队在实践中“跑偏”了。本应专注于领域建模和边界划分的 DDD,变成了某种固定的文件夹结构、服务命名规则、或者对“Repository 模式”的机械化崇拜。


每个人对于 DDD 的理解和解释方式都可能独特且主观。如果基于这样的理解来编写代码,则必然会创造出大量非必要的认知负荷——相当于给后续接手的开发人员埋下一颗颗炸雷。

7.熟悉项目 VS 认知负荷

认知负荷高低,决定了一个项目对开发者有多“友好”。熟悉项目的开发者,已经把代码逻辑内化到脑子里,干活轻松省事;但对新人来说,如果项目充满谜语一样的命名、复杂的模块关系和稀缺的文档,他们很快就会懵圈,效率直线下降。



文章给了一个建议:每当有新人加入项目时,请尝试衡量他们的懵圈程度。如果他们花了 40 分钟还是一头雾水,那肯定意味着代码中存在需要改进的地方。


如果能将认知负荷始终保持在较低水平,那么新人在入职后的几个小时内就可以为代码库做出贡献。

写在最后

减少认知负荷并不是一个高深的哲学,而是开发者日常需要实践的基本功。或许,每次写代码时,我们都该问问自己:


“这段代码,是帮同事省脑子,还是让他们掉头发?”


参考链接:

https://minds.md/zakirullin/cognitive

2024-12-30 15:2216101

评论

发布
暂无评论

深入浅出 Ext4 块和 Inode 分配器的优化(下)

焱融科技

云计算 高性能 文件存储 文件系统

TASKCTL 应用工程与作业类型的定义

敏捷调度TASKCTL

DevOps 敏捷开发 批量任务 ETL系统 自动化运维

如何用WinRAR将大文件分割成多个小文件?

InfoQ IT百科

抖音获客源码,蓝V思域运营,大热的X-Gorgon 0408和8408算法,今年的SaaS源码,编程语言需要变革吗?

yunluohd168

抖音短视频获客系统 抖音获客源码

Excel表格中怎么防止重复录入数据?

InfoQ IT百科

如何对APP进行数据分析?

InfoQ IT百科

亚马逊云科技平台上的无服务器 WebSocket

亚马逊云科技 (Amazon Web Services)

Serverless websocket 亚马逊云科技 appsync

怎么清理钉钉缓存的图片和文件?

InfoQ IT百科

如何在APP原型上写需求?

InfoQ IT百科

银行App为什么都不怎么好用?

InfoQ IT百科

如何制定移动APP的加载与刷新策略?

InfoQ IT百科

如何批量导出PPT里的图片?

InfoQ IT百科

有哪些好用的杀毒软件?

InfoQ IT百科

Chrome如何启用隐身模式?

InfoQ IT百科

常见的中文电脑输入法软件有哪些?

InfoQ IT百科

低代码让人人都是开发者,高校人才有了努力的新方向

一只大光圈

阿里 低代码 数字化 钉钉宜搭 浙江工商大学

APP访问用户的通讯录后,会得到通讯录上的信息吗?

InfoQ IT百科

如何进行APP版本升级管理?

InfoQ IT百科

如何认证成为亚马逊云科技 DevOps 专家?

亚马逊云科技 (Amazon Web Services)

DevOps 亚马逊云科技 tutorial caree

如何共享电脑上的文件?

InfoQ IT百科

如何给电脑文件夹设置密码?

InfoQ IT百科

下载软件哪个好?

InfoQ IT百科

APP、小程序、H5,如何选择不同的开发载体?

InfoQ IT百科

深度学习—人工智能的第三次热潮

云智慧AIOps社区

人工智能 机器学习 深度学习

开源规则引擎——ice:致力于解决灵活繁复的硬编码问题

声网

开源 规则引擎 Dev for Dev

云效钉钉小程序上线啦!业务方请痛快一键三连

阿里云云效

阿里云 云原生 钉钉 研发 云效钉钉小程序

如何清除WinRAR压缩文件历史记录?

InfoQ IT百科

Chrome如何安装插件?

InfoQ IT百科

React Hooks 的实现必须依赖 Fiber 么?

云智慧AIOps社区

前端 大前端 React Hooks preact

电脑上切换输入法的快捷键是什么?

InfoQ IT百科

md文件要用什么软件打开?

InfoQ IT百科

软件设计原则失效了?怎么把代码写得更实在,最新神文让 AI 大神卡帕西和马斯克都点赞_架构_罗燕珊_InfoQ精选文章