views:

695

answers:

7

Consider this line:

if (object.getAttribute("someAttr").equals("true")) { // ....

Obviously this line is a potential bug, the attribute might be null and we will get a NullPointerException. So we need to refactor it to one of two choices:

First option:

if ("true".equals(object.getAttribute("someAttr"))) { // ....

Second option:

String attr = object.getAttribute("someAttr");
if (attr != null) {
    if (attr.equals("true")) { // ....

The first option is awkward to read but more concise, while the second one is clear in intent, but verbose.

Which option do you prefer in terms of readability?

+16  A: 

I've always used

if ("true".equals(object.getAttribute("someAttr"))) { // ....

because although it is a little more difficult to read it's much less verbose and I think it's readable enough so you get used to it very easily

victor hugo
I don't even think this is more difficult to read.
TM
+1  A: 

I like option 1 and I would argue that it is readable enough.

Option 3 btw would be to introduce a getAttribute method that takes a default value as a parameter.

willcodejavaforfood
This question is about the 'if' block so about your option 3: "You can't always rely the method will not ever return a null value
victor hugo
Of course you can ensure that it never returns null for a default value.
willcodejavaforfood
Option 3 would be all about moving the error handling and null checks into a method according to DRY.
willcodejavaforfood
I agree but what I meant is that you not always test methods you've written so you can't rely the return value won't be null
victor hugo
@Victor H Valle - Ummmmmmmm
willcodejavaforfood
A: 

Util.isEmpty(string) - returns string == null || string.trim().isEmpty() Util.notNull(string) returns "" if string == null, string otherwise. Util.isNotEmpty(string) returns ! Util.isEmpty(string)

And we have a convention that for strings, Util.isEmpty(string) semantically means true and Util.isNotEmpty(string) semantically means false.

alamar
+10  A: 

In the second option, you can take advantage of short-circuiting &&:

String attr = object.getAttribute("someAttr");
if (attr != null && attr.equals("true")) { // ....
laalto
Indeed you can, but it is optimisation favored to readibility, always a bad idea.
David Pierre
Huh, favours optimisation? I think, on the contrary, that this is slightly more readable than option 1.
Jonik
Yes - style issues do not have definitive answers. It's what you have used to. Personally I've accustomed to this style since it also works in many other languages deriving syntax from C/C++. And if your organization/project has a code convention, follow its recommendations.
laalto
It's not an "optimization", nor less readable. I'd argue that having two if clauses is actually far less readable, since you end up with more nested blocks than you actually need. The double ifs also open up a window for the infamous "2ifs1else" bug: "if (a) if (b) print("a and b"); else print("not a and b");
gustafc
+1  A: 

Always aspire for shorter code, given that both are functionaly equivalent. Especially in case like this where readability is not sacrificed.

Dev er dev
+1  A: 

There are certain situations where the concise approach feels wrong to start with but effectively becomes idiomatic. This is one of them; the other is something like:

String line;
while ((line = bufferedReader.readLine()) != null) {
  // Use line
}

Side effects in a condition? Unthinkable! Except it's basically nicer than the alternatives, when you recognise the particular pattern.

This pattern is similar - it's so common in Java that I'd expect any reasonably experienced developer to recognise it. The result is pleasantly concise. (Amusingly, I sometimes see C# code which uses the same idiom, unnecessarily - the equality operator works fine with strings in C#.)

Bottom line: use the first version, and become familiar with it.

Jon Skeet
A: 

It's a very good question. I usually use the not graceful:

if (object.getAttribute("someAttr") != null && object.getAttribute("someAttr").equals("true")) { // ....

(and I will not use it anymore)

alexmeia
Nice! What if getAttribute() actually have side effects? Sometimes you're running it once, sometimes you're running it twice.
Vincent Robert
I might wrote this in the "Common programming errors" question I've seen over here
victor hugo
Thanks for the comments. I knew it was no good, I am here to learn things like this one. One more question: what is the problem with this approach if getAttribute() is just a standard getter method - and so has no side-effects?
alexmeia
+1 I think some people don't read the text, just the code. @question in comment: It might have a side effect at a later time. Unlikely to cause too serious damage in getters, but possible. Could result in performance loss, for example, if it returns calculated data in the next version - especially if this code is everywhere.
soulmerge
thanks soulmerge, I understand the problem. I think stackoverflow is great for things like this one.
alexmeia