Musings in real time

Tags - Categories : All | Art | Books | Family | Java | JavaRanch | Linux | Philosophy

Some people laugh when they see my code, because I insist on the (supposedly old-fashioned and unnecessary) practice of using a "wart" to denote Java member variables. For example, I'll write

public class Person {
    private String m_name;
    private Date m_dob;
    ...

The laughers usually see this as a hangover from "Hungarian notation", in which the data type of a variable is encoded in its name. The merits of Hungarian notation have been debated endlessly, so I won't go into that here. Besides, my warts are not Hungarian: they're scope warts.

Scope warts prevent scoping errors; perhaps more precisely, they prevent accidental variable hiding. What's wrong with this code?

public class MyVector {
    private int size;
    private Object[] data;
    public int itemCount() { return size; }
    ...
    public void addAll(MyVector v) {
        ensureCapacity(itemCount() + v.itemCount());
        int size = v.itemCount();
        for (int i=0; i<size; ++i) {
            data[size++] =v.data[i];
        }
    }
}

Can you see it? That last line of code is incrementing the local variable "size", but it actually means to increment the member variable. Ooops. The loop will run until it gets an ArrayIndexOutOfBoundsException.

Scope warts would have prevented this. If we rename the member variable "m_size", then there'd be no name collision. Furthermore, collisions like this would never happen. A whole class of sometimes hard-to-find errors would be eliminated at the source.

Other people eschew the warts, but insist that all member variable accesses be made via the "this" reference. I don't like that, personally -- too much discipline. Scope warts require you to name variables a certain way, and then everything else takes care of itself. The "this" solution requires you to do some extra typing every time you access a member -- which is a lot of work. Anytime you ask people to do extra work, you're asking for trouble.

Why do I bring this up today? Because I just closed a bug report from a user. Seems a class I wrote in a moment of weakness -- perhaps just after someone had made fun of my warts -- didn't use scope warts, and contained a bug just like the one described here! So you see, this happens in real life. I'm going to stick with my warts; they've served me well.


Do you use an IDE? I know Eclipse (and WSAD) will give you warnings about variable hiding in cases like the above, and I'm guessing IDEA would too.
I use both Eclipse and IDEA on various projects; I think IDEA says something about this when you run their "Code Inspection", but not during the normal process of coding. I'll have to pay attention and see how Eclipse tells you about this; thanks for the tip!
While your story has a happy ending (bug fixed, user satisfied), I'm not sure I draw the same moral from it as you did. Before submitting the bug report, I read that code knowing something bad was happening to size. If I took the broken code and globally replaced size with m_size, it would still be valid java and I still might not notice that you had declared an m_ variable inside of a function. Turning on more of the compiler's warnings would have spotted this automatically. Adding the coding convention might have let you catch it manually. I won't argue against your using the prefixes in addition to the compiler switch, but the prefix alone will never be as effective as the compiler switch alone.

Yes, the warning would have been handy -- I've got that warning turned on in my IDE now! You're right that adding the wart to fix the bug after the fact doesn't work, but always using warts on members would have prevented it from ever happening in the first place. Only when I deviated from this policy did the bug arise.

The current version of Eclipse even allows to syntax highlight fields differently from local variables.

Of course all this becomes nonrelevant once you start to test-drive your code - you'll get a failing unit test in a matter of seconds when you introduce a scoping error.

m_variablename is an ugly construct makes code harder to read. While it might help prevent a possible scope error, it is easy to prevent them anyway without that hideous notation. It is just like the c convention of shortening a long variable name to something that is hard to decifer.


Add a comment

Title
Body
HTML : b, i, blockquote, br, p, pre, a href="", ul, ol, li
Math Quiz 2 + 6 = (Helps stop blog spam)
Name
E-mail address
Website
Remember me Yes  No 

E-mail addresses are not publicly displayed, so please only leave your e-mail address if you would like to be notified when new comments are added to this blog entry (you can opt-out later).

TrackBack to http://radio.javaranch.com/ejfried/addTrackBack.action?entry=1122774070608