这是我们 “代码健康 “系列的另一篇文章。本文章的一个版本最初作为 “谷歌厕所测试 “插曲出现在全球的谷歌厕所中。您可以下载便于打印的版本,在您的办公室展示。
作者:孙一鸣(Yiming Sun)
您可能在代码库中遇到过一些复杂难读的布尔表达式,希望它们更容易理解。例如,我们想判断比萨饼是否美味:
// Decide whether this pizza is fantastic.
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();
另一种方法是将逻辑隐藏在单独的方法中。这也提供了使用guard clauses 提前返回的可能性,进一步减少了跟踪中间状态的需要:
boolean isPizzaFantastic() {
if (!hasCheese()) {
return false;
}
if (pepperoniService.empty() && sausages.size() == 0) {
return false;
}
return useOnionFlag.get() || hasMushroom(ENOKI, PORTOBELLO);
}
本文文字及图片出自 isBooleanTooLongAndComplex
你也许感兴趣的: