Why shouldn't I use "Hungarian Notation"?
Asked Answered
G

37

122

I know what Hungarian refers to - giving information about a variable, parameter, or type as a prefix to its name. Everyone seems to be rabidly against it, even though in some cases it seems to be a good idea. If I feel that useful information is being imparted, why shouldn't I put it right there where it's available?

See also: Do people use the Hungarian naming conventions in the real world?

Gastroenteritis answered 21/9, 2008 at 20:9 Comment(1)
Related: stackoverflow.com/questions/202107/…Uralaltaic
C
174

Most people use Hungarian notation in a wrong way and are getting wrong results.

Read this excellent article by Joel Spolsky: Making Wrong Code Look Wrong.

In short, Hungarian Notation where you prefix your variable names with their type (string) (Systems Hungarian) is bad because it's useless.

Hungarian Notation as it was intended by its author where you prefix the variable name with its kind (using Joel's example: safe string or unsafe string), so called Apps Hungarian has its uses and is still valuable.

Cowen answered 21/9, 2008 at 20:9 Comment(13)
Good link, a good summary of what's behind the link, and no fanaticism. Excellent.Hornbeck
Note that Joels example is in VBScript, a language that long didn't have user-defined classes. In a OO-language you would just create a HtmlEncodedString-type and have the Write method accept only that. "Apps hungarian" are only useful in languages without user-defined types.Westsouthwest
True, and a very good point, but it works much better is languages where String isn't sealed/finalized. In such languages, you'd lose type-compatibility with "real" Strings.Hornbeck
Microsoft is known for its past misuse of Hungarian notation. Prepending type information to identifiers is not only useless but it may actually do harm. First, readability is less fluent. Second, in languages that support polymorphism or duck-typing the wrong information is passed.Nuclear
I still like using Hungarian notation if I'm doing straight C development with an older IDE ... that way I know there's no type casting issues.Fraction
@JacquesB: Question is whether you would you do that for every possible type you ever need?Ubangi
Prefixing with a type can be useful in the exact way that Joel is describing. Does the code GetUserByUsername(lblUsername.Text) strike you as a bug? Fanaticism can go both ways.Selfdiscipline
The next time you're writing some code that mixes unsigned and signed integers, you will be glad that you encoded that information into the Hungarian prefix. The compiler will automatically handle casts, and unless your warnings are turned all the way up, you'll have no idea that it's not doing what you wanted it to do.Linalool
I used the 'wrong' Hungarian notation for years and it never appeared cluttered, unreadable or confusing at all. Perhaps it's just what I 'grew up with' so it made perfect sense. I stopped using it a few years ago. Now I'm learning JavaScript and using the 'wrong' Hungarian notation seems quite apt given its nature of not having true types. So for example, a property of nBlades is a number while fSuccess is a function callback if the ajax call returns successfully. A drawback would be if you deliberately change the type of a variable during runtime - then it would simply be confusing.Lambency
@JacquesB: "Apps hungarian" are only useful in languages without user-defined types. I disagree. For example, think of a C#/Java application that works with lengths, weights and densities. All are numbers. But wouldn't it be great to architect your coding convention to identify these? That would certainly prevent adding a length to a density, wouldn't it?Skaggs
@Krumia: This would typically be prevented by having descriptive variable names in the first place. But if you want to be sure, it would be much safer to create distinct types (eg. structs) for lengths, weights etc. and use operator overloading to ensure that only valid operations are possible.Westsouthwest
@JacquesB: Wrappers around int? Not always nice :) Well I'm not saying HN should be there for everything. But the example I gave is a good case. Also, thinking up descriptive variables names is no easy task. How many hours will be wasted thinking up names? It's better to have a Hungarian-like naming convention in situations like this. Then again, HN never fits everywhere.Skaggs
@Krumia: It is absolutely not a waste of time to think up descriptive names for variables! If you cant think of a descriptive name for variable, it is probably because you are not clear on the purpose of the variable. HN or not will not help you there.Westsouthwest
P
276

vUsing adjHungarian nnotation vmakes nreading ncode adjdifficult.

Preston answered 21/9, 2008 at 20:9 Comment(11)
Nice analogy, although slightly unfair. Compare: vUsing adjHungarian nNotation vMakes nReading nCode adjDifficult.Reckford
In that sentence, both Using and Reading are gerunds. But I get the point you were making...Kitsch
@chimp: that makes things even more obvious. now that you've found a mistake in the type are you going to rename all the references or leave them as they are, providing misinformation? you lose either way. but of course, this is the WRONG way of applying Hungarian notation.Nuclear
@Chris Noe: for certain reading styles (parse the prefix and the suffix with a glance at the middle), your example only makes things worse. I see "vUsing" and hear "voosing" in my head.Misesteem
The analogy falls down because no information is added, you already know if a word is a noun. But if I have a variable called "count", is it an integer or a string (eg to display to a user)?Affix
@Jon: if you have a variable name that does not fully give away what it is representing, then by absolutely all means the focus should be to rename it to something more descriptive (and Hungarian notation is not an improvement, in the very, very best case it is fixing the symptom - not solving the problem).Kant
@Jon: I would have my type system help me out and enforce correct use of the int or string variable. No Hungarian needed to keep my use safe. Hurray for statically typed languages!Grillwork
@ThomasEding, variable names are not for the compiler, they're for the programmer :) Types aren't always immediately accessible if you're not viewing code from an IDE.Affix
@Kitsch Of course a gerund is just a subclass of verb which implements the noun interface.Topgallant
Well, it is bad when in a normal sentence like your example, but code is not normal sentences and we read it (and type it) as not normal sentences. Having a prefix in vars is fine, we're used to reading code-like text, especially when using camelCase. $strUserName $intBankSortCode. I use underscore with camelCase - $str_UserName - $ary_TeamNames. You could look at my code and immediately know what type a variable is, and also what it's likely is doing and how you can use it by the descriptive name. It is a balance between readability, functionality, and usability, etc.Vishinsky
This is a very bad example. Natural Languages != Programming Languages.Skaggs
C
174

