complexity-recognition

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Complexity Recognition Review Lens

复杂度识别评审视角

When invoked with $ARGUMENTS, focus the analysis on the specified file or module. Read the target code first, then apply the checks below.
"Complexity is anything related to the structure of a software system that makes it hard to understand and modify the system." — John Ousterhout, A Philosophy of Software Design
Complexity is relative to the task: the same codebase can feel simple for one operation and painful for another. The writer of the code is often the worst judge of its complexity. If reviewers find it complex, it is. Diagnose it using three symptoms, two root causes, and the fundamental formula.
当使用$ARGUMENTS调用时,请将分析聚焦于指定的文件或模块。首先阅读目标代码,再应用以下检查项。
"复杂度是软件系统结构中任何会导致系统难以理解和修改的因素。" — John Ousterhout,《软件设计哲学》
复杂度是相对于任务而言的:同一个代码库对于某项操作可能很简单,对于另一项操作却可能非常难用。代码的编写者往往最无法判断其复杂度。如果评审人员认为代码复杂,那它就是复杂的。可以通过三种症状、两个根本原因和基础公式来对其进行诊断。

When to Apply

适用场景

  • When code feels harder to work with than it should be
  • When small changes require edits in many places
  • When developers frequently introduce bugs in unfamiliar code
  • During "should we refactor this?" discussions
  • 当你感觉代码比预期更难维护时
  • 当微小的变更需要在多处进行编辑时
  • 当开发人员在不熟悉的代码中频繁引入bug时
  • 在"我们是否应该重构这段代码?"的讨论过程中

Core Principles

核心原则

The Complexity Formula

复杂度公式

$$C = \sum_{p}(c_p \times t_p)$$
Each part's complexity weighted by how often developers work with it.
  • Complexity in frequently-touched code matters most
  • Encapsulating complexity where it won't be encountered is nearly as valuable as eliminating it
"Complexity is more apparent to readers than writers." — John Ousterhout, A Philosophy of Software Design
If colleagues find your code complex, it is complex.
A gnarly subsystem that nobody modifies contributes almost nothing. A moderately messy module that every feature passes through dominates the total. A "simple" change to a high-traffic module matters more than a large refactor of something rarely touched.
$$C = \sum_{p}(c_p \times t_p)$$
每个部分的复杂度由开发人员处理它的频率加权计算。
  • 频繁被修改的代码中的复杂度影响最大
  • 将复杂度封装在很少会被接触到的位置,其价值几乎等同于彻底消除复杂度
"复杂度对于阅读者来说比编写者更明显。" — John Ousterhout,《软件设计哲学》
如果同事认为你的代码复杂,那它就是复杂的。
一个没人会去修改的复杂子系统对整体复杂度的贡献几乎为零。而每个功能都会用到的中等混乱程度的模块则会主导整体复杂度。对高流量模块的一个"简单"改动,比对极少被触及的代码进行大规模重构的影响要大得多。

Three Symptoms

三种症状

1. Change Amplification

1. 变更放大

Directly measurable: count files touched for a single-concept change. Use this for refactoring prioritization.
可直接度量:统计完成单个概念变更需要修改的文件数量。可用于重构优先级排序。

2. Cognitive Load

2. 认知负荷

Fewer lines does not always mean less cognitive load. A terse framework requiring reverse-engineering its entire mental model is not simpler. The question is how much do I need to know?
代码行数更少不总是意味着认知负荷更低。一个需要你反向推导其完整心智模型的简洁框架并不会更简单。核心问题是"我需要掌握多少知识?"

3. Unknown Unknowns

3. 未知的未知

Unknown unknowns are the worst symptom because they are invisible. Change amplification is visible and cognitive load is navigable, but unknown unknowns let you finish a change feeling confident while the bug ships. The design goal that counters all three symptoms is to make the system obvious.
"An obvious system is one where a developer can make a quick guess about what to do, without thinking very hard, and yet be confident that the guess is correct." — John Ousterhout, A Philosophy of Software Design
未知的未知是最糟糕的症状,因为它们是不可见的。变更放大是可见的,认知负荷是可以应对的,但未知的未知会让你满怀信心地完成变更,最后却把bug发到了线上。能对抗这三种症状的设计目标是让系统足够浅显易懂。
"一个浅显易懂的系统是指开发人员不需要费力思考就能快速猜出应该怎么做,并且能确信这个猜测是正确的。" — John Ousterhout,《软件设计哲学》

