25

I searched the forum, but I couldn't find the answers why it should be avoided, only why it's not a silver bullet. So I don't think this question is a duplicate.

Is there a VALID reason why I should unlearn Systems Hungarian I'm used to?

So far I see the following benefits in using it:

  • Consistent variable naming
  • You see type without searching (intellisense is dead/indexing half of the time, so it's still a valid reason)
  • Semantics can still be packed into second part of the name

And following downsides:

  • It annoys some people (no idea why)
  • If type is changed, the type might not match the naming of the variable (I don't think it's valid reason, types are changed rarely, and you have "rename all")

So why:

vector<string> vecCityNames;
wstring strCity = L"abc";
//more code here
vecCityNames.push_back(strCity);

is worse than:

vector<string> cityNames;
wstring city = L"abc";
//more code here
cityNames.push_back(city);//Are we pushing back int on a queue? Float on a stack? Something else?
21
  • 4
    if intellisense is dead, your code is invalid. If it is invalid, why assume that the variable name is correct?
    – Bubblewrap
    Commented Oct 12, 2011 at 10:44
  • 7
    @Bubblewrap: Most intellisense implementations bog for 3 seconds occasionally, even on valid code. And sometimes they don't work at all, even though code compiles and links. We are talking about reasonably sized projects.
    – Coder
    Commented Oct 12, 2011 at 10:54
  • 9
    shouldn't vectCityNames be vectStringCityNames so much for your consistent argument, and this "question" is more of a rant than anything, you have your mind made up, this should be closed.
    – user7519
    Commented Oct 12, 2011 at 11:37
  • 8
    What do you consider to be a "valid" reason?
    – Adam Lear
    Commented Oct 12, 2011 at 11:54
  • 15
    I don't think your second example is confusing in the way your comment indicates it is. The meaning of cityNames.push_back(city) is pretty clear. It is a list of city names and you are adding one. Commented Oct 12, 2011 at 12:48

13 Answers 13

63

I used to use it (many years ago) and I don't anymore. The main reason is it's superfluous in the OO languages with strong typing (C++, Java) which I happen to have used most of my career. In these languages, if I define my types well, the compiler can and will enforce type safety for me. So any naming prefixes are just clutter which make the names longer, thus harder to read and to search.

In any well written OO program, most of your variables are (references to) user defined types. If you prefix these with the same general tag (like o for "object"), you won't get any benefit from it, only the drawbacks . If however you prefix them with type-specific tags, you get into a maze of trying to find different abbreviations for a thousand different types with often similar names*, and to remember to change them all when a type or its name changes (which is not rare at all in a well maintained program).

Of course, this doesn't apply to non-OO languages, and may not apply to weakly and/or dynamically typed languages (I have no experience with these, apart from C). Neither to suboptimal editors/IDEs without a usable IntelliSense (or its local equivalent). And this is just my 2 cents. So if Hungarian notation works for your team and your project, go for it. The important thing is to agree on this (as well as on a consistent coding style in general) before the project starts, and keep it consistent at all times.

*just a short list from our current project: we have Charge, ChargeBreakdown, ChargeCalculator, ChargeDAO, ChargeDTO, ChargeLineHelper, ChargeMaps, ChargePair and ChargeType, among others. Moreover we also have Contracts, Countries, Checkouts, Checkins... and this is just the letter C, in a project which probably wouldn't even be called "reasonably sized" by the OP.


Disclaimer: I am actually a Hungarian, so I believe I can speak on this issue with authority ;-)

7
  • "Strong typing" - If C++ had a truly strong type system, you wouldn't have to embed types in the variable name as a hack. Commented Oct 12, 2011 at 10:11
  • 20
    @MichaelBurge: That's the point. You don't have to. Because it does.
    – DeadMG
    Commented Oct 12, 2011 at 10:15
  • 8
    +1 for the point about user-defined types. Using variables named iPos or fAmount may be tolerable, but try working on a codebase where every object variable is given a redundant six-letter prefix informing you only that it is a "pointer to a struct".
    – user31664
    Commented Oct 12, 2011 at 13:40
  • 2
    I would make an exception for GUIs where you need to store a handle for each control in addition to it's value, so text and hText rather than have to think of a different name for the entry box. Especially important on systems where the handle is just an int, not a special type. Commented Oct 12, 2011 at 18:03
  • 1
    I would posit that a major place where Java should have recommended the use of Hungarian notation is to distinguish between references to instances which may be mutated but never shared (e.g. the char[] held by a StringBuilder), and references to instances which may not be mutated, but may be shared with things that won't mutate them (e.g. the char[] held by String, which may be shared among multiple String instances). Both fields are the same type char[], but they hold things which are very different. A lot of mutability-related bugs stem from...
    – supercat
    Commented Aug 19, 2014 at 17:57
