克尼汉定律
调试代码的难度约为写出它的两倍,因此写代码时要控制复杂度。
显示原始英文内容
Kernighan's Law
Debugging is twice as hard as writing the code in the first place.
Takeaways
- Bug detection and removal is more complex than programming because debugging requires understanding both the code and why it doesn't work.
- If you write code at the limit of your intelligence, you won't be able to understand or troubleshoot it later.
- Simple code with good structure and documentation is easier to debug, saving time in the long run.
- Even if your code runs successfully when you write it, it's fragile if it's too complex.
Overview
Kernighan's Law says that debugging requires understanding what the code *actually* does, which can be twice as hard as writing it. When coding, you operate with a specific mental model and full context. When debugging, you might be dealing with someone else's code or your own code after that context has faded.
Writing "clever" or complex code is essentially setting a trap for your future self. A maintainable version is usually superior to an optimized version that is difficult to understand. As Kernighan implies, if you make your code too tricky, you've essentially outsmarted yourself.
Examples
Imagine a developer writing a function in a compressed style, chaining multiple operations in one line:
<pre><code class="language-csharp">public string GetUserDisplay(User u) => u?.IsActive == true ? (u.Name ?? "").Trim() is var n && n.Length > 0 ? n + (u.Role > 0 ? $" ({(Role)u.Role})" : "") : "Unknown" : "Inactive";</code></pre>
The proper, readable version:
<pre><code class="language-csharp">public string GetUserDisplay(User user) { if (user is null || !user.IsActive) return "Inactive";
var name = user.Name?.Trim();
if (string.IsNullOrEmpty(name)) return "Unknown";
if (user.Role > 0) return $"{name} ({(Role)user.Role})";
return name; }</code></pre>
The clever version might have taken 30 minutes to write, but debugging took 3 hours. Had the code been written clearly, it would've taken 45 minutes to write, but only 30 minutes to debug later.
Origins
Brian Kernighan first expressed this idea in *The Elements of Programming Style* (1974, second edition 1978) with P.J. Plauger. Kernighan, famous for co-authoring "The C Programming Language" and "The Elements of Programming Style," wrote about simplicity in the days of resource-constrained computing.
核心含义
写代码时,人们通常只需让自己的设计成立;调试时,还要理解所有可能状态、历史假设和异常交互。复杂度越高,定位问题越困难,调试成本会以超过线性的方式增长。
清晰命名、小函数、自动化测试和可观测性,都是降低未来调试成本的投资。
实践例子
一个看似聪明的单行表达式在边界输入下失败,调试者需要先理解多个隐式转换和副作用。拆成有名字的步骤后,错误位置和测试边界都会更清楚。
来源与边界
这句话通常归于 Brian Kernighan。它是经验性提醒,不是精确倍数;复杂度、领域知识和工具都会影响实际调试成本。