| ## Java 1.1 Unleashed # - 29 - Documenting Your Code by George Reese IN THIS CHAPTER The Role of Documentation The Software Engineering Process Object-Oriented Design Documenting Code If one single thing can define the difference between hackers and serious programmers, it is documentation. The trademark of a hacker is a quick-and-dirty solution developed without the use of any commonly understood process or anything other than the code itself to describe what was done. A programmer, on the other hand, develops an application based on documentation derived from a clearly defined development process. As a result, the quality of the applications built by programmers is worlds above the quality of applications built by hackers. This chapter examines the role of documentation in object-oriented application development. It focuses on approaches to object-oriented development that help produce useful documentation and on the `javadoc` tool, which creates API documentation from comments in your source code. ## The Role of Documentation The complexity of software engineering can equal the complexity of fields like construction and manufacturing. In construction, you create buildings using a process that defines and documents what you are building before you build it. Specifically, an architect puts together a blueprint that others use to define how they will construct the building. Years down the road, if someone decides to expand the building, or simply update it to new fire standards, that old blueprint is brought out and used as the starting point for the changes. Not all construction projects, however, have the same level of complexity. For example, building a doghouse is not quite the same as building a bridge. You do not really need to document the building of your doghouse; but if you are building a bridge, you better have it blueprinted and tested in computer simulations before constructing it. Why should software development be any different? Over the life cycle of an application, documentation plays two important roles: Prescriptive Descriptive ### Prescriptive Documentation Prescriptive documentation outlines how your application should be built. How often have you finished a significant portion of an application that you failed to document only to realize that you forgot a piece? Because good documentation flows from a standard engineering process, you are less likely to find that you have missed a key element, and for each element, you will understand it thoroughly before you begin building it. The basic goal of prescriptive documentation is to provide you with a history of the issues you decided were important and how they fit into the application as a whole. ### Descriptive Documentation Descriptive documentation details how an application is actually built. In a well-structured project, your documentation evolves as the project evolves, continuing even after the application has been deployed. If you have ever had to modify someone else's existing code, you know that the tasks of application testing and maintenance are made much easier by well-written documentation. And much easier translates into less time and money. ## The Software Engineering Process Random documentation does not help you build an application. The documentation you create should tell you, and any potential reader, all the information known about the objects in your system and how they act together. Although scribbling notes into a notebook may be enough to capture this information for yourself, this approach does not help others understand what you are trying to do. Good documentation comes from a sound software engineering process that challenges you to ask the right questions and record the answers in a standard format. It is often said that "it's the planning, not the plan"; to some degree, that cliché is true. A good software engineering process serves as a sort of preflight checklist that helps you be sure that you do not miss anything crucial before takeoff. Let's start out by taking a brief look at object-oriented software engineering and how it relates to the documentation you produce. I first want to take a look at object-oriented software engineering; keep in mind, however, that many volumes have been written on the subject, so I cannot possibly cover all its nuances in this short chapter. Instead, I want to provide an introduction to the subject to help you understand its importance and whet your appetite for more. ## Object-Oriented Design Because Java is a purely object-oriented language, the process of designing applications using Java should follow well-established object-oriented software engineering methodologies. A methodology is simply a step-by-step process for performing a task; at each step along the way, you document what you did. An object-oriented methodology specifically looks at the system as an interplay of objects and thus seeks to understand the objects that make up that system and how they interact with each other. Any software engineering process--object-oriented or otherwise--can be cleanly divided into six stages: 1. Analysis 2. Design 3. Development 4. Testing 5. Implementation 6. Maintenance These steps proceed iteratively, meaning that once a subsystem comes out of testing, it probably goes back into development (or even, sometimes, back into design). This loop repeats as many times as necessary until all testing requirements are met. Traditionally, 80 percent of software development is spent in the last stage: maintenance. In other words, the most effort on a system is spent fixing bugs and correcting things done poorly in the first five stages. Because getting something right the first time is always less costly than going back and redoing it, the goal of object-oriented software engineering is to shift time back to the first and second stages so that much less time is spent in the final stage. ### Analysis Before you begin any software development project, you first have to analyze the problem and understand what it is. The task of analysis is to prioritize system components by classifying them as either wants or needs. You must be able to accommodate the proper amount of time for the design and development of your system's needs. If you still have time on your planning chart after the needs have been accounted for, you then note which wants you will accommodate and which ones you will not. If you plan to implement a want in a future release, you should note that decision in your documentation so that designers can plan for that future expansion. NOTE: This chapter offers a very distilled object-oriented software engineering process geared more towards the casual or small-project developer. There are actually several major object-oriented approaches in common use today. This chapter takes the major components of these well-known methodologies and describes their essence. Regardless of what sort of projects you are involved with, I highly recommend that you familiarize yourself with at least two of the major methodologies, such as OMT and the new Universal Methodology. Furthermore, if you are developing software professionally for a large audience, I strongly advise that you follow one of those methodologies for two reasons: First, a well-known methodology provides a common ground of understanding for a diverse set of people--from entry-level developers to senior architects and managers. Second, whenever you tell a potential customer that you follow object-oriented design practices, their first question, oddly enough, will be "Which methodology do you use?" The documentation of your analysis can be fairly simple. It only has to show which pieces of your system will be considered in scope, that is, what will be built in the first release. For everything out of scope, you should note why it is out of scope and whether you plan to address it in a later release. TIP: If you are building an application for a specific group of people, this is the best time to show them your analysis document and have them sign it. If, at a later date, they come back to you, asking why feature X was not included in the system, you can show them their approval of the document. The following outline captures the essence of what an analysis document should look like: I. General-Use Cases II. Context Model III. Notes To capture the proper wants and needs, you should sit down with potential users and document general-use cases, sometimes called scenarios. A general-use case is a simple statement describing a function of the system. For example, if I were building a program that predicted football games, I might have a use case like this: The user requests a prediction for two teams. Your use cases can help you identify high-level components that you can place into a diagram to graphically illustrate which pieces of the application are in scope and which are out of scope. This diagram is called a context model. Figure 29.1 shows a sample context model for the football game prediction program. The content of a context model is simple. You design and build anything inside the box. Anything outside the box is out of scope. If there is a line connecting something inside the box with something outside the box, that means that your system is interfacing with an external system. The last section of your analysis document should briefly describe any decisions you made about the scope of the application. Specifically, you want to record anything you cut from scope and why you cut it. Figure 29.1. The context model for a football game prediction program. ### Design By understanding the problem, you can go on to design a solution. During the design process, you break the application into objects and provide descriptions of how they interact to satisfy the general-use cases in the analysis document. The end product of your design should be a document that tells you exactly how to build your system without diving into coding details. The outline of a good design document should look something like this: I. Object Model II. Detailed-Use Cases III. Object Specifications To put together the object model, you first have to identify all your objects. Identifying objects is a lot less complex than it sounds. A few people gather around a white board or a piece of paper and name things they think are objects straight off the top of their heads. At first, there are no wrong or right answers. Later, as you start applying the objects to use cases, you will see which objects best describe the system and eliminate from your design those that do not. The following list of objects comes from a brainstorm session on the design for the football program: Team Statistic Game User Points-for Points-against File Once you feel comfortable with the initial list of objects, the next step is to attempt to identify recurring patterns within those objects. The simplest form is that of inheritance, in which one object is simply an extension of another object. Clearly, the points-for and points-against objects are really extensions of a statistic. But is a statistic really a simple attribute of a team? Or is it a more complex object with independent behaviors? Because converting an object into a simple data type is easier than converting a simple data type into an object during the design process, you should keep anything as an object until you are certain it is not. Completing the design involves iterating over the process of fitting objects into use cases, fleshing out those use cases, and then identifying opportunities for abstraction until you feel you have a clearly defined architecture for the development of your system. To reach this stage, you need documentation that identifies every single object you will build for the system, its attributes, and its behaviors. The object model is a diagram that illustrates your understanding of the system as a whole. For a small system like the football game prediction program, the diagram can be simple as the one in Figure 29.2. Figure 29.2. The object model for the football game predictor. This diagram shows you exactly what you have to code. All that is left to figure out is how to code it. In object-oriented programming, an application consists of objects that are made up of methods and attributes. After putting together the object model, you next must detail each step of the general-use cases detailed in the analysis documentation. By going into deep detail on the use cases, you can visualize the things each object does and the data it requires to support that behavior. As you did with the general-use cases, you provide simple English sentences that describe what happens. The general-use case, "The user requests a prediction for two teams," can be divided into the following detailed scenario: 1. The user executes the program with the two teams as arguments. 2. The `prediction` object creates a `team` instance for each of the teams. 3. The `prediction` object requests relevant statistics from each `team` instance. 4. The `prediction` object calculates an outcome. 5. The `prediction` object displays the results to the user. From this detailed-use case, you can see that the `team` object requires methods for retrieving statistics and the `prediction` object requires methods to instantiate `team` objects and predict games. The final important section of a design document is a list of objects with their attributes and methods, called the object specification. Figure 29.3 shows the object specification for the `Team` object in the football predictor. Figure 29.3. The object specification for a `Team` object. ### Into Development and Beyond The final stages of the software engineering process form the traditional bulk of where work is done. During development, you write the code that becomes the system. As you complete each module or subsystem, you test it to make sure that it works. For the purposes of this chapter, testing is simply making sure that each subsystem does exactly what your design documents say it should do. In a very formal environment, however, the testing process is a very complex subject about which entire books have been written. Once the application has been thoroughly tested and you know it does everything it is supposed to do, you release the code to the people who will actually use it. Using Java's ability to create zero-install applications, however, the time you spend in the implementation stage is greatly reduced. You make the classes available over the Internet or intranet and let people run the application. The rest of implementation stage is spent gathering feedback on how the application performs in the real world so that you can prepare and manage the maintenance stage. After you first release a product, chances are you will want to enhance it and fix any bugs you didn't catch in testing. Perhaps you may even want to reengineer portions of it as your development experience grows. The final phase of software development, maintenance, is about doing just that. Of course, the creation of a new release is a full exercise in software development in itself. Maintenance thus brings you full circle back into the analysis stage of software development. ## Documenting Code The documentation created in the analysis and design phases comprises the prescriptive documentation you need to build an application. During the iterative process of systems development, however, you will encounter issues that you simply missed in analysis and design. You therefore need a way to communicate to others exactly how your system was built. Developers commonly write their descriptive documentation from memory after an application is built. They then fail to maintain the documentation along with the application. For someone trying to make a change to an application that has poorly maintained documentation, no documentation is almost as good as what he or she has to work with. Fortunately, Java provides the `javadoc` utility for documenting your code as you write it. ### The javadoc Utility The `javadoc` utility is a small Java program that comes with the JDK to help you create object documentation straight from your code. `javadoc` uses a combination of compiler information and comments made by you to build HTML documentation that describes everything about a Java object. As long as you maintain your comments with your code, your application documentation always reflects the current state of its objects when you use the `javadoc` utility. If you have visited the JavaSoft API documentation pages at `http://java.sun.com/products/JDK/CurrentRelease/api/`, you have seen the kind of descriptive documentation produced by `javadoc`. To produce HTML pages that properly document your objects, you must include the following in each object source file: A description of the object A description of all `public`, `protected`, or `private protected` attributes A description of all `public`, `protected`, or `private protected` methods Each description appears in Java code as a comment just before the element it is describing. To mark the comment as a `javadoc` comment, it must be in this format:
    /** description */
