Hungarian probation

Sylvain Saubier (http://SystemicResponse.com)

Sept 02, 2014

Unless stated otherwise, code examples are in C.

Hungarian notation

Hungarian notation is the embedding of information about a variable in its very name.
There are 2 cases: Systems Hungarian notation and Apps Hungarian notation.

Systems Hungarian

Here, the information is the data type of the variable.
Hence, it leads to a syntax like:

const unsigned char cucRead;    /* Const Unsigned Char */
static double sda_coords [2];   /* Static Double Array */
extern int * eipComeOn;         /* Extern Int Pointer */

Apps Hungarian notation

Here, the information is the logical type of the variable, which always depends on the context.
Hence, it leads to a syntax like:

float dY;                       /* Difference between 2 points 
                                   on the Y axis */
static char b_switch;           /* single Byte (which is equivalent to 
                                   a char (8 bit size) in C) */

Flaws

Compiler

The compiler is not your enemy, nor it is your school master.
The compiler is your very colleague.

While you shouldn’t campaign against it, getting a little help from its warnings is a clever way of using its binary intelligence.

Using Systems Hungarian notation means trying to be the compiler and the language itself.
The machine handles way more data than you possibly (consciously, at least) can. Attempting to be the machine will only lead to chaos.
What is the point of trying to mimick something you can’t comprehend?

Mind bending

Using Apps Hungarian notation is pretty different from using Systems Hungarian notation.
Here, we don’t try to “write” the compiler, we try to “write” our mind, at a precise moment in the programming process.

Unfortunately, while we could easily find a “standard” way of handling Systems Hungarian notation prefixes (a for array, s for static, f for float, etc… ), we can’t say the same for Apps Hungarian notation.

For example: suName: what is su? Is it a sum, an unused sound or an unsafe string?

Apps Hungarian notation is not universal.

While not impossible to read, your own code will, with both notations, require more brain power for immediate understanding.

High-level programming

It also depends on the language.

In Python:

s_name = "Simon"  

is clearly pointless, and can even be harmful, because the language tells you that a variable type is irrelevant in Python as it can be changed anywhere in the program. Indeed, if:

s_name = strlen(s_name)  

happens in your code, the whole Hungarian notation is harmful to its proper comprehension.
It may not happen if you are careful, but the thing is, the language does allow it.

Avoiding replacement

To those understanding struggles adds up a purely functional one: renaming.
Renaming and replacement of variable need to be as scarce as possible while still being able to appreciate an optimal and fast understanding of your own code.

The case for abstract data types

Often, “default” types can be strictly checked by the compiler. Abstract types, however, often can’t. That’s why Hungarian notation can be relevant in this case.

/* variables of an abstract type representing a dog... */
struct dog dog_brutus;      /* ... whose name is Brutus */
struct dog dog_rocky;       /* ... whose name is Rocky */

/* variables of an abstract type representing a cat... */
struct cat cat_mary;        /* ... whose name is Mary */
struct cat cat_cannelle;    /* ... whose name is Cannelle */

A good compromise: focus on the nature

The programmer is much more likely to change the value or the precision of a variable rather than its nature or its scope.
That is why, in this context, the Hungarian notation comes in handy:

F_PrintMOTD ()      /* function printing a message */  
g_countInMinutes    /* global variable, timer in minute */  
l_countLines        /* local variable, count of lines in a file or sthg */  
countLines          /* local variable, count of lines in a file or sthg */  

What is also less likely than changing it’s nature or scope is changing its data structure nature, its type nature.
You might need a float to become an int but you are less likely to want it to become a string or a structure.
Hence, we can optimize such a notation by writing:

F_PrintMOTD ()      /* global function, prints a message */  
gn_countInMinutes   /* global number */  
mind                /* local abstract type (struct mind) */  
s_name              /* local string (char *) */  
n_index             /* local number (int) */  
n_ratio             /* local number (float) */  
n_sheepCount        /* local number (unsigned short) */  

This should be our notation’s final form.