Unless stated otherwise, code examples are in C.
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.
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 ; /* Static Double Array */ extern int * eipComeOn; /* Extern Int Pointer */
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) */
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?
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.
suName: what is
su? Is it a
sound or an
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.
It also depends on the language.
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.
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.
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 */
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.