谨慎使用哨兵值,会给调用方带来心智负担:
// Returns the account balance, or -5 if the account has been closed
int AccountBalance();
int balance = AccountBalance();
if (balance == -5) { // check the `Sentinel Values` -5
LOG(ERROR) << "account closed";
return;
}
int balance = AccountBalance();
if (balance <= 0) { // maybe also works now
LOG(ERROR) << "where is my account?";
return;
}
int balance = AccountBalance(); // forgot to check `Sentinel Values`
// use `balance` here
使用哨兵值的一些问题:
- 不同的组件有不同的哨兵值,需要
API
查询文档 - 代码和文档可能会更新不一致
- 哨兵值,在将来可能会变成合法值
- 一个组件的哨兵值,在另外一个组件中是合法值,增加了组件间的协作难度
- 调用方可能忘记检查哨兵值,或者哨兵值检查不对
使用 absl::optional
作为函数的返回值来优雅的解决问题,对调用方友好:
// Returns the account balance, or absl::nullopt if the account has been closed
absl::optional<int> AccountBalance();
absl::optional<int> balance = AccountBalance();
if (!balance.has_value()) {
LOG(ERROR) << "Account doesn't exist";
return;
}
// use `*balance` here