你可能在你的代码库中遇到过一些复杂、难以阅读的布尔表达式,并希望它们更容易理解。例如,假设我们想要决定一个比萨饼是否很棒:
// 判断这个披萨是否很棒。
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);
}