Every Java member function should include some sort of header, called member function documentation, at the top of the source code that documents all of the information that is critical to understanding the function. This information includes, but is not limited to, the suggestions that follow.
By documenting what a member function does, you make it easier for others to determine if they can reuse your code. This documentation makes it easier for others to put your code into context. You also make it easier for others to determine whether or not a new change should actually be made to a piece of their code (perhaps the reason for the new change conflicts with the reason the code was written as it was in the first place).
You also need to indicate how any parameters to a member function will
be used. This information lets other programmers know what to pass to a
member function. The javadoc
@param tag is used for this purpose.
You need to document what, if anything, a member function returns so
that other programmers can use the return value or object appropriately. The
@return tag is used for this purpose.
Any outstanding problems with a member function should be documented so that other developers understand the weaknesses and difficulties with the member function. If a given bug is applicable to more than one member function within a class, then it should be documented for the class instead of solely for the function.
You should document any and all exceptions that a member function throws
at you so that other programmers know what their code will need to catch.
@throws tags are used for
If you feel that your choice of visibility for a member function will be questioned by other developers -- perhaps youve made a member function public before other objects invoke the member function -- you should document your decision. This makes your thinking clear to other developers so that they won't spend time contemplating your actions.
If a member function changes an object, then this needs to be indicated.
For example, the
withdraw() member function of a bank account modifies
the account balance. This information lets other Java programmers know
exactly how a member function invocation will affect the target object.
One of the easiest ways to determine how a piece of code works is to look at an example, so including an example or two of how to invoke a member function is quite helpful.
A precondition is a constraint under which a member function will operate properly, and a postcondition is a property or assertion that will be true after a member function has finished running (see Object-Oriented Software Construction in Resources). In many ways, preconditions and postconditions describe the assumptions that you have made when writing a member function (see Building Object Applications that Work in Resources), defining exactly the boundaries of how a member function is used.
Concurrency is a new and complex concept for many developers and, at best, is an old and complex topic for experienced concurrent programmers. The end result is that if you use the concurrent programming features of the Java programming language, then you need to document them thoroughly. Doug Lea (see Concurrent Programming in Java in Resources) suggests that when a class includes both synchronized and unsynchronized member functions, you must document the execution context that a member function relies on, especially when it requires unrestricted access to allow other developers to use those member functions safely. When a setter (a member function that updates a field) of a class that implements the Runnable interface is not synchronized, then you should document your reasons why. Finally, if you override or overload a member function and change its synchronization, you should also document why.
Figure 1 depicts an example of documentation
for a Java member function header. Notice how I have applied standard javadoc
tags, such as
@return, as well as non-standard ones, such as
To support these new tags, I would need to either develop a doclet
that recognizes them or purchase a Java development tool that can be tailored
to recognize them.
Figure 1. Example member function header documentation
/** Withdraw the funds from this account. @param amount The amount of the withdrawal. @return The amount withdrawn. @precondition The account must have the funds available for them to be withdrawn. @postcondition If the funds are available they will be withdrawn and a record of the withdrawal will be made. @throws InsufficientFundsException An indication that the account balance and overdraft limit were not sufficient to allow the withdrawal to occur. @modifies Yes Debits the funds and posts a record into the account transaction history. @concurrency Changes to an account balance, such as a withdrawal, must occur as an ACID transaction. */
The important thing is that you should document something only when it adds to the clarity of your code. You wouldnt document all of the factors described above for each and every member function because not all factors are applicable to every member function. You would, however, document several of them for each member function that you write.
- Building Object Applications That Work: Your Step-By-Step Handbook for Developing Robust Systems with Object Technology by Scott Ambler
- The Object Primer 2nd Edition by Scott Ambler
- Concurrent Programming in Java: Design Principles and Patterns, Second Edition by Doug Lea
- Object-Oriented Software Construction, Second Edition by Bertrand Meyer
Scott W. Ambler is President of Ronin International, a consulting firm specializing in object-oriented software process mentoring, architectural modeling, and Enterprise JavaBeans (EJB) development. He has authored or co-authored several books about object-oriented development, including the recently released The Object Primer 2nd Edition, which covers, in detail, the subjects summarized in this article. He can be reached at firstname.lastname@example.org and at his Web site at www.ambysoft.com.