2.7. Dokumentation

Dokumentation er et vigtigt aspekt af ethvert softwareudviklingsprojekt. I dette afsnit fokuserer vi på et værktøj, der kan hjælpe dig med at udarbejde API-dokumentation.

API-dokumentation består af en API-specifikation samt en vejledning i at bruge API'en. API-specifikationen skal ses som en kontrakt mellem den som bruger API'en (klienten) og den som implementerer API'en (leverandøren). Hvis leverandøren f.eks. lover at metoden double sqr(int number) returnerer kvadratroden af number når tallet ikke er negativt så ved klienten at uanset, hvordan metoden er implementeret så vil den altid returnere kvadratroden med så stor præcision, som returtypen tillader. Hvis returværdien viser sig at være forkert i nogle tilfælde så har leverandøren brudt kontrakten og metoden er implementeret forkert. Hvis klienten kalder metoden med et negativt tal så er der også tale om kontraktbrud. Kontraktbrud kan enten resultere i en exception eller også er resultatet ikke veldefineret.

2.7.1. Javadoc

Javadoc er en dokumentationsværktøj, der genererer API-dokumentation ud fra

Denne sektion er ment som en hjælp til at få dig i gang med at bruge Javadoc så der er flere aspekter, som vi vil springe over. Når du har fået blod på tanden så kan du læse JDK's Tool documentation eller besøge nedenstående hjemmesider.

2.7.1.1. Javadoc-kommentarer

Javadoc-kommentarerne er på formen

/** et-eller-andet */

og kan knytte sig til klasser, interfaces, konstruktører, metoder og klassevariable. Alt afhængigt af hvad de knytter sig til så kan/skal man også angive en række beskrivende Javadoc-tags som er på formen.

@tagnavn et-eller-andet

Følgende eksempel illustrerer brugen af Javadoc-kommentarer og Javadoc-tags.

package dk.sslug;

/**
 * Denne klasse repræsenterer en simpel stak, der
 * lagrer heltal.
 *
 * @author Jonas Kongslund (jonas@kongslund.dk)
 * @version 1.1
 */
public class IntStack
{
  /** Antal elementer i stakken */
  protected int count;

  /**
   * Indeholder stakkens elementer. Elementerne er placeret
   * i <code>elements[0...count-1]</code>.
   * <p>
   * Toppen af stakken er <code>count-1</code>
   * når <code>count>0</code> og ellers udefineret.
   *
   * @see #pop()
   * @see #push(int)
   */
  protected int[] elements;

  /**
   * Standardkonstruktør for denne klasse.
   */
  public IntStack()
  {
    /* Øvelse: implementer metoden sådan at
       elements og count initialiseres til
       nogle fornuftige værdier */
  }

  /**
   * Fjerner og returnerer det øverste tal på stakken.
   *
   * @return int Det øverste tal på stakken
   * @exception java.util.EmptyStackException
   *            hvis stakken er tom
   */
  public int pop() throws java.util.EmptyStackException
  {
    /* Øvelse: implementer metoden */
    return -1;
  }

  /**
   * Placerer det angivne tal øverst på stakken.
   *
   * @param element Tallet der skal lægges på stakken
   */
  public void push(int element)
  {
    /* Øvelse: implementer metoden så stakken
       udvides såfremt den er fyldt */
  }

  /**
   * Placerer det angivne tal øverst på stakken.
   *
   * @param element Tallet der skal lægges på stakken
   * @deprecated Siden version 1.1; Metoden er
   *   erstattet af <code>push(int)</code>.
   * @see #push(int)
   */
  public void skub(int element)
  {
    push(element);
  }
}

Bemærk at vi i eksemplet bruger HTML-tags til at fremhæve blandt andet metodenavne. Dette er både tilladt og anbefalelsesværdigt pga. øget læsevenlighed i API-dokumentationen.

Det er desuden anbefalelsesværdigt at lade den første sætning i hver kommentar være beskrivende nok til at man hurtigt får en idé om, hvad eksempelvis en metode gør. Javadoc-værktøjet forventer faktisk dette da den bruger den første sætning til at generere oversigtslister med.

Prøv at kalde Javadoc-værktøjet med følgende argumenter

[jonas@zeta eksempler/dev-env]$  javadoc -author -version dk.sslug

Værktøjet genererer som standard HTML-filer. Åbn index.html med en browser for at se resultatet.

Bemærk

Hvis du har brugt Javadoc på eksempler/dev-env/-kataloget så følger der også pakkedokumentation med i købet, selvom den ikke er medtaget i eksemplet foroven. Hvordan du laver pakkedokumentation beskrives senere i denne sektion.

