Fog Creek Software
Discussion Board




Hungarian Notation

With C++ I make it a point to in fot Hungarian Notation. Just makes reading the code a little easier.

Arethier any norms for VB. I recently started on VB.Net, so I want to get into a habit right away. Has anybody set some rules for themselves?

Gunjan Sinha
Thursday, June 12, 2003

Hungarian notation is falling off in popularity among the .NET crowd. Somewhere on MSDN, MS has published their opinion of good naming conventions.

Mark Hoffman
Thursday, June 12, 2003

i used to code with type notation untill i started programming  those loosed typed languages like perl, php etc. for me, type notation in those languages is a limitation.

abel
Thursday, June 12, 2003

It's a mix of mainly Pascal (LikeThis) and some Camel (likeThis).

You can find it under "Design Guidelines for Class Library Developers" in the MSDN library.

Personally, I prefer it to Hungarian. I also tend to use the universal type names of the FCL in C# (Int32 rather than int), but that's another discussion.

Pietro
Thursday, June 12, 2003

Personally I'm still a big fan of Hungarian, it's ESPECIALLY important in untyped languages, and we even use it in SQL code which I've found very, very valuable.

Joel Spolsky
Thursday, June 12, 2003

I was a huge Hungarian advocate, but something about .Net just makes it seem like a waste of time. Actually, I just realized that .Net *does* follow some of the later hungarian recommendations - over the last few years most standards I read indicated that class variables didn't need a prefix (since adding a "c" doesn't really do anything).

Well, since everything in .Net is a class... [grin]

However, I *do* prefix controls on webforms, since it makes them easier to find in intellisense.

Philo

Philo
Thursday, June 12, 2003

> Personally I'm still a big fan of Hungarian, it's ESPECIALLY
> important in untyped languages, and we even use it in
> SQL code which I've found very, very valuable.

I used to use it all the time, especially when I was using VBScript and Javascript just to keep track of what was supposed to be what.

But in a langauge like C# I feel it makes less sense with namespacing and tighter variable scope. Of course, you could just write code that was one long procedure and it would get very confusing, but if you're doing it right you shouldn't really need Hungarian. Plus as a personal preference I think the code looks less "ugly" than with Hungarian.

Although I do still use it in forms programming, for example a "lbl" prefix for a label.

Pietro
Thursday, June 12, 2003

"... if you're doing it right you shouldn't really need Hungarian..."

Unfortunately, if you're rustling someone else's spaghetti code, it can be very handy to be able to *quickly* see that:

    dwCustNum = dsCustomers.GetI("custno");

... is an error.  As long as there are amateur hacks, there will be Hungarian to help bring order to chaos...

Spaghetti Rustler
Thursday, June 12, 2003

I personnally follow the umain methodology.
http://mindprod.com/unmainnaming.html

Swahili Dilio
Thursday, June 12, 2003

But if you can teach them to use hungarian, can't you just teach them not to check in code they haven't compiled?

BTW, another reason hungarian is less necessary in .Net - no implicit type conversions.

string var1;
int var2;

[lots of code]

var1=var2;  //hard to find bug in VB, throws an exception 
                    //  upon compiling in C#

Philo

Philo
Thursday, June 12, 2003

I have been a hardcore Hungarian Apologist for many years, but lately my faith is wavering.

I am now test-driving one word names, but I still find the m_ and g_ "namespace" prefixes useful. I also like the 'p' pointer prefixes, especially when dealing with pointers to pointers ('pp').

I am giving up Hungarian mostly because of the inconsistent naming of strings, pointers to strings, and arrays of chars. Which is really correct? In most cases, knowing the actual underlying type of the "string" is unimportant, but when it is then Hungarian's supposed advantage of "visual type checking" breaks down when you code: pszUserName = archUserName;

char* pUserName = NULL;
char* pszUserName = NULL;
char* szUserName = NULL;

char achUserName[USERNAME_LENGTH];
char rgchUserName[USERNAME_LENGTH];
char sUserName[USERNAME_LENGTH];
char szUserName[USERNAME_LENGTH];
char pUserName[USERNAME_LENGTH];
char pszUserName[USERNAME_LENGTH];

runtime
Thursday, June 12, 2003

oops, I also forgot:

TCHAR* pUserName = NULL;
TCHAR* pchUserName = NULL;
TCHAR* pszUserName = NULL;
TCHAR* szUserName = NULL;

TCHAR* pUserName = NULL;
TCHAR* ptchUserName = NULL;
TCHAR* ptszUserName = NULL;
TCHAR* tszUserName = NULL;

WCHAR* pUserName = NULL;
WCHAR* pchUserName = NULL;
WCHAR* pszUserName = NULL;
WCHAR* szUserName = NULL;

