Posts Tagged ‘Code Documentation’

You Are Frustrating Your API Users

Sunday, January 6th, 2008

It’s time for a show of hands. How many folks have ever had the following happen to them:

  1. Get excited over a shiny new component, object, or service to integrate with your project.
  2. Download the SDK and API docs.
  3. Copy and paste some trivial examples into your project to learn about the new API.
  4. Son of a …. The examples don’t work!

If you’re fortunate, it’s just a missing semi-colon or other typo that’s easy to find, easy to fix. If fortune is not on your side, it will be the following scenario that happened to me roughly this time last year.

The examples I was using were from the most recent documentation available from the culprit’s web site. The Java code just would not compile; the methods being used just did not exist in the classes that the examples were using. Sure, those classes existed. And sure, those methods existed in other classes. Many other classes. But not as described in the example.

I thought for certain the problem was by my own doing. Was there something else on the classpath screwing me up? Did I copy and paste the wrong example? Was I using an incompatible JDK? The longer I spent on it, the more and more outrageous the possible causes I came up with were.

I did not assume the example was flawed. Why? Call it over-confidence in the documentation, call it a personal trait to first assume that I am the cause of the problem, or perhaps call it a combination of the two.

At this point, having no example, and just figuring it all out myself from scratch would have been far more efficient. It’s sad, but it’s true. It would have been better for me to have no documentation at all than to have started from flawed documentation. The ultimate problem was trivial to say the least… the example code was using the wrong class. Digging through the javadocs, and about an hour or two of trial and error to find the right class to use, finally saved the day.

Not fun.

The most likely cause of the whole problem? I see a common scenario going something like this:

  1. Documentation folks say “Gee whiz! It would be great to show our users some examples of this new whiz bang widget!”. They ask the programmers to whip something together.
  2. Programming folks create a set of examples. They’re designed, documented, compiled, tested, code reviewed, and shipped off to the documentation folks.
  3. Documentation folks insert the code snippets into Word, InDesign, Quark, or whatever publishing platform is used, never to see a compiler again… until the end-user gets their hands on it and puts it through theirs.

Now what can happen between the last time the programmer runs the code, and the first time the end-user does? Well, a lot, quite frankly. Everything from an incomplete insertion of the code into the documentation by the technical writers, to a seemingly benign last-minute global Find and Replace All by the Chief Editor that trips up on a portion of the code, to some creative modifications by the technical writing staff (”Bob in software couldn’t have meant ++i, surely he meant i++! I’ll fix it for him.”).

Even if the first version of the code survives the trip from the programmers to the technical writers and then to the end-user, what happens when the new version of the API is released? Can someone guarantee that they will go back and update the examples in the document? Who’s going to do it and make certain it’s done correctly? The valuable programmers? None-sense! They’re working on new whiz bang widgets! Chances are, this is where most of the problems come from… the actual code behind the API and the API itself are updated, but the examples that use the API are forever trapped in Word, and do not get updated. It’s a classic case of information living in separate places, and thus maintained separately; they are practically guaranteed to grow out of sync over time.

No matter what the cause, however, the result is the same: Frustration for the end user trying to work with the examples. And frustration is bad.

After all, the end-user was gracious enough to try out your software. Heck, they might even want to open up their wallets, take money out, and put that money into your wallet! And you’re going to ask them to debug your code?!? Try not to go out of business too quickly.

A Proposed Solution

Now, here’s where we go from ranting and raving to something a little more productive. I decided that I would do everything I reasonably could to ensure no user of my code suffers the same frustration.

The solution I came up with is two-fold:

  1. Keep the example code where code should live: in source control, where it’s frequently checked out, built by the build server, and regularly run through a gamut of unit tests.
  2. Automate the process of putting code in documentation. No emailing of code, no copying and pasting.

From an implementation standpoint, it’s disgustingly simple. My solution consists of a Word macro that automatically pulls example code out of source control, places it in the appropriately tagged locations in the documentation, and formats it as “code” (e.g., Courier New, special indenting, etc.).

Benefits of This Approach

Before I dive into implementation details, it’s helpful to describe several benefits of this approach to putting example code in documentation.

Easy to Maintain

I am willing to bet that for most organizations, example code is throwaway code. That means that after it’s copied-and-pasted, it’s never edited again… perhaps the original source files aren’t even saved. Why? Because if the cost of properly maintaining the code exceeds a certain threshold such that it impacts other revenue-generating development, it won’t be maintained. No one will maintain example code that they have to copy and paste out of Word into a new project, update and debug, and then once again copy and paste the example code back into Word, right before the new release of the software ships. Won’t happen.

The trick is to make it easy to maintain; to treat the example code as a real project, so there is real motivation to maintain it yet it doesn’t significantly impact other development. Don’t start off on the wrong foot by assuming the code is throwaway. You will create more headaches for yourself in the end.

