哈哈,没错!你提到的这句话,正是出自《代码整洁之道》(Clean Code)的作者、编程界的“洁癖大师”—— Robert C. Martin(大叔 Bob / Uncle Bob) 之口,原话就是这么“嚣张又精辟” 👇
“函数的第一规则是:短小。第二规则是:比第一规则更短小。”
(The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.)
你一定会问:
“啥?函数不是越小越好吗?那到底多小才叫‘短小’?Bob 大叔是不是在开玩笑?”
别急,咱们来认真、幽默、深入浅出地拆解这句话,保证你不仅懂了它的字面意思,更领悟到它背后的工程哲学与代码美学!
🧠 一、字面意思:函数,必须短小!越短越好!
Uncle Bob 用这种看似夸张、重复的方式,其实是在用最直白的语言强调一个核心原则:
✅ 函数,一定要短小!不是“可以短小”,而是“必须短小”!不仅要短小,还要比你认为的‘已经很短了’还要更短!
📏 那么,到底多短才叫“短小”?
🎯 Uncle Bob 的建议:
-
一个函数最好不要超过 20 行,理想情况是 10 行以内!
-
如果一个函数超过一屏(比如 30~40 行),那它就太长了,必须考虑拆分!
🧠 注意:不是强制规定“必须 10 行”,而是倡导一种“追求短小”的代码审美与工程纪律。
🤔 为什么 Bob 大叔这么执着于“函数要短小”?
别急,我们用几个生动形象的类比 + 实用理由,来揭示这条“短小法则”背后的深刻智慧!
🎯 二、为什么函数要“短小”?(核心价值)
✅ 1. 短小 → 逻辑清晰,一目了然
-
函数短小 → 你一眼就能看完
-
一眼能看完 → 你就能理解它在干嘛
-
理解它干嘛 → 你就能放心改、放心测、放心维护
🧠 类比: 你读一篇文章,如果每个句子都短小精炼,你就容易理解;如果一句话写了两三行,还带各种嵌套从句,你读着都累,更别说理解了。
✅ 2. 短小 → 单一职责,职责清晰
-
函数短小 → 往往意味着它只做一件事
-
只做一件事 → 逻辑单一、边界清晰、改一处不会影响其他功能
🧠 类比: 厨师做菜,先洗菜、再切菜、再炒菜。每一步是一个小任务,而不是一锅炖所有步骤。
✅ 3. 短小 → 易于测试,易于复用
-
函数短小 → 输入输出清晰 → 测试用例更容易写
-
函数只做一件事 → 更容易被其他模块复用
🧠 类比: 一个工具只干一个活(比如螺丝刀只拧螺丝),你用起来放心,也更容易复用。
✅ 4. 短小 → 易于命名,表达清晰
-
函数短小 → 功能聚焦 → 容易取一个清晰、有表达力、能自我解释的名字
🧠 类比: 你给一个功能起名字,如果它只做一件事,名字就能准确表达;如果它做十件事,你取啥名都不合适。
✅ 5. 短小 → 让代码像文章一样有节奏感
-
一堆短小函数组合在一起 → 像一段逻辑清晰、层次分明的文章
-
每个函数是一个“段落”或“句子” → 整体代码可读性极高
🧠 类比: 好的代码,就像一篇好文章,句子短小、段落清晰、逻辑流畅。
🎯 三、那函数到底多短算“短小”?—— 实用参考标准
| 函数长度 | 建议 / 看法 |
|---|---|
| 1~5 行 | ✅ 绝佳!逻辑极其聚焦,一目了然 |
| 6~10 行 | ✅ 非常好!依然短小精悍,容易理解 |
| 11~20 行 | ⚠️ 可接受,但接近上限,尽量再简化 |
| 21~30 行 | ⚠️ 偏长,建议考虑拆分 |
| 30 行以上 | ❌ 太长!大概率逻辑混杂,必须重构! |
🧠 一屏原则: 如果你打开代码,一个函数要滚动屏幕才能看完,那它就太长了!
🎯 四、如何做到“比第一规则更短小”?(实战技巧)
Uncle Bob 说“第二规则是比第一规则更短小”,其实是在鼓励你:
“不要满足于‘还行吧,挺短了’,而是要追求‘还能更短、更清晰、更聚焦’。”
✅ 实用技巧:如何让函数更短小?
1. 提取函数(Extract Function)
-
如果一个函数里有一段逻辑可以独立出来(比如校验、计算、转换),就把它抽成一个新函数!
🔧 重构前(长函数):
void processOrder(Order order) {
if (order != null && order.isValid()) {
double total = 0;
for (Item item : order.getItems()) {
total += item.getPrice() * item.getQuantity();
}
if (total > 100) {
applyDiscount(order);
}
saveOrder(order);
}
}
🔧 重构后(短小函数组合):
void processOrder(Order order) {
if (!isValidOrder(order)) return;
double total = calculateTotal(order);
if (needsDiscount(total)) {
applyDiscount(order);
}
saveOrder(order);
}
boolean isValidOrder(Order order) {
return order != null && order.isValid();
}
double calculateTotal(Order order) {
double total = 0;
for (Item item : order.getItems()) {
total += item.getPrice() * item.getQuantity();
}
return total;
}
boolean needsDiscount(double total) {
return total > 100;
}
🧠 结果:每个函数都短小、职责单一、命名清晰,整体逻辑更易读!
2. 遵循单一职责原则(SRP)
-
一个函数只做一件事,不要试图让它“多才多艺”
3. 保持函数只做“一层抽象”
-
不要一会儿处理业务逻辑,一会儿处理底层细节,逻辑要分层清晰
✅ 总结一句话:
“函数要短小,不是为了满足某种教条,而是为了让代码清晰、可读、可维护、可测试、可复用。”
“追求短小,就是在追求代码的优雅与专业。”
🏁 最终大总结:Uncle Bob 的“短小法则”精髓
| 原则 | 说明 | 为什么重要 |
|---|---|---|
| 函数第一规则:短小 | 函数应该尽量短,越短越好 | 逻辑清晰、易读、易维护 |
| 函数第二规则:比第一规则更短小 | 不要满足于“还可以”,要追求“更短、更清晰” | 追求代码的极致简洁与优雅 |
| 核心目标 | 让函数逻辑单一、命名清晰、一目了然、易于协作 | 写出像诗一样优雅的代码 |
🔔
总结以下这三个核心问题,是理解 《代码整洁之道》第三章“函数”与第四章“短小法则” 最核心、最实用、也最能落地的内容:
🧩 三大核心问题:
-
✅ 为什么函数要短小?(逻辑清晰、单一职责、易测试、易维护)
-
✅ 什么是合理的函数长度?(10 行以内是理想,20 行是上限)
-
✅ 如何通过提取函数、分层抽象,让函数更短小?(实战方法)
这三个问题,本质上是在回答:
“函数为什么要追求短小?什么样的长度算合理?以及怎样才能做到短小?”
搞懂这三个问题,你就能写出逻辑清晰、职责分明、干净优雅、易于协作的代码,离“代码艺术家”又近了一步! ✨
✅ 一、为什么函数要短小?
(逻辑清晰、单一职责、易测试、易维护 —— 四大核心价值)
🎯 核心思想一句话:
“函数短小,不仅仅是为了好看,而是为了让代码逻辑更清晰、职责更单一、测试更简单、维护更容易,从根本上提升代码质量。”
🧠 1. 短小 → 逻辑清晰,一目了然(Readability)
-
函数短小 → 你一眼就能看完它的全部逻辑
-
一眼能看完 → 你就能快速理解它在干嘛
-
理解它干嘛 → 你就能放心改、放心测、放心维护
🧠 类比: 你读一段话,如果每句话都短小精炼,你就容易理解;如果一句话写了两三行还带各种嵌套,你读着都累,更别说理解逻辑了。
🔧 举例:
void processOrder(Order order) {
if (order == null) return;
if (!order.isValid()) return;
double total = calculateTotal(order);
if (total > 100) applyDiscount(order);
saveOrder(order);
}
👉 每一步逻辑都短小清晰,你一眼就能明白:校验 → 计算 → 折扣 → 保存。
🧠 2. 短小 → 更容易实现单一职责(Single Responsibility Principle)
-
函数短小 → 往往意味着它只做一件事
-
只做一件事 → 职责清晰、边界明确
-
职责清晰 → 改动影响范围小,不容易引入 Bug
🧠 类比: 厨师做菜,洗菜、切菜、炒菜各是一个独立的步骤,而不是“一锅炖所有”。
🔧 反面例子: 一个函数既校验用户,又计算价格,又发通知,又写日志 → 职责混乱,难以维护。
🧠 3. 短小 → 易于测试(Testability)
-
函数短小 → 输入输出清晰
-
输入输出清晰 → 测试用例更容易写
-
测试容易 → Bug 更少,质量更高
🧠 类比: 一个函数只做一件事,你只需要测试这一个功能点;如果它做十件事,你得测十种情况,成本高、易遗漏。
🔧 举例:
-
函数
calculateTotal(Order order)只负责计算总价 → 你只需传入订单,断言返回的总价是否正确。 -
如果这个函数还做了折扣、日志、校验 → 你的测试用例就要考虑各种组合,复杂度爆炸。
🧠 4. 短小 → 易于维护与重构(Maintainability)
-
函数短小 → 逻辑集中、意图明确
-
逻辑清晰 → 别人(或未来的你)更容易理解与修改
-
修改影响小 → 不容易破坏其他功能
🧠 类比: 一个小模块出问题,你很容易定位并修复;如果一个“大泥球”函数出 Bug,你可能得读几十行代码才能找到原因。
✅ 总结一句话:
“函数要短小,是为了让代码逻辑更清晰、职责更单一、测试更容易、维护更轻松 —— 这是写出高质量代码的基础。”
✅ 二、什么是合理的函数长度?
(10 行以内是理想,20 行是上限 —— 实用标准)
🎯 核心建议(来自 Uncle Bob 与工程实践总结):
| 函数长度 | 建议 / 看法 |
|---|---|
| 1~5 行 | ✅ 绝佳! 逻辑极其聚焦,一目了然,比如简单的计算、调用、返回 |
| 6~10 行 | ✅ 非常好! 依然短小精悍,容易理解,是理想长度 |
| 11~20 行 | ⚠️ 可接受,但接近上限,建议尽量再简化,考虑是否可拆分 |
| 21~30 行 | ⚠️ 偏长! 逻辑可能开始混杂,建议重构 |
| 30 行以上 | ❌ 太长! 大概率逻辑复杂、职责不清,必须拆分! |
🧠 一屏原则: 如果你打开代码编辑器,一个函数需要滚动鼠标或滑动屏幕才能看完,那它就太长了!
🧠 为什么 10 行以内是理想?
-
短小到极致 → 逻辑极度聚焦
-
一眼看完 → 理解成本最低
-
容易命名 → 函数名能准确表达意图
-
容易测试 → 输入输出清晰明确
🧠 10 行以内的函数,往往是高内聚、低耦合、职责单一的典范!
🧠 为什么 20 行是上限?
-
超过 20 行,代码往往开始承载多个职责、多个逻辑层次
-
理解与维护成本显著上升
-
测试用例变复杂,重构难度加大
🧠 20 行是个“警戒线”,超过它,你就该问问自己:这个函数能不能再拆?
✅ 三、如何通过提取函数、分层抽象,让函数更短小?
(实战技巧,立竿见影)
🎯 核心思路:“不要让一个函数做太多事,而是把逻辑拆成多个小函数,每个只做一件事。”
✅ 技巧 1:提取函数(Extract Function)—— 把一段逻辑抽出去!
🔧 适用场景:
你发现函数里有一段逻辑(比如校验、计算、转换、日志、通知)可以独立出来,就把它抽成一个新函数!
🔧 重构前(长函数):
void processOrder(Order order) {
if (order == null || !order.isValid()) return;
double total = 0;
for (Item item : order.getItems()) {
total += item.getPrice() * item.getQuantity();
}
if (total > 100) {
applyDiscount(order);
}
saveOrder(order);
}
🔧 重构后(短小函数组合):
void processOrder(Order order) {
if (!isValidOrder(order)) return;
double total = calculateTotal(order);
if (needsDiscount(total)) {
applyDiscount(order);
}
saveOrder(order);
}
boolean isValidOrder(Order order) {
return order != null && order.isValid();
}
double calculateTotal(Order order) {
double total = 0;
for (Item item : order.getItems()) {
total += item.getPrice() * item.getQuantity();
}
return total;
}
boolean needsDiscount(double total) {
return total > 100;
}
🧠 结果:每个函数都短小、职责单一、命名清晰,整体逻辑更易读、更易维护!
✅ 技巧 2:遵循单一职责原则(SRP)
-
一个函数只做一件事(比如:校验、计算、保存、通知)
-
不要把多个职责混在一个函数里
✅ 技巧 3:保持一层抽象(One Level of Abstraction)
-
函数内部的代码,应该处于同一个逻辑层次(都讲业务规则,或都讲实现细节)
-
不要一会儿高层逻辑,一会儿底层细节,逻辑跳跃太大会增加复杂度
✅ 总结一句话:
“通过提取函数、拆分逻辑、分层抽象,你可以把一个又臭又长的函数,拆成一组短小精悍、职责清晰的小函数,让代码像乐高一样模块化、清晰、优雅。”
🏁 最终大总结:三大问题核心关联
| 问题 | 核心思想 | 实用结论 |
|---|---|---|
| ✅ 为什么函数要短小? | 逻辑清晰、单一职责、易测试、易维护 | 短小是高质量代码的基础 |
| ✅ 什么是合理函数长度? | 10 行以内是理想,20 行是上限 | 超过 20 行就要警惕,超过 30 行必须重构 |
| ✅ 如何让函数更短小? | 提取函数、拆分逻辑、分层抽象 | 用小函数组合出清晰、可维护的系统 |
💡🚀

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



