The ThreadMode discussion below is primarily an argument. A good summary of Hungarian Notation and Systems vs Apps Hungarian can be found on WikiPedia: http://en.wikipedia.org/wiki/Hungarian_notation#Systems_vs._Apps_Hungarian Further reading on the topic can be found in the original paper, as mentioned below: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs600/html/hunganotat.asp -TomBrend A variable naming convention developed by CharlesSimonyi at Microsoft. The word "Hungarian" is used to describe either Simonyi's original nationality or the appearance of the variables, or both (I forget) (''he is Hungarian, for what it's worth''). In Hungarian, the types of variables are encoded into the name. For example, m_pszName would be a (m_) member variable of a class, that is a (p) pointer to an (sz) null-terminated string. Hungarian was originally developed to support C programming by providing visual cues to compensate for C's lax type checking. However, it has been used in other languages. Hungarian notation inspires some of the most bitter religious wars among programmers. Detractors claim that it is indecipherable and that no real standards exist for its usage. Adherents claim that it becomes more likeable with use, and the instant mnemonic recognition of type that one gains with familiarity aids program comprehension immensely. -- MichaelFeathers ''I would normally edit the above to correct the factual errors, but I am reluctant to hack about with anything written by Michael. However, I have to make the note that the characterization given is quite simply wrong, and is based on a very common misreading of Simonyi's original article. To see why, start by reading the article by JoelSpolsky about HungarianNotation:'' : http://www.joelonsoftware.com/articles/Wrong.html * Quote: "The dark side took over Hungarian Notation. Nobody seems to know why or how, but it appears that the documentation writers on the Windows team inadvertently invented what came to be known as Systems Hungarian." ''In essence, the original article never advocated encoding the actual machine representation "type" into the name, but to encode the semantics that the "type" cannot and does not give. Adding "p" to show something is a pointer is pointless, but when integers are used to encode rows and columns, prepending a "c" or "r" makes wrong code look wrong. Read the article - Joel says it better than I can.'' ''Although Michael is presenting a balanced description, he is still presenting the common, modern, wrong understanding. Many people argue about the ideas involved, but before you do, please ensure that you are arguing from knowledge and understanding, not from ignorance or prejudice. Read the original:'' : http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs600/html/hunganotat.asp [You don't mention any of the things you believe to be factual errors in Michael's description, and I don't see any such.] * Michael says "m_pszName would be a (m_) member variable of a class, that is a (p) pointer ..." ** The "m_" practice is extremely widespread in industry, whether Simonyi/MS suggest it or not, it is not only an example of de facto Hungarian notation, it actually is sometimes argued to be a good example of the right thing to do, and that follows Simonyi's original principles, because there's no question but that it helps avoid certain common scoping mistakes. (The counter-argument is that whether something is a member or not could be considered an implementation detail, but the overall answer is not 100% clear.) * I said that putting "p" to show it's a pointer is pointless. * A careful reading with the benefit of doubt shows that the original article did not advocate using this to show the actual types. [You do mention "ignorance and prejudice", but Michael's description is completely free of such; he's not even taking any stand of his own, he merely mentioned that there are religious wars between adherents and detractors. To read something negative into this is so grossly unfair to Michael that it staggers the imagination.] * My comments about arguing from prejudice and ignorance were not aimed at Michael, but at the expected readership. I do now realize that it can be misread and I apologize for any offence inadvertently caused. I have modified what I wrote in the light of this realization, but Michael is describing the common misconception, not the actual system Simonyi originally proposed. [The two URLs you provide are informative, and should remain on this page, but the support for your position is thin. For one thing, the question of how HungarianNotation "should" be used, and how historically it was originally defined, is different from the question of how it '''is''' widely used, and the latter is what forms the pragmatic de facto definition.] * At this point, I abandon the point-by-point reply and direct the reader to my reply below ... [Worse yet, although Simonyi begins in some sane ways, talking about HungarianNotation types being a superset of simple machine representation types, and nodding towards OO language types, and implicitly distinguishing structural types from named types, the microsoft article then goes on to provide official standard examples that violate that sanity, such as "pch" for a variable that is a "pointer to character". This is self-contradictory. It violates the arguments Simonyi made for the whole system. "Pointer to character" is as concrete as a type can get, there's nothing abstract about it.] [One can make an argument supporting the notion that something like "secondRowParameter" is a better name than "i", but your apologia, and criticism of Michael, completely falls apart in the face of that "pch" example, which typifies what detractors dislike about HungarianNotation, yet is explicitly part of it - and is the aspect that seems to be most widely implemented.] [I think Michael's description should remain intact, but that it would be appropriate to add a note explaining the sane part of Simonyi's original suggestion, and that Microsoft itself corrupted it into something lacking sanity. Joel's example is a nice one, I think: "us" as a prefix on unsafe strings and "s" for safe strings. Aside from religious wars over whether it would be better as "unsafe" and "safe", that's a perfectly legitimate convention to help keep the code straight.] [It's also worth mentioning that a certain percentage of this stuff is fixable by creating assignment-incompatible objects to avoid errors. Even in C, one can do this by, for example, wrapping an int inside a struct. Joel's example could be struct { char *s; } Safe; and struct { char *s; } Unsafe; - and one then gets compiler assistance in catching errors.] Doug, everything you say here is true. It's frustrating when people present the common, modern understanding of "Hungarian notation" and then tear it apart - as it should be. They then never look at the original paper, never try to find something useful, and never learn the lessons that are there. It's true that "rows" and "columns" can be wrapped and then the compiler catches the errors. Some programmers do. Do you? * Yes, and ditto, I train people to do this, whether they work for me or not (the latter is of course more difficult, since one must persuade rather than insist). In C++, it turns out to be an interesting rare good use of the preprocessor: I created a terse macro for completely painlessly creating such wrapper classes (templates didn't seem to cut it for this), and that convenience eliminated all resistance. Everyone loves the type safety that this sort of thing affords, when it is sufficiently convenient that they're never tempted to shortcut it. * It's extremely cynical of you to ask that question of me. :-) You were pretty sure the answer was "no". The original paper is its own worst enemy, and the terminology and examples led directly to the misunderstanding, but there is a really good idea here that's been lost, trashed, spat upon and generally had scorn heaped upon it. So perhaps here is the lesson: : Abandon all hope of ever being understood, all ye who have a good idea but don't say it perfectly. -- Seeker of truth, finding of things that help, frustrated that people seem only ever to find why things don't work, rather than trying to find why it's a good idea and should be made to work. Well, I sympathize, but consider that you started out frustrated with all these people viewing HungarianNotation purely in terms of its misshapen dark side form, so you were further frustrated by Michael pointing to that, which lead to a certain tone in your post, to which I responded with a certain tone of my own, leading to more frustration on your part. These things snowball. Frustration leads to more frustration. I think you are correct in all this, including the suggested lesson (from which I myself have often suffered), so presumably the above can be refactored whenever someone gets the energy. I would add an emphasis here: I think that HungarianNotation done correctly is not a substitute for object wrappers, but again, too many people implicitly or even explicitly think they are. MeaningfulName''''''s are a documentation aid, and as such, do not substitute for automated safety aids, such as static type safety, when the latter are possible. This is something that troubles me about the most common kinds of reflection (the ones based purely on matching names as strings) as well. It's great, it's cool, but it's a house of cards when relied upon too heavily, because too often there is no safety net. -- Doug ---- For what it's worth, I - as a Hungarian - can tell you, that Hungarian as a language does not read or sound (at all) like Hungarian notation. Except for the "szar" prefix (zero terminated character array, IIRC), which has a meaning in Hungarian. Homework is to find out what. When you do, you will know that no Hungarian tends to use it. -- WhiteWolf Hungarian notation is far older than Simonyi's tenure at Microsoft. He had definitely developed it by the time he was at Xerox, and I'd bet it was before I started working at Xerox in 1984. -- ChrisHibbert The first I heard of "Hungarian" was in Charles's Ph.D. thesis ''Meta-Programming: A Software Production Method'' (1976), which is available online at http://www.parc.com/about/history/pub-historical.html#CSL. -- PaulMcJones ''I have to add that "Hungarian" is a human language from the Ural-Altaic/Finno-Ugric family of languages being used for probably 2000 years now. And it's agglutinative, so while Simonyi was indeed Hungarian, Hungarian Notation is also a bit like the human language. Agglutinative means that word's "types" are indicated by appending various phonemes at the end of words.'' ''Example:'' English: Hungarian: money penz my money penzem to eat enni he's eating eszik house haz in the house hazban (int) c; iC; ''Maybe not coincidence...'' ----- See also CodingStandard, MisunderstandingHungarianNotation. ---- '''HungarianNotation is the last resort of scoundrels.''' Why not the first resort? That's where it counts! ---- Here is the URL for a document which fairly completely describes Hungarian notation and its benefits: http://www.songtrellis.com/testSite/docstore/DescriptionofHungarianNotationanditsbenefits.doc To summarize, the Hungarian notation for data instances makes use of three notions. 1) UNIQUE TAGS ARE DEFINED FOR TYPE DEFINITIONS AND INSTANCE VARIABLES A large software project might use thousands of different data types. Some of the type declarations for these data types would assign a restrictive meaning to a primitive data type supplied by a programming language. Many others would supply type names to record or object declarations used within the software project. Creating a new Hungarian tag for each allows a software developer to easily identify what a data instance describes by examining its name without referring to the instance declaration. The notation has greatest utility when it is used in the coding of very large software systems (Microsoft Word, Excel, Access). There are primitive types corresponding to the data types defined by a particular programming language. Petzold, the source from which many have formed their impressions of HN, described these primitive types in his "Inside Windows" volumes without pointing out the utility of derived types that restrict the usage of the primitive types or that are used to name record structures or object types. Many of the objections below concern the folly of limiting a naming scheme to a restrictive primitive type vocabulary. It is folly. Large programming projects that use Hungarian Notation do not much utilize the primitive type names except when very generic kinds of code are being written (low level heap managers, string handlers, etc). When a data type is not primitive, a more restrictive tag is almost always employed to label a data item and the actual primitive implementation of the type is not mentioned in the Hungarian tag. 2) PREFIXES ARE USED TO LABEL COMPOSITIONS OF DATA TYPES The data types defined in a software project can be composed and transformed in a number of interesting ways. Hungarian Notation defines a number of standard prefixes to make clear when a data instance is intended to be used in such a composition operation. Some of the standard prefixes that can be applied to data type tages are: p for a pointer. A pfoo would be a pointer to data item of type FOO pp for a pointer to a pointer. h for a heap handle. This is a pointer to a pointer that points at a data item recorded within a heap. rg for an unstructured array containing data items of a certain data type. An rgfoo would be an array that contains data of type foo. Individual elements would be selected by an ifoo index variable. mp for an array which is used to map from one data type to another. Eg. A mpdochdod would be indexed via a doc index. The expression mpdochdod[doc] would produce a handle to a document descriptor. dn for an array whose elements that describes a meaningful index such as an opcode. If the meaningful index were an OP type, a data structure of type EOP (entries for OP) would be defined, and a dnop array would be defined which describes what each individual op means 3) SUFFIX MODIFIERS ARE USED TO DISAMBIGUATE INSTANCE VARIABLES AND EXPRESS INVARIANTS When more than one instance of a data type is declared in a programming name space, a unique suffix is affixed to the item to disambiguate it from all of the other instances in use within a function or procedure. This suffix can be a hint to describe the usage of the data item. More interestingly, when a data item is an instance of a pointer or array index, a standard suffix modifier can be affixed to a Hungarian, which expresses the invariants that must be maintained when that data item is used. Some of the standard suffixes which express invariants are: Max - added to an index data instance which records the actual size of an array or data block. eg. the declaration of a an array of type FOO in C would be: FOO rgfoo[ifooMax]; Mac - added to an index data instance to indicate the limit of an actual usage within an array. Mac stands for current maximum. It is invariant that ifooMac <= ifooMax. ifooMac == ifooMax is the condition which is true when all entries within an array are in use. First - added to an index or pointer which designates the first element within a range that may be validly processed Last - added to an index or pointer which designates that last entry within a range that may be validly processed. Lim - stands for limit. An ifooLim is equal to ifooLast + 1 and designates the location where a new foo item could be recorded in an array or data block. There is a Hungarian standard for naming functions and procedures. In many cases, these names quote the data tags used as parameters and the type of the return value if one is generated. This is explained in the document referenced above. The discussion below shows little cognizance of the usage of Hungarian Notation to notate composition of data types and to express invariants that must be maintained as a data item is used in a program. I have found these features of the notation to have very high utility. -- DavidLuebbert ---- Why HungarianNotation is good: * Instant mnemonic recognition of types ---- Why HungarianNotation is bad: * Hides the purpose of the variable under all the "warts". * If a type changes, you're forced to rename your variables to reflect the new type. * Violates OnceAndOnlyOnce. ---- One of my past ObjectOrientationTips is about "Hungarian Notation - The Good, The Bad, And The Ugly" (see http://ootips.org/hungarian-notation.html - it also has links to tutorials and to an explanation of the name). Personally, I like PronounceableName''''''s. Must be my HyperCard background. :) -- YonatSharon ---- For a long time, there's been one rule in my Naming Guide (http://www.objectmentor.com/publications/naming.htm) that goes against hungarian, and that says pretty much all I want to say about it. -- TimOttinger ---- See the discussion in ShieldPattern; HungarianNotation is an Anti Shield (DesignBurp?). -- DaveHarris Exactly. which makes it interesting to evaluate... if a DesignShield hides the internals, could its opposite be a DesignBurp?... Why was this DesignBurp so popular, where/why does it pay well? -- AlistairCockburn ---- I like hungarian notation in C because C forces me to declare variables at the start of blocks - so by the time they're used, their type may have scrolled off the screen. The other thing about C is that being non-OO it tends to encourage larger functions; I'd say that the typical C function is 20-100 lines long where the typical C++ one is maybe 5-20. Long functions also make it likely that the type has gone some place that requires some scanning. In C++, I think it's a lot less use; apart from the two issues above, in C++ you're usually dealing either with an accessor function, and most of these are actually named after the type. For example, if I have a class Foo with a member of type Bar then I'll usually call the member myBar and have an accessor called bar(). So if I have an object of class Foo called foo, it's obvious what the type of foo.bar() is. And C++ used with STL generates more types than you could ever shake a stick at - hungarian notation for one of these would be longer than the variable name itself. If you've ever looked at the mangled names of variables that compiler generates to stick in object files you'll see some hungarian notation that'll drill your eyes out of their sockets. Contrast this with Perl, where the type is determined by the use. Sort of mandatory hungarian ... well maybe not ... -- PeterMerel ''If you think about it perl already makes you use a hungarian notation by making you prepend scalars with $, arrays with @ and hashes with %'' Not really because perl is contextual. You could have an array named "i" and use it in a scalar context as $i. What now, huh? :-P ---- The claim that "C encourages long functions" is more controversial than the claim "many C programmers write long functions"! Older versions of C didn't do much strong type checking, so encoding types in names could help avoid mistakes which today's compilers would catch. The Windows header was an example - Microsoft had scores of "handle" types all of which were integers. (They have improved things since.) If we stipulate that Hungarian never replicate information the compiler checks, then it can be useful today. For example, many people encode scope in names: using capitals for globals (like class names), "my" as a prefix for instance variable and lowercase with no prefix for stack variables. The cost is low because only a few things need distinguishing. -- DaveHarris ---- I feel obligated to put in my DevelopmentTools case here (again): HungarianNotation seems to be used to embed type information about a certain variable everywhere in the code where it is used. But, my standard human factors rant about this kind of practice applies: * It obfuscates code from being "read" like text, and thrusts this property of the variable forward even if you didn't care about it as the reader * Refactoring the type of that variable becomes an O(number of uses) operation that wastes the developer's time * It is a human-maintained convention that can be erroneous, thereby misleading code readers even more than they might have been if it wasn't there. So, should you check every notational assertion with its declaration anyway? If so, then what is the point of this notation? What I think you really want is for your interactive development environment to give you a rollover (ToolTip, for you Windows junkies, or minibuffer message for you Emacs junkies) that shows you the declaration of this variable at every use point when your cursor goes over it. -- RusHeywood ''Visual Slick Edit (Windows) does this.'' VC6 has something approaching this. They copied it from VB - when you're typing code to call a method, it pops up with a prompt window showing the names of the arguments. It's not perfect, but it's a step in the right direction. -- RogerLipscombe ----- My problem with Hungarian Notation is more fundamental and stylistic - I think it encourages sloppy, sprawling, poorly decomposed code and careless, ill-coordinated maintenance. Simply put, if your namespace is so polluted that you need a cheap trick like HN to keep track of your variables, you've made a terrible mistake somewhere. You should never have so many variables and constants visible at one time; if you do, then you need to review either your data structures, or your functions. This is especially true for code written under either the OO or FP methodologies, as a primary goal in each is to isolate (in OO) or eliminate (in FP) those variables that are not immediately needed. HN notation also presents a problem in the case of OO, in that it interacts very poorly with polymorphism. It is actually undesirable to know the class of an object in many instances, but at the same time marking it with the parent class tag is misleading and contradicts the goal of HN. As for marking globals as separate from locals, why on earth do you have any globals in the first place? ;-) -- JayOsako ''I agree that HungarianNotation is bad because it's a crutch for overly large namespaces. That's why I use single character variable names to force myself to write clear code.'' -- EricUlevik ''My Response:'' 26 variables? At once? How can you manage that? Seriously, HungarianNotation is only a symptom of a larger problem. Too many programmers see the solution for excessive state to be more state; they end up with variables to track variables to track variables, all bound up with arcane rules for naming that are supposed to be indicative of their meaning (which it rarely is). The point isn't so much that you have to limit the number of variables, but rather that large proliferations of variables in the local namespace is a sign of a design mistake. Why would they all be visible at once? Aren't there some abstractions they can bound into? Why do you need this particular bit of state visible here, anyway? The rule should be simple: if you don't need to see it, you shouldn't be able to. Period. Like VisualTools, HungarianNotation is not SoftwareEngineering, its TheIllusionOfSoftwareEngineering. It's an easy and comfortable fix that ''looks'' good because you can DoItNow and you don't have to do all the hard thinking that comes from trying to do the RightThing. The time you 'save' using it will be more than spent later trying to maintain the resulting morass. -- JayOsako ''This is very well put, and pretty much sums up my feelings on the matter. -- KevlinHenney'' HungarianNotation is yet another example of a SystemOfNames. ---- '''A possible rationale for using it ...''' In strongly-typed languages, variables have a constant type for the duration of their life that is known at compile time. This ensures a low number of typesafety issues as most are caught during compile time, the '''second cheapest''' time to detect them. It's hard to determine the type of a variable when you are coding. Problems like whether or not a string is a plain ASCIIZ char *, or a fully wrapped string object are hard to resolve from use. However, semantically, they are somewhat different. It's important in C when utilizing printf() as the difference between %ld and %d could be the world. The '''cheapest''' time to detect type bugs is when writing the code. Also, it helps code review and summary reading of the code as one doesn't have to go back and forth between the declaration (typically in a separate file) and the use. More importantly, HungarianNotation makes for SelfDocumentingCode. The other solution may be a DataDictionary. Ugh! Could you please justify how HungarianNotation makes for SelfDocumentingCode? It seems to only cover primitive data types, which are often implicit in the name and are explicitly declared in the language (I am assuming you are not applying HungarianNotation to languages that are not typed), and does not handle objects, classes, or interfaces. What does "oPerson" tell me that "thePerson" does not? '''However, ...''' ''"It's alphabet soup. I don't understand what all these characters are supposed to mean."'' This argument against it is pretty weak; it doesn't take long to learn and get used to a given decoration system. ''"Everyone uses a different convention."'' This is a very good argument against this. However, within a given codebase, consistency will generally get you where you want to go. Even then, programmers are slow to change habits sometimes, so different styles may collide. This is resolvable on small projects when it is easy to become familiar with other programmers' styles. On larger projects, a company-wide standard may be useful, albeit annoying. ''"When I change the type of the variable, I have to do a global search and replace!"'' Granted, however, the type of a variable changes very infrequently compared to the number of times one has to look at its declaration to determine its type. Overall, you'll save time. ''"It makes it easier to come up with meaningless names."'' The thrust of this argument is that you are now given a set of characters to be the symbol just from the type, so you don't have to bother coming up with MeaningfulName''''''s. This is very true, especially for so-called "temp" variables. ---- '''An historical rationale for using it ...''' It is suggested on other parts of this page that C encourages long blocks of code with variables declared at the top. I read in other parts of Wiki about SwitchStatementsSmell. Suppose your toolbox includes Windows 2.0, a C compiler, and a text editor with no color highlighting. The way we were encouraged to program user controls in this environment was to write a ''''''WindowProc with the responsibility of processing all the messages of interest. Each message has an associated integer constant defined. The preferred way to build such a method is to build a big switch statement with a case for each message of interest. An interesting control will have non-trivial code for many messages. The probability that you write expressions using such variables that is textually far removed from the declaration is high. You've got to do something to help understand what you meant when you declared the variable in the first place. Now, if your product enjoys an unprecedented success in the marketplace and becomes the overwhelmingly predominant platform in the world, that code winds up being ubiquitous. There are better tools these days. OO languages abound. Compilers, and other development tools are more mature. We don't have to use HungarianNotation any more to make sense of code as much as we used to. However, since there is so much of that code in the world, we will all have to understand it for the foreseeable future. If we do maintenance on such code and wish to maintain consistency of style, we will have to write using HungarianNotation. -- SkipSailors ---- '''"It's alphabet soup. I don't understand what all these characters are supposed to mean."''' ''This argument against it is pretty weak; it doesn't take long to learn and get used to a given decoration system.'' That doesn't resonate with my experience. I've been stumbling through Hungarian for years now and I still read code written with it noticeably slower and with less comprehension than code written without. New code is much harder for me to write because I have to look up a wart anytime I use a type that is unusual for me. I think that I may use type information differently than people who use Hungarian notation. Most of my type-sensitive code deals explicitly with translating from one type to another. The rest of my code either uses the right type for it's ''[its]'' context or calls a translator very early on. The code I'm working with right now uses several representations of the same thing: BSTRs, ASCII strings, WinNT Unicode strings, and JNI Unicode strings for strings; and pointers and jobjects for object references. So I have the problem. We use Hungarian here and what I've noticed is that it doesn't help - I still have to write and call the translation code - it's just that now I have to remember how to mangle the names after I've done the real work and I have to remember to mangle them differently whenever I change my mind. Other people on my team write the translation code inline. I can see how they would have a difficult time keeping the type information straight while writing code that does several type translations on top of the job it was originally intended to do. -- PhilGoodwin ''[The problem with your type conversion code is that the variable names should be the types, in your case. They are what the code is about.'' ''HungarianNotation is just decoration to carry information about the type along that you'd otherwise lose and have to go somewhere else to look up. They help you keep focused on the section of code you are maintaining instead of flying all over the place to figure out what the heck is going on.'' ''But if you're manipulating a variable through a type conversion, you are playing with the types themselves, not the variable. Thus, locally, the so called variables should be named after the types.'' ''As in, say, char *InputAsciizString; BSTR OutputByteString; or whatever. The decoration is worse than useless here.'' ''This is similar to when you postfix the type as in TransitionQueue. You don't need to prefix a 'Q' or whatever (???) because that would be redundant.'' ''-- SunirShah]'' ---- ''The '''cheapest''' time to detect type bugs is when writing the code.'' I disagree. Is your compiler really that slow or your environment really that cumbersome? Let the compiler do what the compiler is better at. -- WayneConrad ''Discussion in response to this statement moved to DealingWithCumbersomeEnvironments.'' ---- HungarianNotation came from the practices Charles Simonyi developed working with Fortran. So why on Earth would I want to make my '''' code look like Fortran? -- KevlinHenney ---- When I first used Fortran, its 'Hungarian' approach to declaring variable type was very appealing. Now, I favor prefixes that show conceptual type, not implementation type. As an example, an application team might standardize on 'sec' for seconds, 'hr' for hour, and 'ft' for feet, though they are all implemented as, say, doubles. Thus when you write ftsecTravelSpeed = ftDistanceTraveled/hrElapseTime you are likely to see the mistake. This is especially helpful when working in a strongly typed language that does not allow operator overloading, and the application has many dimensions and units with calculations between them. I do wish the developers of Fortran would get more respect for this idea. I don't know why Microsoft seems to get credit for so many ideas that seem to come from prior work... -- Dale Strickler ---- Fortran was the first real programming language. We use many idioms and constructs that originated from Fortran. What's your point? -- SunirShah Presumably that HungarianNotation addresses the lack of type information in Fortran (or C). In C++, with better typing, we don't need it. -- EricUlevik ---- Perhaps HungarianNotation is a pattern generated by a set of forces specific to C and C++. I don't feel a great need for it in Java, and I can't imagine a SmallTalk programmer using it. Does anyone have any experience using HungarianNotation in any languages besides C and C++? -- JohnBrewer I have been forced to use HungarianNotation (HN) many times on VisualBasic (VB, and derivatives VBA and AccessBasic) projects over the past seven years. Upon first encounter, I immediately recognized the CodeSmell since HN violates the philosophy underlying StructuredProgramming, ModularProgramming, and ObjectOrientedProgramming. I made attempts on many projects to convince other team members to dump it, but usually unsuccessfully. I have found that the HN CodeSmell never exists in isolation. If you find HN, you will also find many other CodeSmell''''''s. If you find many CodeSmell''''''s, you often find HN. I began the switch to Java about three years ago, recognizing that I had been stereotyped as a VB developer in the market. Escaping VB, and Microsoft, allowed me to escape HN. In the Microsoft world, and especially the VB world, HN is a matter of course. Disputing it is considered irrational. In the Java world, HN is practically unknown and disputing it is unnecessary. HN is attractive to those that find VB or Microsoft attractive. If you can digest one, you can digest the other. If you can recognize the inappropriateness and ineffectiveness of one, you avoid the other. -- RobWilliams Similar experience - I worked on VB in high school, and we were taught to use 3-letter type prefixes on controls in the form. So you'd have frmMain, lblName, txtName. Not as bad as HN, as it was human-legible and I probably would've ended up including the type in the name anyways (NameLabel and NameTxtBox). ---- I have worked on a large Fortran program (a flight simulator). We had 6 characters for the name, the 1st was the system (E for engine) leaving us with 5. Would have been fun to add HN to this. KevlinHenney says HN was developed for Fortran. That doesn't make much sense, because the 1st letter in Fortran is the type ... In reading all that has been written, it seems that most agree that HN is bad, or that something is wrong with the code. -- NissimHadar ---- I began using HN several years ago, and now when I look at code I wrote prior to that time (no HN) it's harder to read. I find HN useful, even though it can get ugly sometimes. But I suppose I'd hate it if I were forced to use it and hadn't already decided it was good. -- FrankBrown Could this be because you wrote the code several years ago? Also, might there be other ways in which your code has improved in clarity? -- MattRyall ---- I don't get this at all. To quote the ProgrammersStone, if you don't know what your variable is for, knowing its type won't help you. I've never seen the notation applied consistently, either - not even in Microsoft's code. In one of those amusing and ironical twists of fate, a couple of years back CharlesSimonyi endowed a chair at Oxford University dedicated to the public understanding of science. Currently occupied by RichardDawkins. -- DavidHarvey ---- Microsoft recently published Simonyi's original paper at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs600/html/hunganotat.asp -- WolfWolfswinkel I think the listing near the end of the article at the above link is a good example of how unreadable Hungarian notation is. It looks like the winner of an obfuscated C competition - ... while (*pch!=0 wHash=(wHash<>11+*pch++; cch=pch-sz; pbsy=&rgbsyHash[(wHash&077777)%cwHash]; ... etc -- JonHanson And reading Simonyi's paper (in the section "Naming for Writability"), one concludes HungarianNotation's original intent/motivation was to allow developers to better communication, express, and agree on interfaces. In the specific context of APIs (and possibly others), HungarianNotation generally works well in that regard, but then it arguably also duplicates the compiler's function of compile-time checking without promoting understanding. HungarianNotation falls down when interfaces change (e.g., Win16 to Win32) and when complex types are involved (i.e., classes). HungarianNotation is not a OneSizeFitsAll/SilverBullet/BestPractice. -- AnthonPang ---- I don't know if my style has a name, it is derived from Apple's MacApp naming system, Metrowerk's PowerPlant naming system, and maybe some other sources. * Prefix 'g' for global variables or class static variables. * Prefix 'm' for member variables. * Class name is a word or MultipleWordName that start with an uppercase letter. * Local variable is a word or MultipleWordName that start with a lowercase letter. Use 'i' only for a for-loop-index variable. * Member function is a word or MultipleWordName that start with [pick one:] lowercase or uppercase. (PowerPlant uses uppercase; Java uses lowercase). * Parameter name is a word or MultipleWordName that starts with a lowercase letter. It may have a suffix 'in', 'out', or 'inOut' if the data-flow direction needs emphasis. * A function return value is stored in a local variable named 'result' and initialized to a good default value at the beginning of the function. There is only one 'return' in the function, and that is always 'return result' at the end of the function. This allows inserting stuff - resource allocation/deallocation or locking/unlocking or debugging printf's - at the top and bottom of the function without having to look for returns all over the place. Oh yeah - I got this idea from Eiffel, as well as using assertions at the beginning and end of functions (not demonstrated here). Application* gApplication; // a totally made-up example... class Application {private: static Toolbar* gToolbar; Menu''''''Bar* mFileMenu; Menu* mPopupMenu; bool mPopupExist; public: .... virtual void StartApplication( Environment* anEnvironmentInOut ); virtual MenuItem* GetMenuItem( const Command* commandIn ) { MenuItem* result = mFileMenu->FindItem( commandIn ); if ( result == NULL && mPopupsExist ) { result = mPopupMenu->FindItem( commandIn ); } if ( result == NULL ) { result = gToolbar->FindItem( commandIn ); } return result; } }; -- KeithRay Well, I would have written the above example as: Application* theApplication; // a totally made-up example... class Application { private: static Toolbar * THE_GLOBAL_TOOLBAR; Menu''''''Bar * my_file_menu; Menu * my_popup_menu; bool popup_is_up; public: virtual void start(Environment* the_environment); virtual MenuItem* get_menu_item(const Command* the_command) { MenuItem* item = my_file_menu->find_item(the_command); if (item) { return item; } else if (popup_is_up) { return my_popup_menu->find_item(the_command); } else { return THE_GLOBAL_TOOLBAR->find_item(the_command); } } }; To me, it reads more like English, and is thus clearer. Comments? -- AlainPicard ''Your version is much better, Alain!'' Please see MisunderstandingHungarianNotation. I believe that CharlesSimonyi has complained in particular about Apple's failure to understand the notation. Hungarian notation is more than mere data-type or scope tagging. ''If you have an idea, and a single individual fails to grasp it, it might be the fault of that individual. If you have an idea, and whole organizations as large as Apple fail to grasp it, there's at least something wrong with the way you expressed it. If Apple [sic] "failed to understand" the notation, then that's a pretty sure sign the whole idea is bogus.'' Hm. It is in general easier for individuals to understand things than to get the correct version enshrined in corporate (or governmental, &c.) policy. And this effect is if anything exacerbated as organizations get larger. Cf. GroupThink. It's not especially rare for organizations to do things that 80% of their members would (or do) disapprove of. ---- HungarianNotation is one of those religious arguments with no grey zone in the middle. In my 15 years of Microsoft development, I have seen more fights over this than anything else. It used to be more important in the earlier days. I still swear by it (as opposed at it!) because I can be pages down in a function and look at a variable and know its type instantly without going all the way to the top and checking. -- sg "...I can be pages down in a function..." As I said above, one will easily swallow HungarianNotation along with all the other lunacies of a bad approach. In most Microsoft development environments, HungarianNotation is one of the few things that one can try in an attempt to bring order out of chaos. Unfortunately, the result is most analogous to throwing gasoline on a fire in order to put it out. -- RobWilliams I have to agree with Rob's sentiment, Sam. Your example suggests that HN is a useful band-aid on bad design. ---- Many moons ago in a different life I worked for Nantucket on Clipper (an ExBase derivative). Back then, I wrote an article called ''HUNG - Hungarian without the Arian'' (pun intended) which was a scaled down version of Hungarian for Dbase languages. This was an extremely generalized notation that I still use today - though less and less, mostly just for primitive types. All numbers, regardless of 16 or 32 bit, signed or unsigned start with the mnemonic "n" (nNames), an array starts with "a" (aNames), all strings start with "s" (sName), all pointers start with a "p" (pnName, psName), and so on. Exceedingly simple and purposefully non-precise. Non-POD (PlainOldData) class instances don't normally use any mnemonic. The idea is that I don't [''...?''] ---- I avoided HN for such a long time, because of various reasons stated above. I have recently changed my stance, based on findings that provide counterpoints to the strongest arguments against HN. Putting my counterpoints in text is also a way for me to think out the problem space :) If a type changes, you have O(N) 'wasted' time to fix all references. * If you are constantly changing types, you are not designing your software. If you're not designing your software, you can't expect it to last. If you don't expect it to last, you don't need to worry about conventions. (You will usually be wrong in this respect, though, since software has a tendency to take on a life of its own.) * Changing types underneath a large N number of dependent lines of codes introduces a high probability of tricky bugs. Overflow errors, sign shift errors ('>>' IA-32 SAR is not your friend), general serialization, comparison. Basically, the compiler forces you to check these type of things out. If you don't, you're just lazy, which may be okay for you... (can't vouch for your customers if any though). ** ''This is highly language-dependent. It is worst in languages where implicit conversions (that change the abstract value) and static overloading are common. In languages with ImplicitTyping and/or ArbitraryPrecisionArithmetic and no implicit conversions, changing types is almost a non-issue: if you make a mistake, the code either fails to compile or fails immediately in UnitTest''''''ing; it doesn't introduce silent, tricky bugs.'' The HN warts are nasty ugly things that detract from the readability. * Camel-casing the actual name of the variable allows you to visually filter out the 'noise' of the type ids. When you need to get more detailed information about the code, you can examine the type ids. ** ''Subjective. Most people find HN still to detract from readability regardless of the case of the name.'' * Correct usage of the warts allows you and others unfamiliar with your code to understand the intent of your types. You have to use a standard convention for types and understand the flexibility of the system. Simply using dwType, wType, lType, iType does not correctly convey the depth of tagging conventions that are available. ** ''See MisunderstandingHungarianNotation about "intents".'' You have to train new people in your system, which is an unnecessary cost. * All professional developement houses should have at least a small piece of documentation on their coding standards. If you lack standards, you will end up spending more time in lost productivity and dead-end development then you ever would have spent training your new hires. -- JacobRepp '''What about the strongest argument against Systems HN (it violates OnceAndOnlyOnce)?''' * If you use the brain-dead, understandingless idea of encoding the machine type in the name, then it does, and you shouldn't do that. If you use the originally intended but poorly explained idea of encoding the intent, or "additional type" information, then it doesn't. If you use a language that actually has proper, user-defined, machine-checked types, then it's of no value. If you use C, then it is of value. ------ '''Avoiding HN is philosophically impossible'''. If we go by the definition that "types are classifications", then almost everything is potentially a classification. For example, "leftFrameBorderWidth" has four classifications in it: * Left-ness (member of all things that belong to "left") * Frame-ness (member of all things that belong to "frame") * Border-ness (member of all things that relate to or belong to "borders") * Width (Member of all widths) A strict interpretation of HN would leave us with a zero-lengthed named, which is obviously ridiculous. In practice its usually about not duplicating the *languages* or app's types. But generally what becomes a formal or declared type is somewhat arbitrary or situational. --top I think you hit the relevant point at the end there, but didn't emphasize it nearly enough. Avoiding HN is '''only''' about not duplicating types already described in the language environment. After all, duplicating the type violates OnceAndOnlyOnce: the classification is represented in both the name and the declaration (or context, for TypeInference). Avoiding HN means that if you change the formally recognized type, you don't need to also change the name. Of course, given a good RefactoringBrowser, doing so would be a non-issue. ------- '''Practical - Only When Helpful''' In general I see cases where they seem helpful and cases where they just create unnecessary verbosity. For example, "amount" is almost clearly a number. One does not need to repeat the fact that it's a number. But at this point I cannot state any clear rules on when to use it. It takes experience and guessing what the reader might be thinking when they see it. I once got into an EditWar over the term '''"book" appended to wiki titles''' because I kept mistaking them for "real" titles instead of book titles. Example: CleanCode. Being that I kept making this mistake with such titles, I decided to "improve the world" by adding "book" to the titles. This set off the no-HN purists. I lost the EditWar and would like to thunk the purists on the head for what to me was a very practical concern. (I stated this before, but it got deleted or lost.) --top Venting Jul. 2012 - Still pissed about this issue. -t Venting Nov. 2012 - Still pissed about this issue. Got "tricked" yet again twice in one week. -t Venting Feb. 2014 - Got tricked again. Arrrgggg. Venting Apr. 2014 - Got tricked again. Venting Jun. 2014 - Arrrrg II Venting Jul. 16, 2014 - PurelyFunctionalDataStructures did it to me again. Venting Nov. 17, 2014 - Snagged again. Arrrrg III. Anybody want to form a coalition to change this stupid convention? -t ''The simplest way to change this convention is this: '' ''personally deprecate or obsolete your own use of it'' * ButUnless ** you program for a living and the stuff you code involves other's code, then you just have to live with it. (It's a ten-ton rock, you probably won't dislodge it or chip it away) ** you can still code in such a way as to avoid your use of it I tried that. It created an EditWar. I'd rather the rationality of doing it properly (non-misleading titles) kick in and a consensus reached to fix it. ---- You mean change it and fix back-links? I tried doing that before, and met with resistance in an EditWar. I'm not sure if the resistance was a small number of determined individuals or a group decision; although fits the pattern of the first. Either way, I'd like to approach the decision a bit more formally this time, hopefully with more backing this time around. -t How about a handle it by people expressing their preferences by a '''vote''': Bookify wiki titles: * TopMind * [your handle here] Keep title as-is: * [your handle here] Change presentation, leaving title CleanCode as it is, separating page into classifed areas, First, treat the title as a subject, with paragraph or section in the page describing what constitutes "CleanCode" Second, a separate paragraph or section within the page treating CleanCode as a Book Title with ISBN (link), a short summary followed by a formal bibliographic note -- DonaldNoyes WeNeedExamples: see re-write of the page CleanCode -- DonaldNoyes.20140408 * ''I'm not sure I understand the above paragraph. What does CleanCode have to do with this? You offered it as an example, I merely expanded by offering a treatment * ''While I agree it's good to make it clear ON the target page that it's a book; the main problem is that one does not know it's a book until '''after''' they click. "Book" should be ''in'' the title. Clarifying at the topic page itself is not really a problem that needs a vote because one can do that without asking permission by making "Book" visible and bold on the first line. The formatting of the page has almost nothing to do with HungarianNotation. The Book-ness aspect is important enough to be part of the title. -t'' ---So you would prefer: subjectCleanCode bookCleanCode two pages rather than one pages treated with a Hungarian-like notation of page-type included as part of the page name No. I just want the one and only title to be BookCleanCode or CleanCodeBook. The actual content of the page is mostly a non-issue. If the book spawns a bigger discussion, then CleanCodeBookDiscussion can be formed. ---- There is a recent article by an expert on the subject at http://www.intentsoft.com/hungarian_notat/ ---- See also NoStrings (which is also about typing of primitives) CategoryProgrammingLanguage