Contents:
This document describes one way to document a software system that you have written.
This document is long, but do not be overwhelmed. It has a lot of detail to give you structure. Additionally, if you have built a substantial software system, there is probably a lot to say about it!
A poorly documented system is not worth much, however well it once worked. For small, unimportant programs that are only used for a short period of time, a few comments in the code may be enough. But for most programs, if the only documentation is the code itself, the program rapidly becomes obsolete and unmaintainable. A surprise to most novices is that a small amount of effort on documentation is rewarded even within the confines of a small project.
Unless you are infallible and live in a world where nothing ever changes, you will find yourself returning to code that you have already written, and you'll question decisions you made earlier in the development. If you don't document your decisions, you'll find yourself repeating the same mistakes or puzzling out what you once could have easily described. Not only does lack of documentation only create extra work, but it also tends to hurt the quality of the code. If you don't have a clear characterization of the problem, for example, you're unlikely to develop a clean solution.
Learning how to document software is hard, and it requires mature engineering judgment. Documenting too little is a common mistake, but the other extreme can be just as bad: If you document too much, the documentation will be overwhelming to a reader, and a burden to maintain. It's vital to document only the right things. The documentation is no help to anyone if its length discourages people from actually reading it.
Novices are often tempted to focus their efforts on the easy issues, since these are easier to document. But that's a waste of time; you don't learn anything from the effort, and you end up with documentation that is worse than useless. Novices also tend to be reluctant to document problems. This is short-sighted: if you know that some aspect of your design is not quite right, that some part of the problem has not been clarified, or that some code is likely to be buggy, then say so! You'll spare the reader time puzzling over something that appears to be wrong, you'll remember where to look yourself if you run into problems, and you'll end up with a more honest and useful document.
Another issue is when to document. Although it sometimes makes sense to postpone documentation while performing experiments, experienced developers tend to document systematically even temporary code, initial problem analyses, and draft designs. They find that this makes experimentation more productive. Furthermore, since they've established habits of documentation, it feels natural to document as they go along.
This handout gives you guidelines on how to document a software system such as Husky Maps. It gives an outline structure and some required elements, but it leaves in the details much leeway for your own judgment. It is crucial that you don't treat documentation as a dull, rote affair; if you do, your documentation will be useless, painful to read, and painful to write. So document consciously: ask yourself as you do it why you're doing it, and whether you're spending your time most effectively.
You should feel free to cut and paste text from any handouts we have given you into your documentation. In particular, you may want to use parts of the problem set handout in describing the requirements. Make sure to indicate clearly, however, any changes you make, so that your TA will not need to emulate Unix diff by hand!
Your document should have the following structure. Rough sizes in pages are provided; these are guides, not requirements.
The requirements section describes the problem being solved, as well as the solution. This section of the document is of interest to users as well as implementors; it should not contain details about the particular implementation strategy. Other parts of the system documentation will not be of interest to users, only to implementors, maintainers, and the like.
You may find use cases helpful in writing the revised specification and/or the user manual. A use case is a specific goal and a list of the actions that a user performs in order to achieve the goal. Among other things, a client can examine the list of actions to decide whether the user interface is reasonable. If the collection of use cases covers all desired user goals, then the client can have some confidence that the system will fulfill its objective.
The design section of your documentation gives a high-level picture of your implementation strategy.
To explain the decomposition and other design decisions, argue that they contribute to simplicity, extensibility (ease of adding new features), partitionability (different team members can work on different parts of the design without communicating constantly), or similar software engineering goals.
The testing section of your documentation indicates the approach you have taken to verifying and validating your system. (For a real system, this might include user tests to determine the system's suitability as a solution to the problem described in the requirements section, as well as running test suites to verify the algorithmic correctness of the code.) Just as you should not convey the design of your system by presenting the code or even listing the classes, you should not merely list the tests performed. Rather, discuss how tests were selected, why they are sufficient, why a reader should believe that no important tests were omitted, and why the reader should believe that the system will really operate as desired when fielded.
Explain what classes of errors you expect to find (and not to find!) with your strategy. Discuss what aspects of the design make it hard or easy to validate.
The reflection (more commonly called "post mortem") section of the document is where you can generalize from specific failures or successes to rules that you or others can use in future software development. What surprised you most? What do you wish you knew when you started? How could you have avoided problems that you encountered during development?
The appendix contains low-level details about the system that are not necessary in order to understand it at a high level, but are required in order to use it in practice or verify claims made elsewhere in the document.
Abstract data types. Every abstract data type (class or interface) should have:
Method Specifications. All public methods of classes should have specifications; tricky private methods should also be specified. Method specifications should follow the requires, modifies, throws, effects, returns structure described in the specifications handout and in class. Note that for CSE 331, you may assume arguments are non-null unless otherwise specified.
Implementation notes. Class comments should include the following elements (which, for notable classes, appear also in the Runtime Structure section of the design documentation):
Runtime assertions. These should be used judiciously, as explained in lecture. For a longer discussion of the how runtime assertions can improve the quality of your code, see Writing Solid Code by Steve Maguire, Microsoft Press, 1995.
Comments. Your code should be commented carefully and tastefully. Stylistic guidelines are available in the handout Java Style Guide. For an excellent discussion of commenting style and for much good advice in general about programming, see The Practice of Programming by Brian W. Kernighan and Rob Pike, Addison-Wesley, Inc., 1999. A short and C-focused but helpful discussion is Six ways to write more comprehensible code: How to keep your code from destroying you from IBM's DeveloperWorks website.