I eksemplet er der knyttet Javadoc-kommentarer til metoder og klassevariable samt klassen selv. I de fleste af kommentarerne anvendes der Javadoc-tags.

  • @author, der er obligatorisk, angiver ophavsmanden er for Javadoc-kommentarernes vedkommende beregnet til klasser og interfaces . Det er muligt at angive flere @author-tags på separate linjer såfremt der er flere ophavsmænd.

  • @version, der er obligatorisk, angiver versionsnummeret og er for Javadoc-kommentarernes vedkommende beregnet til klasser og interfaces. Versionsnummeret har ikke nogen speciel betydning og kan derfor være hvad som helst.

  • @since, angiver i hvilken version af API'en som tilføjelsen fandt sted og kan bruges overalt. Versionsnummeret har ikke nogen speciel betydning og kan derfor være hvad som helst.

  • @param beskriver et argument og er beregnet til metoder og konstruktører. Først angives argumentets navn og dernæst beskrivelsen.

  • @return beskriver returværdien og er beregnet til metoder. Først angives returtypen og dernæst beskrivelsen.

  • @exception beskriver en exception og er beregnet til metoder og konstruktører. Der kan naturligvis være flere @exception-tags og hvis du synes @throws virker mere logisk så kan du også anvende denne.

  • @see henviser til en pakke, klasse, klassevariabel, interface, konstruktør eller metode. En af de mulige henvisningsformer er pakkenavn.klassenavn#medlem, hvor medlem kan være et metodenavn på formen flaf(type1,type2,...) eller et variabelnavn. Pakkenavn og klassenavn kan udlades, hvis der henvises til en metode eller klassevariabel indenfor samme klasse. Dette Javadoc-tag kan anvendes i alle Javadoc-kommentarer.

  • @deprecated kan bruges overalt og indikerer f.eks. at en metode ikke længere bør anvendes fordi den vil udgå i en senere version. Det er anbefalelsesværdigt at henvise til et alternativ ved hjælp af @see.

2.7.1.2. Pakkekommentarer

En pakkekommentar laves ved at oprette en HTML-fil kaldet package.html, der placeres i pakkens katalog. Hvis pakken f.eks. hedder dk.sslug så placeres filen i dk/sslug. Javadoc-værktøjet sørger automatisk for at medtage filen.

Forneden har vi et eksempel på en pakkekommentar.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>dk.sslug</title>
  </head>
  <body>
    Tilbyder containerklasser, som kan lagre forskellige typer
    data. Indtil videre er der kun én klasse, IntStack, men
    dette bliver der ændret på i næste version.

    @see dk.sslug.IntStack
    @since 1.0
  </body>
</html>

Javadoc-værktøjet bruger kun det der står mellem <body> og </body>, så titlen kan være hvad som helst.

Ligesom med Javadoc-kommentarer er det muligt at anvende Javadoc-tags i pakkekommentarer. Blandt dem der er nævnt tidligere kan du anvende

  • @author (ikke obligatorisk som hos Javadoc-kommentarer)

  • @version (ikke obligatorisk som hos Javadoc-kommentarer)

  • @since

  • @deprecated

  • @see

Bemærk at pakkekommentarer må ikke indeholde /** ... */ og en linje må ikke starte med *.

2.7.1.3. Linke til andre API-dokumenter

I eksemplet foroven kan pop()-metoden smide en java.util.EmptyStackException, men denne har vi ikke selv lavet og derfor linker API-dokumentationen ikke til den. Dette kunne dog godt være ønskværdigt såfremt man ikke lige kan huske hvad EmptyStackException dækker over (hvilket i dette tilfælde dog nok er ret usandsynligt).

Javadoc-værktøjet er så smart at det kan linke din API-dokumentation til klasser og interfaces, der er indeholdt i andre API-dokumenter. Det eneste man skal gøre er at fortælle Javadoc, hvor den eksterne dokumentation befinder sig.

Her er et eksempel, der forudsætter at JDK's API-dokumentation er indeholdt i $JAVA_HOME/docs/api.

[jonas@zeta eksempler/dev-env]$  javadoc -link $JAVA_HOME/docs/api dk.sslug

Du kan også angive en URL.

[jonas@zeta eksempler/dev-env]$  javadoc -link \
http://java.sun.com/products/jdk/1.3/docs/api/ dk.sslug

I begge tilfælde bliver der kun lavet links til dokumentationen for en ekstern klasse eller interface såfremt følgende er opfyldt

  • Den er eksplict angivet i en import-sætning, f.eks. import java.util.EmptyStackException;. Det er ikke nok at der står import java.util.*;.

  • Den er angivet som returtype eller argumenttype i en metode eller konstruktør.

  • Den anvendes i en implements-, extends- eller throws-sætning, f.eks. public int pop() throws java.util.EmptyStackException

I eksemplet er det tilfælde tre som gør sig gældende.