Rational agrument against Hungarian notation?



  • I know a lot of people don't like Hungarian notation (includng me) but I can't seem to come up with a convincing reason as to why it's bad.  The only argument I can come up with is it's OK for procedural languages like C but bad for OO because it separates the type from the method.  To me,

        rsCustomers.Open()

    doesn't make as much sense as

        CustomersRecordset.Open()

    because the recordset is the thing being opened, not the customers.  If you think of Open() as a verb, Recordset as a noun, and Customers as an adjective describing the type of recordset, the first example reads like "the ball red bounced" while the second reads like "the red ball bounced."   But that in itself doesn't seem convincng enough.  Ideas?



  • Well, if you want your program to look like English text, use COBOL. ;-)



  • I like hungarian in some situations, but I do have a good argument against it.....

    Original code:

    ------------------

    int intNumberOfWidgets=0;

    ------------------

    Then, 2 years later, you decide that a long is more appropriate.  New code:

    ------------------

    long intNumberOfWidgets=0;

    ------------------

    You see, if you rename the variable, you might break some code.  Why create a naming scheme that requires a major code review to regression test a simple type promotion or else force your hungarian notation to be misleading.  It turns out that hungarian notation is really only useful for local variables because of this.  My favorite example of hungarian gone awry is a view called tblCustomers.  See, it was created originally as a view, but then address data was normalized out and to prevent the re-write of 400 reports, it was replaced with a view.  However, the view must be named tblCustomers in order to prevent visiting all 400 reports.

    BTW, how many easy-to-use, widely accepted APIs have any of you used that use hungarian notation for anything other than parameters?  Even using it on parameters makes the API look a little childish, besides in a large number of languages you don't see the parameter variable names anywhere other than the documentation.

    Hungarian notation also makes some things a little more cumbersome.  Example - a database with 500 stored procedures all starting with "sp".  If they started with a range of letters, then it would be easier to navigate the list by typing the first letter in Enterprise Manager.



  • @jsmith said:

    I like hungarian in some situations, but I do have a good argument against it.....

    Original code:

    ------------------

    int intNumberOfWidgets=0;

    ------------------

    Then, 2 years later, you decide that a long is more appropriate.  New code:

    ------------------

    long intNumberOfWidgets=0;

    ------------------

    You see, if you rename the variable, you might break some code.  Why create a naming scheme that requires a major code review to regression test a simple type promotion or else force your hungarian notation to be misleading.  It turns out that hungarian notation is really only useful for local variables because of this.  My favorite example of hungarian gone awry is a view called tblCustomers.  See, it was created originally as a view, but then address data was normalized out and to prevent the re-write of 400 reports, it was replaced with a view.  However, the view must be named tblCustomers in order to prevent visiting all 400 reports.

    BTW, how many easy-to-use, widely accepted APIs have any of you used that use hungarian notation for anything other than parameters?  Even using it on parameters makes the API look a little childish, besides in a large number of languages you don't see the parameter variable names anywhere other than the documentation.

    Hungarian notation also makes some things a little more cumbersome.  Example - a database with 500 stored procedures all starting with "sp".  If they started with a range of letters, then it would be easier to navigate the list by typing the first letter in Enterprise Manager.



    Prefixes like "int" are the MS-specific false interpretation of hungarian notation. The idea is not to put the datatype like int, long as a prefix, but rather the meaning - is it a counter, an index, a coordinate etc.


  • Interesting.....   Hungarian Notation was invented by Charles Simonyi while working at Xerox, it was brought to Microsoft by Simonyi himself when he became Microsoft's Chief Architect (the position Bill Gates now holds).  Hungarian notation doesn't specify prefixes other than stating that the prefix should be description of the "type" of data the variable will hold.  It has branched out in many directions from there.  90% of all implementations of Hungarian Notation have more bad features than good ones and are susceptible to the issue I described above.

    Also, nearly every naming system can be claimed to be Hungarian Notation.  As long as it uses prefixes to describe something about the data, it would fall under a broad interpretation of Hungarian Notation.  So, yes, there are some good implementations.



  • Pretty much the only good prefix system I've seen so far shows the scope of a variable, and never the type. For instance..

    int bar::foo(int aParameter)
    {
       int local; // no prefix
       local = baz(aParameter, mMember);
       return gGlobal * local;
    }



  • @ammoQ said:

    Prefixes like "int" are the MS-specific false interpretation of hungarian notation. The idea is not to put the datatype like int, long as a prefix, but rather the meaning - is it a counter, an index, a coordinate etc.

    Hungarian notation itself is pretty much Microsoft centric, except in the Visual C++ world it's frowned upon everywhere...
    And it's exactly designed to have the type of a variable instantly available in the variable name, not its function (which should be available from the non-Hungarian part of the name already).



  • @jwenting said:

    @ammoQ said:

    Prefixes like "int" are the MS-specific false interpretation of hungarian notation. The idea is not to put the datatype like int, long as a prefix, but rather the meaning - is it a counter, an index, a coordinate etc.

    Hungarian notation itself is pretty much Microsoft centric, except in the Visual C++ world it's frowned upon everywhere...
    And it's exactly designed to have the type of a variable instantly available in the variable name, not its function (which should be available from the non-Hungarian part of the name already).

    Failed, that stupidity also known as Systems Hugarian is absolutely not what the original creator of the hungarian notation (Charles Simonyi) intended, and results from a mis-interpretation of Simonyi's HN by the Windows team.

    The original Hungarian Notation (also called Apps Hungarian) prefixed the names with the purpose, the semantics of a variable. What the variable means, what and how it's used. Not it's type as in "C type" (int, long, array of characters) which are completely useless and can be extracted with a pair of keystrokes in any editor worth using, it's type as in it's high level meaning. For example in Apps Hungarian you'd prefix a name with "ix" if it was an index on an array, with "c" for a count (such as the length of a collection). It was actually useful, because it made some semantic errors obvious (a count as the result of computations involving length for example).

    Systems Hungarian, which is what you describe, prefixes the name with the C type of the value, which is basically useless.



  • if you use proper variable naming you don't need to prefix it with anything to tell you what it does...
    Why should I use something like 'int ixIndex = rsResultSet.getIxRowId()'?


  • ♿ (Parody)

    I prefer diacritical notation in case insensitive languages. This way you can easily keep your variables only one-character long ...

    int à = á * ä;
    if (À < Â) { å(); }

    Look at how many less bytes that takes up, and consider how much faster it will compile.



  • @Alex Papadimoulis said:

    I prefer diacritical notation in case insensitive languages. This way you can easily keep your variables only one-character long ...

    int à = á * ä;
    if (À < Â) { å(); }

    Look at how many less bytes that takes up, and consider how much faster it will compile.



    å for arrays so small they fall in the Angstrom range?



  • >look at arrays

    I see no arrays here.

    >_



  • Quantum Javascript.

    var planckArray = new Array(0.00000000000000000000000000000000001616);



  • I've spent quite a while integrating old Windows-style HN C code into newer C++ programs,
    and the most annoying aspect to me is the prefixes becoming out-of-date when eg. converting from char * to std::string.
    (Not to mention the fact that most strings are simply called lpThing - long pointer? To what?
    This code isn't compatible with any segmented architecture anyway!)

    As has been pointed out, this isn't really a problem with proper HN, but it is with the most common style in use (ie. windows').

    On another note, I remember being taught all the standard datatype-based prefixes (i, str, rs, tbl, rpt, etc.) in classes,
    but as far as the potentially useful prefixes are concerned, all I can think of are things like ix and cb... basically different descriptions
    of what you're using an int for (I tend to use size_t for things that are intended as a count of bytes anyway).
    Are there other functional prefixes that are applicable to (say) a string or an object?
    I'd be interested to hear from anyone who actually uses HN to describe the function of a variable, not its data-type.



  • @Sol_HSA said:

    Pretty much the only good prefix system I've seen so far shows the scope of a variable, and never the type.


    Oh and I meant to add, I also find the scope prefixes quite useful, although primarily in the context of members.



  • @Sol_HSA said:

    Pretty much the only good prefix system I've seen so far shows the scope of a variable, and never the type.


    Oh and I meant to add, I also find the scope prefixes quite useful, although primarily in the context of members.



  • @aihtdikh said:

    I've spent quite a while integrating old Windows-style HN C code into newer C++ programs,
    and the most annoying aspect to me is the prefixes becoming out-of-date when eg. converting from char * to std::string.
    (Not to mention the fact that most strings are simply called lpThing - long pointer? To what?
    This code isn't compatible with any segmented architecture anyway!)

    lpThing isn't a string, if it were a string it would be lpstrThing. An lpThing is a simple long pointer to an unidentified datatype other than string!



  • @jwenting said:

    @aihtdikh said:

    I've spent quite a while integrating old Windows-style HN C code into newer C++ programs,
    and the most annoying aspect to me is the prefixes becoming out-of-date when eg. converting from char * to std::string.
    (Not to mention the fact that most strings are simply called lpThing - long pointer? To what?
    This code isn't compatible with any segmented architecture anyway!)

    lpThing isn't a string, if it were a string it would be lpstrThing. An lpThing is a simple long pointer to an unidentified datatype other than string!



    Hehe but that's assuming that the original author used HN correctly, which they didn't. ;)
    That was my point - sorry I didn't make it more clear.
    For reference though, MS do the same thing - have a look at the declaration of MessageBox in MSDN.
    I get "int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);"
    Also, most of the Win32 API seems to use lpsz as a prefix - but ATL and MFC seem to mostly use lpstr, referring to a char *, not a CString or std::string.
    Ok, maybe too much detail... but I was wondering how consistent their naming schemes are.

    aiht


  • The reason that I don't like Hungarian notation is that it simply makes the code hard to read and write.  We humans have learned to be very good at reading language.  Language consists of phrases (like sentences and their subordinate phrases), which consist of words, which consist of a structure of syllabic groups (morphemes) which follow precise rules for combination.    Computer languages create their own kind of strict phrase structure, which, as programmers, we have learned to understand well.   The words in these phrases are variables, function names, and operators.   To be able to quickly and correctly understand the meaning of a line of code, you need to be able to read these words quickly and correctly.  A clump of letters in the front of a word is simply an obstacle to clear and correct understanding of the code. Similarly, writing the code is harder, since you have to remember what exact wart goes on the front of the word, rather than the word itself.

    Reed



  • Didn't microsoft say goodbye to HN 4 years ago???

    now with the good old days of VS.NET it has been declared that HN should NEVER EVER BE USED, and MS orders the head of any (wo)man that uses it to be affixed to a stake asnd skewered in the nearest barbeque



  • No.  MS told the average developers who are too stupid to use HN properly (Apps Hungarian) not to use it anymore, because it didn't clarify anything, and usually made the code less readable and maintainable.

    Internally MS still uses AHN in core work groups; at the very least on the Office team, and probably others (though I'd have to ask to be sure how widespread it is).  Apps hungarian often makes code a lot more readable, and a lot more debuggable, since it describes how a variable should be used, and the usage semantics.  Life is a lot easier when you know that you shouldn't be returning the result of a function to a variable of the same type, that has an unsafe usage semantic.

    See joelonsoftware for a good article on why you're probably not a good enough programmer to use hungarian notation properly.



  • @Hitsuji said:

    Didn't microsoft say goodbye to HN 4 years ago???

    now with the good old days of VS.NET it has been declared that HN should NEVER EVER BE USED, and MS orders the head of any (wo)man that uses it to be affixed to a stake asnd skewered in the nearest barbeque

    Maybe internally, but the entire public SDKs are still riddled with it (including the examples).
    If they'd really sworn it off they should have changed all that to reflect sane coding conventions.



  • @dhromed said:

    @Alex Papadimoulis said:

    I prefer diacritical notation in case insensitive languages. This way you can easily keep your variables only one-character long ...

    int à = á * ä;
    if (À < Â) { å(); }

    Look at how many less bytes that takes up, and consider how much faster it will compile.



    å for arrays so small they fall in the Angstrom range?


    That should be "Ångström", you just have a deficient language.


  • One simple, rational reason not to use Hungarian Notation:

    Prefixes break autocomplete!

    It's that simple. Take your typical m_ prefix for member variables, something still recommended by "modern" code convention pundits like IDesign. If you want to utilize a variable with that prefix using autocomplete, you have to type m <shift> -.. three keystrokes. And, the _ key almost always involves a hand-shift, as very few people *actually* use their pinky to type that in. It slows down typing, period.

    Embedding purpose in a method name *is* a Good Idea (tm) most of the time, but with modern auto-sorted auto-complete technology, *prefixing* it is bad. We have to type the entire prefix just to get to a list of names. Suffixing semantics (and then, only when necessary) is the better way to go.



  • @Alex Papadimoulis said:

    I prefer diacritical notation in case insensitive languages. This way you can easily keep your variables only one-character long ...

    int à = á * ä;
    if (À < Â) { å(); }

    Look at how many less bytes that takes up, and consider how much faster it will compile.

     

    I find your ideas intriguing, and would like to subscribe to your newsleter.

     

    Wait, scratch that -- I already have.



  • I guess I'm the only person on the planet that likes HN.  I like
    member variables to be m_... and strings to be prepended "str".  I
    fond code easier to read and understand like that.



    I very very rarely have to change the type of a variable and when you do a find and replace all almost always works first time.



    The original version of HN is a good idea also.  The best use of
    that I ever saw was completly unreadable if you didn't understand the
    naming convention.



    It was something like low level network code with variable everywhere
    like "uuxxvvv", "xxvvvuu", "x", "uxvx" etc.  But then the x,u and
    v's represented some particular kind of byte so you knew from the
    variable name exactly what each byte in there does and it's endian-ness.



  • Can I ask you...

    What does a prefix get you that a suffix does not? Could you not obtain all of the information and readability of your code by, say, writing "MemberVariable_m" rather than "m_MemberVariable"?



  • most people stop reading as soon as they have the information they want, so people wanting only the datatype would stop reading as soon as they read the prefix.

    HN supposes that people are more interested in the type of a variable than in what that data actually means I guess.



  • I use HN when there can be doubt about a type.

    Take the varname 'coordSet', seen at a place [i]other[/i] than its declaration.

    Array?
    Map?
    String?


    'arrCoordSet', of course!



  • @dhromed said:

    I use HN when there can be doubt about a type.


    In Ecclipse, I just have to move the mouse cursor over the variable and wait a secong, then a popup tells me the type. If you need HN for that, you should consider switching the IDE.



  • @jwenting said:

    most people stop reading as soon as they have the information they want, so people wanting only the datatype would stop reading as soon as they read the prefix.

    HN supposes that people are more interested in the type of a variable than in what that data actually means I guess.

    But, again, a prefix doesn't get you anything more than a suffix. Our brains are inherently parallell in nature, and we can just as easily split a word into name - type as we can type - name. People interested only in type would simply look at the *end* of the word, rather than the beginning. No extra time involved at all. Even then, as ammoq has suggested, modern IDEs make determining the type of a variable easy to determine.

    Of course, embedding the *type* of a variable is against the original intent of hungarian notation. You're supposed to embed *purpose*, not *type*.



  • @dhromed said:

    I use HN when there can be doubt about a type.

    Take the varname 'coordSet', seen at a place [i]other[/i] than its declaration.

    Array?
    Map?
    String?


    'arrCoordSet', of course!

    That seems to indicate that you don't know the code very well.  I can go through my code and I know what types the variables are.  Whenever I need to change/read someone else's code, I read it first, to learn what the variable types are.

    Maybe Hungarian notation really does have some use (I don't think so), but you're making it sound like an excuse to not learn the code, which in turn means you wouldn't be safe modifying the code.



  • Well I too am one that has gotten into the habit of using type prefixes (str, bln, int, dbl, etc...) but I blame that on the way college courses are.

    All of the programming classes I have taken (VB 6.0, VB.NET, C#.net, C++, Java) all of them have DEMANDED that you use the type prefixes for all variable declarations, after loosing about 50 points on various programming assignments it became a habit. 

    Personally I have mixed emotions about it as in some ways it does help, but in a lot of ways it just makes intellisense less helpful and longer variable names......

    ....damn teachers!



  • @Jörg said:

    @dhromed said:
    I use HN when there can be doubt about a type.

    Take the varname 'coordSet', seen at a place [i]other[/i] than its declaration.

    Array?
    Map?
    String?


    'arrCoordSet', of course!

    That seems to indicate that you don't know the code very well.  I can go through my code and I know what types the variables are.  Whenever I need to change/read someone else's code, I read it first, to learn what the variable types are.

    Maybe Hungarian notation really does have some use (I don't think so), but you're making it sound like an excuse to not learn the code, which in turn means you wouldn't be safe modifying the code.


    Of course I know my own code.

    You don't make your code understandable for yourself, but for other people and your future self.

    It's about the other guy who goes directly to line 258 to fix a bug that occurred at line 258, sees "coordSet" and would like to know what the hell it is.

    Though in many cases he can get it from the context.



  • @dhromed said:

    Of course I know my own code.

    You don't make your code understandable for yourself, but for other people and your future self.

    It's about the other guy who goes directly to line 258 to fix a bug that occurred at line 258, sees "coordSet" and would like to know what the hell it is.

    Though in many cases he can get it from the context.

    Sorry, I used you to mean both "you" and "one".  The part directed actually at you was a little sarcastic.  I expect that you know your own code.  As for someone else editting your code, I still stand by the assertion that if one doesn't understand the code, then one isn't safe changing the code.  I wouldn't want anyone messing with my code who was so lost that he couldn't (easily) figure out the type of a variable.

    Seriously, editting code that one doesn't understand is dangerous.  e.g. Let's say the error at line 258 is a null pointer exception.  So, the obvious solution is to simply wrap the code in an "if (arrCoordSet != null)" block.  Howver, that only works if the coordSet is expected to be null sometimes.  If instead coordSet should never be null, then it's a dangerous hack, because now it's just masking the bug, which will likely come back later in a harder-to-diagnose form.  That's probably an overly-simplified example, but I think the point is correct.  One can't safely edit code that one doesn't know.



  • Good news, everyone!



    Nobody mentioned the visual appearance of words yet. Like, when you encounter the word

        table

    then you don't actually decipher every single character. The outline of
    the word already associates the word with its meaning a lot. That still
    works for

        Table    .

    It doesn't work for

        CTable

    any more - the outline is broken and doesn't relate to any known word.



    Yes, I've been using this sick "C" for a class from non-visual studio
    intentionally. Try naming a class "Controller" there and it'll propose
    "ontroller.[h|cpp]" as file names. Sick.



  • @Hubert Farnsworth said:

    Try naming a class "Controller" there and it'll propose
    "ontroller.[h|cpp]" as file names. Sick.

    Blech.  That's some really obnoxious behavior.

    Prefixing classes with C makes no sense. (I'm gusesing that)  Microsoft only did it to avoid naming conflicts (since they either chose not to use namespaces or they weren't yet available).  And of course, now Microsoft alone has three different CString implementations.  Not to mention the million other CString implementations in other libraries/frameworks.



  • It adds nothing. If you are the coder you know what it is and if you aren't the coder you can't be sure it is still the same as it was intended without looking.
    Unless you LIKE ugly names to prove you're l33t.



  • @masklinn said:

    The original Hungarian Notation (also called Apps Hungarian) prefixed the names with the purpose, the semantics of a variable. What the variable means, what and how it's used. Not it's type as in "C type" (int, long, array of characters) which are completely useless and can be extracted with a pair of keystrokes in any editor worth using, it's type as in it's high level meaning. For example in Apps Hungarian you'd prefix a name with "ix" if it was an index on an array, with "c" for a count (such as the length of a collection). It was actually useful, because it made some semantic errors obvious (a count as the result of computations involving length for example).

    Systems Hungarian, which is what you describe, prefixes the name with the C type of the value, which is basically useless.

    More than useless, actually.  It makes refactoring much more complex, breaks autocomplete, and is generally a massive pain in the arse.

    A much better plan is to use Kent Beck's seminal "Smalltalk Best Practice Patterns" (despite its name, not restricted to the esoteric world of smalltalk programming, but actually relevant for anyone coding in any language).  The relevant patterns are:

    Intention revealing message / selector

    Type suggesting parameter name

    Role suggesting instance variable name

    Role suggesting temporary variable name

    In short, it boils down to this: Name your methods after what they do.  Indicate type in the parameters to a method (if you're using a 'C' based language this one is taken care of as your parameters are specified with type).  Instance and temporary variables should be named in a way that suggests their role.

    Simon




  • The easy argument against it is that it confuses the hell out of you when you look at stuff, and it's ugly as sin.  The point about changing a type and having to change it everywhere else or it breaks also comes to mind.  Personally, I used Hungarian when I first learned to program (only a few years ago) because all the books used it at the time, but now I only use it (well, a modified version.  i prefix for an integer, s for string, b for boolean, etc) in scripting languages like JavaScript and VBScript since those don't have declarations.  I never use it in code anymore, but I admit that I sometimes use the "int i" stuff for simple loops.



  • Wow... nothing beats thread necromancy!



  • If it looks like a duck, but it stopped quacking or walking like one, and you do it hard, then you probably are a duck.



  • I really abhor HN.

    I inherited several applications from a developer who is no longer here. The code is [b]filled[/b] with examples of why you shouldn't use HN.

    For a variable to hold an instance of a StringList? strLstFileList

    For a variable to hold an instance of a TreeView? trvwFileView

    For a variable to hold an instance of a QuickReport? qckrptRptBill

    I believe in meaningful variable names, and sometimes for visual controls I'll use a prefix - not to indicate type, but to make sure they're all grouped together in Delphi's Object Inspector or it's equivalent in Visual Studio. I use i for loop counters with local scope, and add j and k if I need multiple counters. I use i for indexes into arrays, because it's obvious what it's being used for and it's quick to type between the brackets.

    I always call my StringList variables SL if there's only one and it's in local scope, because it's short and quick to type. I'm very consistent in doing this, and so anyone reading my code catches on pretty quickly.

    I think the tendency to use overly short variable names stems from the old days, when compilers had very small limits. (I did some work in Clipper back in the DOS days, and it had a limit of 10 characters for variable names.) It doesn't make any sense these days... The current limit in Delphi, IIRC, is 256 characters. I don't think I'd get anywhere near that, ever, but it means I don't have to use cryptic names.
     



  • @dhromed said:

    I use HN when there can be doubt about a type.

    Take the varname 'coordSet', seen at a place [i]other[/i] than its declaration.

    Array?
    Map?
    String?


    'arrCoordSet', of course!

    Not a very good justification. In Java and, I assume, C#, a variable is either local, a method parameter, a class/instance variable, or an imported constant. All very easy to find, even for people like myself who eschew IDEs and do all work in vim.

    And "coordSet" is a pretty poor name. The solution isn't Hungarian; it's a name like "coordinates" or "coordinateName" or "coordinatesByType".



  • @VGR said:

    @dhromed said:
    I use HN when there can be doubt about a type.

    Take the varname 'coordSet', seen at a place [i]other[/i] than its declaration.

    Array?
    Map?
    String?


    'arrCoordSet', of course!

    Not a very good justification. In Java and, I assume, C#, a variable is either local, a method parameter, a class/instance variable, or an imported constant. All very easy to find, even for people like myself who eschew IDEs and do all work in vim.

    And "coordSet" is a pretty poor name. The solution isn't Hungarian; it's a name like "coordinates" or "coordinateName" or "coordinatesByType".

    Fair enough. :) 



  • I'm going to resurrect this thread to weigh in against Hungarian – or at least the version of it that's commonly used. The prefix letters make it much harder to read the word (which actually tells you what the variable does) at a glance, because the eye 'picks' words by looking at the beginning, the end and the shape. By slapping some nonsense letters on the front, any prefix (or indeed suffix, although less so) convention makes it hard to read.

     There's also the issue of what happens when a variable changes type, which while not common is certainly not unheard of (int to long or int to double happens quite often).

     The 'wordy' part of the name should tell you the purpose, so you don't need a prefix to do that. And I agree that if you don't know where to find the declaration, you've no business changing the code until you understand it more (plus, modern IDEs will tell you what type a variable is and where it's declared).  
     



  • prepBut nI vrbLike adjHungarian! qWhat's artThe adjBig nProblem?



  • @asuffield said:

    prepBut nI vrbLike adjHungarian! qWhat's artThe adjBig nProblem?

    nice.



  • Hungarian Notation is the tactical nuclear weapon of source code obfuscation techniques; use it! Due to the sheer volume of source code contaminated by this idiom nothing can kill a maintenance engineer faster than a well planned Hungarian Notation attack.


  • Now, the question is: What do you tell Hungarians who come to the US, and all they know is how to program in Hungarian notation?
     

     


Log in to reply