Listing 29.1 shows what the `Team` class source code looks like. #### Listing 29.1. The Team class source file, with javadoc comments.
    /**
     * The Team class has statistics and receives updates from users.
     * It represents one football team and maintains the statistics for
     * that team.
     * @version 1.0
     * @author George Reese
     */
    public class Team {
      private TeamFile file;
      private int wins, losses, points_for, points_against;
      /**
       * Constructs a new Team object based on a team name.
       * Specifically, it creates a TeamFile object to access
       * The file in which team data is stored.  It then uses
       * the file object to get all of the team's stats
       * from storage.
       * @exception FileException caused by a failure to read storage file
       * @param name the name of the team
       * @see TeamFile#getField
       */
      public Team(String name) {
        file = new TeamFile(name);
        wins = f.getField("wins");
        losses = f.getField("losses");
        points_for = f.getField("points_for");
        points_against = f.getField("points_against");
      }
      /**
       * Adds the statistics for a recently completed game.
       * In this release, we are ignoring ties.
       * @exception FileException thrown by a failed attempt to save the file
       * @param pf the points this team scored in the game
       * @param pa the points scored by the opponent
       * @see TeamFile#setField
       * @see TeamFile#save
       */
      public void addGame(int pf, int pa) {
        if( pf > pa ) wins++;
        else if( pa > pf ) losses++;
        points_for += pf;
        points_against += pa;
        file.setField("wins", wins);
        file.setField("losses", losses);
        file.setField("points_for", points_for);
        file.setField("points_against");
        file.save();
      }
      /**
       * Allows the Prediction class to get team statistics
       * for this team.
       * @exception NoSuchStatException thrown if a bad stat is requested
       * @param stat the desired stat
       * @return the value for the requested stat
       */
      protected int getStat(String stat) {
        if( stat.equals("wins") ) {
          return wins;
        }
        else if( stat.equals("losses") ) {
          return losses;
        }
        else if( stat.equals("points_for") ) {
          return points_for;
        }
        else if( stat.equals("points_against") ) {
          return points_against;
        }
        throw new NoSuchStatException(stat);
      }

    }