Most people use Hungarian notation in a wrong way and are getting wrong results.

Read this excellent article by Joel Spolsky: Making Wrong Code Look Wrong.

In short, Hungarian Notation where you prefix your variable names with their type (string) (Systems Hungarian) is bad because it's useless.

Hungarian Notation as it was intended by its author where you prefix the variable name with its kind (using Joel's example: safe string or unsafe string), so called Apps Hungarian has its uses and is still valuable.

Cowen answered 21/9, 2008 at 20:9 Comment(13)
Good link, a good summary of what's behind the link, and no fanaticism. Excellent.Hornbeck
Note that Joels example is in VBScript, a language that long didn't have user-defined classes. In a OO-language you would just create a HtmlEncodedString-type and have the Write method accept only that. "Apps hungarian" are only useful in languages without user-defined types.Westsouthwest
True, and a very good point, but it works much better is languages where String isn't sealed/finalized. In such languages, you'd lose type-compatibility with "real" Strings.Hornbeck
Microsoft is known for its past misuse of Hungarian notation. Prepending type information to identifiers is not only useless but it may actually do harm. First, readability is less fluent. Second, in languages that support polymorphism or duck-typing the wrong information is passed.Nuclear
I still like using Hungarian notation if I'm doing straight C development with an older IDE ... that way I know there's no type casting issues.Fraction
@JacquesB: Question is whether you would you do that for every possible type you ever need?Ubangi
Prefixing with a type can be useful in the exact way that Joel is describing. Does the code GetUserByUsername(lblUsername.Text) strike you as a bug? Fanaticism can go both ways.Selfdiscipline
The next time you're writing some code that mixes unsigned and signed integers, you will be glad that you encoded that information into the Hungarian prefix. The compiler will automatically handle casts, and unless your warnings are turned all the way up, you'll have no idea that it's not doing what you wanted it to do.Linalool
I used the 'wrong' Hungarian notation for years and it never appeared cluttered, unreadable or confusing at all. Perhaps it's just what I 'grew up with' so it made perfect sense. I stopped using it a few years ago. Now I'm learning JavaScript and using the 'wrong' Hungarian notation seems quite apt given its nature of not having true types. So for example, a property of nBlades is a number while fSuccess is a function callback if the ajax call returns successfully. A drawback would be if you deliberately change the type of a variable during runtime - then it would simply be confusing.Lambency
@JacquesB: "Apps hungarian" are only useful in languages without user-defined types. I disagree. For example, think of a C#/Java application that works with lengths, weights and densities. All are numbers. But wouldn't it be great to architect your coding convention to identify these? That would certainly prevent adding a length to a density, wouldn't it?Skaggs
@Krumia: This would typically be prevented by having descriptive variable names in the first place. But if you want to be sure, it would be much safer to create distinct types (eg. structs) for lengths, weights etc. and use operator overloading to ensure that only valid operations are possible.Westsouthwest
@JacquesB: Wrappers around int? Not always nice :) Well I'm not saying HN should be there for everything. But the example I gave is a good case. Also, thinking up descriptive variables names is no easy task. How many hours will be wasted thinking up names? It's better to have a Hungarian-like naming convention in situations like this. Then again, HN never fits everywhere.Skaggs
@Krumia: It is absolutely not a waste of time to think up descriptive names for variables! If you cant think of a descriptive name for variable, it is probably because you are not clear on the purpose of the variable. HN or not will not help you there.Westsouthwest
B
104

Joel is wrong, and here is why.

That "application" information he's talking about should be encoded in the type system. You should not depend on flipping variable names to make sure you don't pass unsafe data to functions requiring safe data. You should make it a type error, so that it is impossible to do so. Any unsafe data should have a type that is marked unsafe, so that it simply cannot be passed to a safe function. To convert from unsafe to safe should require processing with some kind of a sanitize function.

A lot of the things that Joel talks of as "kinds" are not kinds; they are, in fact, types.

What most languages lack, however, is a type system that's expressive enough to enforce these kind of distinctions. For example, if C had a kind of "strong typedef" (where the typedef name had all the operations of the base type, but was not convertible to it) then a lot of these problems would go away. For example, if you could say, strong typedef std::string unsafe_string; to introduce a new type unsafe_string that could not be converted to a std::string (and so could participate in overload resolution etc. etc.) then we would not need silly prefixes.

So, the central claim that Hungarian is for things that are not types is wrong. It's being used for type information. Richer type information than the traditional C type information, certainly; it's type information that encodes some kind of semantic detail to indicate the purpose of the objects. But it's still type information, and the proper solution has always been to encode it into the type system. Encoding it into the type system is far and away the best way to obtain proper validation and enforcement of the rules. Variables names simply do not cut the mustard.

In other words, the aim should not be "make wrong code look wrong to the developer". It should be "make wrong code look wrong to the compiler".

