卫语句是什么
用卫语句替换嵌套条件:把异常、边界与不合法输入在函数开头处理掉并提前返回,让主流程保持在同一层缩进。深层嵌套往往意味着条件被反向表达——把必须成立的前提先写清楚,主逻辑自然浮到表面。
基本信息
| 适用场景 | 条件深层嵌套,主逻辑被边界推向内部 |
|---|---|
| 写法 | 异常与边界条件提前返回或抛出 |
| 收益 | 主流程平铺,缩进层级减少 |
| 语言差异 | 返回多值用元组,单一出口风格可与卫语句共存 |
| 前提 | 提前返回不改变原有副作用顺序 |
典型使用场景
- 参数校验先做,主体逻辑不再包在判断里
- 资源或状态未就绪时提前返回,避免层层包裹
- 权限不足直接拒绝,后续代码不必再判断
- 循环里跳过不满足条件的元素,减少嵌套
- 值对象构造时先把非法输入挡在门外
替换前后
替换前后
// 之前:两层嵌套,主逻辑被挤到最里面
if (isSeparated) {
if (isRetired) result = 0; else result = amount;
} else {
if (isRetired) result = amount * 0.9; else result = amount * 0.8;
}
// 之后:先处理边界,主流程平铺
if (isSeparated) return isRetired ? 0 : amount;
return isRetired ? retiredAmount() : normalAmount();两种风格对照
| 情形 | 推荐 | 理由 |
|---|---|---|
| 边界与异常较多 | 卫语句 | 边界先出局,主流程更短 |
| 副作用需统一收尾 | 卫语句加尾部处理 | 中途返回会跳过收尾逻辑 |
| 需要返回多个值 | 元组或结果对象 | 单一返回点便于统一构造 |
单一出口并非必须:当收尾逻辑需要集中时,可以让放行路径统一在函数尾部;否则提前返回通常更容易读。
卫语句里做副作用(日志、计数、埋点)会让重构悄悄改变行为:搬动位置前先确认原有调用顺序是否被依赖。
另一种常见写法是先把不合法输入转成明确的错误结果再返回,调用方按结果分支处理:既不抛异常,也避免把校验逻辑散落在主干里。