37

Why is std::vector<string> vecCityNames;bad?

The problem with Hungarian notation as it is usually used it that, if profiling shows that city names should rather be kept in a std::deque, all variable names referring to an object of that type will suddenly have a misleading name.

Are you then going to rename all your variables? Have you ever tried to do that in a big project? With Murphy's help (and the guy is incredibly helpful there) someone somewhere will certainly have used variables called something like deqCityNames, making your changes break the build, leaving you sitting for hours fiddling with code that, for half a decade, nobody dared to even look at, for fear of being bitten by a poisonous beast.

From what I know, however, the way Charles Simonyi came up with Hungarian, the prefix was denoting the variables semantic usage, rather than it's syntactic type. That is, the proper prefix for your list of city names, no matter what type it is implemented in, would probably be listCityNames (or lstCityNames, if list isn't cryptic enough for you).

But I consider that prefix quite superfluous, because the plural ("names") already conveys that it is a bunch of cities. Bottom line: When you pick your identifiers with care, Hungarian notation is rarely needed. OTOH, the way it is commonly used it is, in the long run, actually doing damage to the code.

14
  • 6
    @Coder: The type is used throughout the whole project, and all variables of this type will have the prefix. You will have to rename not one global variable, but hundreds of local ones.
    – sbi
    Commented Oct 12, 2011 at 11:11
  • 7
    You should add a link to Joel Spolsky's blog post where he offers his explanation for why using a variable type to come up with Hungarian notification is a misunderstanding of what it is all about. Yours is good but some people might be looking for something more authoritative and you could use that to back up your case. joelonsoftware.com/articles/Wrong.html Commented Oct 12, 2011 at 11:58
  • 2
    @Coder: Unfortunately, typedef is a seriously undervalued tool
    – sbi
    Commented Oct 12, 2011 at 12:31
  • 4
    @Shane: I have written down my own opinion on the matter. Should that happen to fit with Joel's, then that's fine with me, because I value his opinions even though I happen to disagree with some of them. But I see no need to appeal to other "authorities" to back up my own opinion when that is based on more than a decade of hard-won experience. It's nice that you have posted that link, though, it's always good to see other people's opinions to compare with.
    – sbi
    Commented Oct 12, 2011 at 12:39
  • 4
    A long time ago, I was the CVS guy for the shop, and one of the top developers changed initials (sex-change surgery etc., and his and her first names didn't have the same initials). Whenever she touched a file (or a similar one), she changed all his initials into the new form. I found this extremely annoying, as we'd have all sorts of minor changes in the historical features, and it was hard to figure out what actually had been changed and why. Change vecCityNames to deqCityNames in a few hundred files and you do the same thing. Commented Oct 12, 2011 at 14:24
16

For whatever reason, the existing answers here seem to be dancing around the rationale for Hungarian notation, without stating it outright. Hungarian notation is useful for adding type information (in a type theoretical sense) when it would be difficult to do so in the language itself. As it happens, it usually is not that difficult to use C++ or Java's type system in such a way that Hungarian notation (as usually described) is completely superfluous, and this is probably what has lead to the backlash against it - it adds programmer work to maintain those annotations in all our variable naes, but provides little-to-no additional value (and may even cause harm, as the code looks more cluttered).

On the other hand, if one restricts the use of Hungarian-notation to type information (again, in a type theoretical sense) that is not naturally encapsulated by the language, then it can be very useful. For example, C and C++ pass array references as pointer types, but array references and pointers have different operations that should be performed against them: arrays can be indexed beyond the first element, while pointers should not. This is useful information that gets lost to the type system as soon as an array is passed to a function as an argument. As such, in our group we've adopted variable-name annotations in C and C++ code to distinguish whether a pointer variable is actually a pointer to a single element, or a pointer to an array. Adopting this convention has been partly responsible for a large reduction in the occurrence of memory corruption problems in our code base.

3
  • What made Hungarian fail was that it was misused (by the WinAPI team) to encode a variable's syntactic type, rather than its semantic meaning. (Think dw vs. cb.) It is not that its original form would be less helpful in OO languages: An index is still an index, even if stored in a class type rather than a built-in.
    – sbi
    Commented Oct 12, 2011 at 12:46
  • 1
    +1 for pointing out that the real argument here is about type theory. Hungarian notation is a technique for augmenting the type system with additional information, and as such should be compared and contrasted with other techniques for augmenting the type system (e.g. templates, typedef, etc.), rather than being discussed on its aesthetic merits (or lack thereof). Commented Oct 12, 2011 at 17:58
  • 1
    The question is specifically about "Systems Hungarian", pointless duplication of the declared type, with no extra semantic information. There may be a case for using the original "Hungarian notation" concept of semantic tags to give information beyond that allowed by the language syntax (in some languages, including C, though not C++ where you can do it more reliably with user-defined types), but that's not what the question is about. Commented Oct 13, 2011 at 11:46
14

It annoys some people (no idea why)

The reason it annoys me is that it's a little speed bump on every single identifier that slows down my visual scanning of the code. sIt's mAs bIf pYou kHad zTo qRead iEnglish cText lLike uThis.

10

Hate is too strong a word, IMO. You can write your code any way you want; I simply prefer not to use Hungarian notation in my own code, and given a choice I'd also prefer not to have to read it or work with it in other people's code.

You asked why some people find Hungarian notation annoying. I can't speak for others, but the reasons that it annoys me are:

  1. It's ugly. Hungarian takes perfectly reasonable names and prepends what amounts to a code. Once you've internalized this code, I'm sure makes perfect sense, but to the uninitiated it just looks like somebody unleashed the C++ name mangler on my source code.

  2. It's redundant. A variable's declaration establishes its type; I don't feel the need to repeat that information in the variable name. This isn't true in every language: in Perl, for example, sigils such as @ or $ prepended to the variable name essentially define the type of the variable, so you don't have any choice but to use them.

  3. It solves a problem that I don't have. Methods and functions shouldn't be so long that you have to look hard to find the declaration of a local variable or parameter, and they shouldn't involve so many variables that you have trouble keeping track of what's what. Declaring local variables close to the code that uses them helps in this respect, too. C compilers of the past required that all local variables be declared at the beginning of the function, but that limitation was removed long ago.

  4. It's incomplete. Hungarian notation was invented for a language (BCPL) that didn't have a type system, and was later used widely in a language (C) that had a fairly limited number of native types. IMO, it doesn't work well with languages like C++ or Java that have extensive type systems. Why would I want to use a prefix to indicate the type of a variable that's a native type, like char[], but not one that's a class? Alternately, if I start inventing prefixes like vec for classes, I'll end up with a large hierarchy of prefixes parallel to my class hierarchy. If that appeals to you, you're welcome to it; just thinking about it is giving me a headache.

  5. It's ambiguous, at least as I understand it. What's the difference between szFoo and pszFoo? The first is a zero terminated string, and the second is a pointer to a zero terminated string. But in C or C++, as far as I know, any string variable is effectively a pointer, so are they the same or not? Which should I use? The actual answer really doesn't matter -- the point is that I can't discern the answer using the very notation that's supposed to help me avoid these sorts of questions. The variable's declaration, on the other hand, has to be unambiguous because it's what the compiler uses.

Those are the things that annoy me about Hungarian notation. Even as a group, though, I don't think they fully explain why Hungarian has been largely abandoned. Here are the three biggest reasons that most programmers don't use Hungarian:

  1. There's no compelling reason to use it. See items 3 and 4 above. I could probably live with the annoyances if Hungarian offered some big advantage over not using Hungarian, but I don't see one, and apparently most other folks don't either. Perhaps the best thing about Hungarian was that it was a widely used convention, and if you stuck to the standard use you could reasonably expect other programmers with similar skills to be able to understand the notation.

  2. Increased influence of companies that aren't Microsoft. It's probably fair to say that most programmers that adopted Hungarian notation did so because that's the way Microsoft wrote code, and its often easier to go with the flow. Companies like Google and Apple have much, much larger spheres of influence now than they did in the past, and more programmers than ever before are adopting the styles of those companies and others that mostly eschew Hungarian. (It's only fair to point out that you do still see some remnants, e.g. both Google and Apple often use a 'k' prefix for constant names.)

  3. Microsoft itself has abandoned Hungarian. If you check Microsoft's General Naming Conventions section of its coding guidelines, you'll find that it says, in bold: Do not use Hungarian notation.