Beaut answered 21/9, 2008 at 20:9 Comment(20)
You are so wrong. What you are talking about is Petzold's mistaking interpretation of Simonyi's original idea! It's not type, as in int or long or char, etc. It's in the intent of the variable itself. Read Joel's paper to understand the different.Trumpery
The intent of the variable should be encoded within the type of the variable, not left to something so fragile as a frigging naming scheme.Beaut
I would love to make it the compiler/interpreter's job also, but that would incur a huge overhead for dynamic languages (Python, Ruby, PHP or Javascript).Maze
In general, I agree wholeheartedly; in the context of this post I couldn't disagree more.Theotheobald
@Beaut - I think you make a very interesting point, and I certainly agree with writing your code in such a way as to make the compiler do as much checking as possible.Appetency
"What most languages lack, however, is a type system that's expressive enough to enforce these kind of distinctions" And there lies the problem. AppsHungarian is a pragmatic method to highlight problems when using these languages in an obvious ways to programmers viewing the code, rather than examining the bug reports.Autoroute
It would be wonderful if the File functions would not accept unsafe strings but the most-widely used environments Java and C# do not function this way so we're stuck. I suppose you could create your own layer for file access which only accepts SafeString but that would be a lot of work and tricky to enforce. Also, how do you determine what is a safe string? This definition varies a lot in different apps. The developer would have to implement this themselves and I can see most developers just making it allow anything. Still, a neat concept.Humbertohumble
@DrPizza: I believe you have missed one of the very important points that Joel is making while advocating Apps Hungarian: this notation is just a very pragmatic tradeoff. Making the compiler capable to see "wrong code" is a great goal, but is it always worth its cost?Aeneid
He has missed much more, like, whole article.Ubangi
Good use of type system aside, is there still not an argument that such use can simply benefit readability, regardless? Immediately getting a handle on what the variable does. Spolsky goes on to use this argument to support the detection of errors - yes perhaps the type system is a better tool for this. But that’s not to fall short and perhaps miss out opportunities for readability (with considered use).Gaal
+3 for the last paragraph. I could not have said your whole post better than you have. The only purpose of using HN would be in languages that cannot use the type system to express your concerns. Good thing a language like Haskell makes this trivial <3Grillwork
@DrPizza, So if we need to store "customer names" and "admin names", do you suggest that we create a StrCustName and StrAdmName type just for that, instead of using apps hungarian's String custName and String admName?Marcosmarcotte
@Marcosmarcotte - how about you just name your variables properly?Unnecessarily
@Davor, DrPizza's argument is that we should let the compiler enforce it via the type system. No matter how "properly" we name the variables, it still wouldn't be enforced by the type system.Marcosmarcotte
@Marcosmarcotte - sure it would. The type is string, and it will be enforced. If you want types to be AdminName and CustomerName, you obviously have to make those types.Unnecessarily
@Davor, And that's exactly why I'm posing that question to DrPizza.Marcosmarcotte
@DrPizza: Joel is wrong, and What most languages lack, however, is a type system that's expressive enough to enforce these kind of distinctions. So, since most languages do lack the expressiveness enough to enforce these kind of distinctions, Joel is right. Right?Skaggs
+100, couldn't agree more! Rust has a very strong type system and eliminates a lot of unsafe code. @Krumia Then ditch that language. A strongly typed language such as C++14 or Rust is always preferable.Ocrea
@Centril: Say you are coding an engineering application that involves lengths, volumes, and densities. How do you distinguish between lengths, volumes and densities if they are all ints? Would not you rather lxTank, lyTank, lzTank, vTank, dTank (where l = length, v = volume, d = density, xyz = dimension) than tankWidth, tankHeight, tankLength, tankVolume, tankDesity? I might miss that I accidentally did this: tankHeight + tankVolume. But I would not miss lyTank + vTankSkaggs
@Krumia I would use a language that lets you do zero cost abstractions and declare unit types that can't be mixed, such as C++ (watch: youtube.com/watch?v=0iWb_qi2-uI ca 20 minutes in) or rust: web.archive.org/web/20150315005317/http://rustbyexample.com/… In rust, a struct Density(f32) cant be mixed with a struct Volume(f32). With some meta programming and operator overloading, you can add all math operations you need. You could easily make a mistake and mix up lxTank + dTank. With compile time checked types you can not make a mistake, the compiler wont let you.Ocrea
H
46

I think it massively clutters up the source code.

It also doesn't gain you much in a strongly typed language. If you do any form of type mismatch tomfoolery, the compiler will tell you about it.

Harmonicon answered 21/9, 2008 at 20:9 Comment(6)
Wow. 90 rep in 15 minutes. Good call.Hornbeck
If you use it for type, then yes, it's useless. It's useful to impart other information.Foscalina
@Lou, exactly - personally, i store a revision history in my variable names: string firstName_wasName_wasNameID_wasSweetCupinCakesGastroenteritis
@nsanders: Try using compiler to check whether you used the same units of measure when both variable types are integer.Ubangi
@Shog9: I think you did not understand the Apps Hungarian Notation. It's more about sFirstName vs unFirstName (safe vs unsafe, unsanitized), this way you know something more about it. Still I think in static languages it's better to subtype String to make UnsafeString and SafeString and only allow SafeString to output. Convention is ok, but (more often) compilation enforcements are better.Curtsey
@Gastroenteritis that's even worse. That way lies madness. That is why we have source controlSwagman
W
28

Hungarian notation only makes sense in languages without user-defined types. In a modern functional or OO-language, you would encode information about the "kind" of value into the datatype or class rather than into the variable name.

