2

So, I work as a developer. We are a small team. The majority of the people (everyone except the project manager and the senior developer) are still in university. We have very flexible work hours, sometimes I don't see some of the people for 3-4 days.

You can imagine that communication is key here. We write a lot of emails and use a bug tracking system and as long as you are somewhat connected to the task you can be well informed. (as long as you read all the correspondence).

One of the weak points of the team is the documentation that people leave behind. The code is reasonably well written and as long as you take the time to read it in it's entirety you will understand it. (problem: this usually takes quite a bit of time when tackling modules of a couple of thousand lines of code) Note: There is very good documentation for the users which is written to the end users, however we are discussing the documentation shared between the programmers.

When a new person has to enter some of the things a part of the team is working on, or when someone has to modify old code or someone's old code things get a bit complicated. As I mentioned before sometimes we don't see eachother for days so unless the project manager knows(and remembers) the details of the code the newcommer will have the following options:

1 Read the source

2 Read the old emails with the discussions.

When you have to refactor large pieces of the code This is fine (esp the first thing) however when an algorithm needs to be changed or someone just has to use an old module as part of new module or script or whatever you can imagine that waiting to meet the guy who created the module or reading tons of emails will waste time.

I have started adding small documentation in the beginning of each module. It consists of:

  1. 2-3 sentences about what the module does
  2. A bit of information for each function that is not a part of another function. Basically what it does and some specific information about the arguments it takes if the arguments are objects. If they aren't I just write "see the source for more on the arguments"

Since I don't know if I am on the right track the question is simple: What should such a minimal documentation contain so it can give a general idea about what the module does and how people can use it?

  • Your question is oddly redolent of literate programming. – Michael Jun 24 '14 at 19:07
  • The description of the website says that it is for software development questions, so I guess it's place is here. – Bloodcount Jun 24 '14 at 19:09
  • It definitely belongs. More what I meant was that the problems you are looking to solve (highly coupled documentation and code) were the same as those that literate programming sought to solve. – Michael Jun 24 '14 at 21:10
  • :-) "redolent" = suggestive; reminiscent (I had to look it up) – x457812 Dec 2 '15 at 12:52
4

This is the set of guidelines I have seen used in multiple teams:

  • Class: Document what the responsibility of the class is (and usually a class must have one responsibility).
  • Method: Document what goes in the method, what method does with it, and what comes out.
  • Inside code: Do not document what a developer can understand by skimming through the code, rather focus on assumptions, or things that are harder to discover, or a brief explanation of a complex piece of code.

This also forces a little bit of better design, because if the class has too many responsibilities, then there's a problem. The purpose of the documentation is to find out when the classes and methods are expected to be used without reading the code. If someone has to read the code, then documentation is usually a waste and you are duplicating code in English.

We use C# heavily, so C# code documentation tags and auto-generation of the documentation helps significantly. We produce MSDN-style documentation using SandCastle and put it on an internal share so that the developers can look at it. That acts as a forcing function. You may be able to find such a tool for whatever you are working on. And I have also been asked to find out if we can likewise generate documentation extracted from our XSD (which is also documented inline using the xs:annotation tags).

Lastly, if possible, especially for classes that are exposed out of the DLL and to be used by other DLLs, I encourage (and personally try to add) example code in the comments. This can be rather onerous, especially keeping the evolution of code in mind, so it is something we wouldn't do if the usage can be found by looking at other code including tests.

2

I will suggest a different approach to tackle this problem.

I am guessing that you don't have enough abstraction levels and that you have modules of code that are too large. Consider adding abstraction layers and/or objects that, by fully descriptive names, effectively provide the developers that read it with good documentation.

For example, in Ruby, I will frequently see classes with hundreds of methods and methods themselves with thousands of lines. Frequently for the User god class. Such code, no matter how well written will take some time to understand. However refactoring into classes no bigger than 100 lines and methods no bigger than 5 lines ('Sandi Metzs rules') can help with this. Almost every time I refactor code with techniques like Extract Method, Extract Class or tackle problems like Too Many Parameters I find that the code afterwards is easier to read.

2

You can have two good sources of documentation in your code. The first is inline comments that use a standard format, like Javadoc or the aforementioned C# code documentation tags. These should accompany each class and each method that may be used by others (you don't need to do this with private methods/classes, though it may help in some cases). Because they are a standard format, many programmers are already familiar with them, or can become familiar with them quickly. Additionally, tools are able to recognize and extract data from these specially formatted comment blocks. You could write Javadoc for a method like Math.abs as follows:

