Skip to content

Files

Latest commit

 

History

History
45 lines (35 loc) · 1.29 KB

TotW171.md

File metadata and controls

45 lines (35 loc) · 1.29 KB

Tip of the Week #171: Avoid Sentinel Values

谨慎使用哨兵值,会给调用方带来心智负担:

// 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

使用哨兵值的一些问题:

  1. 不同的组件有不同的哨兵值,需要 API 查询文档
  2. 代码和文档可能会更新不一致
  3. 哨兵值,在将来可能会变成合法值
  4. 一个组件的哨兵值,在另外一个组件中是合法值,增加了组件间的协作难度
  5. 调用方可能忘记检查哨兵值,或者哨兵值检查不对

使用 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