Several answers reference Joels article. Note however that his example is in VBScript, which didn't support user-defined classes (for a long time at least). In a language with user-defined types you would solve the same problem by creating a HtmlEncodedString-type and then let the Write method accept only that. In a statically typed language, the compiler will catch any encoding-errors, in a dynamically typed you would get a runtime exception - but in any case you are protected against writing unencoded strings. Hungarian notations just turns the programmer into a human type-checker, with is the kind of job that is typically better handled by software.

Joel distinguishes between "systems hungarian" and "apps hungarian", where "systems hungarian" encodes the built-in types like int, float and so on, and "apps hungarian" encodes "kinds", which is higher-level meta-info about variable beyound the machine type, In a OO or modern functional language you can create user-defined types, so there is no distinction between type and "kind" in this sense - both can be represented by the type system - and "apps" hungarian is just as redundant as "systems" hungarian.

So to answer your question: Systems hungarian would only be useful in a unsafe, weakly typed language where e.g. assigning a float value to an int variable will crash the system. Hungarian notation was specifically invented in the sixties for use in BCPL, a pretty low-level language which didn't do any type checking at all. I dont think any language in general use today have this problem, but the notation lived on as a kind of cargo cult programming.

Apps hungarian will make sense if you are working with a language without user defined types, like legacy VBScript or early versions of VB. Perhaps also early versions of Perl and PHP. Again, using it in a modern languge is pure cargo cult.

In any other language, hungarian is just ugly, redundant and fragile. It repeats information already known from the type system, and you should not repeat yourself. Use a descriptive name for the variable that describes the intent of this specific instance of the type. Use the type system to encode invariants and meta info about "kinds" or "classes" of variables - ie. types.

The general point of Joels article - to have wrong code look wrong - is a very good principle. However an even better protection against bugs is to - when at all possible - have wrong code to be detected automatically by the compiler.

Westsouthwest answered 21/9, 2008 at 20:9 Comment(1)
Languages with user-defined types do not make it always practical to use types instead of "kinds". Consider prefixes "c", "d", "ix" from Joel's Apps Hungarian. Do you use custom integer types for those, in every modern languages? I don't think so. Because modern languages still do not have builtin custom integer types for indices, counts, and differences between two numbers. As long as we are still using vanilla ints, Apps Hungarian will be non-redundant and useful.Weltanschauung
F
27

I always use Hungarian notation for all my projects. I find it really helpful when I'm dealing with 100s of different identifier names.

For example, when I call a function requiring a string I can type 's' and hit control-space and my IDE will show me exactly the variable names prefixed with 's' .

Another advantage, when I prefix u for unsigned and i for signed ints, I immediately see where I am mixing signed and unsigned in potentially dangerous ways.

I cannot remember the number of times when in a huge 75000 line codebase, bugs were caused (by me and others too) due to naming local variables the same as existing member variables of that class. Since then, I always prefix members with 'm_'

Its a question of taste and experience. Don't knock it until you've tried it.

Fathom answered 21/9, 2008 at 20:9 Comment(9)
Encoding signedness into variable names is great when the piece of code is actually dealing with signedness. Using that as an excuse to enforce the convention for all variables is just domatism IMHO.Conchology
You have a good point with member variables, though. But in languages like Python where you are forced to qualify members with the self/this object it's moot.Conchology
It's just a trick to help productivity. Just like IDE autocomplete. There is nothing fundamentally evil about it. I believe that experienced coders must be allowed to use their own style. Forcing anyone to choose a certain style is bad. I work as as a single developer now, but I would not enforce a style on anyone I worked with unless they lacked a consistent style in the first place.Fathom
So, you're using the a naming convention to filter the variables, huh? I must agree that it is kinda clever. :-) However, the way I'm wired, the anchor point (or filter criterion, if you like) is always the semantics for me. Rarely the type (unless it is the semantic). I hope that made sense. TL;DR:I'd still stick to naming variables according to what they represent than how they're represented.Conchology
I upvoted this back then since I was in favour of Hungarian. Now I regret it, and would never go back to prefixing something to a variable..Anastaciaanastas
If you have 75000 lines of code that can access the same set of member variables, you have an entirely different problem.Topgallant
That is beside the point. Every 75000 line code base has issues. Programming is not a science. As long as something lets you avoid errors it's good practice. By errors, I mean that the logic is correct but the program is wrong because of something like a local variable shadowing a member variable or when you are mixing signed and unsigned types.Fathom
75,000 line code base, and nobody turned on the warning flag to check for shadowed variables?Iffy
No... this was VC 98, I am not sure if that warning even existed.Fathom
O
22

You're forgetting the number one reason to include this information. It has nothing to do with you, the programmer. It has everything to do with the person coming down the road 2 or 3 years after you leave the company who has to read that stuff.

Yes, an IDE will quickly identify types for you. However, when you're reading through some long batches of 'business rules' code, it's nice to not have to pause on each variable to find out what type it is. When I see things like strUserID, intProduct or guiProductID, it makes for much easier 'ramp up' time.

I agree that MS went way too far with some of their naming conventions - I categorize that in the "too much of a good thing" pile.

Naming conventions are good things, provided you stick to them. I've gone through enough old code that had me constantly going back to look at the definitions for so many similarly-named variables that I push "camel casing" (as it was called at a previous job). Right now I'm on a job that has many thousand of lines of completely uncommented classic ASP code with VBScript and it's a nightmare trying to figure things out.