What do I mean by making the example code easy to maintain? Easy to maintain means source control. Easy to maintain means test-driven development that guarantees unit tests exist for all of your example code. Easy to maintain means that a build server checks out, compiles, and tests the code every time a change is made. Easy to maintain means that when your programmers inevitably make a change to the API or to the underpinnings of the API that breaks the example code, they find out that the example code stopped working as soon as possible, so they can make the corresponding updates to the example code, too.

Support Change

Refactoring is good. It keeps your code lean, mean, and no more complicated than it needs to be. Refactoring should save you work in the long run, not add more work.

Typically, a user’s guide for an API will have the names of classes and methods sprinkled throughout. Not just in code snippets, but inline in paragraphs as actual subjects of sentences (e.g., “The WidgetFactory class is rather nifty because it does A, B, and C.”). If there’s a need to rename this class, say from the WidgetFactory to the GadgetFactory, have fun keeping your documentation in sync with the change. Even a global “Find and Replace All” operation for changing “WidgetFactory” to “GadgetFactory” in the documentation can introduce more problems than it solves (e.g., it will trip up on “Note: The WidgetFactory class was renamed to the GadgetFactory class as of release 4.”).

With the approach shown here, the code itself will still live in source control. The documentation pulls the example code from source control. Refactoring and committing a change in source control would coincidentally update the documentation when it is next accessed.

Consistent Formatting

The formatting of code is different from the formatting of your descriptive content. Programmers should have their way for code, technical writers and graphic design folks should have their way for the rest. Crossing the two will only lead to problems.

To combat this, all the programmers need to do is adhere to predefined line-width restrictions provided by the design folks, and display consistency in their usage of tabs versus spaces, and life will be good. For me, this was as simple as adding a code formatter in Eclipse that capped the line-width for my example code project, and imposing a rule for converting all tabs to spaces.

With this approach, the code will appear in the documentation exactly as the programmer intended. No word wrapping or inconsistent indentations across lines that may break the code (think Python), no mismatched curly braces, no none-sense.

Implementation

As earlier described, the bulk of the solution lives in the form of a Word macro. As a programmer, all I’ve done is created and tested my example code, formatted it within the parameters defined by the design staff, tagged it appropriately to indicate what portions of code should be pulled out into the documentation (more on this in a moment), and checked it into source control.

As a technical writer preparing the documentation, I’ve undoubtedly asked the programmer for example code showing a couple of common workflows, to which I receive in response a list of tag names that correspond to the examples. All I have to do is put those tags into my documentation, and run the macro.

Let’s walk through an example. We’ll have Calvin, a technical writer, and Bob, our programmer, working together to make a Developer’s Guide for the WebReboot Enterprise API. The most common reason to use this API is to programmatically reboot servers attached to a WebReboot Enterprise. You may reboot them because your monitoring software told you they crashed, or you received a command from your support desk software that indicated a user has filed a trouble ticket for a reboot. Details aside, as the technical writer, Calvin will want to show our users how easy it is to do this very common task with the API. For completeness, we’ll show how to get status information for a server, and power it off and on as well.

Calvin will fire off an email to the programmer to get the ball rolling:

Howdy Bob,

I would like to get some code examples to insert into our developer documentation how easy it is to use our API. Can I get a couple of examples showing:

  • How to reboot a server
  • How to get status information on the server, such as whether the server is on or off
  • How to power off and on a server

That should do it. Thanks!

Calvin the Technical Writer

A couple dozen cups of coffee later, Bob will shoot back to Calvin:

Hola Calvin,

All set! Here are the tags that correspond to the code examples you asked for:

  • How to reboot a server
    • Usage example tag:
      { PRIVATE
      code_java/path_to/Examples.java:refJCodeShowPowerSwitchReboot
      }
  • How to get status information on the server, such as whether the server is on or off
    • Method name tag:
      { PRIVATE
      code_java/path_to/Examples.java:refJMethodGetPortConfiguration }
    • Usage example tag:
      { PRIVATE
      code_java/path_to/Examples.java:refJCodeShowServerStatus
      }
  • How to power off a server
    • Method name tag:
      { PRIVATE
      code_java/path_to/Examples.java:refJMethodDoPowerOff
      }
    • Usage example tag:
      { PRIVATE
      code_java/path_to/Examples.java:refJCodeShowPowerOff
      }
  • How to power on a server
    • Method name tag:
      { PRIVATE
      code_java/path_to/Examples.java:refJMethodDoPowerOn
      }
    • Usage example tag:
      { PRIVATE
      code_java/path_to/Examples.java:refJCodeShowPowerOn
      }

All you have to do is use our standard Servprise documentation Word template, and insert the above tags where you would like the code to appear, and then run the GetCodeExcerpts macro whenever you want to update the code in the document. That’s it!

Enjoy!

Bob the Programmer

