长布尔表达式的优化
这是关于布尔表达式优化的一篇文章,刚开始是贴在谷歌的厕所中的🤡。
当我们在代码中遇到过一些复杂的、难以阅读的布尔表达式,一定希望它们更容易被阅读。
例如,假设我们想决定一个披萨是否美味:
// 决定一个披萨是否美味
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) {
...
}
但是,布尔表达式仍然太复杂,想到读懂其中的含义,可能需要拿起笔和纸,或者在本地启动服务器并设置断点。
我们提供了两种的优化思路
方法1:
我们可以尝试将不同的判断进行分组提供到更有意义抽象的中间布尔值中。下面的每个布尔值代表一个定义’披萨美味‘的条件,这样将不再需要在表达式中混合使用 & & 和 | | 。在不改变业务逻辑的情况下,可以更容易地看到布尔值之间的相互关系:
# 有优质的肉🍖
boolean hasGoodMeat = !pepperoniService.empty() || sausages.size() > 0;
# 有优质的蔬菜🍃
boolean hasGoodVeggies = useOnionFlag.get() || hasMushroom(ENOKI, PORTOBELLO);
# 好披萨🍕 = 优质的肉 + 肉质的蔬菜 + 干酪
boolean isPizzaFantastic = hasGoodMeat && hasGoodVeggies && hasCheese();
方法2:
另一种选择是将逻辑隐藏在单独的方法中,通过某些条件的提前返回,大大减少了去理解结果的难度:
boolean isPizzaFantastic() {
# 没有干酪🧀
if (!hasCheese()) {
return false;
}
# 没有胡椒🧂或者香肠🍖
if (pepperoniService.empty() && sausages.size() == 0) {
return false;
}
# 是否有洋葱🧅或者蘑菇🍄
return useOnionFlag.get() || hasMushroom(ENOKI, PORTOBELLO);
}
原文:Google Testing Blog: isBooleanTooLongAndComplex (googleblog.com)
License:
CC BY 4.0