Oxidation answered 21/9, 2008 at 20:9 Comment(3)
As a VIM (no IDE, no highlighting, no hover-tell-you-what-type) user I don't understand this argument at all. I naturally comprehend that a variable called name is a string, and a variable called i or count is an int. Does one really need sName and iCount? How does it really help? I would argue that your product id example is a special case, and maybe there it would be fine. But even then, being consistent and representing product IDs with ints or strings everywhere would be a much better solution, no? The whole naming thing seems like a cop-out.Dogy
It's for consistency. Yes, "name" inherently implies a string. But what would you presume "userid" to be? A GUID? String? Integer? Even something like "acctno" could have a value of 42 or "23X". Documentation is sparse enough in most code. This standard helps the maintenance programmer along a bit.Oxidation
@Oxidation I absolutely agree with your answer - knowing at a glance the intent of the variable is the reason I prefer prefixing as well, more so in a dynamic language like JS.Yellowthroat
W
10

Tacking on cryptic characters at the beginning of each variable name is unnecessary and shows that the variable name by itself isn't descriptive enough. Most languages require the variable type at declaration anyway, so that information is already available.

There's also the situation where, during maintenance, a variable type needs to change. Example: if a variable declared as "uint_16 u16foo" needs to become a 64-bit unsigned, one of two things will happen:

  1. You'll go through and change each variable name (making sure not to hose any unrelated variables with the same name), or
  2. Just change the type and not change the name, which will only cause confusion.
Wheatworm answered 21/9, 2008 at 20:9 Comment(0)
D
9

Isn't scope more important than type these days, e.g.

* l for local
* a for argument
* m for member
* g for global
* etc

With modern techniques of refactoring old code, search and replace of a symbol because you changed its type is tedious, the compiler will catch type changes, but often will not catch incorrect use of scope, sensible naming conventions help here.

Despondency answered 21/9, 2008 at 20:9 Comment(1)
Then again, the code probably shouldn't be depending on scope so much. :-)Conchology
B
9

Joel Spolsky wrote a good blog post about this. http://www.joelonsoftware.com/articles/Wrong.html Basically it comes down to not making your code harder to read when a decent IDE will tell you want type the variable is if you can't remember. Also, if you make your code compartmentalized enough, you don't have to remember what a variable was declared as three pages up.

Banal answered 21/9, 2008 at 20:9 Comment(0)
A
8

There is no reason why you should not make correct use of Hungarian notation. It's unpopularity is due to a long-running back-lash against the mis-use of Hungarian notation, especially in the Windows APIs.