Accordingly, one valid reason to stop using Hungarian notation is:

Hungarian notation's popularity has diminished to the point that the convention is no longer helpful. Far fewer programmers use or even understand Hungarian these days, and the convention is therefore much less effective at conveying the information that it's supposed to. If you find it a useful way to write code in your own personal projects, then there's little reason to stop. However, if you're writing code as part of a team that doesn't use Hungarian, it may become a wall between you and the rest of the team instead of a successful communication strategy.

4
  • "What's the difference between szFoo and pszFoo"? One is char*, the other char**, took me 0,25 secs to tell the difference. Try to beat that with Intellisense.
    – Coder
    Commented Oct 12, 2011 at 16:16
  • 2
    @Coder, pnFoo would probably be int*, not int**, so you have to know that the sz also means a pointer. I'm sure it's not a big problem for the limited number of types that have established Hungarian prefixes, but in any large project defined types number in the thousands. I don't know about Intellisense, but IDEs have steadily improved over the last 25 years, and I expect that trend to continue.
    – Caleb
    Commented Oct 12, 2011 at 16:32
  • If you read docs.microsoft.com/en-us/windows/win32/stg/… you'll find that in Win32 applications Hungarian is still used (at least in 2018). The naming convention you refer to are for .Net. This is not an edorsement for using HN by the way. It's hideous IMHO. Commented May 26, 2020 at 15:03
  • @RubenSteins Yes, it's typical to adhere to established conventions in a given ecosystem even if you wouldn't choose those conventions for new work. Win32 is a very old platform, and it's more likely that it'll eventually be phased out than that it'll be revised with a completely new set of naming conventions.
    – Caleb
    Commented May 26, 2020 at 16:10