WCHAR* pUserName = NULL;
WCHAR* pwchUserName = NULL;
WCHAR* pwszUserName = NULL;
WCHAR* wszUserName = NULL;

runtime
Thursday, June 12, 2003

Referring to the above example:
dwCustNum = dsCustomers.GetI("custno");

How do you know that dwCustNum is of type DWORD. dw prefix? Are you sure? That prefix means nothing to the compiler. In a typeless language you can put anything to a variable regadless the prefix.

Personally I hate hungarian notation, it pollutes names, making the code harder to read. And as to the spaghetti code, don't you think that you are applying wrong methods to solve the problem, isn't it better in the long run to educate people instead of having a policy to use this notation, which I am sure will fall apart during the maintenance period of the product life time.

Passater
Thursday, June 12, 2003

I use p for pointers and that's about it.  I could see m for members as well.  But microsoft goes totally overboard.  The code looks nasty.  I don't understand the whole point of having the types in your variable name.  Isn't that what the compiler is for?  (at least in a statically type-checked language which almost all MS code is in)

Having a decent code browse feature in an editor or those tooltips lets you know the type.  I've seen people use hungarian on functions to indicate the return value, i.e.

void vFunction();
int iFunction();
float fFunction();
int* piFunction();

well why not

int ifipiFunction( float f, int i, int* pi )

since the arguments are part of the type for a function.  It gets ridiculous.

Andy
Thursday, June 12, 2003

> don't understand the whole point of having the types in
> your variable name.  Isn't that what the compiler is for?

As I pointed out the last time this came up in JOS, there are two completely contradictory philosophical approaches to Hungarian naming conventions.

The one I call "the sensible philosophy" is the one actually espoused by Simonyi in his original article: Hungarian prefixes concisely describe semantics and explicitly do not describe storage.  Simonyi is very clear on this point.

The one I call "the pointless philosophy" is the one espoused by Petzold in "Programming Windows": Hungarian prefixes connote the storage type and do not describe semantics at all.

Most arguments about Hungarian are, at their root, based on this fundamental dichotomy.

As you correctly note, the pointless philosophy is, in fact, pointless.  The compiler does that for you, and all the hungarian does is make the code redundant and hard to maintain.

However, the sensible philosophy is very valuable when writing low level C code.  Case in point: one day about seven years ago I rewrote the entire VBScript string runtime library -- which had to work on European, Far East and Bi-Di Win16/Win95/WinNT systems -- so that all the Hungarian prefixes correctly described the semantics of every variable.  If a variable was a maximum count of characters then it was cchMax.  If it was a pointer to a string of not-null-terminated unicode characters then it was a pwch.  Etc.

By simply renaming all the variables correctly I found SO MANY BUGS.  Every place that a cb was assigned to a cch, I knew that there was a Unicode or DBCS bug right there.  Hungarian greatly improved the code quality, particularly on DBCS machines.

I still use semantic Hungarian prefixes in my C# code, but to a much smaller extent because most of the problems that Hungarian solves were designed out of the language in the first place.  I try to never use "storage" Hungarian prefixes in any code, C# or C++.

Eric

Eric Lippert
Thursday, June 12, 2003

That's interesting, I didn't realize that the original intent was for semantics.  I do use stuff like that, nFoos/numFoos for the number of Foos, max and min as prefixes.  But I don't think that is what most people associate with hungarian now.  Most people think it is p for pointer, m for member, s static, i integer, f float, etc.  It might be marginally okay if everyone used the same hungarian, but everyone uses a different one so it's not.  Like in perl it's built into the language kind of, you can use $ for scalar, @ for lists or associative arrays, I forget.  But anyway it's standard, so it sort of works.

I think your example is a fine use of a naming convention, but most people wouldn't call it hungarian.  I think within each _individual_ program, it is very often necessary to come up with a consistent naming convention.  However, most people associate hungarian with a system you adopt for _all_ programs that you write.

Incidentally, it would be nice if typedefs in C/C++ really created new types.  That is, if I say

typedef double Inches;
typedef double Pounds;

Pounds p = 1.0;
Inches i = 2.0;

void f( Pounds p ) { ... }

p = i; // should give an error, but doesn't
f( i );  // also shouldn't work, but does

I think this would let the compiler solve certain problems that you would use a naming convention for.

Andy
Thursday, June 12, 2003

I'm inclined to think that, if you want a new type, you should ask for one.  If typedef generates a new type, it looses much of its effectiveness.

Of course, if you want to take the blue pill, see
http://www.accu.org/cgi-bin/accu/rvout.cgi?from=0au_b&file=s001117a

