Reflections on Hungarian notation

Coding style is very sensitive subject. The war on Hungarian notation, for instance, has been going on for ages and is still very much alive.

A few days ago I stumbled upon Herb Sutter’s latest remarks on his personal preference and some of the comments to his post sparked my interest. For instance, I find the following statement particularly bad:

“The compiler or IDE knows the type of the variable, so why do you need to prefix it?”

The answer is readability. I think John hit it spot on in his comment to Herb’s post:

“Variable names are for the code reader, not just the compiler. … Most people read code more often than they write it. The IDE is not always available (and it’s certainly not quick, if we’re talking about Visual Studio). The variable declaration is often far away from its usage. Having the type embedded in the name saves people from having to dig around for the declaration.”.

Personally, I don’t prefix variables with type information such as dw or ul since I don’t believe it makes the code any clearer. I’m more interested in how the variable is used. For instance, I use p to denote pointer types since the semantics are clearly different from using an integral type, as illustrated below:
“if (foo == 0)” and “if (pFoo == 0)”

One of my biggest pet peeves is member variables. Here at work, people have very different ideas on how member variables should be identified. Some just write them like they do local variables, others capitalize the first letter, and yet others prefix the variables with an underscore or m_. I prefer the latter simply because it improves readability. It enables me to quickly get an overview of a piece of code and the scope of its variables without having to use any features of the IDE.

To demonstrate to our coworkers the usefulness of showing the scope of their variables by augmenting the variable name, a friend and I compiled a list with three different scenarios:

  • If intelligent syntax highlighting isn’t available, you cannot figure out whether you’re assigning a value to a local or a member variable just by looking at the code. Instead, you have to manually search through the function or rely on the IDE (e.g. by hovering the cursor over the variable name)
  • Local and member variable name clashing:
    void SomeClass::SomeFunc()
    {
        // Define a local variable
        int foo = ...;
    
        // Assign the local variable to a member variable
        // We have to use the 'this' keyword since the two variables are named identically
        this->foo = foo;
    }
  • Prefixing member variables makes auto-suggestion tools like IntelliSense and Visual Assist more accurate. For instance, typing ‘m_’ would cause the IDE to suggest only member variables, whereas typing the variable name would bring up local, global, and member variables in the suggestion box. (I know this point sort of contradicts the first scenario since it relies on the IDE, but I think it’s important to highlight how prefixing can also increase the usefulness of such tools.)

Before concluding this post, I think it’s also worth commenting on some peoples’ habits of embedding type information in variables. As I said before, I don’t personally do it, but not because I think it creates a huge maintainability issue. Changing the type of a variable (e.g. from int to float) changes the contract between the variable and the code, and the programmer is forced to go through every single location that uses it to make sure the code still behaves correctly. Not too bad, in my opinion…

These viewpoints are, of course, completely my own, and I’m sure a lot of people disagree with me. If you’re one of those, I’d love to hear your sentiments about why you think I’m wrong.


About this entry