8

So far I see the following benefits in using it:

  • Consistent variable naming

If I name all my variables after characters from The Simpsons, that's consistent too, but is it a benefit?

  • You see type without searching (intellisense is dead/indexing half of the time, so it's still a valid reason)

This is the only valid reason, based on the weakness of one specific tool...

  • Semantics can still be packed into second part of the name

That's not a benefit; you're merely claiming the absence of a (massive) downside.

0
6

The IDE will trivially tell me what the type of a variable is when I mouse over it. So why bother duplicating that information? Fundamentally, Systems Hungarian Notation is a violation of DRY, with all the pitfalls that's associated with it. When that information is trivially accessible in a modern environment, there's no reason to pay that price.

Consistency is not an advantage in as of itself. Not naming them with the type is also consistent. You would only have inconsistency if only some variables had their types in the name. And packing semantics into the second part is simply "Well, it's not that bad.", everyone else gets to use the whole name for semantics. You don't have any real advantages listed.

3
  • 4
    "The IDE will trivially tell me what the type of a variable is when I mouse over it.", in hello world, yes. On larger projects I find this feature extremely unreliable/slow. ctrl+space, ctrl+space, ctrl+space, ctrl+space, ctrl+space, no go...
    – Coder
    Commented Oct 12, 2011 at 10:56
  • 3
    Get a new IDE. Or an SSD, that works wonders. Or just include less unnecessary headers.
    – DeadMG
    Commented Oct 12, 2011 at 15:15
  • 1
    Even if the IDE is too slow when showing a variable's type, or if it is simply not capable of doing that, methods/functions should be kept short, so that a variable's declaration will never be very far away from its use. Commented Oct 12, 2011 at 17:45
6

Another point with traditional forms of Hungarian notation is they are usually prefixes. there are 2 problems imho here:

1) A human reader would generally like the most important information first, in most forms of Hungarian the information encoded is arguably of less importance than than name itself.

2) Prefixes effect lexical sorting, so if for instance you are going to use a prefix to denote interfaces or classes and your IDE provides a sorted list of these, related classes/interfaces are going to be separated in this list.

2

