【C/C++基本功】函数的第一规则是:短小。第二规则是:比第一规则更短小。

哈哈,没错!你提到的这句话,正是出自《代码整洁之道》(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 的“短小法则”精髓

原则说明为什么重要
函数第一规则:短小函数应该尽量短,越短越好逻辑清晰、易读、易维护
函数第二规则:比第一规则更短小不要满足于“还可以”,要追求“更短、更清晰”追求代码的极致简洁与优雅
核心目标让函数逻辑单一、命名清晰、一目了然、易于协作写出像诗一样优雅的代码

🔔 

总结以下这三个核心问题,是理解 《代码整洁之道》第三章“函数”与第四章“短小法则” 最核心、最实用、也最能落地的内容:


🧩 三大核心问题:

  1. ✅ 为什么函数要短小?(逻辑清晰、单一职责、易测试、易维护)

  2. ✅ 什么是合理的函数长度?(10 行以内是理想,20 行是上限)

  3. ✅ 如何通过提取函数、分层抽象,让函数更短小?(实战方法)

这三个问题,本质上是在回答:

“函数为什么要追求短小?什么样的长度算合理?以及怎样才能做到短小?”

搞懂这三个问题,你就能写出逻辑清晰、职责分明、干净优雅、易于协作的代码,离“代码艺术家”又近了一步! ✨


✅ 一、为什么函数要短小?

(逻辑清晰、单一职责、易测试、易维护 —— 四大核心价值)


🎯 核心思想一句话:

“函数短小,不仅仅是为了好看,而是为了让代码逻辑更清晰、职责更单一、测试更简单、维护更容易,从根本上提升代码质量。”


🧠 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 行必须重构
✅ 如何让函数更短小?提取函数、拆分逻辑、分层抽象用小函数组合出清晰、可维护的系统

💡🚀

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值