将布尔检查提取到局部变量

时间:2009-08-10 13:37:51

标签: java

有时我会将布尔检查提取到局部变量中,以实现更好的可读性。

你怎么看?

有什么缺点吗?

如果变量未在其他地方使用,编译器是否为line-in或其他内容?我还考虑使用额外的块“{}”来缩小范围。

if (person.getAge() > MINIMUM_AGE && person.getTall() > MAXIMUM_SIZE && person.getWeight < MAXIMUM_WEIGHT) {
    // do something
}

final boolean isOldEnough = person.getAge() > MINIMUM_AGE;
final boolean isTallEnough = person.getTall() > MAXIMUM_SIZE;
final boolean isNotToHeavy = person.getWeight < MAXIMUM_WEIGHT;

if (isOldEnough && isTallEnough && isNotToHeavy) {
    // do something
}

9 个答案:

答案 0 :(得分:11)

我一直这样做。这种代码更具可读性。不这样做的唯一原因是它禁止运行时进行快捷方式优化,尽管智能VM可能会解决这个问题。

答案 1 :(得分:3)

这种方法的真正风险在于它失去了对不断变化的价值观的反应。

是的,相对于大多数程序的运行时间,人们的年龄,体重和身高不会经常变化,但是他们确实会发生变化,例如,如果年龄发生变化,而您的片段仍然存在的对象,你的最终isOldEnough现在可能会得到一个错误的答案。

然而我不相信将isEligible置于人物中也是合适的,因为对于什么构成资格的知识似乎具有更大的范围。一个人必须要问:有资格获得什么?

总而言之,在代码审查中,我可能会建议您在Person中添加方法。

boolean isOldEnough (int minimumAge)  { return (this.getAge() > minimumAge); }

等等。

答案 2 :(得分:1)

你的两段代码是不相等的。

有许多案例可以用来表明这一点,但我会用一个。假设person.getAge()&gt; MINIMUM_AGE为true,person.getTall()引发异常。

在第一种情况下,表达式将执行if代码块,而第二种情况将抛出异常。在可计算性理论中,当抛出异常时,这被称为“底层元素”。已经证明,当使用急切的评估语义(如第二个例子中)评估一个程序时,如果它终止(不解析到底部),那么可以保证一个懒惰的评估策略(你的第一个例子)得到保证终止。这是编程的一个重要原则。请注意,您不能编写Java的&amp;&amp;自己动手。

虽然你的getTall()方法不太可能抛出异常,但你不能将你的推理应用于一般情况。

答案 3 :(得分:0)

我认为支票可能属于人类。您可以传递Min / Max值,但在我看来,调用person.IsEligable()会是更好的解决方案。

答案 4 :(得分:0)

您可以更进一步,创建人物的子类型:

Teenager extends Person
ThirdAgePerson extends Person
Kid extends Person

子类将以自己的方式覆盖Person的方法。

答案 5 :(得分:0)

后一种情况的一个优点是,您可以在代码中稍后重用isOldEnough,isTallEnough和isNotToHeavy(sic)变量。它也更容易阅读。

您可能需要考虑将这些布尔检查抽象为自己的方法,或将检查结合到方法中。例如,person.isOldEnough()方法将返回布尔检查的值。你甚至可以给它一个整数参数,这个参数是你的最小年龄,为它提供更灵活的功能。

答案 6 :(得分:0)

我认为这是个人品味的问题。我发现你的重构非常易读。

在这个特殊情况下,我可能会将整个测试重构为

isThisPersonSuitable()

方法

如果有太多这样的代码,我甚至可以创建一个PersonInterpreter(也许是内部)类,它可以容纳一个人并回答有关他们资格的问题。

一般来说,我倾向于支持可读性,而不是任何轻微的性能考虑。

答案 7 :(得分:0)

唯一可能的负面影响是你失去了AND被短路的好处。但实际上,如果您的任何检查在很大程度上比其他检查更昂贵,那么这只是真正有意义的,例如,如果person.getWeight()是一个重要的操作,而不仅仅是一个访问者。

答案 8 :(得分:0)

我没有反对你的构造,但在我看来,在这种情况下,可读性增益可以通过简单地设置换行符来实现,即

if (person.getAge() > MINIMUM_AGE
  && person.getTall() > MAXIMUM_SIZE
  && person.getWeight < MAXIMUM_WEIGHT)
{
  // do something
}

其他答案带来的更大问题是它是否属于Person对象。我认为简单的答案是:如果有几个地方你做同样的测试,它属于人。如果有些地方你做类似但不同的测试,那么它们属于调用类。

就像,如果这是一个销售酒精的网站的系统,而且你有很多地方必须测试这个人是否达到法定饮酒年龄,那么拥有一个Person.isLegalDrinkingAge()函数是有意义的。如果唯一因素是年龄,那么拥有MINIMUM_DRINKING_AGE常数会达到相同的结果,我想,但是一旦涉及其他逻辑,例如不同法律管辖区内的不同法定饮酒年龄,或者有特殊情况或例外,那么它应该是成员函数。

另一方面,如果你有一个地方可以检查某人是否超过18岁,而在其他地方你检查他是否超过12岁以及其他地方检查他是否超过65岁等等,那么就没有什么可以获得的了。将此功能推送到Person。