不要在 API 命名中使用 check
本文讨论的是 check 命名在业界的默认语义约定,而不是个人风格偏好。
在很多项目中,checkXxx 被滥用于 API、Service 甚至业务逻辑中,导致调用语义混乱。
check 的定位
check 是可以用的,但是它只能在一个非常窄的语义里使用。
在大多数项目里, checkXxx() 是一个前置条件检查,不满足时抛出异常且没有业务副作用。
- 返回类型是
void而不是boolean。 - 失败时抛出异常。
- 成功时什么都不发生。
例如:
1 | private void checkStatus(); |
check 的滥用
对 check 的最严重最常见的滥用出现在命名 API 时。
命名 API 时,我们的目标是消除惊讶,而 check 在 API 语境下是语义不稳定的命名。 对外的 API 一旦叫 checkXxxx,使用者就会在多种猜测中不知所措:
- 成功时返回的是一个
boolean还是一个结果? - 失败时是一个
false异常 还是结果? - 我调用这个 API 会不会修改一些状态?
举一个更具体的例子,当一个方法叫 checkOrder() 时:
如果想知道订单是否有效,我们会期待它叫 isValid()。
如果想触发校验流程并拿到错误列表,我们会期待它叫 validateOrder()。
如果想在订单无效时阻止程序运行,我们会期待它叫 ensureOrderValid()。
check 就像一个黑色盲盒,不看实现永远不知道它会静默失败还是原地爆炸。 因此,它只适合作为类内部的辅助方法(Helper methods)。
正确命名 API 的方式是这样的:
1 | validateXxx() // 有结果 |
总结
团队中可以将 check 约定为仅用于内部前置校验的方法命名,对外 API 必须使用结果或行为导向的动词。
| 场景 | 用 check 吗 |
|---|---|
| 返回 boolean | ❌ |
| 返回 Result / Error | ❌ |
| Controller / API | ❌ |
| 有业务副作用 | ❌ |
| 失败直接抛异常 | ✅ |
| 内部前置校验 | ✅ |
| private / protected | ✅ |
| Domain 规则校验 | ✅ |