/**
 * <p>
 * Returns the absolute value of an int value. If the argument is not negative, the argument is returned. If the argument is negative, the negation of the argument is returned.
 * <p>
 * Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.
 *
 * @param a the argument whose absolute value is to be determined
 * @return the absolute value of the argument.
 */
public static int abs(int a)
{ ...

and using Java's built-in Javadoc tool, you can generate something like this. Some IDEs are able to read formatted comments and provide embedded documentation. For comments like these, it is important to focus on behavior not implementation. What your method does is unlikely to change, but how it does it may change frequently. Focusing on what it does means less potential for drift between comments and code.

The second source of documentation in your code is your tests. Someone should be able to figure out what your methods do by looking at the tests. Rspec and other behavior-driven test frameworks are designed to read like a natural language to reduce the barrier to entry, but a capable programmer can get what they need to know from any valid test framework. To test our Math.abs method, we could have the following test (with JUnit):

@Test
public void testAbs() {
    assertEquals(5, Math.abs(5));
    assertEquals(5, Math.abs(-5));
    assertEquals(0, Math.abs(0));
    assertEquals(Integer.MIN_VALUE, Math.abs(Integer.MIN_VALUE));
}

From this test, I can see that positive values are returned as-is, negative values are returned negated, zero is returned as-is, and Integer.MIN_VALUE is returned as-is (in accordance with the documentation we wrote for the method). Additionally, if I was still not clear about what happens for a particular input (say Integer.MAX_VALUE), I can easily add another test and find out, without interfering with anything else. While tests are not always as plainly clear as comments, they provide executable verifiability. That is, I can prove that the code does what the tests say by running the tests and seeing that they pass. Tests generally cannot drift from the code as comments can, since drift would manifest as failing tests.


If you find yourself having to read a lot of code just to find out what a method does, you also need to put more effort towards making your code as self-documenting as possible. Descriptive class, method, and variable names can improve legibility significantly. Small methods that you can essentially treat as black boxes (like Math.abs above, where we don't know the actual implementation) can also help by hiding complexity behind a friendlier name.

1

At the very least, add -perhaps after the copyright notice- a comment in a few paragraphs describing what your source file does. This is helpful (for the future persons working on the same code). Also add a README file!

Look inside the source code of small free software projects for inspiration!

1

What should such a minimal documentation contain so it can give a general idea about what the module does and how people can use it?

Nothing.

Needing documentation to describe what your code does is a sign that your code is poorly named, poorly structured, and/or overly complex. Sure, there are times when there are no good names, or the code needs to be complex because the problem is complex. But that's a exceeding minority of any codebase.

In all honesty, I don't even read comments at the top of files/classes/methods anymore (comments in methods can be useful though). Comments lie. They quickly get out of date. The code can be misleading due to poor naming. The code can be confusing due to poor structuring. But the code can't out and out lie about what it actually does.

  • I don't want to read 100s of lines of code (if not more) to just understand what the code does. Are you saying that it would be preferable to read code for the .NET class libraries rather than using the MSDN documentation? – Omer Iqbal Jun 24 '14 at 19:18
  • @OmerIqbal - No, I'm saying that it should be obvious what WriteAllLines does. Or what sort of things MemoryStream takes care of since they're well named. If you actually are going to be working in the classes, then yes - you should actually read them. – Telastyn Jun 24 '14 at 19:23
  • WriteAllLines where? Let's assume file. Does encoding matter (Unicode vs ASCII vs UTF-8 text)? Let's assume that's discoverable via types, what about binary data? Should it be encoded in a particular way? Does it write over network shares? I don't have time to read the code to understand all this, otherwise there would be no documentation in the world, just code. We won't get articles for ASP.NET identity or MSDN, just code -- read it. – Omer Iqbal Jun 24 '14 at 19:39
  • @omeriqbal - because the msdn documentation spells all that out. Oh wait, it does no such thing. – Telastyn Jun 24 '14 at 20:09
  • +1 for "Comments lie. They quickly get out of date." This is the primary problem with comments. The ONLY thing that can tell you what the code really does is the code itself. Reserve comments for WHY you are coding a certain way, like adherence to business rules and whatnot. – Graham Jun 25 '14 at 13:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.