Now, for this to all come together, here’s what Bob did prior to sending that email back to the technical writer. He wrote the Java example code for each requested operation, and put all of the code in a class called Examples. The tag names he emailed back (shown above) specify two pieces of information:

  1. What file the code is in. In this case, a path to Examples.java.
  2. What portion of code in that file to pull into Word. In the case of powering off a server:
    1. The method name to use is tagged:
      refJMethodDoPowerOff
    2. The example snippet is marked with the tag:
      refJCodeShowPowerOff

What does the actual code in Examples.java look like? Here’s the relevant portion for powering off a server:

  /**
   * Example showing how to perform a power off
   *
   * @throws RemoteException
   */
public void showPowerOff() throws RemoteException
{
    // refJCodeShowPowerOff .

  // Prompt user for information.
int portNumber = getPortNumber();
GetWebRebootPortRequest infoRequest =
    new GetWebRebootPortRequest();
infoRequest.setPortNumber(portNumber);
GetWebRebootPortResponse infoResponse =
    wr.getWebRebootPort(infoRequest);
WebRebootPort port = infoResponse.getWebRebootPort();

// Check that the server supports power operations.
if (true == port.getServerPowerSwitchSupported())
{
  System.out.println("You are about to power-off: " +
    port.getName());
  // Prompt user for confirmation of power toggle action.
  boolean confirm = confirmAction();

  if (true == confirm)
  {
    PowerOffRequest powerOffRequest = new PowerOffRequest();
    powerOffRequest.setPortNumber(port.getPortNumber());
    PowerOffResponse powerOffResponse =
        wr.doPowerOff(powerOffRequest);

    // Check if there was an error executing the command.
    CommandResult result = powerOffResponse.getCommandResult();
    if (result.isError())
    {
      System.err.println(result.getResultMessage());
    }
  }
}

    // refJCodeShowPowerOff .

PowerOffRequest powerOffRequest = new PowerOffRequest();
PowerOffResponse powerOffResponse = wr.
doPowerOff // refJMethodDoPowerOff .
(powerOffRequest);
Assert.assertNotNull(powerOffResponse);

}

You can see the tag refJCodeShowPowerOff exists twice… surrounding a code segment that shows how to do a power off operation.

You can also see the tag refJMethodDoPowerOff exists only once in this code… next to the relevant method name.

That is really all that’s required from a code standpoint to pull the code out into our documentation. The macro in our Word document will parse this file looking for the relevant tag names. When two tags are found, the macro pulls out the lines in between the tags. That’s how we show a code snippet. When a single tag is found, it pulls out the content preceding the tag on the same line. That’s how we show just a method name (or a variable, or a single line of code in general).

From the technical writer’s perspective, all he has to do is enter in the tag names that Bob sent over into Word as field codes. The field codes are a “hidden” portion of the document that is viewable by selecting Show Symbols in Word.

Here’s an example with Show Symbols turned on, and the field code to insert the method name for powering off a server is selected:

Field Code in Word

And now, with Show Symbols turned off, we just see the example code, exactly as our programmer intended us to:

Text in Word

Implement for Yourself

Since most of the magic exists in the Word document, that’s really all you’ll need. Use our API manual document as a starting point:

WebReboot Enterprise API Manual

I’ve released the macro under the Apache License, Version 2.0.

For your own needs, do the following:

  1. Create your example source code, and insert the tags as appropriate to indicate which portions should get pulled into Word. You can see the Examples.java file I’ve used for our own examples, but this won’t be directly applicable to your project.
  2. Copy the GetCodeExcerpts Macro into your own document. Make sure macros are enabled in Word.
  3. Insert the tags as described above into your Word document as field codes where you want the example code to be placed. It may be easiest to enable Show Symbols in your Word document, and then copy and paste the tags from the API Manual document, and then modify the tag as necessary.
  4. Add a Custom Property to the Document Properties in Word to indicate where your source code is stored. The macro needs this to locate your source code. The property name is “codeBaseUrl”, and the value should be to your source path.
    1. For Word 2003 and older, go to File -> Properties. Select the Custom tab.
    1. For Word 2007, this can be found by clicking the Office Pearl button in the top-left corner, then going to Prepare -> Properties. On the tab that appears at top, click Document Properties, then go to Advanced Properties. Finally, select the Custom tab. Some upgrade, huh?

For my needs, the value for the property “codeBaseUrl” is “D:\servprise\wre\documentCode\wreApiManual\”. The paths specified in the tags above are relative to the path specified in this property.

The Document Properties

Results

We’ve been using this approach since the WebReboot Enterprise API was first released in November, 2006. We’ve had a number of updates and enhancements to the API since then, as well as a number of improvements to our code examples we provide to customers.

To say the least, knowing that after the code changes are complete, having updated documentation to distribute just a click away (rather than a multi-hour editing session away) has made the whole process a lot more pleasant. We know we’re giving examples to our customers that work, so they can get started on their own development without delay, and without unnecessary frustration.


Home - Contact - Copyright 2007-2008 Cory von Wallenstein. All rights reserved.