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.
So, more or less these are the guidelines contents:
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:
/etc/init.d ? a script somewhere? in a screen session ? do you need to start other services before?
ctrl+c ? /etc/init.d/ script ?
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.
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.
xxx.kaboom.core.conf: Package that manages all configuration stuff (reading conf from files, etc)
xxx.kaboom.core.dao: Package that provides access to the underlying stored objects.
xxx.kaboom.core.ws.passwordChecker: Password Checker web service stubs.
xxx.kaboom.core.ws.alarmSystem: Alarm System web service stubs.
xxx.kaboom.core.queue: Simple wrap up class to work with the queue, provides easy methods to queue messages and to connect to the queue.
xxx.kaboom.core.util: Some util classes to create MissileLaunchPetition's and other handy data structures.
xxx.kaboom.core: Main classes.
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();
}
}
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.
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.
nuke1.coolcountry machine. You can start it with /etc/init.d/kaboom start. Make sure that the database 'countries' is accepting connections in nukedb.coolcountry machine.
nuke1.coolcountry machine. Just /etc/init.d/kaboom stop in root.
/var/log/kaboom/kaboom.log. Log4j format.
nuke2.coolcountry (postgres), the 'passwordChecker' system in nuke3.coolcountry (RMI or Soap + Axis2 + Tomcat 4.0), the 'AlarmSystem' in nuke4.coolcountry (RMI) and the Queue system installed in missilelauncher.coolcountry (JBoss).nuke1-backup.coolcountry1 machine.
/home/nuker/kaboom via 'svn update', build the system and deploy the new jar in /usr/local/kaboom/lib. Then restart the system via /etc/init.d/kaboom restart.
/etc/kaboom/ you'll find some conf files. A standard log4j.properties file, a nukedb.conf with the ip and password for the 'countries' database and a kaboom.conf files with other values, such as debugging mode.
http://nuke1:8888/~nuker/graphs.php
/var/log/kaboom and /var/log/apache. Then restart the system.
svn+ssh://nuker@nuke-dev.coolcountry/SVN/kaboom/trunk
(/src) another one with the tests (/test) and another one with the configuration files and scripts (/conf). Easy.
'ant build' should be enough.
'ant test'. The tests do not cover the missile launching.
fake-nuke.coolcountry. It uses all the live stuff but the 'AlamSystem' and the Queue System, those are mocks.