Clearly, this comes down to opinions, so it's going to be difficult to work with facts here. Personally, I find that the argument for Hungarian notation runs a bit thin in strongly-typed, object oriented languages. In my experience, OO applications tend to handle complexity by keeping classes coherent and concise, and the same thing can be said about functions. This means that all other things being equal, you end up with:

  • More classes / types
  • Shorter methods

Now, if you want to use Hungarian notation, you have to decide whether to apply it across the board, or to just use it for certain privileged types and classes (such as core library classes). The latter makes no sense to me, and the former leads to the "maze of trying to find different abbreviations to a thousand different types" that Péter Török was referring to. This means that there is a significant overhead in maintaining abbreviation lists, and usually "consistent variable naming" goes out the window.

The second point about shorter methods means that in most cases, you are not going to have to go through hundreds of lines of code to check what type a variable is. Naming variables slightly more carefully would eliminate some of your other questions - e.g. cityName vs. just city. I would hope that cityName is not a float :)

Regarding why it annoys people - again, this is probably down to being used to it or not. But as someone who is not used to it, I can tell you that the use of Hungarian notation breaks the flow of code for my eyes, making it harder to read quickly. To summarise, I am not saying that it has no merit (although I haven't discussed some of its drawbacks, in terms of refactoring, etc), I am saying that the effort is not worthwhile, for strongly-typed, OO languages.

1

I don't know in the context of C++ but in the Java/C# world I would much prefer having meaningful names that convey either a domain language or context than telling me that strFirstName is a String; it should be obvious that it's a string, or the name needs to be refactored to convey better intent. If you require a prefix to know the type of what you are working with, I would argue your naming is inconsistent, not descriptive enough, or downright wrong. In modern languages I always prefer longer names that leave no ambiguity than vague or ambiguous names.

The only time I use Hungarian is for ASP.NET controls, and that's more so I A) don't have to type something really long like CustomerFirstNameTextBox versus txtCustomerFirstName, and B) So Intellisense will sort all of the control types. I feel "dirty" even doing that, though, I just have yet to find a better way.

1
0

Meh - it is really all about personal preferences, no matter how hard one tries to rationalize their choices. I personally stick to the "When in Rome..." rule and use Hungarian in code that calls Windows API a lot. For platform-independent code, I tend to follow the C++ Standard Library style.

0

The answer lies in this question: Please tell me how to name the following variables:

char * nullTerminatedString;
wchar * nullTerminatedWideString;
string stlString;
wstring stlWideString;
CString mfcString;
BSTR comString;
_bstr_t atlString;

Add to these constant strings, pointer to these and constant pointers to these.

1
  • 3
    szFoo, wczFoo, strFoo, (w)strFoo, strFoo, bstrFoo, bstrFoo
    – Coder
    Commented Oct 12, 2011 at 16:13
0

I strongly dislike the form of Hungarian notation you describe. The Reason? It serves no point 90% of the time.

For instance, a bit of (equivalent C++. actually written in Delphi) code from a legacy project I'm forced to endure:

pRecords[0]->FooMember=10;

... pRecord is a variable, it's of type TRecordList. TRecordList *pRecords[10];

It's a class consisting of a orioerty named FooMember that points to fFooMember... or mFooMember depending on if it's a "field" or a "member" (hint: they're the same thing)

Problems? fFooMember could be something like FooMember_ because we will always access it through the FooMember public property. pRecords? It's pretty obvious it's a pointer from the fact that you dereference it all over the place. TRecordList? When can you possibly confuse a type name and an object of that type? The compiler will yell at you, and types are used in almost no places that objects are (except for static properties/methods)

Now, there is one place where I do use hungarian notation. This is when dealing with lots of UI variables that would have the same name as other UI variables or regular variables.

For instance, if I had a form for your First Name on it.

I'd have a class named FirstNameForm. Within it, lblFirstName and txtFirstName for the label and textbox respectively. And a public FirstName property for getting and setting the name in the text box.

This could also be solved by using FirstNameLabel and FirstNameTextBox but I find it gets long to type. Especially with something like GenderDropDownList and such.

So basically, hungarian notation is, at best, annoying at the systematic level and Worst case harmful (as the other answers give about problems with refactoring and consistency).

Not the answer you're looking for? Browse other questions tagged or ask your own question.