To boldly go where no tech writer has gone before (one can dream, right?)

Importing Code Samples with DITA (or How to Avoid Serious Headaches)

So now we know that good API documentation must include code samples. But if we want our users to base their code on our examples, we must make sure that they are valid and always up-to-date.

In general, the code samples are simply copied from the developers’ source files and pasted into the documentation. If the source code is updated after the documentation is released–for example, if a new mandatory parameter is added to the API–then the documentation must also be updated. Manually checking that all the code samples are still valid may be possible if the documentation is short and simple, but that is rarely the case when documenting APIs. Updating code samples manually can quickly become unmanageable (not to mention be the source of a serious headache, as I unfortunately had the chance to experience recently).

To solve this issue, the code samples in the documentation should be linked to the developers’ source files so that any change to the code will be reflected automatically in the documentation. In DITA, this can be done with the <coderef> element, which is available inside a <codeblock> element.

For example, consider the following source file:
C:\SVN_Checkout\product_x\src\samples\HelloWorld.java


class HelloWorld {
 public static void main(String[] args)
 {
 System.out.println("Hello World!");
 }
}

In the DITA XML file, the reference to this sample would be coded as follows:


<p>The following code shows the infamous "Hello World!" Java class:</p>
<codeblock>
  <coderef href="..\..\SVN_Checkout\product_x\src\samples\HelloWorld.java"/>
</codeblock>

When transforming the DITA file, the output would be similar to the following:

Some guidelines when importing code samples:

  • The imported source files should be short and sweet; importing a Java class that goes over four or five pages in the documentation is not very useful (or readable).
  • The source files should be well commented and include white space for readability.
  • The documentation should be stored with the software, using a control management system, so that the paths to the source files are always valid.

One disadvantage of using <coderef> is that the source code cannot be formatted once it’s imported, so for languages with amazingly long class names (like Java!), it can be downright ugly. Another disadvantage is that <coderef> imports the complete source file, which is not always optimal. Sometimes I only want to include short sections from the source file. Fortunately, this can also be done in DITA, but it’s a bit more complicated.

Including code snippets
To include code snippets in a document, one solution is to create a script that extracts from the source files only the sections that are of interest to the documentation. The script looks for keywords in the comments, indicating the beginning and end of the code samples, along with an ID in a <ph> element uniquely identifying the sample. The output of the script is a DITA file that contains all the code snippets with their IDs.

For example, assuming that the script looks for the DITA_START and DITA_END keywords, a code snippet could be coded in the Java file as follows:


/** DITA_START:<ph id="helloworld_example"> **/
class HelloWorld {
 public static void main(String[] args)
 {
 System.out.println("Hello World!");
 }
}
/** DITA_END:</ph> **/

Running the script generates a valid DITA file (for example, dynamic_code_sample_library.dita) that contains the code snippet:


<codeblock> 
 <ph id="helloworld_example"> 
   class HelloWorld {
     public static void main(String[] args)
     {
     System.out.println("Hello World!");
     }
  }
 </ph> 
</codeblock>

The snippets are included in the documentation using conkeyrefs:


 <p>The following code shows the infamous "Hello World!" Java class:</p>
  <codeblock>
    <xref conkeyref="dynamic_code_sample_library/helloworld_example"/>
  </codeblock>

With this solution, I run the script to make sure that the code snippets are up-to-date, I generate my DITA output, and voilà! Well, that’s the plan anyway. I’m currently working on the script, so the headache occurs at the beginning of the project ;-) But I’m having fun and know that it will be worthwhile in the long run!

For more information on creating good samples

Peter Gruenbaum from SDK Bridge has written some of the most interesting articles I’ve read on how to document APIs:

Share this article:
Facebook Twitter Email Linkedin

10 Responses to “Importing Code Samples with DITA (or How to Avoid Serious Headaches)”

  1. Very interesting! I have a few questions/comments.

    Is it possible to have syntax highlight in the code sample inside the document? It is fairly easy to read the code if the sample is small like in the example, but for larger sample, syntax highlighting would help a lot for the developer reading the sample code.

    Also, I noticed that the document referring to the java file seems to be outside the code SVN repository. This means that the code repository have to be checked out at the proper revision for the generated document to refer to the right implementation snippet. If the referring document was inside the code repository, then the version would always be in sync. But I understand that there might be reasons to keep it outside if the document’s life cycle is different than the code life cycle. For example, if the document is modified to add a section in all versions of the software, then having it in a separate repository would make it easier. I’m just curious to have your opinion on what is normally the best way :)

  2. Nathalie says:

    A syntax highligher is a great idea! I’ll have to look it up, maybe there is a plugin that exists. It would be applied during the DITA transformation. If it doesn’t exist, we should invent it :)

    As for the reference being outside of the repository, it’s my bad. I did not use a real example (I did not want to display the actual path publicly), but I did not fake it well enough :) In this specific example, the documentation is always inside the code repository so that they are always in sync. But that is not always the case. It really depends on the product, the number of releases that must be supported, how often the doc needs to be updated, etc.

    Thanks for your comment! :)

  3. Jeanne says:

    Hi Nathalie,

    It seems I’ll be writing a huge API document, due in a month. Thanks so much for the links – they’re very good.

    Jeanne

  4. Nathalie says:

    Lucky you! :)

    You might also find the following interesting:
    What developers want by Sarah Maddox. It provides very good examples of great API documentation.

    Good luck!

  5. I’m just catching up on your blog and I found this post very interesting. One question came up to me while I was reading this since it looks like DITA can be integrated in a continuous integration system:
    If a reference code sample can’t be found, does DITA report back an error or does it just fail to generate the code sample output in the doc? The former would be great as you could get notified immediately as things change if the references need updating. Not unlike smoke tests failure.

    • Nathalie says:

      Actually, it does both. So you would get an error (or maybe a warning) when the output is generated, but the output would be generated anyway, without the code sample. So it’s not terribly user-friendly…

      Thanks for your comment!

      • Any error or warning is probably good enough for continuous integration. I’ve never worked on a project where doc is embed inside the application source but I like the idea of having a fresh document as part of a build output. If someone breaks documentation generation by removing some code that is used, you could know immediately and that’s probably a good thing. Of course, it also means that the tech writers might become responsible for breaking builds. Much fun :)

  6. Vicki Thomas says:

    I have a question – we’re using codeblock for the code snippets. When we create our PDF documents with Flare, a – is inserted at the end of each line – making the code incorrect…
    Any ideas on how to get around this – I’m thinking I have to do something creative in the stylesheet that controls the PDF output.
    Any advice/ideas appreciated!

    cheers,
    vicki

    • Nathalie says:

      Hi Vicki! Sorry for taking so long to answer, for some strange reason the notice was lost in my junk mail.

      Yes, you have to change the stylesheet or script that transforms the DITA files to PDF, in particular the rendering of the element. I’m not sure how it works with Flare (I work mostly with the DITA OT) and I’m no expert (yet, I’m working on it! :), so I can’t provide specific pointers.

      Have you tried the dita-users Yahoo group (http://tech.groups.yahoo.com/group/dita-users/)? I have found it very useful in the past when I had to deal with specific DITA issues.

      Good luck and thanks for writing!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>