Danil
Thursday, June 12, 2003

> typedef double Inches;
> typedef double Pounds;

Indeed, that would be nice.  An even stronger approach towards solving this problem is the use of unit classes. 

At one point there was a proposal to add unit classes to ECMAScript, but I don't think anything came of it.  (Then again, I haven't read the committee procedings for a while, so it might still be there.)

The idea of a unit class is to declare a class which can lexically decorate literals.  For example:

var distance : inches = 4 inches + 3 cm;
var speed : velocity = length / 12 seconds;

The type system presumably has enough information about conversions between various units to determine that adding foot-pounds to Newton-metres is OK, but will throw compile errors if you try to add inches to kiloPascals.

Eric

Eric Lippert
Thursday, June 12, 2003

<Incidentally, it would be nice if typedefs in C/C++ really created new types.  That is, if I say>

I'm with Danil on this one!

If you do this you have a problem. If T is "std::vector<Ty>", what is "typename T::value_type"? How many bloody types do you want?!?!

I'd have to think about this a bit more, but my gut reaction is that a whole bunch of template stuff would not be half so useful it typedef introduces new types. (Note, I'm not necessarily talking about using typedef to massage the syntax into something usable, but that too.)

You can do kind of what you want using templates incidentally. Template your class on random type T and instantiate multiply with different typedefs. Voila, N incompatible classes that are otherwise identical. Manual instantiation of template classes will solve your "but it all has to go in the header file and what about the code bloat" questions :)

Tom
Thursday, June 12, 2003

Well, clearly there are potential uses for both "create an ALIAS for an existing type" and "create a NEW TYPE from an existing type". 

Your example of alising ugly template type names is a good example of the former.  Creating typesafe enums from of subsets of the integer type, or traditional OO class extension are good examples of the latter.

I predict that as computing power continues to increase we will see more and more ability to put arbitrary constraints on types -- there is no reason why we couldn't implement languages with type constraints like

var c : int( c > 0 );
c = -1; // Whoops, type system violation.

Of course, such a system requires the compiler to solve the Halting Problem if you want to guarantee type safety at compile time -- but as computing power increases, we can start with check-on-write constraints and then move up to systems which compute dependency graphs to determine when type system violation checks must occur.

Eric

Eric Lippert
Thursday, June 12, 2003

Hungarian is crap. It has been utter crap ever since C supported function prototypes and type checking arguements.

Untyped languages are a different story. Hungarian is less crappy there.

Clutch Cargo
Thursday, June 12, 2003

At my first programming job, coding C in 1995, Hungarian was quite helpful. However, it's unnecessary now that I'm using Java in 2003, for these reasons:

1)  In Java and C++, type mismatches are much less likely to shoot you in the foot than they are in C.
2)  IDE's can instantly tell you the type of any variable, and for better IDE's instanctly display any type errors before you compile.
3)  Better programming practices, such as shorter functions/methods and refactoring, make it easier to keep track of your variables, removing the need for Hungarian notation.

Julian
Friday, June 13, 2003

Well, now that I think of it, there are some things you could do with templates.  I haven't fully thought of all the implications of making typedef create a new type, but I know in at least some cases it would be nice.  typedef is barely better than defining a macro, instead of what its name implies -- defining a type.  Another keyword would be cool.

But I guess for the subsets of an integer problem, if you could just do something like:

template<int lowerbound, int upperbound>
class BoundedInt
{
  // constructor, assignment operator, etc. check the bounds
  // if you need arithmetic, operator+ etc would have to check bounds too
}

But that's a lot of typing for something that's not too hard to avoid in other ways, depending on the program.  Maybe for debug builds this would be useful, and then for release you could typedef it away to just an int, to eliminate the overhead.

Andy
Friday, June 13, 2003

One of the problems of overlaying any informal naming structure onto variables (whether strongly typed or no), is that it sets up the sin of mistaking the map for the territory.

I've come across bugs where an 'h' was misplaced in that it implied it referred to a handle when in fact it semantically was not.  As a handle is itself an abstraction outside of the language that was just sin on top of sin.

In these kinds of areas we are poorly served by current languages.

Simon Lucy
Friday, June 13, 2003

"...  isn't it better in the long run to educate people instead of having a policy to use this notation..."

Ha!!

If I could educate people to write better code, I'd be so rich Bill Gates would be my pool boy!

Also, I have better things to do than proselytize (sp?)...

Spaghetti Rustler
Friday, June 13, 2003

The thing that turned me on to using some notation was the fact that you often need a bunch of variables grouped on a particular concept. So, it not only the issue of showing the user the data type, but in fact that using notation gave me a natural grouping of variables. I find that there is less mental effort needed to come up with variable names. More important this is natural grouping also.

