Skip to main content

How not to write documentation...

Posted by timboudreau on February 9, 2009 at 11:11 PM PST

I've got this draft box full of unpublished blogs - mostly because they might insult somebody. This one is five years old and as apropos today as it was then.


2005-07-25 00:48:52
A java newbie posted to nbusers saying "I want to put an image into an AWT frame. What component do I use?"

Strangely, the answer is, there isn't any. It's trivial to write one:

public class ImagePanel extends Canvas {
    private BufferedImage img = null;
    public ImagePanel(String name) {
        setImage (name);
    }

    /** Load an image from the jar, path relative to ImagePanel.class */
    public void setImage (String name) throws IOException {
       img = ImageIO.read(ImagePanel.class.getResourceAsStream(name));
    }

    public Dimension getPreferredSize() {
        return img == null ? new Dimension() : new Dimension (img.getWidth(),
                img.getHeight());
    }

    public void paint (Graphics g) {
        if (img != null) {
            ((Graphics2D) g).drawRenderedImage(img,
                AffineTransform.getTranslateInstance(0,0));
        }
    }
}

Before someone cries "Ha! Gotcha! You Sun employees are dummies!", yes, there is a blazingly, stunningly non-obvious way to do this in one line of code:
new JLabel (new ImageIcon (ImagePanel.class.getResource("some_jpeg.jpg")))

No newbie is ever going to figure that out. It's compact and cute. But it doesn't count. Too non-obvious.

The thing is, I can totally imagine this guy's situation. I want to display an image. Seems simple enough - there ought to be a component for that. But there isn't any obvious candidate. Putting myself in his shoes (screen goes fuzzy as we flash back to my first days coding in Java)...

So I look at the docs for java.awt.Image. It says "The abstract class Image is the superclass of all classes that represent graphical images. The image must be obtained in a platform-specific manner." Well, that's not too useful... [not to mention wrong - or at least, misleading - ImageIO.read() is pretty platform independent, and so is Toolkit.loadImage()]. Hmm, I'll try the docs for BufferedImage, it's a subclass. Hey, that's better. It says "The BufferedImage subclass describes an Image with an accessible buffer of image data. A BufferedImage is comprised of a ColorModel and a Raster of image data." Hmm, nothing about reading or loading an image here. Where do I get one? I'll try Raster, that's its data, maybe that's where you load the data...

At this point I've gone down the rabbit hole - I'll spend at least a half hour digging through Rasters, ColorModels, ImageObservers and all sorts of other bric-a-brac that's useful if you're writing HotJava or Photoshop - when all I want to do is get my grubby little paws on an image!

There is a school of thought that says reference documentation should only describe the topic being discussed - and I disagree violently with it. This is a perfect example of why - someone is trying to do a very simple task - display an image. They have components. Fine. They have images. Fine. But nowhere in the documentation does it say either how to get an instance of an image, or how to paint one once you've got it!

I'm just amazed. The code above is very simple, but one could easily spend a day trying to figure out what to do and end up with something massively more complex. How many hours have how many people wasted over the years, starting out in Java, just trying to do this simple thing and running into this particular brick wall?

So, please, for all that's precious in the world: If you're writing javadoc for a class and it's not incredibly obvious how to get an instance of that class, describe where you get one. Describe the basic steps of how to use it. Especially if the thing someone does with it is not expressed in methods on it. If a documentation style maven says your docs are cluttered, tell them I told you they should be cluttered. If someone very clever comes along and says (ominous soundtrack), "Ah, but you're going to have to maintain that documentation. You say, okay, I'll maintain it. And if your documentation maven then says,
"What if one day your example is WRONG!!!" pat him on the head, tell him he's very clever (that's all he wants anyway) - and send him on his way.

Reference documentation may be intended to be "reference" documentation - i.e. it talks about the thing the documentation refers to. That doesn't mean it should talk about nothing else, like how to use the thing being referred to.

Comments

mr_light says: > skipping training or reading the tutorial/document and go with only with what the javadoc saids? The bottom line, today, is that developers learn APIs through the code completion in their IDEs, and documentation needs to be written to be compatible with that fact. Provide enough info and links for someone to get something done. The cost-benefit ratio of most tutorials is not favorable toward people doing the whole tutorial, no matter how advantageous doing it might be. The Javadoc is the last point at which a developer of an API has a reasonable chance to influence use of that API. jwenting says: > BUT, AWT is no longer actively maintained Well, that's not entirely true. Not actively *evolved* perhaps - there probably won't be any new java.awt.* classes. But the XAWT toolkit emerged not that long ago, and generally, you can't maintain the top of a skyscraper and ignore the 20 floors below the top. But in terms of new methods added to java.awt.Label, yes, from that perspective, don't expect anything new. And, having slammed the JDK javadoc this way, I suppose I really should submit an OpenJDK patch to fix the documentation to be more sane. That would be the responsible thing, having identified a problem. I'll do that in the next day or two and post here when I do. -Tim

