函数应只做一件明确的小事,如“把字符串转成小写”;若含条件、副作用或多重职责(如排序+过滤+日志),即违反单一职责原则。

一个函数只做一件事,且这件事要足够小
函数不是“能塞多少逻辑就塞多少”,而是“刚好够解决一个明确问题”。比如 calculateAverage 的职责是算平均值,它不该顺手把数组排序、过滤负数、写入日志也干了。一旦你发现函数里出现了“和”“或”“顺便”“再处理一下”这类词,基本就是边界被打破了。
怎么判断功能是否“单一”?看调用方能不能一句话说清它的作用
如果别人问“这个函数是干啥的”,你的回答必须是主谓宾结构、无连词、不带条件分支,比如:
- “它把字符串转成小写” —— ✅ 清晰
- “它把字符串转成小写,但如果含数字就抛异常,否则返回空字符串” —— ❌ 已混入校验、错误处理、默认行为三类职责
后者其实该拆成 toLowercase + isValidInput + 上层的错误分支逻辑。
容易被忽略的隐性功能:副作用和状态依赖
即使函数体只有一行 return a + b;,它也可能悄悄承担了不该有的功能:
立即学习“C++免费学习笔记(深入)”;
- 修改全局变量或静态成员(比如在加法里偷偷更新计数器)
- 依赖外部状态(比如读取未传入的
config::timeout) - 调用非纯函数(如
std::time(nullptr)或std::rand()),让结果不可预测
这些都会让函数从“计算单元”退化为“行为黑盒”,破坏可测试性和线程安全性。
复杂逻辑不是不能存在,而是得有明确的分层归属
真正难的是把“一件事”拆对。比如实现“用户登录”,它本身不是单个函数该做的事;合理的切分是:
-
validateCredentials(只校验账号密码格式与长度) -
lookupUser(只查数据库,不处理失败重试) -
checkRateLimit(只读当前IP请求次数,不执行拦截) - 上层组合逻辑(如
attemptLogin)负责调用顺序、错误聚合、日志埋点
最后一层才是协调者,而不是把所有 if-else 和 try-catch 全塞进去。越靠近业务主流程的函数,越容易因“看起来方便”而膨胀——这是最常被纵容的破口。


















