代码大全2——控制结构与函数——把复杂度关进笼子
核心观点
程序的大部分复杂度,不是来自单个算法,而是来自控制流的组合爆炸。McConnell 花了大量篇幅讲如何让控制结构「简单、直白、可预测」。
关键要点
- 复杂度是可以度量的
全书推崇用圈复杂度(Cyclomatic Complexity)等指标来量化「这段代码有多难懂」。
经验值:单个子程序的圈复杂度最好控制在 10 以内,超过就考虑拆分。
判断复杂度的直观信号:if 嵌套层数、switch 分支数量、布尔表达式里 &&/|| 的个数。
2. 简化布尔表达式
复杂条件应拆成具名布尔变量,把意图写进名字:
cpp
// 差:读者要自己脑内解析
if ((age > 18 && age < 65) && (hasId || isCitizen)) { ... }
// 好:意图一目了然
bool isWorkingAge = age > 18 && age < 65;
bool isIdentified = hasId || isCitizen;
if (isWorkingAge && isIdentified) { ... }
3. 避免深层嵌套
用卫语句(Guard Clauses)/ 提前返回代替 if-else 的层层包裹。
理想形态:先处理异常/边界情况并返回,主逻辑保持在函数体的「快乐路径」上。
cpp
// 差:主逻辑被埋在三层缩进里
if (input != null) {
if (input.isValid()) {
if (hasPermission()) {
// 真正要做的事
}
}
}
// 好:逐层排除,主逻辑清晰
if (input == null) return;
if (!input.isValid()) return;
if (!hasPermission()) return;
// 真正要做的事
4. 循环的三件事
写循环时永远问清楚:初始化、循环条件、递进 三部分是否都正确、边界是否考虑清楚(开区间/闭区间、< 还是 <=)。
尽量让循环体只做一件事,用「从内到外」的方式构建循环。
5. 函数要短、要单一职责
好函数的特征:短小、只做一件事、参数少、无副作用。
一个实用的判断标准:能否用一句话说出这个函数做什么?说不清,就该拆。
我的思考
这篇的核心方法论是「把复杂度拆解并命名」。无论是拆布尔变量、写卫语句,还是拆小函数,本质都是:用「命名」这个动作,把隐式复杂度变成显式、可读的结构。
我最大的收获是:复杂不是罪,不透明的复杂才是。一段代码可以客观上很复杂,但如果它的结构清晰、每个局部都能被单独理解,它就是可维护的。
浙公网安备 33010602011771号