Igniting Ideas! Thoughts from the team at Spark Plug Games

4Jun/110

Hungarian Notation, pseudo-constants and C++ references

When I first learned about Hungarian Notation, it struck me as a very silly concept and contrary to what makes software soft. I was still in school and used it at my professor's request/insistence. After some time, it still struck me as very silly. I did adopt some aspects of it my coding, most notably m_ for instance members. I also adopted something I had never seen before, but I'm sure that it had already been invented, using s_ for static members.

Software is soft; it's malleable. If I want to change a variable from an integer to a single precision floating point number, I should be able to do so easily.  And I don't want to end up with:

float nMyValue=1.5f;

I could rename the variable and find and fix every place it is used.  I could even use Find And Replace and hope I don't get any false positives.  There are refactoring tools on the market and they are getting better with time, but refactoring C++ is hard; really, really hard.  But I will talk about that more later.  Back to the point of this post, that n or f at the front of that variable name is just a burden without any real benefit.

Thanks to Joel Spolsky's excellent blog, I have since read the original white paper describing Hungarian Notation. You can find the paper here http://msdn.microsoft.com/en-us/library/Aa260976 and Joel's blog entry about it here http://www.joelonsoftware.com/articles/Wrong.html. The intention of Hungarian notation was not to describe the static type of a variable, but rather it's functional type.

int32_t iOffset; doesn't say nearly as much as int32_t xOffset;

Or to use an example closer to what Joel describes; game development is full of different coordinate systems, even 2D games. Immediately there are screen coordinates and texture coordinates. Screen coordinates are not good basis for anything in a PC game* so there is a need to add more coordinate systems. Nymph uses four different classes of coordinate spaces.  I say classes of coordinate spaces because some types of assets where each instance of that type defines its own coordinate space. So in the example above, while xOffset is better than iOffset, it's not as good as lxOffset for horizontal layer space offset. Even then the question remains, which layer?

There's another convention that is used in Nymph that is in direct contradiction to widespread misunderstanding of Hungarian notation and one could argue, also of the original intent.

static size_t kSomeValue;

Non-const variables that start with a lowercase k. I call these pseudo-constants. They are initialized to a default value which can then be replaced during start-up with a value that is loaded from a configuration file.  The value's const-ness is not compiler enforced, but kSomeValue=someOtherValue; just looks wrong.  Which brings us to this:

someXmlNode->GetAttribute("some_value",kSomeValue);

References.  I tend to avoid using C++ references because they violate the "wrong code should look wrong" rule.  The fact that the line above modifies kSomeValue would be clearer if required the use of &kSomeValue by taking a size_t*.  That would make the line look wrong.  But alas, there is nothing wrong with line as long as someXmlNode is part of a configuration file being read during start-up.

My objection to references goes beyond the "wrong code should look wrong" rule into a more general "code should look like what it does."

someParameter.someMember=10;

Tell me, does the line above modify a stack variable or a some variable that was passed by reference?  Now answer the same question for this line:

someParameter->someMember=10;

There's no mistake about what the second one does.  But like I said, I only tend to avoid references;  It is not a hard rule.  One reason is closely tied to my argument against the misunderstood version of Hungarian Notation; reference syntax makes software more maliable, or softer if you will.  I can change something from a reference to an instance or back with a few keystrokes.  Something that can not be said of pointer syntax.  The cost of that softness is a lack of clarity in usage.

*In windowed mode, the player should be allowed to resize the window and in fullscreen mode people have different monitor and video card configurations.  So trying to say something like alertWindow.location=Point(400,300); where the point is in screen space will only get your alert in the center of the screen for a handful of users.

Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

No trackbacks yet.