Lets assume we are dealing with a student table.

So, if I need to open a table of students, it is likely that I also need a variable to hold the table name, and also a recordset. The result might be placed into a collection. Without some notation system I have to come up with 3 variable names that really represent the same data, or same concept.

A imaginary example could be:

Dim rstStudents    as recordset
Dim strStudents    as string
Dim colStudents    as new collection
Dim lngStudentid  as long

You can see, all of the 3 vars above are “grouped” together.  All of the above vars are to deal with a chunk of code that has to do something with a student. This kind of grouping was the first benefit I noticed about using some notation.

IMHO, the reason for Hungarian notation falling out of favor is that now with OO programming, all of the above vars would be a member of a object. So, now that “natural” group of vars in reference to “student” is not needed.  You might get:


Students.RecordSet
Students.TableName
Students.Collecton

In other words, due to more OO, then there is less need as a developer to use some notation that “groups” the above set of vars together. Since the values are grouped in the object, then there is LESS benefit to using some notation.

For sure some notation does still help the issue of the data type used, but again with OO you are dealing with a object that has all kinds of stuff, and thus again it makes less sense to try and “type” the object.  You can type the members of the object, but it don't give you that grouping I talked about.

Albert D. Kallal
Edmonton, Alberta Canada
kallal@msn.com
http://www.attcanada.net/~kallal.msn

Albert D. Kallal
Friday, June 13, 2003

A number of variables grouped together is called a structure. You don't need any kind of notation to show that.

Passater
Friday, June 13, 2003

I mean even without having classes you could group variables in the old structural languages like c and pascal.

Passater
Friday, June 13, 2003

I think VB programmers tend to like Hungarian because it is useful for controls, as well as for what Albert says. It does make naming controls or variables easier.

Now lblStudentID is the same as StudentIDLabel  and many people prefer the latter naming convention. I can't see that it makes a big difference, but using a notation to show controls and variable types (whether something is a string or an integer is useful to know in VB) seems a good idea for amateur (and maybe not so amateur) programmers.

Stephen Jones
Friday, June 13, 2003

There are non-struct groupings.

For example, textStudentID is the textbox, while iStudentID is the local variable which is the integer representation of the contents of the textbox.

You then might use this to create the Student object which has other properties.

mb
Friday, June 13, 2003

>>A number of variables grouped together is called a structure. You don't need any kind of notation to show that.

>> I mean even without having classes you could group variables in the old structural languages like c and Pascal.

That is true. I loved working in Pascal, and that is where I got real hooked on User Defined Types (UDT).

Remember, this natural grouping is only ONE of the many benefits that some notation system gives you.

There are a number of limitations as to when a UDT can be used in VB. You can’t define them in VB class objects for example. Further, unlike Pascal, you can’t define UDT’s local in a sub or function. So, the amount of effort to start defining a new user types every time that you need simple recordset and table name gets to be a bit of work. You now have to come up with a “name” for the UDT type, and THEN also have to define this var  “group” using that type name. I was trying to save mental effort here!.  There are also some issues of scope of the UDT also. I mean, do you have to define the UDT as global (vb = yes you must)? And, you also often will have to pass individual members of the UDT to other routines anyway. Often that natural grouping I talked about is not worth the extra effort to define a global UDT.

Unfortunately, the lack of flexibility in UDT’s is a true weak spot in the VB language. However, since it is a weak spot, this just again favors using some notation system to make up for this fact.

Obviously many people are finding that with .net some notation is not worth the extra effort.

So, this is kind of a horse for the course kind of thing. It seems that some programming styles and languages seem to benefit more from notation then other languages.

So, if I just need two vars in a routine (one for a recordset and a table name) then VB does not sit well from the effort to define a new type for this. However, that is not such a bad idea here either! I am actually open to suggestions on this concept because of my Pascal roots. No question that creating a UDT does give a natural grouping “concept” that I talked about. 

With OO so much of the conceptual grouping occurs by methods of objects.

Another important issue here is that new languages are less strongly typed then they used to be. (casting of data types is rather automatic in VB as compared to Pascal for example). With OO this is even more so as code must handle different types of data objects passed. Hence, modern languages care less about data types now.

There is also a bit of a style issue going on here. Some developers don’t care, or bother to use some type of notation.

For me, VB is certainly one of those languages that seems to really benefit from some notation.

Sure....Peoples mileage will vary on this issue...


Albert D. Kallal
Edmonton, Alberta Canada
kallal@msn.com
http://www.attcanada.net/~kallal.msn

Albert D. Kallal
Saturday, June 14, 2003

*  Recent Topics

*  Fog Creek Home