认知负荷才是关键 • Artem Zakirullin
本文围绕 认知负荷(Cognitive Load)这一核心概念展开,指出开发者在编写代码时应尽量减少不必要的认知负荷,从而提升代码的可读性和可维护性。认知负荷是指开发者为完成任务所需的思考量,当认知负荷超出人类工作记忆的容量(约 4 个信息块)时,理解和处理任务会变得困难。文章区分了两种认知负荷: 内在认知负荷:由任务本身的复杂性决定,无法减少。 外在认知负荷:由信息的呈现方式引起,与任务无关,可以通过优化代码设计显著减少。 作者通过多个实际例子和反模式分析,强调了减少外在认知负荷的重要性,并提供了具体的实践建议。 1. 复杂条件与嵌套逻辑 问题:复杂条件和嵌套 if 语句会增加认知负荷,尤其当条件过多时,开发者难以追踪逻辑。 解决方案:引入中间变量或采用早返回(early return)模式,简化逻辑。例如,用有意义的变量名替代复杂条件表达式。 2. 继承的复杂性 问题:深层继承链(如多级 Controller 继承)导致开发者需要逐层理解父类逻辑,容易造成认知过载。 解决方案:优先使用组合(composition)而非继承,以减少类之间的耦合和复杂性。 3. 浅模块与信息隐藏 问题:过多浅层模块(方法、类或微服务)会增加模块间交互的复杂性,反而不利于理解。 解决方案:构建深层模块,提供简单接口但隐藏复杂实现。例如,UNIX I/O 的五个简单调用隐藏了数十万行代码的实现细节。 4. 微服务与分布式单体 问题:过度拆分微服务会导致复杂的依赖关系和高认知负荷,容易形成“分布式单体”。 解决方案:在系统设计初期避免过早引入微服务,优先构建清晰的模块化单体架构(monolith)。仅在团队规模或部署需求迫切时,才逐步拆分服务。 5. 语言特性与框架滥用 语言特性: 问题:过多语言特性(如 C++ 的初始化方式)会增加学习成本和认知负荷。 解决方案:减少依赖复杂特性,优先选择简单、直观的实现方式。 框架滥用: 问题:过度依赖框架的“魔法”可能导致开发者需要额外学习框架的细节。 解决方案:将业务逻辑与框架分离,框架仅作为工具使用,避免代码与框架深度耦合。 6. HTTP 状态码与自描述错误 问题:使用数字状态码(如 401、403)会让开发者和 QA 需要额外记忆这些状态码的具体含义。 解决方案:返回自描述的错误信息(如 "code": "jwt_has_expired"),减少对数字状态码的依赖。 7. DRY 原则的滥用 问题:过度追求代码复用可能导致不必要的耦合,增加认知负荷。 解决方案:适度重复代码,避免引入不必要的抽象和依赖。引用 Rob Pike 的观点:“一点点复制优于一点点依赖”。 8. 分层架构与 DDD 的误用 分层架构: 问题:过多抽象层(如 Hexagonal/Onion Architecture)可能增加跳转成本,带来额外的认知负荷。 解决方案:仅在有实际扩展需求时引入抽象层,避免为追求架构模式而增加不必要的复杂性。 DDD(领域驱动设计): 问题:误将 DDD 的问题域概念(如领域语言)应用到解决方案域,导致主观性和复杂性增加。 解决方案:专注于 DDD 的问题域部分,避免过度强调技术实现细节。 9....