Grinding Java - Real World Java

Written by Shai Almog

Introduction
[NOTE: Here is a link to a zip of the source code for this article. Ed] A friend of mine recently went over some resumes which arrived at his office and found out that one of the applicants listed under programming languages: C++, Visual Basic, Word and Powerpoint!

This was a matter of great amusement to us. Many people want to become programmers since they assume that anyone who knows the language can write the code, but we all know that it is more than that. The slightly obvious but desperately needed Java coding standards at javaCodingStandards.pdf begin with the cute phrase:
 * A good developer knows that there is more to development than programming.
 * A great developer knows that there is more to development than development.

I don't think any of us would write that we have programming experience in MS-Word on our resume but we can show lack of experience when developing real world applications.

A recent Java article in Byte describes Java as the child prodigy which can play a beautiful Rachmaninov yet is still not potty trained, the potential is there but it is still an infant.

I am now working on two Java projects. Both projects are 100% Java (no native code) and require a fast compiler, hopefully by the time they reach the market there will be better compilers.

Both projects are still in the very early stages of design and are not fully formed yet.

In the months to come I will cover the development of these 2 projects from inception, choice of tools, OO design and to the final product.

Why do I think you should care? There are quite a few Java success stories, but most of them revolve around Sun and are early development projects. In the course of my development I will examine the problems facing Java developers in today's real markets.

I would appreciate your feedback, if you spot mistakes in the conceptual or technical level or if my explanations/conclusions were not clear. It will be very helpful to tackle these problems in the development stage rather than during beta testing.

My most basic toolbox: Don't do Java without it!
I remember reading once that programming is different from every other profession because programmers develop their own tools unlike a carpenter (for example) who does not develop his own hammer. I don't agree with that suggestion (but that's irrelevant). This is a list of the tools I will use to develop these projects. It is not complete and I am testing new tools all the time.
 * 1) VisualAge for Java - I feel that VAJ is the best Java development tool. It suffers from several drawbacks which require me to go back to other tools:
 * 2) * It is very slow, I am now using a 64mb computer which was upgraded for the purpose of running VAJ. The problem is that upgrading all the computers I use is not practical.
 * 3) * It is not well suited for team development. The team version is over my budget.
 * 4) * It does not support inner classes. Inner classes are a very nice feature of JDK 1.1 which allows you to define a class within a class, eg: Observer will be visible only in MyWindow but it will in effect be a different class. VAJ will run code that uses inner classes but it will not let you write inner classes.
 * 5) * VAJ is not based on the JDK. Normally this could be an advantage but I am targeting JDK 1.2 and will be taking advantage of many of the features it has to offer. VAJ might be late on adopting the changes in JDK 1.2. Although the Swing API (of JFC) runs under VAJ I doubt if the more esoteric APIs will function will.
 * 6) OS/2's JDK and Mr Ed text editor - I calibrated Mr Ed to jump to the error line correctly when it compiles JDK code. I had significant problems working with Java packages using the Mr Ed macro since the javac command must be invoked from the parent directory of the package, Mr Ed refused to accept a startup directory so I created a batch file to execute the javac command and ran it through Mr Ed.
 * 7) Under Windows 95 double clicking on a class file refuses to work as it does under OS/2. OS/2 uses %N to symbolize the name of the file without the extension, since you cannot invoke a class file with its file name, but only with a class name. I wrote a small Java application which I associated with Java .class files and it accepts file names. Note: at first glance the fact that Java will accept "Java MyApp" but not Java MyApp.class" seems very stupid, but it is not quite so stupid. The reason for that oddity is that when you invoke a class you must state its full name i.e.: "Java my.package.App". I still think the .class should be an exceptional behaviour, but at least Sun's engineers were consistent.
 * 8) The Swing beta release - in the Java universe you must be ahead of everyone. That is why I am targeting JDK 1.2 before it is even out. Sun is quite open on the Java standard and publishes APIs all the time. It is not wise to write for an API which is not fully formed but it must be done in order to form the API. I do my best to keep my code generic so it can be modified easily, and Swing is an absolute necessity since it supports all the widgets which Java is currently lacking and it is 100% pure Java (it runs under OS/2 perfectly).
 * 9) JDK source code - 40mb of source code for free (after you sign an agreement). I cannot use this source in my programs since the license I signed only covers educational use, but it is a wonderful tool for understanding the inner workings of Java. In the early days of programming when a novice had a question the answer would usually be: "Check the source code".
 * 10) The JavaDoc generated JDK documentation and all of the future APIs from the JavaSoft documentation directory - The most basic tools in every Java programmers tool box.