How should a newbie know that AWT is no longer actively maintained? There isn't a hint in the javadoc. Adding a hint would be documentation maintenance. But documentation maintenance isn't done - Catch 22. How should a newbie know that looking into a class called "Image" to figure out how to display an image is a dead end? Certainly not from the javadoc. From other sources? Maybe from Sun? Let's see. Sun has tutorials and articles about this, distributed over many systems and initiatives. SDN, JDC, java.net, java.sun.com, Tech Tips, Core Java Tech Tips, Tech Tips Blog, Technical Articles, Code Samples, TSC, BluePrints, wikis, blogs, and whatnot. Holy mackerel, Batman! That is so disorganized, I bet it takes an MBA to tech ration of at least 2:1 to reach that state of disorganisation. Looking at the information chaos, starting with the javadoc reference documentation is not a bad idea for newbies. But then they are let down. There is an old proverb in programming: Make simple things simple, and difficult things not impossible. From a programmer's point of view displaying an image is a simple thing. Java and javadoc fail miserably in making this and other simple things simple.

yes, documentation should be updated. BUT, AWT is no longer actively maintained as it's been superceded and the example Tim uses to demonstrate how the documentation is wrong (and always has been wrong) is inaccurate as it assumes an API that doesn't exist within the context of that documentation.

The image stuff is indeed fun, for strange values of fun. It gets really absurd when you just want to display an array with pre-calculated image data. There are many more such examples in Java. Another one would be java.awt.Toolkit. My favorite Toolikit method: http://java.sun.com/javase/6/docs/api/java/awt/Toolkit.html#lazilyLoadDesktopProperty(java.lang.String) > lazilyLoadDesktopProperty > > protected Object lazilyLoadDesktopProperty(String name) > > an opportunity to lazily evaluate desktop property values. How that could get past Sun's QA tells a lot about Sun's QA :-( @mr_light Yes, it is open source, but have you checked out the red tape Sun wrapped around it? You'll have to sign over your first-borne just for being allowed to suggest a correction of a spelling error.

Always specify the "-use" option for the standard doclet. In the absence of good documentation at least you can see where you might get an instance of a particular type, or where it might be used.

this just comes to show how ossified java really is. in fact i wouldn't be surprised if the javadocs for java.awt.Image and friends have never been edited since first writing. sad.

If he asked for a date picker, the JXDatePicker component of SwingLabs.org might have helped him out.

Who ever wants to 'just' display a image? The comparison with MSDN on Javalobby simply scares me, I always loathed that pile of text where I got information on everything and more except for the information which I was actually looking for. Could the documentation be a little more straightforward, yes sir. and its opensource so you can change it now to make it state more definitely that its a class in which image data is stored and provides some functionality for loading them. That and the JLabel and ImageIcon names throwing you off, doesn't help iether. As far as pure awt goes there is only canvas, it's pretty superseded by swing. Now as for swing: Let me ask you a question, do you guys try to use spring or hibernate, skipping training or reading the tutorial/document and go with only with what the javadoc saids? How well is that going to go over? If you actually look at the Swing Tutorial you are going to end up with that one liner. I'm not against writing better more helpful documentation, but we have different perspectives. Use javadoc to describe the contract of your class/method/package - and yes a contract should include intent - and yes if something is not-so-obvious it should be intended or be revised - and yes you document why you opted for the not-so-obvious way. Don't add examples for the sake of examples or similar in the same way that you shouldn't document for the sake of documenting. And how to use a whole system/library/framework is better left for separate documentation. - should you want do connect the two create/add @SeeDocumentionAnnotation that way it doesn't get in the way.

"Do see this documentation in the light of the era in which it was created. At the time neither Toolkit nor ImageIO existed." which is exactly why DOCUMENTATION SHOULD BE UPDATED. I agree wholeheartedly with what Tim has written here and it does annoy me at how many places the official Sun Javadoc API give completely out-of-date or archaic information regarding a class use. Image is a particularly good example though.

I believe Jaroslav Tulach uses that as an example in his API design book too. Now I'm just curious as to what you would've answered the newbie had he asked for a date picker. ;)

Spot on Tim.

"not to mention wrong - or at least, misleading - ImageIO.read() is pretty platform independent, and so is Toolkit.loadImage()]. " Do see this documentation in the light of the era in which it was created. At the time neither Toolkit nor ImageIO existed. Java as a whole was in ints infancy, file IO itself was something of an arcane art.

Try creating an application that loads and displays an image using only the language elements available in 1.0.0.

I think you mix documentation with cookbook. In documentation the whole picture should be served, in cookbook short recipes. -- Tomek