|
For me, I used to use Hungarian when I was coding in MFC and C++. Now that I have been using .NET I don't use it for a few reasons. The modern IDE can show you the type very easily. People have changed types and then were lazy to rename the variables. Names like these are like specs, they get out of date pretty quickly.
Some people on my team use the old m_ or just m to say member variable. One person just uses an _ but at the end of the name, not the beginning. So typically since it is a religious war when it comes to things like this or where he proper place to put the curly braces, we typically just state to follow the coding convention that the person wrote the code in. If you cannot understand it, then I really don't want you on my team anyways.
Of course taking home 300 lines of code from your work is actually concidered IP theft where I work unless you have a company laptop and can VPN in. That and then picking notepad to view the code is just not right. At least get Notepad+.
Steve Maier
|
|
|
|
|
Because most people do it incorrectly.
The guy, Simonyi, who invented Hungarian notation meant for the names of variables to carry the kind of thing it is, not its type.
So, instead of
int iRowScr, iColScr.
List<int> ilBal;
you'd have
int rwScreen, colScreen;
List<int> Balances;
He never intended for the variable name to carry the underlying type, but rather the name should be informative of what it is.
If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams You must accept one of two basic premises: Either we are alone in the universe, or we are not alone in the universe. And either way, the implications are staggering” - Wernher von Braun
|
|
|
|
|
As pointed out above, hungarian notation was meant to signify the purpose of a type, not it's underlying type. The only notation I use is "p" for pointer, "m" for member data and "h" for handle since they indicate a fundamental difference in how they are used.
My biggest problem with Hungarian notation are:
1) The abbreviations frequently makes no sense.
2) If code is ported or variables changed, the notation is often wrong. In the current code I'm working on, it's common to find sz in front of pointers, dw in front of long longs. is "b" a bool, BOOL or int? I just looked at some code with an 'h' prefix, but the original programmer had turned it into a pointer (he argues that it's a pseudo-handle--great, then encapsulate it.)
3) In connection with the above, if a data type becomes an abstract type or is extended, it can cause serious confusion. (I've see way too much code where something like bCanReplace actually holds an enumerated value. (Last year, I ported a bunch of code to Unicode in preparation for a CE port. I removed what Hungarian that I could, but the code is littered with "sz" prefixes, among other things--is the sz an ANSI or Unicode string?)
4) It is often accompanied with short variable names. Once you make variable names longer, the meaning becomes clear and the Hungarian notation becomes redundant (and, going with the above, often misleading.)
Any developer that insists on using Hungarian should be forced to write a style guide on their personal notation.
(On par with my hatred of Hungarian is excessive typedef'ing. Some it nice, even necessary, but I've seen code where they redefine EVERY type for no reason.)
|
|
|
|
|
1) Hungarian notation does not work well with generics or templates or code refactoring (changing an int for a long for example).
2) With modern editors, you will know the type simply by a mouse over a variable.
3) With properly written code (small functions, single responsibility classes...), it should be easy to understand the code anyway.
4) You should avoid cast and the compiler will show most incompatibilities anyway. And if you use int consistently when it make sense, type information won't be that much useful.
5) After having stop to use that notation for more than 5 years, I can say it is much better that way. By using sensible variable and function names, it is generally relatively easy to figure out what the code does.
6) If you are using primitive data types 90% of the time, then you are probably reinventing the wheel and you classes probably have way too much responsibilities. Either with BCL in .NET or STL (or boost) in C++, you should be able to use a lot of existing stuff.
7) If you want to review code, then you should also print the header.
Philippe Mori
|
|
|
|
|
1. It's pug-ugly.
2. It encodes the data type directly in the variable name, if the variable's type changes, all references must be updated.
3. If you have a 300 line code block with no variable declarations, I suspect you have worse problems than use of Hungarian notation.
4. Most people who claim to use HN actually use the HN exemplified by MS in the 1990's. This is mis-use. Original usage used, for example, "i" for index, not for "integer". The prefix was meant to give the usage, not the data type.
5. Insistence of HN in your coding conventions is likely to scare off talented developers.
Nowadays, with long variable names, I (along with most other developers) prefer to give variables descriptive, readable names rather than obscure names relying on "conventions" which change with the code-base.
|
|
|
|
|
I understand #2 but it's a wee bit silly.
How often do you change a variable type - and even if you did the IDE asks to change all of 'em for you. It takes 3 seconds.
|
|
|
|
|
It occurs more often than you might be aware.
If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams You must accept one of two basic premises: Either we are alone in the universe, or we are not alone in the universe. And either way, the implications are staggering” - Wernher von Braun
|
|
|
|
|
Agreed to the fact that, Hungarian notation helps us to identify the variable type..
But in the modern world of OO programming where we mostly now-a-days with custom classes and entities. You will mostly be using Custom types for your variable.
In that case its seen people will use objFirstCustomer where obj will stand common for all of the custom types... which doesn't show what data type it is.
Or you'd better name its as curManFirstCustomer where the same curMan doesn't even will denote what type of object is it.
So thus its completely meaningless to use hungrily notation... where its doesn't serve the purpose fully...
Also normal .Net notation keep your code neat, presentable and shows more uniformity...
|
|
|
|
|
I use the class name only with a leading lower case letter for local and add m_ for class level s_ for static and p_ for parameter - it's easy. It may look ugly but it's clear.
|
|
|
|
|
A more interesting question is, why do you need to know the type in the first place?
My take against it is code without prefixes are more readable. If the variable name tells me nothing, then the name is the problem, not the type or lack of prefix.
Another thing is I find it impractical. It's easy to find prefixes for primitive types, but what about custom types? Should we invent prefixes for all of them? What if we do, doesn't accAccount look pretty stupid?
|
|
|
|
|
Custom types are easy - I just use the class name only starting with a lower case letter
|
|
|
|
|
David Roh wrote:
Custom types are easy - I just use the class name
only starting with a lower case letter
And what do you use for a template that references two other templates where those reference other classes?
|
|
|
|
|
Sure, we can always find difficult issues - the idea is to find ways to make our code more readable and understandable for whoever has to maintain it.
My style has changed a lot over the passed 44 years of coding and it is still changing as I discover better ways of making my code more reliable and more maintainable.
It's really frustrating, for example, when I am reading someone elses code that makes it impossible to tell a local variable from a class level variable - maybe that does not bother you but it does me.
I certainly welcome any ideas for making my code better; however, not doing the best that I can to let the reader know about the type, scope, and usage of a variable is a non-starter for me.
|
|
|
|
|
David Roh wrote: Sure, we can always find difficult issues - the idea is to find ways to make our code more readable and understandable for whoever has to maintain it.
Yes that is a common way to rationalize subjective preferences.
David Roh wrote: It's really frustrating, for example, when I am reading someone elses code that makes it impossible to tell a local variable from a class level variable - maybe that does not bother you but it does me.
Nope that doesn't happen to me.
What does happen to me is that I get frustrated when I realize the code has no error checking. Or is ignoring part of the API Is it supposed to be interacting with. Or it is just doing something wrong with the API. Or it has some horribly inefficient design based on a piece of code that by definition must handle high volumes. And other types of problems like that.
If my most serious problem or even close to most serious problem was confusion about the type of a variable then I would suspect that I had moved into an alternative reality.
David Roh wrote: I certainly welcome any ideas for making my code better; however, not doing the best that I can to let the reader know about the type, scope, and usage of a variable is a non-starter for me.
And I welcome ideas that objectively make code better. I do however realize that most ideas not not backed by anything objective. I also recognize as well that vast majority of development problems do not have anything to do with the minor subjective details of syntax. Similar to worrying about what color of nail polish works best while ignoring the symptoms of a heart attack.
|
|
|
|
|
Well, I am a firm believer in Hungarian and here is why - I believe that the name of a variable should instantly convey three vital pieces of information to the dev:
- it's type and I do mean type as in compiler typeof not semantics (regardless of what Charles did or did not intend)
- it's scope - is it local, a parameter, is it a passed in reference, a class level variable
- a clear indication of it's function or purpose
Different devs have their own view on how to write code; however, I believe that it's better to have a good logical reason for a belief rather than just a prejudice.
I believe that one of the reasons that Hungarian is considered bad is due to the way that many devs implement it - that is, each group uses very short abbreviations that are not clear to someone who is not part of the team so when you look at another teams code, you have to learn their abbreviations. Different teams have different rules and different ways of implementing Hungarian which make it a hassle to read another teams code.
I believe that it is not Hungarian that is the problem but rather the way that it is implemented that is the problem.
First we do very little abbreviation and only if it is an abbreviation that is so common that a noob would clearly understand it. We use longer names - yes we believe in self documenting code which means my manager should be able to read my code and understand what is being implemented in general terms (we don't however go to extremes).
If a passed in parameter is a reference that will live after a function is finished, then it is important to know that altering it can have long term consequences. If a variable is a class level variable, it is extremely important to know.
It should also be obvious that the more accurate the variable name clearly indicates it's purpose and function, the less potential there is for another dev to misunderstand or the original dev when returning to old code.
Saying that Intellisense will solve the problem or that we can mouse over a variable is not a solution because when we read code and think we understand, we rarely mouse over or use Intellisense on what we think we already understand.
Saying that Hungarian is bad because the type might change is a really weak argument - in the first place, types don't usually change that much; second, if a type does change, I certainly want to know; and lastly, with today's IDE refactoring capability, is really that hard to change a variable name (it's certainly easy for me).
We can argue about the best style to use to convey information to another dev reading our code, but I find it difficult to believe that any professional dev would say it's not important to be able to easily and quickly understand a variables:
- compiler type
- scope
- purpose
but I am sure some will.
It's about trying to find better ways to write reliable, easy to understand code - so what ever helps is a good thing.
|
|
|
|
|
Well argued.
I simply disagree.
Variable types change a lot more than you seem to be aware. Especially in an agile environment.
If a variable is given a descriptive enough name, then it's underlying type is already apparent in the name.
Hey, but if it works for you go for it. I'll never read your code and won't work somewhere where it's required.
If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams You must accept one of two basic premises: Either we are alone in the universe, or we are not alone in the universe. And either way, the implications are staggering” - Wernher von Braun
|
|
|
|
|
David Roh wrote: Different devs have their own view on how to write code; however, I believe that
it's better to have a good logical reason for a belief rather than just a
prejudice.
Devs come up with all sorts of ways to rationalize that their personal subjective preferences are objectively better.
David Roh wrote: Saying that Intellisense will solve the problem or that we can mouse over a
variable is not a solution because when we read code and think we understand, we
rarely mouse over or use Intellisense on what we think we already
understand.
In my experience, I can't recall ever seeing a single bug traced to a misunderstanding of the type.
On the other hand there are vast other categories of bugs that show up over and over again and which cost businesses real money to find and fix.
So given your stict approach to just variable naming could you provide some detail as to what other process practices you mandate to insure that real and costly errors which impact development efforts do not show up as well?
David Roh wrote: ...but I find it difficult to believe that any professional dev
You must really work in some different domains than I do. In the sectors that I work am I am just happy to come across code (like whole methods and classes) that are easily understood from a functional point of view. Too often I come across code with problems like the following.
- Code that was obviously never tested fully
- Code that was never even used.
- Code that was not even appropriate for the business (no known use ever.)
- Code that does absolutely no error checking.
- Code that is so convoluted and has such a high coupling that it scares me just to look at it. And of course there is no unit tests for such code.
|
|
|
|
|
I don't care for Hungarian notation because it doesn't add any useful information.
Consider the following two variable names:
CustomerName
strCustomerName
There is no added value to the 'str' prefix in that example because both variables are obviously string variables. All my variable names have a tendency to make their type obvious - there is no reason to use short, confusing names where a particular notation is required.
The tool tip will tell one the type anyways.
|
|
|
|
|
CustomerName could also be a class. such as (in shorthand):
class CustomerName
String FirstName
String MiddleName
String LastName
Int32 SalutationID
Int32 TitleID
|
|
|
|
|
While I doubt anyone would create a CustomerName class, I think your point still stands.
Regardless, I've never found Hungarian Notation to have enough benefit to stick with it - and that is after having used it for years. If someone else wants to use it that's fine with me.
|
|
|
|
|
Same here. I neither recommend it nor discourage it. I do like the idea of a shared notation when working as a team.
|
|
|
|
|
Hungarian Notation expresses data type, but it does nothing for, and can even obscure, data semantics. I'm sure that was no part of Charles Simonyi's intent, but it does seem to work out that way quite often.
The old guideline that one should keep one's procedures / functions / methods short enough to be completely viewed on the monitor screen tends to produce the best legibility. If you can see everything at once, it's more difficult to go astray about either type or semantics.
My personal practice is to keep procedures as short as possible -- it's been a long time since I last wrote a procedure that can't be displayed in its entirety on the screen -- and to adhere to an inside / outside convention regarding variable names:
- Variables declared inside the procedure will have short names, with the exception of static variables whose significance extends beyond individual invocations of the procedure.
- Variables declared outside all procedures will have long, maximally descriptive names, since this is the space in which most problems of coupling and timing arise.
- Of course, those "outside-all-procedures" variables will be minimized in number, and protected from thread collisions with mutexes as appropriate.
Now, I'm a real-timer; my applications are always heavily multi-threaded, and I'm always intensely concerned with attaining a reliably predictable response time to any imaginable event. If you do other sorts of programs, you're likely to have different desiderata...but I can't imagine that the conventions described above would harm you, even so.
(This message is programming you in ways you cannot detect. Be afraid.)
|
|
|
|
|
I used Hungarian notation in C++ all the time as it is close to the machine and so things like pAddress and ppAddress and dwAddress and lpdwAddress and wAddress, or sStructure and tTypedef etc are very useful distinctions.
With higher level languages I tend not to annotate strings, and booleans are usually posed as a question like hasLoaded, isUserFemale. Though annotations to suggest private / protected variables like the underscore (_) I still find useful. We don't often have to consider whether something is 16, 32, or 64bits long though, and we rarely access raw pointers so pAddress and ppAddress have less use, and sStructure and tTypedef are generally just full classes at the detriment to performance. Also we use var a lot and let the compiler define the type so this is another factor.
The next factor is the IDE, if the solution is fully integrated like in MS Visual Studio then you can easily go to the definition or hover over the variable so it is less necessary. Though as you say C&P'ing snippets elsewhere and you won't always know what they are though you can usually guess primitives and anything complex you will need the class/structure/typedef anyway.
So I would say - carry on for C/C++, ASM etc but for higher level language where vars are often chosen at compile or even runtime then sometimes it is ok to leave it out.
|
|
|
|
|
VuNic wrote: I just open it in notepad and try to figure out what datatypes all these variables are.
Well, I might not know why you're using notepad instead of VS. But couldn't you at least use Notepad++?
I mean, you can't be doing this for nostalgia purposes only. Or could you?
"To alcohol! The cause of, and solution to, all of life's problems" - Homer Simpson
"Our heads are round so our thoughts can change direction." ― Francis Picabia
|
|
|
|
|
Before writing the coding standard, I would recommend reading "Code Complete" which gives some very specific arguments about naming conventions and other things that would be in the standard. The good news is that no matter what, just HAVING the standard, even if it's not perfect, will go a long way.
For our company which is largely focused on embedded projects using C, we adopted one that was already well developed (Michael Barr's Netrino embedded standard), bought a few hard copies for our reference, and made a one or two page document that says that's what we're using and what changes to it we're implementing (very few tweaks). Taking this route (adopting an already written standard) saved us a TON of time (read money) and took out some of the "persona preference" discussions.
If you're using C#, why not adopt Microsoft's standard and call it a day?
(I realize this isn't exactly what you were asking about.)
|
|
|
|
|