6.170 / Fall 2000 / Documenting a Software System
Handout H10
Objective
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 other programs, if the only documentation is the code
itself, the program rapidly becomes obsolete. Without good documentation, a
program is 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, you will find yourself returning to code that you
have already written, and will 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. Lack of documentation can not only
create extra work; it also tends to damage 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 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 the
right things. 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, of
course; you don't learn anything from the effort, and you end up with useless
documentation. 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,
or 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. And 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 your 6170 project. 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 (and painful to produce). So document consciously: asking 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!
Outline
Your document should have the following structure. Rough sizes in pages
(pp) for a typical 6170 project.
(1) Requirements
- Overview (0.2 - 1pp). An explanation of the purpose of the system
and the functionality it provides.
- User Manual (1-5pp). A detailed description of how the system is to
be used; what operations the user can perform; command line arguments; etc.
Detailed specifications of formats should be relegated to the Appendix. Any
environmental assumptions should be made explicit here: for example, that
the program only runs on certain platforms, or assumes a certain directory
hierarchy is present, or assumes certain other applications are present,
etc. Along with the overview, this manual should provide all the information
needed by a user of the system.
- Performance (0.5-1pp). What resources the system requires for
normal operation, and what space and time it should be expected to consume.
- Problem Analysis (2-10pp). A clear description of the underlying
problem. Should include one or more problem object models, definitions of
their sets and relations, and a discussion of tricky issues. Object models
should include both diagrams and any essential textual constraints.
Alternatives considered but rejected, with reasons; unresolved issues, or
aspects not fully clarified to be resolved later.
(2) Design
- Overview (0.5-3pp). An overview of the design. Top-level
organization; where the design 'hotspots' are; use of libraries and
other 3rd party modules; pointers to any aspects that are unsettled or most
likely to change. Problems with the
design: decisions that may turn out to be wrong; tradeoffs between
flexibility and performance, for example, that may turn out to be
ill-judged.
- Runtime Structure (1-5pp). A description of the state structure of
the running program, expressed as a code object model. This model should
hide the representations of abstract data types; its purpose is to show the
relationships amongst objects. Object models should include both diagrams
and any essential textual constraints. Representations of data types should
be explained (along with their rep invariants and abstraction functions) if
those representations are unusual, particularly complex, or crucial to the
overall design. Note that abstraction functions and rep invariants should
still appear in their natural place in the code itself.
- Module Structure (1-5pp). A description of the syntactic structure
of the program text, expressed as a module dependency diagram. Should
include package structure and should show Java interfaces as well as
classes. It is not necessary to
show dependences on individual Java API classes. Explain why the particular
syntactic structure was chosen (e.g., introduction of interfaces for
decoupling -- what they decouple and why), and how particular design
patterns were used.
(3) Testing
- Strategy (0.1-2pp). An explanation of the overall strategy for
testing. Black box or glass box; top down or bottom up; kinds of test bed
used; sources of test data.
- Test results (0.5-2pp). Summary of what testing has been
accomplished, and what if any remains; which modules have been tested, and
how thoroughly. Degree of confidence in the code: what kinds of fault have
been eliminated? what kinds might remain?
(4) Reflection
- Evaluation (0.5-1pp). What you regarded as the successes and
failures of the development: unresolved design problems, performance
problems, etc.
- Lessons (0.2-1pp). What lessons you learned from the experience;
how you might do it differently a second time round; how the faults of the
design and implementation may be corrected.
(5) Appendix
- Module Specifications .You should extract the specifications
from your code and present them separately here. If you write your
comments in the style accepted by Javadoc with the 6170 doclet, you'll be able to
generate the specification documents automatically from the code. The
specification of an abstract type should include its overview,
specification fields, and abstract invariants (specification
constraints). The abstraction function and rep invariant are not part
of a type's specification.
- Test cases. Ideally your testbed generates tests from a file of
testcases in a format that is convenient to read and write. You need not
include all test cases; in stress testing, for example, you might just note
the size of a random input generated. Indicate for each group of tests what
they are for (e.g., "stress tests, huge inputs", "partition
tests, all combinations of +/-/0 for integer args").
- Formats. A description of all formats assumed or guaranteed by the
program, whether for file I/O, command line arguments, user dialogs, message
formats for network communications, etc.
Documenting Code
Back to the Handouts page.
For problems or questions regarding this page, contact: 6.170-webmaster@mit.edu.