Sunday, November 4, 2012

Reduce the scope of local variable in Java

Old programing languages such as C,C++ force us to declare local variables at the head of the code block. Some programers used to continue the same with Java. But it is not a good practice though Java lets us declare local variable anywhere in the code.

The most easy way to reduce the scope of local variable is, declare local variables where it is first used. This will reduce the scope of local variables and also this will increase the code readability. If you declare your local variable at top of code block or method, by the time that variable is used, the code reader might not remember about the variable.

With this small post, I am going to give you an example which creates a bug in the application which is very hard to detect. We know that "Loops" have a special opportunity to minimize the scope of variables. The traditional for loop and new for-each loop allows you to declare loop variables limiting their scopes to the region where they are needed. 


If we use a 'while' loop, it depends on some variable which has more wider scope. Let's see some practical scenario which can happen frequently when using 'while' loops. 

Suppose, we have a method which has two "while" loops.

Iterator<Employee> i = c.iterator();
while (i.hasNext()) {
    doSomething(i.next());
}
...
Iterator<Employee> i2 = c2.iterator();
while (i.hasNext()) {
    // BUG!
    doSomethingElse(i2.next());
}

If you see carefully, the above code generate bug which is very hard to discover. Since we are using 'while' loops, we have declared two element variable "i" and "i2" which has more wider  scope.Those tow variable has more wider scope which out side the while loop as well. But we don't really need that scope.

It seems, the developer has cut and pasted the above code of first 'while' loop to second and he has left one thing unchanged copied from first while loop. Developer has declared "i2" new variable for the second "while" loop, but still using "i" in one place in the second loop mistakenly. Since "i" is still in valid scope, even compiler does not complain. 

The above code compiles and runs without throwing an exception, but it gives a wrong result. This bug may remain undetected for a long time.

If the similar cut and past was done in conjunction with "for" loops, the code would not even compile. You are more safe. Look at the following code.

for (Iterator<Employee> i = c.iterator(); i.hasNext(); ) {
    doSomething(i.next());
}
...
// Compile-time error - cannot find symbol i
for (Iterator<Employee> i2 = c2.iterator(); i.hasNext(); ) {
    doSomething(i2.next());
}
Same mistake has done even in the above code. But you are safe at this time. The scope of tow element variables,"i" and "i2" is limited only inside the "for" loop itself. If you use "for" loops, it reduces the likelihood of happening this kind bugs in your application. Also there is not incentive to use different element variables in two loops. You can use the same element variable in both loops.

As a conclusion of this small post, try to use reduce the scope of local variable as much as you can and declare your variable just before use it except any special scenario.

9 comments:

  1. Thanks for an insightful post. These comments are really helpful.. I found a lot of useful tips from this post

    ReplyDelete
  2. You made me laugh, thx a lot.

    Anyway, you missuse "for" loops. They should be use only if you got an init, a condition and a loop step instruction. Otherwise, use "while" (or do/while).

    Your problem here came from 2 things : you shouldn't copy/paste, and you should name your variables correctly. Solving these with "for" loops doesn't make any sense.

    ReplyDelete
    Replies
    1. Yes, Waddle. You are correct. We should not copy and past. But some are doing. I can not agree with your first statement. When iterating object collection, most appropriate approach is the for-each loop which makes us more safe and reduce mistakes that can happen.

      Delete
  3. waddle already pointed out 2 problems with your code. I don't agree with his statement that for" loops should always have all 3 parts though.

    Anyway, a 3rd problem with your code: don't use iterators as an illustration: they scream for for-each loops like:
    for(Employee i : c) { ... }
    (keeping your variable names for comparison, but as waddle said: awful practice)

    ReplyDelete
  4. That was 5 minutes of my life I will not get back. What a bunch of useless drivel. You obviously have no clue how to properly use either for or while loops.

    ReplyDelete
    Replies
    1. Exactly this is drivel snip of code, because it has a bug which is very hard to detect. Sorry about your 5 minutes. :)

      Delete
  5. Simple but nice post. Reduction of visibility will lead to lesser bugs!

    ReplyDelete

Share

Widgets