Two Root Causes

两个根本原因

Dependencies

依赖

Represent code that cannot be understood or modified in isolation. Not all are bad. The goal should always be to have fewer dependencies, and make remaining ones obvious rather than hidden.
指无法独立理解或修改的代码。并非所有依赖都是不好的。目标始终应该是减少依赖数量,并且让留存的依赖清晰可见,而非隐藏起来。

Obscurity

模糊性

Important information is not obvious. Vague names, undocumented assumptions, invisible dependencies, inconsistency.
"The need for extensive documentation is often a red flag that the design isn't quite right." — John Ousterhout, A Philosophy of Software Design
These two root causes intersect in hidden dependencies, where a dependency exists without any surface representation in the code. Hidden dependencies produce the worst bugs because there is no signal to search for and no warning that information is missing.
重要信息不够清晰明确。比如命名含糊、未记录的假设、不可见的依赖、不一致性等。
"需要大量文档往往是设计不够合理的危险信号。" — John Ousterhout,《软件设计哲学》
这两个根本原因在隐藏依赖中会交叉出现,即依赖真实存在,但代码中没有任何表面体现。隐藏依赖会引发最严重的bug,因为没有任何信号提示你需要去查找相关信息,也不会警告你存在信息缺失。

Complexity Is Incremental

复杂度是逐步累积的

"Complexity isn't caused by a single catastrophic error; it accumulates in lots of small chunks." — John Ousterhout, A Philosophy of Software Design
Every developer can justify their small addition, but if everyone reasons this way, the total grows steadily. Discipline must be applied at the level of individual decisions, because that's the only level where complexity enters.
"复杂度不是由单个灾难性错误导致的;它是由大量小碎片逐步累积而成的。" — John Ousterhout,《软件设计哲学》
每个开发人员都能为自己的小改动找到合理的理由,但如果所有人都这么想,整体复杂度就会稳步增长。必须在单个决策层面就执行规范,因为这是复杂度流入系统的唯一层级。

Elimination vs. Encapsulation

消除 vs 封装

  1. Eliminate: Redesign so the complexity doesn't exist. Always best.
  2. Encapsulate: Hide it in a deep module so most developers never encounter it.
"Isolating complexity in a place where it will never be seen is almost as good as eliminating the complexity entirely." — John Ousterhout, A Philosophy of Software Design
  1. 消除:重新设计,让复杂度不复存在。始终是最优方案。
  2. 封装:将其隐藏在深度模块中,让绝大多数开发人员永远不会接触到它。
"将复杂度隔离在永远不会被看到的地方,其价值几乎等同于彻底消除复杂度。" — John Ousterhout,《软件设计哲学》

Review Process

评审流程

  1. Identify hot paths: Which code is modified most frequently?
  2. Check for change amplification: Pick a likely change, count files touched
  3. Assess cognitive load: What must a developer know to work here safely?
  4. Hunt unknown unknowns: Hidden dependencies, implicit invariants, undocumented constraints?
  5. Trace root causes: Dependency or obscurity?
  6. Recommend: Eliminate the complexity, or encapsulate it in a deep module
Red flag signals for complexity are cataloged in red-flags (Repetition, Overexposure, Information Leakage, Non-obvious Code).
  1. 识别热路径:哪些代码被修改的频率最高?
  2. 检查变更放大情况:选择一个可能的变更,统计需要修改的文件数量
  3. 评估认知负荷:开发人员要安全地在此处开发,必须掌握哪些知识?
  4. 排查未知的未知:是否存在隐藏依赖、隐式不变量、未记录的约束?
  5. 追溯根本原因:是依赖问题还是模糊性问题?
  6. 给出建议:消除复杂度,或者将其封装到深度模块中
复杂度的危险信号已收录在red-flags(重复、过度暴露、信息泄漏、不直观代码)中。