Save a developer, document your system.

by Marc de Palol
private insults / comments : phlegias@gmail.com
public insults / comments: Blog

After some years of working as a developer I've realized the lack of standard guidelines when it comes to writing technical documentation. Not user manuals. Technical documentation, the one you should write when you develop a system, or the one you should get when you start maintaining a system somebody developed.

So, no standard guidelines around ? (at least that i liked), no problem, open source, open world. I made my own.

I started researching, getting technical documentations from different projects, getting the opinions from lots of good professional developers and using lots of common sense (my common sense, well, and sometimes other people's common sense) and this is what i came to:

To understand what a good technical documentation is we need to get into the role of someone who has just been assigned the maintenance of a project. What documentation would you like to get?

First, what kind of documentation you don't want to get ?

You don't want any of those. A good documentation is the one which is easy to read and step by step introduces you to the system, first with an overview and then more in depth in a coherent, organized and logical way. You don't want high level system design decisions mixed with low level code.

Documentation must only cover the parts that are not clear, or for any reason are not easy to understand, and all code should be completely commented using the standard tools (i.e. Javadoc, Doxygen...).

These guidelines focuses on complex systems or architectures, where more than one system interacts. Of course these same rules can be applied to big programs with OO design.

System documentation must be written using common sense and keeping in mind that its objective is being useful to someone, so writing documentation is not a system requirement that must be done (and that nobody will use).

The most important point here is: Documentation must be up to date. Repeat with me: "UUUPP TOOO DAATE", it's not that difficult dammit! if you're coding in (Perl/Erlang/Java/_insertyourlanguage_) you can update a simple (English/Tokipona/_whateverlanguage_) text!!!.

*cough* sorry about that.

Summing up:
Document your code / system thinking that the guy who will maintain it is a cannibal psychopath and knows where you live (Rick Osborne, free adaptation by myself).

So, more or less these are the guidelines contents:

  1. Save a developer, document your system.
    1. Technical documentation at architecture / system level.
      1. Functional level (what does(should) the system do)
      2. Technical level (how the system works)
      3. Usage level (how you use the system)
    2. Example (Kaboom System).
      1. Functional level.
      2. Technical level.
        1. System architecture:
        2. Components.
          1. KaboomCore Component Role.
          2. KaboomCore Design Decision.
          3. KaboomCore Package description.
          4. KaboomCore Example.
          5. KaboomCore Roadmap.
          6. Class level javadoc: Ex KaboomCore Class.
      3. Usage level.
  2. Other stuff.
      1. Code level Documentation
      2. Links

Technical documentation at architecture / system level.

Three big points, functional (what does the system do), technical (how the system does that) and usage (what do you need to make the system work / to test it)

Functional level (what does(should) the system do):

Hold on, first of all; before classes, databases, code and interactions answer this: What does the system do? Ex:

Technical level (how the system works):

Once we know what the system does we want to know how it works internally. It comes in two parts: Ok. Now we should have an idea of the overall system. It is likely to be composed of several different subsystems. Each one deployed as server, web service, stand alone program, database, whatever. You should indicate here where do they have their individual documentations. This brings us to the next point:

Usage level (how you use the system).

You need to explain how to use this thing.

If this is a server you'll need to maintain it, this means that you're the one that will have to restart the server when it crashes at 4am on a Saturday when you're completely drunk. You better have a nice documentation then.

This last paragraph made sense if we're talking about a server which is in production, it doesn't if you're documenting an API. In this case you just would be interested in having some tutorial with examples.

This section is basically a reference guide. If this is a server, remember to document:



Example (Kaboom).

I like examples, everybody likes examples. Here's an example. Let's write a documentation for a system. Something simple, the open source Kaboom project (intercontinental missile launch system).

Functional level.

Technical level.

System architecture:

First a high level diagram of the system:

As you can see the overall architecture is formed of different systems. KaboomCore is the main system, it uses a 'countries' database where it will get the information about the country we want to nuke, the 'passwordChecker' system which checks if we are authorized to nuke a country, the AlarmSystem which will turn on some nice red lights in the base and the QueueSystem where we will queue all nuke launches. The FireWorkR system just polls the queue to get nuking petitions in a concurrent fashion (we don't want four missiles to nuke the same country, what a waste).

Components.

For each component (Kaboom Core, countries database, passwordChecker, AlarmSystem, QueueSystem) we would need to have the component level documentation, in this case i'll just document the KaboomCore.

Again, until here, this documentation should be in a Wiki or web page. From now on, every component should be documented in its own Javadoc/Doxygen whatever. So, this would be javadoc and overview.html pages inside javadoc. In this case the design kind of sucks, please bear with me.
KaboomCore Component Role.
Again, first a diagram:

This Component (group of classes, likely to be a project on its own) acts as the orchestrator of the whole Kaboom system. The component is started by KaboomStarter, which is the main program (started via /etc/init.d/kaboom start). It creates an instance of the KaboomCore class and a KaboomClient which is the UI.

When a user uses the Kaboom Client to nuke a country, he/she provides name of the country to nuke and the password. The KaboomCore class orchestrates the petition.

First it checks the password. It uses a PasswordFactory to get one of the two interfaces that the passwordChecker system provides, via SOAP or via RMI, depending on the level of sadomasochism of the developer. When it gets the PasswordCheckerWSIface it uses its methods (documented in the API) to get if the password is valid or not. In case it is valid it will carry on with the launch, it will ask for the password again otherwise.

Once the password thingie is done the system checks if the soon-to-be-ashes country belongs to the Bad Guys, Good Guys or Other Guys. KaboomCore will check the result, if the country belongs to the good guys it will launch a NotOurEnemiesYetException which will be transformed in the KaboomClient class to display it to the user. If the country belongs to the Other Guys the system will ask for confirmation and if the country belongs to the Bad Guys it will carry on with the launch.

After all these confirmations the system creates a message that gets queued in the Queue using the QueueWrapper class and it calls the AlarmSystemWSIface to switch on some red lights and some sirens. You know, itz typical.

as you've seen, there's a little bit of explanation about each system and more or less the technologies. So you now should have a general idea of the interactions between components.

KaboomCore Design Decision.
No big surprises here. Just check the code.
KaboomCore Package description.
KaboomCore Example.
Here is an example of a java kaboom client. It implements the main interface and hence it can be used to launch missiles

(obviously wrong and nonsense, but if the API needs examples, please do it here).

    import xxx.kaboom.core.*;

    public class KaboomClient implements KaboomClientIface {
	public static void main(String args[]) {
	    KaboomClient kcl = new KaboomClient(args[0],args[1]);
	    System.out.println("Password please:");
	    kcl.setPassword();
	    System.out.println("Which country do you want to nuke?");
	    kcl.setCountry();
	    kcl.nukeIt();
    	}
    }
KaboomCore Roadmap.

The system is working and is stable. It would be nice to do a little of work / research to improve the sound effects and sync them with the lights in the AlarmSystem.

There are two implementations of the passwordChecker system. The first one was using SOAP. When used in production the SOAP calls were so slow that our clients' enemies had time to nuke them before the call ended. That's why we offer now a RMI implementation. The SOAP one is deprecated, but still in the release trunk for nastiness.

Class level javadoc: Ex KaboomCore Class.

this goes in the javadoc for every class (if the class is big and this is needed of course). So for every class the javadoc for every method, but also an introduction that should have:

Description: This is the class that does the actual work for the project. It orchestrates all confirmations and then creates the message that will be sended to the missile.

Initialization: The class gets some arguments from KaboomStarter. These arguments are basically used for using the external countries database and the other remote services.

Overview: This class contains just on method, nuke(String password, String country), used by the KaboomClient UI, so fairly simple. It basically uses the other services and catches the Exceptions to transform them to error messages in the UI. First checks the password. It just gets a passwordService object from the passwordFactory and uses it. If the password is correct then checks the country. It connects to the database and checks if the country is nukeable in case that it isn't it gets the exception and displays the error message. Otherwise it asks for confirmation, once confirmation is granted (only for Other Guys) it also gets the geo location of the country.

It stores it in the NukeMessage object, which is basically a bean with some info of the country. Once we've got this information, the program uses the AlarmSystemWSIface to turn on some alarms. There're several methods to turn on and off several different colors of lights and sounds in the alarms. The current implementation plays 'The Final Countdown' with red and blue lights, feel free to change it.

After this is done, the system just uses the queue(NukeMessage msg) method from the QueueWrapper to queue the message in the queue.

Usage level.

This section of the documentation is for the KaboomCore program, not for the overall Kaboom system, as the overall system is composed of 6 systems. So each of them should have this sections, as this is the example i'm doing just this one.

Other stuff.

Code level Documentation

You may like to have two lines of commentaries for each line of code or you may thing your code is easy to understand and doesn't need documentation. That's up to you. But remember the cannibal psycho that knows where you live. This is not about documenting code, it's about documenting big systems.

Links

James Benett's blog entry about documentation.
Reddit entry discussing documentation

Back to the blog