文章目录
在软件工程中,写出能运行的代码只是最低标准。随着项目的演进,维护成本往往远超开发成本。Clean Code 的核心在于降低认知负荷,让后来者(包括未来的你自己)能像阅读散文一样顺畅地理解代码逻辑。本文将深入探讨 Clean Code 中两个极易被忽视却至关重要的维度:注释与格式化。
第一部分:注释的辩证法 (Comments)
很多开发者认为“注释越详细越好”,但在 Clean Code 的哲学中,注释往往是代码表达能力失败的体现。如果你的代码足够清晰,你就不需要注释。
核心准则
🔴 总则:尽可能地避免使用注释。
与其花时间编写解释混乱代码的注释,不如花时间清洁代码本身。
下面的思维导图总结了注释的分类体系:
1. 坏注释:代码的“坏味道” (Bad Comments)
坏注释不仅占用屏幕空间,还可能因为更新不及时而撒谎,甚至误导维护者。
1.1 冗余信息 (Redundant Information)
注释仅仅是把代码翻译了一遍,没有提供任何额外价值。
❌ 错误示例:
// 将 i 增加 1
i++;
// 如果账户为 null,则抛出异常
if (account == null) {
throw new IllegalArgumentException();
}
1.2 废话注释与位置标记 (Drivers or Block Markers)
试图用注释将代码分割成块,或者仅仅为了满足某种文档生成工具的强制要求。这些通常是背景噪音。
❌ 错误示例:
/**************************
* Manager Methods
**************************/
public void manage() { ... }
// @param arg1 The first argument
// @return nothing
public void doSomething(int arg1) { ... }
1.3 误导性注释 (Misleading Comments)
这是最危险的。代码修改了,但注释没改。程序员倾向于信任注释,结果掉进坑里。
1.4 注释掉的代码 (Commented-out Code)
这是极其恶劣的行为。 其他人不敢删除它,因为他们以为这些代码以后还有用,结果这些僵尸代码越积越多。
解决方案:使用 Git 等版本控制系统找回历史代码,而不是留在源码里。
❌ 错误示例:
/*
* 2023-01-20: 暂时禁用,等待API上线
* String response = api.call();
* return response.parse();
*/
return null;
2. 好注释:必要的补充 (Good Comments)
虽然我们极力避免注释,但有些场景下注释是必不可少的。
2.1 法律信息 (Legal Information)
文件头的版权声明、许可证引用。
// Copyright (C) 2024 MyCompany, Inc. All rights reserved.
2.2 解释代码无法表达的意图 (Intent)
解释为什么这么做,而不是做了什么。比如使用了某种晦涩的算法是为了性能优化。
✅ 正确示例:
// 因为在大数据量下 Arrays.sort (双轴快排) 可能导致栈溢出,
// 此处特意选用归并排序以保证稳定性。
mergeSort(data);
2.3 警示 (Warnings)
警告其他开发者修改此代码可能带来的后果。
// 警告:此测试运行耗时极长,除非你需要通过全量回归,否则请使用 @Ignore
2.4 TODO 注释
作为临时的技术债务标记,现代 IDE 都能自动扫描这些标记。
// TODO-202405: 这里需要重构为策略模式,目前硬编码是为了赶上线
2.5 公共 API 文档 (Documentation Strings)
如果你在编写第三方库,Javadoc 或 Python Docstring 是必须的。但不要为非公开 API 写废话文档。
3. 决策流程:我该写注释吗?
第二部分:代码格式化的美学 (Code Formatting)
代码格式化关乎沟通。代码的版式(Layout)展示了你对细节的关注。如果代码看起来乱七八糟,读者会怀疑代码的逻辑是否也同样混乱。
1. 垂直格式化 (Vertical Formatting)
垂直格式化关注的是代码在文件中的纵向流动。代码应该像一篇报纸文章。
1.1 报纸隐喻 (The Newspaper Metaphor)
- 头部:高层概念和算法概览。
- 中部:细节逐渐展开。
- 尾部:最低层的实现细节、辅助函数。
读者应该能自顶向下阅读,如果没有兴趣了解细节,读完头部函数即可停止。
1.2 垂直距离与概念关联
- 紧密度:关系紧密的代码行应该靠在一起。
- 垂直间隔:用空行将不同的思维概念(如方法之间、逻辑块之间)隔开。
🎨 视觉对比:
| ❌ 糟糕的垂直格式 | ✅ 良好的垂直格式 |
|---|---|
package com.x; import java.util.*; public class A { int x; String y; public A() {} public void m1() { if(x>1){y="a";}else{y="b";} } } (像压缩饼干,令人窒息) | package com.x;public class A {private int x;public void m1() {if (x > 1) {y = "a";} else {… |
1.3 声明顺序 (Step-down Rule)
调用者函数应该位于被调用者函数之上。这建立了自然的阅读流。
2. 水平格式化 (Horizontal Formatting)
水平格式化关注的是单行代码的宽度和元素间的间隔。
2.1 避免水平滚动 (No Scrolling)
这曾是一个由于显示器尺寸限制而产生的规则(如80字符),现在虽已放宽(100或120字符),但核心原则不变:读者不应该通过左右滑动滚动条来阅读代码。
如果一行太长,通常意味着这一行干了太多的事,或者嵌套层级太深。
2.2 水平间隔与亲密性
利用空格来强调运算符的优先级或参数的分隔。
- 赋值两边加空格:
int a = b + c;(强调这是两个要素) - 函数名与左括号不加空格:
functionName()(强调它们是一体的) - 参数逗号后加空格:
method(arg1, arg2)(强调参数的分隔)
2.3 缩进 (Indentation)
缩进不仅是语法要求(如Python),更是逻辑层级的可视化地图。它让程序员在左侧就能扫视出代码的结构(循环、判断、方法体)。
❌ 违反水平格式化的极端例子:
public class FitNesseServer implements SocketServer { public void serve(Socket s) { try { doService(s); } catch(Exception e) { e.printStackTrace(); } } }
这不仅是格式错误,更是对阅读者的折磨。
总结:从工匠到艺术家
Clean Code 关于注释和格式化的建议可以总结为以下两点:
- 注释:最好的注释是代码本身。当你觉得需要写注释时,先尝试重构代码,用函数名和变量名来讲述故事。保留注释给那些真正需要解释意图、法律声明或严重警告的地方。
- 格式化:代码是团队沟通的媒介。遵循团队统一的格式化规则(使用 Linter/Formatter 自动化工具),保持垂直方向的逻辑流和水平方向的简洁性。
2983



被折叠的 条评论
为什么被折叠?