In the bad-old days, before anything resembling an IDE existed for DOS (odds are you didn't have enough free memory to run the compiler under Windows, so your development was done in DOS), you didn't get any help from hovering your mouse over a variable name. (Assuming you had a mouse.) What did you did have to deal with were event callback functions in which everything was passed to you as either a 16-bit int (WORD) or 32-bit int (LONG WORD). You then had to cast those parameter to the appropriate types for the given event type. In effect, much of the API was virtually type-less.

The result, an API with parameter names like these:

LRESULT CALLBACK WindowProc(HWND hwnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam);

Note that the names wParam and lParam, although pretty awful, aren't really any worse than naming them param1 and param2.

To make matters worse, Window 3.0/3.1 had two types of pointers, near and far. So, for example, the return value from memory management function LocalLock was a PVOID, but the return value from GlobalLock was an LPVOID (with the 'L' for long). That awful notation then got extended so that a long pointer string was prefixed lp, to distinguish it from a string that had simply been malloc'd.

It's no surprise that there was a backlash against this sort of thing.

Armoury answered 21/9, 2008 at 20:9 Comment(0)
G
6

As a Python programmer, Hungarian Notation falls apart pretty fast. In Python, I don't care if something is a string - I care if it can act like a string (i.e. if it has a ___str___() method which returns a string).

For example, let's say we have foo as an integer, 12

foo = 12

Hungarian notation tells us that we should call that iFoo or something, to denote it's an integer, so that later on, we know what it is. Except in Python, that doesn't work, or rather, it doesn't make sense. In Python, I decide what type I want when I use it. Do I want a string? well if I do something like this:

print "The current value of foo is %s" % foo

Note the %s - string. Foo isn't a string, but the % operator will call foo.___str___() and use the result (assuming it exists). foo is still an integer, but we treat it as a string if we want a string. If we want a float, then we treat it as a float. In dynamically typed languages like Python, Hungarian Notation is pointless, because it doesn't matter what type something is until you use it, and if you need a specific type, then just make sure to cast it to that type (e.g. float(foo)) when you use it.

Note that dynamic languages like PHP don't have this benefit - PHP tries to do 'the right thing' in the background based on an obscure set of rules that almost no one has memorized, which often results in catastrophic messes unexpectedly. In this case, some sort of naming mechanism, like $files_count or $file_name, can be handy.

In my view, Hungarian Notation is like leeches. Maybe in the past they were useful, or at least they seemed useful, but nowadays it's just a lot of extra typing for not a lot of benefit.

Garibold answered 21/9, 2008 at 20:9 Comment(2)
Interesting that your example with .str() in Python isn't a result of the language being dynamic. Java, definitely not a dynamic language, does the same thing.Hornbeck
C# also does the same thing, every class in the language implements .ToString() so that it all can be printedGamut
L
6

Hungarian Notation can be useful in languages without compile-time type checking, as it would allow developer to quickly remind herself of how the particular variable is used. It does nothing for performance or behavior. It is supposed to improve code readability and is mostly a matter a taste and coding style. For this very reason it is criticized by many developers -- not everybody has the same wiring in the brain.

For the compile-time type-checking languages it is mostly useless -- scrolling up a few lines should reveal the declaration and thus type. If you global variables or your code block spans for much more than one screen, you have grave design and reusability issues. Thus one of the criticisms is that Hungarian Notation allows developers to have bad design and easily get away with it. This is probably one of the reasons for hatered.

On the other hand, there can be cases where even compile-time type-checking languages would benefit from Hungarian Notation -- void pointers or HANDLE's in win32 API. These obfuscates the actual data type, and there might be a merit to use Hungarian Notation there. Yet, if one can know the type of data at build time, why not to use the appropriate data type.

In general, there are no hard reasons not to use Hungarian Notation. It is a matter of likes, policies, and coding style.

Latifundium answered 21/9, 2008 at 20:9 Comment(0)
M
5

Apps Hungarian is Greek to me--in a good way

As an engineer, not a programmer, I immediately took to Joel's article on the merits of Apps Hungarian: "Making Wrong Code Look Wrong". I like Apps Hungarian because it mimics how engineering, science, and mathematics represent equations and formulas using sub- and super-scripted symbols (like Greek letters, mathematical operators, etc.). Take a particular example of Newton's Law of Universal Gravity: first in standard mathematical notation, and then in Apps Hungarian pseudo-code:

Newton's Universal law of gravity for Earth and Mars

frcGravityEarthMars = G * massEarth * massMars / norm(posEarth - posMars)

In the mathematical notation, the most prominent symbols are those representing the kind of information stored in the variable: force, mass, position vector, etc. The subscripts play second fiddle to clarify: position of what? This is exactly what Apps Hungarian is doing; it's telling you the kind of thing stored in the variable first and then getting into specifics--about the closest code can get to mathematical notation.

Clearly strong typing can resolve the safe vs. unsafe string example from Joel's essay, but you wouldn't define separate types for position and velocity vectors; both are double arrays of size three and anything you're likely to do to one might apply to the other. Furthermore, it make perfect sense to concatenate position and velocity (to make a state vector) or take their dot product, but probably not to add them. How would typing allow the first two and prohibit the second, and how would such a system extend to every possible operation you might want to protect? Unless you were willing to encode all of math and physics in your typing system.

On top of all that, lots of engineering is done in weakly typed high-level languages like Matlab, or old ones like Fortran 77 or Ada.

So if you have a fancy language and IDE and Apps Hungarian doesn't help you then forget it--lots of folks apparently have. But for me, a worse than a novice programmer who is working in weakly or dynamically typed languages, I can write better code faster with Apps Hungarian than without.

Montero answered 21/9, 2008 at 20:9 Comment(0)
P
5

The IDE should impart that useful information. Hungarian might have made some sort (not a whole lot, but some sort) of sense when IDE's were much less advanced.

Pogue answered 21/9, 2008 at 20:9 Comment(1)
Then again, you shouldn't rely on the IDE telling you more. After all, code can viewed outside of the IDE...Descender
A
4

Debunking the benefits of Hungarian Notation

  • It provides a way of distinguishing variables.

If the type is all that distinguishes the one value from another, then it can only be for the conversion of one type to another. If you have the same value that is being converted between types, chances are you should be doing this in a function dedicated to conversion. (I have seen hungarianed VB6 leftovers use strings on all of their method parameters simply because they could not figure out how to deserialize a JSON object, or properly comprehend how to declare or use nullable types.) If you have two variables distinguished only by the Hungarian prefix, and they are not a conversion from one to the other, then you need to elaborate on your intention with them.

  • It makes the code more readable.

I have found that Hungarian notation makes people lazy with their variable names. They have something to distinguish it by, and they feel no need to elaborate to its purpose. This is what you will typically find in Hungarian notated code vs. modern: sSQL vs. groupSelectSql (or usually no sSQL at all because they are supposed to be using the ORM that was put in by earlier developers.), sValue vs. formCollectionValue (or usually no sValue either, because they happen to be in MVC and should be using its model binding features), sType vs. publishSource, etc.

It can't be readability. I see more sTemp1, sTemp2... sTempN from any given hungarianed VB6 leftover than everybody else combined.

  • It prevents errors.

This would be by virtue of number 2, which is false.

Antho answered 21/9, 2008 at 20:9 Comment(0)
J
4

Joel's article is great, but it seems to omit one major point:

Hungarian makes a particular 'idea' (kind + identifier name) unique, or near-unique, across the codebase - even a very large codebase.

That's huge for code maintenance. It means you can use good ol' single-line text search (grep, findstr, 'find in all files') to find EVERY mention of that 'idea'.

Why is that important when we have IDE's that know how to read code? Because they're not very good at it yet. This is hard to see in a small codebase, but obvious in a large one - when the 'idea' might be mentioned in comments, XML files, Perl scripts, and also in places outside source control (documents, wikis, bug databases).

You do have to be a little careful even here - e.g. token-pasting in C/C++ macros can hide mentions of the identifier. Such cases can be dealt with using coding conventions, and anyway they tend to affect only a minority of the identifiers in the codebase.

P.S. To the point about using the type system vs. Hungarian - it's best to use both. You only need wrong code to look wrong if the compiler won't catch it for you. There are plenty of cases where it is infeasible to make the compiler catch it. But where it's feasible - yes, please do that instead!

When considering feasibility, though, do consider the negative effects of splitting up types. e.g. in C#, wrapping 'int' with a non-built-in type has huge consequences. So it makes sense in some situations, but not in all of them.

Jarita answered 21/9, 2008 at 20:9 Comment(0)
S
4

I tend to use Hungarian Notation with ASP.NET server controls only, otherwise I find it too hard to work out what controls are what on the form.

Take this code snippet:

<asp:Label ID="lblFirstName" runat="server" Text="First Name" />
<asp:TextBox ID="txtFirstName" runat="server" />
<asp:RequiredFieldValidator ID="rfvFirstName" runat="server" ... />

If someone can show a better way of having that set of control names without Hungarian I'd be tempted to move to it.

Selwyn answered 21/9, 2008 at 20:9 Comment(0)
G
4

It's a useful convention for naming controls on a form (btnOK, txtLastName etc.), if the list of controls shows up in an alphabetized pull-down list in your IDE.

Giana answered 21/9, 2008 at 20:9 Comment(0)
H
4

In Joel Spolsky's Making Wrong Code Look Wrong he explains that what everybody thinks of as Hungarian Notation (which he calls Systems Hungarian) is not what was it was really intended to be (what he calls Apps Hungarian). Scroll down to the I’m Hungary heading to see this discussion.

Basically, Systems Hungarian is worthless. It just tells you the same thing your compiler and/or IDE will tell you.

Apps Hungarian tells you what the variable is supposed to mean, and can actually be useful.

Hemophilia answered 21/9, 2008 at 20:9 Comment(0)
M
4

Im my experience, it is bad because:

1 - then you break all the code if you need to change the type of a variable (i.e. if you need to extend a 32 bits integer to a 64 bits integer);

2 - this is useless information as the type is either already in the declaration or you use a dynamic language where the actual type should not be so important in the first place.

Moreover, with a language accepting generic programming (i.e. functions where the type of some variables is not determine when you write the function) or with dynamic typing system (i.e. when the type is not even determine at compile time), how would you name your variables? And most modern languages support one or the other, even if in a restricted form.

Marmolada answered 21/9, 2008 at 20:9 Comment(0)
P
4

If I feel that useful information is being imparted, why shouldn't I put it right there where it's available?

Then who cares what anybody else thinks? If you find it useful, then use the notation.

Poetaster answered 21/9, 2008 at 20:9 Comment(1)
'Cause there's only one of me and a bajillion other people who might maintain my code later on. Since all those people are on the team (but they don't know it yet), I'd like to have some idea if they outvote me.Hornbeck
E
4

It's incredibly redundant and useless is most modern IDEs, where they do a good job of making the type apparent.

Plus -- to me -- it's just annoying to see intI, strUserName, etc. :)

Empiric answered 21/9, 2008 at 20:9 Comment(1)
As TraumaPony told Paul Batum, not everyone sees the code in the IDE.Chuck
H
4

I've always thought that a prefix or two in the right place wouldn't hurt. I think if I can impart something useful, like "Hey this is an interface, don't count on specific behaviour" right there, as in IEnumerable, I oughtta do it. Comment can clutter things up much more than just a one or two character symbol.

Hornbeck answered 21/9, 2008 at 20:9 Comment(1)
I never got the the ISomethingable. If it's an -able, that implies interface anyway. (At least in java)Pierro
P
3

Several reasons:

  • Any modern IDE will give you the variable type by simply hovering your mouse over the variable.
  • Most type names are way long (think HttpClientRequestProvider) to be reasonably used as prefix.
  • The type information does not carry the right information, it is just paraphrasing the variable declaration, instead of outlining the purpose of the variable (think myInteger vs. pageSize).
Purgation answered 21/9, 2008 at 20:9 Comment(0)
M
3

In the words of the master:

http://www.joelonsoftware.com/articles/Wrong.html

An interesting reading, as usual.

Extracts:

"Somebody, somewhere, read Simonyi’s paper, where he used the word “type,” and thought he meant type, like class, like in a type system, like the type checking that the compiler does. He did not. He explained very carefully exactly what he meant by the word “type,” but it didn’t help. The damage was done."

"But there’s still a tremendous amount of value to Apps Hungarian, in that it increases collocation in code, which makes the code easier to read, write, debug, and maintain, and, most importantly, it makes wrong code look wrong."

Make sure you have some time before reading Joel On Software. :)

Motherwort answered 21/9, 2008 at 20:9 Comment(1)
No time now that I have Stackoverflow. I thinks Spolsky's mere association with the project must be doing it. :)Hornbeck
E
2

I started coding pretty much the about the time Hungarian notation was invented and the first time I was forced to use it on a project I hated it.

After a while I realised that when it was done properly it did actually help and these days I love it.

But like all things good, it has to be learnt and understood and to do it properly takes time.

Eaglestone answered 21/9, 2008 at 20:9 Comment(0)
D
2

Of course when 99% of programmers agree on something, there is something wrong. The reason they agree here is because most of them have never used Hungarian notation correctly.

For a detailed argument, I refer you to a blog post I have made on the subject.

http://codingthriller.blogspot.com/2007/11/rediscovering-hungarian-notation.html

Dorelle answered 21/9, 2008 at 20:9 Comment(0)
F
2

I don't think everyone is rabidly against it. In languages without static types, it's pretty useful. I definitely prefer it when it's used to give information that is not already in the type. Like in C, char * szName says that the variable will refer to a null terminated string -- that's not implicit in char* -- of course, a typedef would also help.

Joel had a great article on using hungarian to tell if a variable was HTML encoded or not:

http://www.joelonsoftware.com/articles/Wrong.html

Anyway, I tend to dislike Hungarian when it's used to impart information I already know.

Foscalina answered 21/9, 2008 at 20:9 Comment(3)
I think that first sentence might belie the answers on this page.Hornbeck
@Hornbeck Well, don't you already know that C strings are null terminated? I do see how it'd be useful when the string might not be but that's rare and so I think that the use of the convention should be confined to those cases.Conchology
Not every char* is a null terminated c string. The point of Hungarian is to use it for every variable, even the ones that fall into the common case. Ultimately, I feel as you do -- and therefore I don't use it in C.Foscalina
B
1

I think the whole thing of the aesthetical aspect is over-hyped. If that was the most important thing, we would not call ourselves developers, but graphic designers.

One important part, I think, is that you decribe what your objects role is, not what it is. You don't call yourself HumanDustman, becuase in another context, you would not most importantly be a human.

For refactoring-purposes it's really important too:

public string stringUniqueKey = "ABC-12345";

What if you decide to use a GUID instead of a string, your variable name would look stupid after refactoring all refering code.

Or:

public int intAge = 20;

Changing this to a float, you would have the same problem. And so on.

Boole answered 21/9, 2008 at 20:9 Comment(0)
P
1

The Hungarian notation was abused, particularly by Microsoft, leading to prefixes longer than the variable name, and showing it is quite rigid, particularly when you change the types (the infamous lparam/wparam, of different type/size in Win16, identical in Win32).

Thus, both due to this abuse, and its use by M$, it was put down as useless.

At my work, we code in Java, but the founder cames from MFC world, so use similar code style (aligned braces, I like this!, capitals to method names, I am used to that, prefix like m_ to class members (fields), s_ to static members, etc.).

And they said all variables should have a prefix showing its type (eg. a BufferedReader is named brData). Which shown as being a bad idea, as the types can change but the names doesn't follow, or coders are not consistent in the use of these prefixes (I even see aBuffer, theProxy, etc.!).

Personally, I chose for a few prefixes that I find useful, the most important being b to prefix boolean variables, as they are the only ones where I allow syntax like if (bVar) (no use of autocast of some values to true or false). When I coded in C, I used a prefix for variables allocated with malloc, as a reminder it should be freed later. Etc.

So, basically, I don't reject this notation as a whole, but took what seems fitting for my needs.
And of course, when contributing to some project (work, open source), I just use the conventions in place!

Pravit answered 21/9, 2008 at 20:9 Comment(0)
S
0

If you don't know the type of a variable without being told, you probably shouldn't be messing with it anyways

The type might also not be that important. If you know what the methods do, you can figure out what is being done with the variable and then you'll what the program is doing

There may be times you want it; when type is important and the declaration isn't near or the type can't be inferred with ease. But it should never be seen as absolute

Sphenic answered 21/9, 2008 at 20:9 Comment(0)
S
0

For years I used Hungarian notation in my programming. Other than some visual clutter and the task of changing the prefix when I changed the data type, no one could convince me otherwise. Until recently--when I had to combine existing C# and VB.NET assemblies in the same solution.

The result: I had to pass a "fltSomeVariable" to a "sngSomeVariable" method parameter. Even as someone who programs in both C# and VB.NET, it caught me off guard and made me pause for a moment. (C# and VB.NET sometimes use different names to represent the same data type--float and single, for example.)

Now consider this: what if you create a COM component that's callable from many languages? The VB.NET and C# "conversion" was easy for a .NET programmer. But what about someone that develops in C++ or Java? Does "dwSomeVariable" mean anything to a .NET developer not familiar with C++?

Subtropics answered 21/9, 2008 at 20:9 Comment(0)
N
0

I cannot find a link but I remember reading somewhere (which I agree with) that avoiding Hungarian notation results in better programming style.

When you program a statement of your program, you should not be thinking about "what type this object is" before calling its method, but rather you should think "what do I want to do with it", "which message to send to it".

Kind of vague concept to explain, but I think it works.

For example, if you have customer name stored in variable customerName, you should not care if it is a string or some other class. More important to think what do you want from this object. Do you want it to print(), getFirstName(), getLastName(), convertToString() etc. Once you make it an instance of String class and take it as granted, you limit yourself and your design since you have to build up all other logic you need elsewhere in the code.

Narrate answered 21/9, 2008 at 20:9 Comment(0)
N
0

Hungarian is bad because it takes precious characters away from variable names in exchange for what, some type information?

First of all, in a strongly typed language, the compiler will warn you if you do any truly stupid.

Second, if you believe in good modularized code and don't do too much work in any 1 function, you're variables are probable declared just above the code they are used in anyway (so you have the type right there).

Third, if you prefix every pointer with p and every class with C, your really screwing up your nice modern IDE's ability to do intellisense (you know that feature where it guesses as you type what class name your typing and as soon as it gets it right you can hit enter and it completes it for you? well, if you prefix every class with C, you always have at least 1 extra letter to type)...

Nibble answered 21/9, 2008 at 20:9 Comment(0)
M
0

See also What kind of prefix do you use for member variables?

Melodious answered 21/9, 2008 at 20:9 Comment(0)
P
0
  • They're a humongous eyesore
  • Your IDE should be able to tell you all you need to know about a variable's type
  • Good names (which HN gets in the way of) should communicate to you everything else you need to know about a variable.
Phosphorous answered 21/9, 2008 at 20:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.