Manifesto
Download Demo
FAQs
Contact
  HomeSupport

How do you write comments for DocJet?

If you clicked on this topic first, give yourself a gold star! When evaluating a documentation tool, it's easy to get caught up in all the glitz and glamour of the GUI configuration tools and whatever, but the bulk of the time you'll spend in your documentation effort should be in writing comments. The comment parser is the real "user interface" of any documentation tool.

It's DocJet's comment parser that really separates DocJet from its competitors. DocJet is built on the idea that one of the necessary steps in getting people to write comments is to make it as easy as possible to write good comments.

This fact is at the core of DocJet's design philosophy. DocJet is built to accommodate a wide variety of commenting schemes, including that used by NDoc and JavaDoc. It does this through a variety of plug-in interfaces. But the preferred method of writing comments for DocJet is in the freeform ASCII style that people have been using since the concept of the comment was invented. There's no requirement for how you introduce your comments either, the comment just has to be adjacent to the object being defined.

It's hard to fully describe what we are talking about here because DocJet supports so many different languages and many different conventions employed in each language. But let's throw an example out there:

// Description: Starts a paragraph finding
//
// Arguments:
//  bmfo - The markup function used to combine the elements of the
//         paragraph finding
//
// Return Value:
//  The new, empty, block
//
// Remarks:
//  Before calling CreateBlock again, you need to call either
//  SetBlockLimits or CancelBlock.
[ ... ]
HRESULT CreateBlock( [in]IBlockMarkupFunctionObject *bmfo,
                     [out,retval]IBlock **out );

You can see that the comment is broken up into sections with words, like "Description:", but that isn't really necessary. While it's pretty much necessary to do a proper job of commenting a method, it's really not needed when documenting, say, an enumeration constant or a member variable. The introductory words are, of course, under your control. In the case of the "Description:" section, the comment author chose to start the text on the same line as the introductory word. Elsewhere the author chose to start a new line. That's fine, DocJet can adjust.

DocJet will automatically hyperlink the output. That is, when the "Remarks" section is processed, the words "SetBlockLimits" and "CancelBlock" will become hyperlinks. This hyperlinking mechanism is quite sophisticated - if, for instance, we were implementing a class that inherited from a class that implemented an interface named "CancelBlock", that would still be picked up. Similarly, if "CancelBlock" was a function in a namespace visible from the current object through a "using namespace" statement, it would also be resolved.

The comment showed here is pretty basic in terms of its formatting requirements. If you need something more, like preformatted blocks for code examples, numbered lists, etc., they can be done as well. Pretty much anything that a human can figure out how to format, DocJet can figure out how to format.

Documenting the Obvious

What do we mean by "fully documented?" On the surface, we might say that a system is fully documented if every published interface has a comment associated with it that fully describes the interface. That turns out not to be a very good definition on a couple of fronts. One of them is rather surprising: it's not necessary to comment each and every public interface.

Take a look at these two constructors:

void CFoo::CFoo()
// Default constructor
{...}
void CBar::CBar()
{...}

Would you say that CFoo's constructor is documented and CBar's is not? CFoo does have a comment in front of it, but the comment doesn't say anything that isn't immediately obvious from the declaration. For all practical purposes, CFoo and CBar are both equally well commented and the author of CFoo wasted effort in creating the comment.

DocJet understands the code it's documenting a great deal better than your average documentation tool. As a result, one of the things it's able to do is supply comments for obvious cases like what we have above. If you submit that code to DocJet, it would fill in the blank on CBar::CBar, producing documentation that is essentially the same as that for the commented CFoo.

Let's increase our sophistication a bit and move on to the copy constructor:

CFoo::CFoo( const CFoo &c )
{...}

Suppose you were a programmer on a documentation binge and came across that dude. In the absence of DocJet's automatic commenting, almost all programmers would either type in "// Copy constructor" or cut & paste the comment from another copy constructor into this spot. Programmers know a downhill road when they see one.

However, if you were commenting along and ran across this and you knew that a reasonable default will be provided for you, you could either (1) skip the comment altogether, or (2) provide more detail. For instance, in DocJet, if you supplied:

// This makes a deep copy of c.
CFoo::CFoo( const CFoo &c )
{...}

Your comment, regarding the deep vs. shallow copy, would become the "Remarks" in the output and the default copy constructor brief description would be used as well. To put it another way, writing that, above, would be as good as writing this, in NDoc:

// <description>This creates a new instance of the object.</description>
// <remarks>This makes a deep copy of c.</remarks>
CFoo::CFoo( const CFoo &c )
{...}

What DocJet is doing here goes beyond code. DocJet's goal is to provide an environment where the easiest thing for the programmer to do is also the best thing a programmer can do. When faced with the constructor, the programmer is asked to think, "Is there anything that is special about this particular copy constructor?" If so, they can supply a comment that specifically addresses that. If there really isn't anything special about the constructor, fine, move on to another object where there is something important to say.

The Perils of Commenting by Cut&Paste

Now let's take it up another notch into the world of inherited methods:

interface IFoo {
  // <extensive comment>
  void frob();
};

class CFoo implements IFoo {
  void frob();
};

DocJet employs the notion of inherited comments as well as the automatic comments we discussed before. In this case, any comment you put in front of CFoo::frob would override and complement IFoo::frob in much the same way as we discussed before for DocJet's notion of automatic commenting. For just about any reasonable case, the root method defines the purpose and interface of a method. That is, in IFoo::frob, you would talk about what the inputs are, what the effects are, and what the output is. In CFoo::frob, all that would continue to be the same; all you have to add there is any comments on how the class implements the method. In most cases, there's no need to put any comment at all on CFoo's frob method, because, in most cases, the reader of the documentation really doesn't care how CFoo implements frob.

Now that we have talked about the advantages of inherited documentation, let's talk about what happens in its absence. In that event, given the mandate to "document" all the code, how would a programmer react to seeing this bit:

void CFoo::frob();
{
...

In most cases, a programmer will "document" the above code by cutting&pasting the extensive comment from IFoo. That certainly works for the first go at documentation, but what happens later when someone updates the interface to IFoo::frob? Only the most determined optimist would expect that the comment for CFoo::frob will get updated to reflect the change.

Summary

Probably the most crucial thing you have to understand when selecting a documentation tool is this: no matter how good the tool is, it won't produce anything useful if the programmers don't write good comments. Motivating a programmer to write a good comment takes three things. First, you have to make it as simple as possible to write comments. Second, you have to give the writer confidence that their comments will be part of a high-quality document that people will actually read.

In this article, we have discussed how you make DocJet makes it easy to write comments. But comments are not the whole of a good document, you also need organizational and supporting documents to tie the whole thing together.