2009-08-10 43 views
1

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

您认为如何?

有什么缺点?

如果该变量没有在其他地方使用,编译器是否需要输入?我还考虑用一个额外的块“{}”来缩小范围。

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 
} 

回答

11

我做这一切的时候。该代码更具可读性。不这样做的唯一原因是它禁止运行时从快捷方式优化,虽然一个聪明的虚拟机可能会解决这个问题。

+4

这可以通过提取检查方法而不是简单变量分配来解决。 – 2009-08-10 14:22:18

+0

这是来自Code Complete的推荐做法。 – 2009-08-10 15:39:33

0

我认为检查可能属于人类。你可以传入最小值/最大值,但在我看来,调用person.IsEligable()会是一个更好的解决方案。

+3

我不同意。 “合格”的定义可能由客户端代码定义,而不是目标对象。 – skaffman 2009-08-10 13:44:46

+0

我认为没有什么可以肯定的信息。给出的例子比较了三件事,每件事都来自人,并与(根据上限)进行比较。 Eligable只是一个词,可以扩展到IsEligableForXXX等。 – Jimmeh 2009-08-10 13:46:56

+0

嗯,你确定吗?我不是,那么这个人是可以决定的。你可以想象这个人可能适合不止一种情况。恕我直言,商业逻辑应该移到别的地方而不是人。所以你不能分开这个问题。 – codevour 2009-08-10 13:48:09

0

你可以走一步,创造人的亚型:

Teenager extends Person 
ThirdAgePerson extends Person 
Kid extends Person 

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

+1

由于(缺少)Java中的多重继承,他不得不使用接口。 我看不到投票的理由(特别是没有任何评论)。当然,在创建时动态地获取接口是明显的下一个问题---大量专门的构造函数vs。反射。 – ShiDoiSi 2009-08-10 14:13:05

+0

这是一个可能的解决方案,但它高度依赖于上下文以及它正在处理的域对象的类型。 – aberrant80 2009-08-11 08:13:57

0

后一种情况的一个好处是,您将在代码中稍后使用isOldEnough,isTallEnough和isNotToHeavy(sic)变量。它也更容易阅读。

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

0

我认为这是个人品味的问题。我发现你的重构很可读。

在这种情况下,particualr我可能重构整个测试成

isThisPersonSuitable() 

方法。

如果有很多这样的代码,我甚至可能创建一个PersonInterpreter(可能是inner)类,它持有一个人并回答关于他们资格的问题。

一般来说,我倾向于偏好可读性而不考虑任何次要的性能问题。

0

唯一可能的负面情况是您失去了AND短路的好处。但实际上,如果您的任何支票比其他支票贵很多,例如person.getWeight()是一个重要的操作而不仅仅是一个访问者,那么这实际上只有任何意义。

+0

嘿,这是一个非常好的方法调用这个昂贵的代价不应该使用,或者我们必须像在等于执行检查 boolean equals = true; equals = equals && this.field.equals(other.field); equals = equals && this.field1.equals(other.field1); [...] 但我认为这没有找到这种情况或你有什么想法? – codevour 2009-08-10 13:57:31

+0

对不起,我不知道评论功能不解释换行符 – codevour 2009-08-10 13:59:38

+0

我说“可能”和“例如”,所以不,我不认为它适用于你的情况。 – 2009-08-10 14:52:13

3

这种方法的真正风险是它失去了对变化值的响应。

是的,相对于大多数程序的运行时间,人们的年龄,体重和身高并不会经常变化,但是它们确实会发生变化,并且,例如,如果年龄发生变化,而代码段仍然存在活着,你的决赛现在可能会产生一个错误的答案。

然而,我不相信把isEligible到人是合适的,因为相关的什么是合格的知识似乎是一个更大的范围。你必须问:有资格获得什么?

总而言之,在代码审查,我可能会建议你在人添加方法,而不是。

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

等等。

0

我对你的结构不算什么,但在我看来,在这种情况下,可读性增益可以通过简单地在换行符投入来实现,即

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

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

比如,如果这是一个销售酒精的网站系统,并且您有很多地方必须测试该人是否合法饮酒,那么拥有Person.isLegalDrinkingAge()函数是有意义的。如果唯一的因素是年龄,那么拥有MINIMUM_DRINKING_AGE常数就可以达到同样的结果,但是一旦涉及其他逻辑,如不同法定饮酒年龄在不同的法律管辖区或者有特殊情况或例外,那么它确实应该是一个成员函数。另一方面,如果你有一个地方,你检查是否有人超过18岁,并在其他地方,你检查他是否超过12,并在其他地方,你检查他是否超过65等等,那么几乎没有通过将此功能推入Person来获得。

1

您的两个代码块是不等价。

有很多情况下,可以用来展示这一点,但我会用一个。假设person.getAge()> MINIMUM_AGE为true,person.getTall()抛出异常。

在第一种情况中,表达将执行如果代码块,而第二种情况将抛出异常。在可计算性理论中,当抛出异常时,这被称为“底层元素”。已经证明,当使用急切的评估语义进行评估时(如在第二个例子中),如果它终止(不解决底部问题),那么就保证了一个懒惰评估策略(第一个例子)是有保证的终止。这是编程的一个重要原则。注意,你不能自己编写Java的函数。

虽然这是不可能的,你getTall()方法将抛出一个异常,你不能你的推理适用于一般情况。