I will probably add many tools as I go along, most noticeably I neglected to mention a storage system or an ORB (RMI or Corba). I am considering using an object database (http://www.odmg.com), and I am testing a product by poet (http://www.poet.com). The poet product seems very promising and if it will run under OS/2 I will probably start using it. Both of the products I am working with don't need any distribution features but they could benefit from their implementation, so I am examining Visigenic ORB (which ships with Netscape 4 and suite spot). I will probably not use RMI.

Development rules
Anyone who was ever involved in a large scale project knows the importance of development rules to maintain a consistent code appearance, thus simplifying the work of maintainers. AmbySoft's coding standards at javaCodingStandards.pdf are OK (although very basic) and I will try to stick to them in my development.

However I do intend to divide the entire code into packages (the hierarchy of which I have not yet finalized). Sun originally standardized the commercial package name to begin with COM.companyname but they will change that with JDK 1.2 to com.companyname.

I use some rules myself (in addition to AmbySoft's rules) which are specific to Java:
 * When designing a class, every class (unless very simplistic or inner class) must have a "main" method so we can test that the class actually works.
 * There are 2 types of event handling code:
 * The code that operates some program logic such as save, undo, calculate etc...
 * The code that controls the UI, such as dismissing a closed dialog.
 * Type a must be linked directly into the UI code. Type b must be separated from the UI code and be in a separate class.


 * I use a simple log file class which implements a file stream to a standard log file. I use a simple standard syntax so in the release version it will be easy to locate all the logfile entries and comment them out.
 * I try to test the code in Hebrew every once in a while. Internationalization is a great feature of JDK 1.1, however it is not seamless. I suggest testing your code on at least one extra language. It is easier to do this during development than as an after thought. I developed a simple subclass of ResourceBundle which allows me to easily support an easily modifiable set of languages, through a simple AWT UI. Any user can easily add a new language to my application.
 * I write pseudo code and method stubs before I begin the actual programming. This allows me to generate JavaDoc documentation which is very readable, before I write code. I share this documentation with colleagues and get their opinion on my API before I write it.

There are plenty of excellent books on software design and I will not tread on their territory.

Software design
I believe in design by simplification: I divide a large complex task into a group of smaller tasks which are simpler to perform, thus when designing the visual side of the first project I decided to build it out of beans. I am now developing the beans for the first project which will be 90% of my work on that project.

My second project is very VM specific and is quite complex. I am designing the class hierarchy and building the most basic classes at the moment.

There are a few CASE tools for Java but I chose not to use any of them since the programs being developed are not well suited for CASE tools.

When developing a Java design spec you must remember the open nature of Java programming. It is not unlikely that some programmers may want to make use of your program in their application. Now that I am writing my design specification I try to make it into a manual for the application and it could in the future be just that. There is no reason to do the job twice.

When designing a Java application be sure you understand what Java is all about! Corel made a mistake of trying to copy their C++ experience to the Java realm, their Java suite was painfully slow and light on features. A Java application should have the same features as a Windows application but those features need to be dynamic. The application itself should be as minimalist as possible and manage all the extra features dynamically.

The applet question
Should we write the program so it could run as an applet? I never really liked applets, they used to be slow and they lacked any useful feature. Netscape now supports signed applets and has Symantec's JIT compiler inside, this allows us to write the applet as if it was an application.

I feel that a good Java application will be able to run as a very small applet on the client so today I believe that a good Java developer should develop an application and think of an applet.

Instead of building a large JAR file containing all your class files in one mesh, separate your code into the client and the server. The client should strive for small speed and size and the server should strive for functionality. Using this and a good distributed objects policy you should be able to make every application an applet and shift to the realm of robust client server development.

Are applets useful? They might be. The network computer hasn't caught on yet but many users may want to sample your application: what better way to sample it than with an applet. The problem with many of the early Java adopters was that they did not understand Java and developed large (600K+) applets. Your application should not care whether it is running under Netscape or the JRE, it should be a small client and the server can be local or remote, and this should be invisible to the user. Many users already have Netscape but don't have the JDK or the JRE, an applet could be excellent for them since they will not have to download the full JRE code. When running locally applets have very few security limitations.

Programming in Java
I am currently working on a large C++ project and I find the change to Java to be a dramatic change in the way I think when developing patterns: In this large C++ project, the entire project is one huge mass of objects coupled together very tightly. (This is essential for speed purposes in this particular product). In my Java projects I try to make the objects as individual as possible, my patterns include many times the Class.forName method which dynamically loads the class and thus removes the dependency for modifications in the class. Dynamically allocating classes allows me to break apart my application when needed, which increases my code reuse, eg:

When handling Component based events in my application I name the Components (using the Component.setName and Component.getName methods) and when an event is triggered by a Component I try to load the class whose name is in the getName for the component which triggered the event. I usually prepend the event's package name in front of the class name.

When the event is invoked it searches, using the Class.forName method, the class which has the same name as the name of the Component, creates an instance of it and invokes the methods setObserverClass and then the actionPerformed method on it. The class must implement actionListener (or any appropriate event interface) and the DynamicEvent interface.

This pattern solves the following problems: And that's it for now.
 * Events can be broadcasted dynamically and created at runtime easily.
 * No large switch statements which are considered by me as bad programming.
 * Small memory footprint, no need to create new instances of listeners for every possible event. They are created dynamically.