Part 1 of this article appeared last week:
Applying Hungarian Notation to Java programs: Part 1
Other issues
So far, I have used the term “variable” without distinguishing between local variables in methods and variables in classes (otherwise known as “fields”). Hungarian Notation can be applied to both equally, even though the local variables have a more temporary flavor to them.
HN makes variable and field names longer, but you might be wondering if it has an effect on .class file size. This is a good question, because the size of the .class file impacts the download speed.
In fact, HN does increase the .class file size, but not as much as you might expect! Class names, method names, and variable names are included in the generated .class files, but only once. There is no penalty for actually using variables with long names, no matter how many times they appear in the source code.
Local variables do not appear by name in .class files, so using HN for them has no impact on file size. It’s a win-win situation.
Before and after
Here is an apparently simple piece of code that handles GUI events, in a class that implements the ActionListener interface (Java Examples in a Nutshell, p. 182).
/** Handle the button presses */ public void actionPerformed(ActionEvent e) { Object o = e.getSource(); if (o == quit) System.exit(0); else if (o == print) printDemoPage(); } |
This code is so short that you can take it all in with one glance. However, there is always room for improvement. The parameter e and the local variable o shouldn’t cause too much trouble. But what do quit and print represent? Because they are compared to o (which is the object that was the source of the event) you can infer that quit and print are GUI objects, perhaps buttons. . .
In fact, after hunting through the code, I found the following declaration earlier in the program:
// Buttons used in this program protected Button print, quit; |
Of course, “inferring” and “hunting” should not be a part of programming, so Hungarian Notation should be applied liberally.
// Buttons used in this program protected Button btnPrint, btnQuit; [ ... code omitted ... ] /** Handle the button presses */ public void actionPerformed ( ActionEvent pEvent ) { Object oSource = pEvent.getSource(); if (oSource == this.btnQuit) System.exit(0); else if (oSource == this.btnPrint) this.printDemoPage(); } |
I have also added the this keyword in a couple of spots. Although it is optional, it makes the code very clear. It boils down to these rules:
- Any variable that starts with “p” is a parameter.
- Anything that starts with “this.” is a field or instance variable or method.
- All the rest are local to the method.
Another sample
Here is another sample, this time an entire program (from Java Examples in a Nutshell, p. 186). I am not going to show you the “before,” just the “after.”
01 public class GetURL { 02 public static void main ( String[] args ) { 03 java.io.InputStream inStream = null; 04 java.io.OutputStream outStream = null; 05 06 try { 07 if ( (args.length != 1) && (args.length != 2) ) 08 throw new IllegalArgumentException( 09 "Wrong number of arguments"); 10 11 java.net.URL url = new java.net.URL(args[0]); 12 13 inStream = url.openStream(); 14 15 if ( args.length == 2 ) { 16 outStream = new java.io.FileOutputStream(args[1]); 17 } else { 18 outStream = System.out; 19 } 20 21 int iBytesRead; 22 byte[] abyBuffer = new byte[4096]; 23 24 while ( (iBytesRead = inStream.read(abyBuffer)) != -1 ) { 25 outStream.write(abyBuffer, 0, iBytesRead); 26 } 27 28 } 29 30 catch (Exception e) { 31 System.err.println(e); 32 System.err.println( 33 "Usage: java GetURL <URL> [<filename>]"); 34 } 35 36 finally { 37 try { 38 inStream.close(); 39 outStream.close(); 40 } 41 catch (Exception e) { 42 } 43 } 44 45 } 46 } |
You might have noticed the lack of import statements at the start of this program. I could have included these lines:
import java.io.*; import java.net.*; |
The profusion of classes and methods in Java can be overwhelming. You may find that it is reasonable not to specify any import statements at the beginning of your Java programs, at least until you become more familiar with where the many classes belong in the hierarchy. In the body of your code, use the full path like java.io.InputStream. You can see this on lines 03, 04, 11, and 16 of the program.
Is this Hungarian Notation? I think it is, at least in the sense that it makes the code clearer. (You may be interested to know that the generated .class file is byte-for-byte identical, whether you use import statements or in-line paths.)
I have not explicitly indicated the java.lang. path (as in java.lang.System.IllegalArgumentException on line 08 and java.lang.System.out on line 18) because the classes in the java.lang package are imported automatically by the compiler. And the source code just looked too busy.
In this sample, you can see inStream and outStream as variable names. This is an example of the variable type (or a version of it) being used as the name. It works here because there is only one InputStream variable in the program. You can also see the minimalist variable name e used on lines 30, 31, and 41. In addition, the args parameter name is left unaltered, mainly because it is used in almost all Java programs. Calling it something like paArguments seems a bit redundant.
Why use Hungarian Notation?
The fact that there is no single “perfect” name for a variable indicates a problem somewhere. The shortcoming is either in the way the source code is written or in the programming language itself.
For example, in TabControl:page, is “page” supposed to be interpreted as “oPage” or “nPage”? If “oPage”, then it is probably the object that appears on a page of the TabControl (most likely a window of some kind). However, if it is “nPage”, then it probably represents the number of the currently visible page.
Certainly the documentation for TabControl will clarify this, but why can’t the variable name do it instead, saving me the trip to the help file?
In an actual implementation, both of these variables would probably exist and nPage might be given a clearer name, like nCurrentPage.
A common problem in programming is that comments always get out of sync with the code they attempt to describe. The reader looks at the comments before (or instead of) studying the code, and then naturally assumes that the code works exactly as indicated.
Because of this, programmers often wish for a language where the comments themselves are the actual program so that the problem of synchronization would not occur. Of course, this is not workable given the imprecise nature of human language, so a lot of programmers simply don’t provide comments at all. They rely on the code to speak for itself. But this is only possible if a lucid naming convention is consistently applied.
In addition, I submit that the argument in favor of Hungarian Notation is the same as the argument in favor of object-oriented programming. If you believe in OOP, then you must believe in Hungarian Notation. Why is that?
Our strength as humans is the ability to see the general form of something and ignore the details, and then zoom-in to see the details in one area while ignoring everything else. That’s why OOP “fits” us so well. It is all about making small, local changes where tasks are split into manageable chunks. When we work on a piece of object-oriented code, we can rely on all the rest of the code to keep working. No side-effects. That’s called “encapsulation.”
Each line of code should stand alone.
You should be able to look at a line of code and fully understand the role and origin of each entity in it, and that is the real value of Hungarian Notation.
Conclusion
A consistently applied naming convention can help make variable names easier to remember when writing code, easier to understand when reading it, and make both tasks faster. Less time is spent “pondering the name of a single quantity,” as Charles Simonyi points out in his monograph “Program Identifier Naming Conventions.”
I recommend that you try Hungarian Notation. But remember that it is a convention that is generally agreed upon by programmers as the “right” way to name variables. It is not enforced by the Java compiler — it’s just a good idea.
References
- “Meta-Programming: A Software Production Method”
Author: Charles Simonyi
Publisher: Stanford University, 1977
http://msdn.microsoft.com/library/techart/hunganotat.htm Doctoral thesis. - “The Hungarian Revolution”
BYTE, Aug. 1991 (vol. 16, no. 8)
Authors: Charles Simonyi and Martin Heller
Publisher: McGraw Hill
http://www.byte.com/ - Java Examples in a Nutshell
September 1997, First Edition.
Author: David Flanagan
Publisher: O’Reilly & Associates
http://www.ora.com/
ISBN: 1-56592-371-5 - “Program Identifier Naming Conventions”
Author: Charles Simonyi
http://www.strangecreations.com/library/ c/naming.txt
A summary of the major ideas behind HN, with prefix listings. - Article: “Programming, Hungarian Style”
http://www.quinion.demon.co.uk/ words/articles/hungary.htm
A short, lighthearted essay on one person’s first exposure to HN. - “Standards in Programming”
http://www.aloha.net/~smunk/standards/
Contains a useful list of common prefixes for visual programming objects, such as forms, buttons, and reports. - “Jon Grover’s version of Hungarian Notation for C++”
http://www.iei.net/~jgrover/hungary.html
Every letter of the alphabet is accounted for in this “relaxed” version! - “Greg Legowski’s Guide to Hungarian Notation”
http://www.pobox.com/~gregleg/hungarian.html
This page is a very readable summary of the “official” Hungarian Notation. - “Hungarian Naming Conventions”
http://www.qucis.queensu.ca/Software-Engineering/ archive/hungarian
A shell archive (with nroff and ASCII text) that contains something closer to the original HN document. Shows how complex HN can be, but worth looking at. - “Hungarian Notation”
http://www.ghservices.com/gregh/clipper/hungar.htm
My short page that presents Hungarian Notation for CA-Clipper programs.
About the Author
Greg Holmes has been a freelance consultant since 1983 — GH Services. He has created information systems and provided client support and training in various programming languages. His specialties are mobile computing, data replication, client-server technologies, and sensible user-interface design. He was a founding member of CDAT — the Clipper Developers Association of Toronto, and was the original editor of "The Navigator" (CDAT’s newsletter). He was a member of the CDAT Executive since the Association’s inception in May of 1989 until 1993. He can be reached at gregh@ghservices.com.