Hungarian Notation is a naming convention in which the type and/or scope of a variable is used as a naming prefix for that variable. For example:
int value; // non-Hungarian
int nValue; // the n prefix denotes an integer
double width; // non-Hungarian
double dWidth; // the d prefix denotes a double
Hungarian Notation was invented in 1972 by Charles Simonyi, a Microsoft programmer. The original idea of Hungarian Notation was to encode information about the variable’s purpose, which is known as Apps Hungarian. Over time, this focus changed to encoding information about the variable’s type and/or scope, which is known as Systems Hungarian.
There is a lot of controversy over whether Hungarian Notation is useful in modern programming languages and with modern IDEs. We believe the advantages still outweigh the disadvantages, though you will find plenty of programmers who disagree.
One advantage of Hungarian Notation is that the variable type can be determined from it’s name. Many argue that this is an obsolete advantage, because most modern IDEs will tell you a variables type if you mouse-hover over the name. However, consider the following snippet:
float applesPerPerson = totalApples / totalPersons;
Casually browsing the code, this statement would probably not attract notice. But there is a good chance it’s wrong. If totalApples and totalPersons are both integers, the compiler will evaluatetotalApples / totalPersons using integer division, causing any fractions to be lost before the value is assigned to applesPerPerson. Thus, if totalApples = 5, and totalPersons = 3, applesPerPerson will be assigned 1 instead of the expected 1.66!
However, if we use Hungarian Notation variable names:
float fApplesPerPerson = nTotalApples / nTotalPersons;
The n prefixes make it clear from just browsing the code that this is an integer division that’s going to cause us problems! Furthermore, as you code, the n prefix will remind you to watch out for integer division and overflow issues every time you use an integer variable in an expression or statement.
Another advantage of Hungarian Notation is that it gives us a way to name variables using shorthand. For example, bError is understood to mean isError, and nApples is a shorthand way of writing numberOfApples.
One perceived disadvantage of Hungarian Notation is that it leads to extra work when a variable’s type changes. For example, it is common to declare an integer variable and then later change it to a double variable because you need to deal with fractional values. Without using Hungarian Notation, you could change int value to double value and go on your merry way. However, in Hungarian Notation, you’d not only have to change the declaration int nValue to double dValue, you’d have to change every use of nValue in your entire program to dValue! If you do not, your naming scheme will be misleading and inconsistent.
While replacing a potentially huge number of variable names is certainly a nuisance, we believe it is also a good thing. Because different types have different behaviors, having to explicitly replace your variable names encourages you to examine your code to ensure you’re not doing anything dangerous with the new type.
For example, without Hungarian Notation, you might have written
if (value == 0)
// do something
When value is changed from an int to a double, your safe integer comparison is now an unsafe floating point comparison that may produce unexpected results! In the best case, this error shows up when testing your program, and you have to spend time debugging it. In the worst case, the bug ships out and you end up with millions of customers have software that doesn’t work right!
However, if you’d used Hungarian Notation and written:
if (nValue == 0)
// do something
And were forced to change it to:
if (dValue == 0.0)
// do something
Hopefully at this point you’d say, “Hey, wait a second, I shouldn’t be doing naked comparisons with floating point values!”. Then you could modify it to something more appropriate and move on. In the long run, this can actually save you lots of time.
A real disadvantage of traditional Hungarian Notation is that the number of prefixes for compound types can become confusing. Wikipedia provides an appropriate example: “a_crszkvc30LastNameCol : a constant reference function argument, holding contents of a database column of type varchar(30) called LastName that was part of the table’s primary key”. a_crszkvc is non-trivial to decipher, and makes your code less clear.
As an aside, Hungarian Notation got it’s name from prefixes such as a_crszkvc that look like they’re written in Hungarian!
Caste Hungarian
Different programmers and/or companies tend to use different varieties of Systems Hungarian of varying complexity. Although most of them have some commonality (like using a d prefix for double, and an n(or i) prefix for integers), there is a lot of variation as to which types get what prefixes, and how those prefixes should combine.
We believe that using a different prefix for each data type is overkill, especially in the case of structs and classes, which can be user defined to a high degree. Furthermore, long Hungarian looking prefixes obscure code clarity more than they help it. Consequently we advocate a simplified version of Systems Hungarian called “Caste Hungarian”. In Caste Hungarian, Hungarian Notation is used mostly to denote which “caste” of data type a variable falls into (integers, floating points, classes, etc…).
Variable prefixes are composed of 3 parts: a scope modifier, a type modifier, and a type prefix (in that order). Scope modifier and type modifier may not apply. Consequently, the overall prefix length is kept reasonable, with the average prefix length being around 2 letters. This system conveys most of the advantages of Hungarian Notation without many of it’s disadvantages, and it keeps the entire system simple and easy to use.