Ideally, you should be commenting your code to this degree anyway. Why not have those comments help you get your documentation done? You may have noticed some fields in the comments beginning with an `@` symbol. The `javadoc` utility enables you to pass certain information using these `@` keywords. In the `Team` class example, I used `@version`, `@author`, `@exception`, `@param`, `@return`, and `@see` to tell `javadoc` about the class version, class author, method exceptions, method parameters, method return values, and other references. Table 29.1 lists all the keywords you can use in your `javadoc` comments, along with their meanings. #### Table 29.1. Keywords used by javadoc.
Keyword | Description
`@author` | Used in class comments. Identifies who wrote the class. You can have multiple `@author` tags for a class.
`@exception` | Used in method comments. Identifies the full class name for any exceptions thrown by the method. You can have multiple `@exception` tags for a method.
`@param` | Used in method comments. Identifies a method parameter. You should specify as many of these as the method has parameters.
`@return` | Used in method comments. Describes what the method will return.
`@see` | Used in any comment type. Allows you to reference other classes, attributes, and methods with a hypertext link.
`@version` | Used in class comments. Identifies the version number for this class.
Among the advantages of this style of documentation is that you can embed HTML tags inside any comments that will appear in your final HTML documentation. You can even go so far as to embed applets inside your applet documentation! More importantly, this kind of documentation enables you to create links to related documentation that is beyond the ability of the `@see` keyword to handle. The only limitation is that you cannot embed an `<HR>` or `<H1>` through `<H6>` HTML tag inside a comment. Although doing so does not generate an error, it may produce unexpected results in your output documentation. Once your source files are complete--both in terms of code and commenting--you are ready to build the documentation for the application. To do this, simply execute the `javadoc` command with the class file as an argument. The `javadoc` command creates five output HTML files with documentation for your class. The generated files are listed here:
Filename | Description
`YourClassName.html` | Detailed documentation for your class.
`Package-YourPackageName.html` | For each package, one of these files is created listing all the classes in that package.
`AllNames.html` | A list of attributes and methods for all classes (in this case, just one class) in alphabetical order.
`packages.html` | A list of all packages in your application.
`tree.html` | A list of all classes shown as an inheritance tree.
Of course, you probably want to document more than one class at a time, and you probably do not want that documentation stuck in the same directory as your source code. The `javadoc` command accepts a host of options so that you can customize your documentation to your needs. Before you worry about those options, however, you should understand what Java does count on. It expects a directory tree that ships with the JDK, containing stock graphics as well as the Java API documentation (`javadoc` produces documentation that contains appropriate links to Java API documentation). Managing links to existing documentation is one place in which `javadoc` gets a little messy. Unfortunately, `javadoc` likes to pile all your documentation into one huge directory. Additionally, `javadoc` is not smart enough to determine any class dependencies on its own. If you are generating documentation for classes with dependencies, you must tell `javadoc` so that it regenerates any old documentation. Finally, the HTML files created by `javadoc` expect an `images` subdirectory under the directory in which they are located. You can generally take care of this problem by creating a link to the `images` directory that came with the JDK. On the command line, `javadoc` can take one of two forms: `javadoc [`options`]` file `javadoc [`options`]` package You can customize `javadoc` output with the options listed in Table 29.2. #### Table 29.2. Options for use with javadoc.
Option | Comment
`-author` | If there are `@author` tags in the comments, list them in the documentation.
`-authors` | Same as the `-author` option.
`-classpath` path list | Manually sets the classpath for finding source code. Remember that your `CLASSPATH` environment variable is generally set to where your `.class` files are located, so you almost always have to specify this option.
`-d` directory | The directory in which the generated documentation should be placed.
`-depend` package list | A list of dependencies for the package being documented.
`-version` | As with the `@author` tag, you must specify that version information should be included in the documentation.
`-verbose` | Print information about the progress of `javadoc` as it is generating documentation.
## Summary Although generating documentation may not be the most enjoyable part of software development, it is a necessity. Successful applications built in a timely fashion with small maintenance requirements invariably are well-documented applications flowing from a proven engineering methodology. The analysis and design stages of development provide you with prescriptive documentation that tells you exactly what has to be built before you build it. In the development stage, you can use the `javadoc` utility to create up-to-date descriptive documentation that helps people maintain and modify your code down the road--even if you are the one doing the maintenance and modification.
| ©Copyright, Macmillan Computer Publishing. All rights reserved.