Clean Code 技能
本技能体现 Robert C. Martin(Uncle Bob)《Clean Code》的原则。用于将「能工作的代码」转化为「整洁的代码」。
🧠 核心理念
"代码如果能让其他开发者(而非原作者)阅读并扩展,那就是整洁的代码。" — Grady Booch
何时使用
以下情况使用本技能:
- 编写新代码:从一开始就确保高质量。
- 审查 Pull Request:提供基于原则的建设性反馈。
- 重构遗留代码:识别并消除代码异味。
- 改进团队规范:对齐行业标准的最佳实践。
1. 有意义的命名
- 使用揭示意图的名称:用
elapsedTimeInDays而非d。 - 避免误导:如果实际是
Map,不要用accountList。 - 做出有意义的区分:避免
ProductData与ProductInfo这种无意义的区分。 - 使用可发音/可搜索的名称:避免
genymdhms。 - 类名:使用名词(
Customer、WikiPage)。避免Manager、Data。 - 方法名:使用动词(
postPayment、deletePage)。
2. 函数
- 短小!:函数应该比你想象的更短。
- 只做一件事:一个函数应该只做一件事,并把它做好。
- 单一抽象层次:不要混合高层业务逻辑与底层细节(如正则表达式)。
- 描述性名称:
isPasswordValid比check更好。 - 参数:0 个最理想,1-2 个可以接受,3 个以上需要非常充分的理由。
- 无副作用:函数不应该悄悄改变全局状态。
3. 注释
- 不要注释烂代码——重写它:大多数注释是我们未能用代码表达自己的失败标志。
- 用代码解释自己:
对比# Check if employee is eligible for full benefits if employee.flags & HOURLY and employee.age > 65:if employee.isEligibleForFullBenefits(): - 好的注释:法律声明、信息性(正则意图)、澄清(外部库)、TODO。
- 坏的注释:喃喃自语、冗余、误导、强制要求、噪音、位置标记。
4. 格式
- 报纸隐喻:高层概念在顶部,细节在底部。
- 垂直密度:相关的行应该靠近彼此。
- 距离:变量应该在使用处附近声明。
- 缩进:对结构可读性至关重要。
5. 对象与数据结构
- 数据抽象:将实现隐藏在接口之后。
- 迪米特法则:模块不应该知道它操作对象的内部细节。避免
a.getB().getC().doSomething()。 - 数据传输对象(DTO):只有公共变量、没有函数的类。
6. 错误处理
- 使用异常而非返回码:保持逻辑清晰。
- 先写 Try-Catch-Finally:定义操作的范围。
- 不要返回 Null:这会强制调用者每次都检查 null。
- 不要传递 Null:会导致
NullPointerException。
7. 单元测试
- TDD 三定律:
- 在编写失败的单元测试之前,不要写生产代码。
- 只编写足以导致失败的单元测试。
- 只编写足以通过失败测试的生产代码。
- F.I.R.S.T. 原则:快速、独立、可重复、自验证、及时。
8. 类
- 短小!:类应该有单一职责(SRP)。
- 向下规则:我们希望代码像自上而下的叙述一样阅读。
9. 异味与启发式
- 僵化:难以修改。
- 脆弱:在多处崩溃。
- 不可移植:难以复用。
- 粘滞:难以做正确的事。
- 不必要的复杂性/重复。
🛠️ 实施检查清单
- 这个函数是否少于 20 行?
- 这个函数是否只做一件事?
- 所有名称是否可搜索且揭示意图?
- 我是否通过让代码更清晰来避免注释?
- 我是否传递了太多参数?
- 这个变更是否有失败的测试?
局限性
- 仅当任务明确符合上述范围时使用本技能。
- 不要将输出视为环境特定验证、测试或专家审查的替代品。
- 如果缺少必要的输入、权限、安全边界或成功标准,请停下来请求澄清。