【翻译】布尔表达式是否太长太复杂?

Daotin 于 2024-06-11 发布 编辑

你可能在你的代码库中遇到过一些复杂、难以阅读的布尔表达式,并希望它们更容易理解。例如,假设我们想要决定一个比萨饼是否很棒:

// 判断这个披萨是否很棒。
if ((!pepperoniService.empty() || sausages.size() > 0) && (useOnionFlag.get() || hasMushroom(ENOKI, PORTOBELLO)) && hasCheese()) {
  //...
}

改进这一点的第一步是将条件提取到一个命名良好的变量中::

boolean isPizzaFantastic = (!pepperoniService.empty() || sausages.size() > 0) && (useOnionFlag.get() || hasMushroom(ENOKI, PORTOBELLO)) && hasCheese();

if (isPizzaFantastic) {
  //...
}

然而,布尔表达式仍然太复杂。从给定的一组输入计算 isPizzaFantastic 的值可能会令人困惑。您可能需要拿起笔和纸,或者在本地启动服务器并设置断点。

相反,尝试将细节分组为提供有意义的抽象的中间布尔值。

下面的每个布尔值代表一个明确定义的质量,您不再需要混合 &&|| 在一个表达式中。在不更改业务逻辑的情况下,您可以更轻松地了解布尔值之间的相互关系:

boolean hasGoodMeat = !pepperoniService.empty() || sausages.size() > 0;

boolean hasGoodVeggies = useOnionFlag.get() || hasMushroom(ENOKI, PORTOBELLO);

boolean isPizzaFantastic = hasGoodMeat && hasGoodVeggies && hasCheese();

另一种选择是将逻辑隐藏在单独的方法中。这也提供了使用保护子句提前返回的可能性,进一步减少了跟踪中间状态的需要:

boolean isPizzaFantastic() {
  if (!hasCheese()) {
    return false;
  }
  if (pepperoniService.empty() && sausages.size() == 0) {
    return false;
  }
  return useOnionFlag.get() || hasMushroom(ENOKI, PORTOBELLO);
}