Methode

Spezifi­kation mit Java­doc

Eine Java-Klasse kann durch spezi­elle Kommen­tare im Quell­text ange­reichert werden. Hier­für kommen Java­doc-Kommen­tare zum Ein­satz, die dazu dienen, die Klasse, seine Methoden und Felder näher zu beschrei­ben. Java­doc wird als Teil des Quell­textes versio­niert.

Das Java­doc-Tool ist ein Doku­mentations­werk­zeug aus dem JDK, das aus Java-Code mit Java­doc-Kommen­taren auto­matisch HTML-Dateien erstellt. Neben der Standard­aus­gabe in HTML sind alter­native Aus­gaben durch spezi­elle Doclets mög­lich.

Die Ver­wendung von Java­doc-Kommen­tare als Spezi­fikation lässt sich am Bei­spiel eines Daten­satzes einer Wetter­station zeigen. Der Infor­mantions­objekt beschreibt das Wetter mit Anga­ben zu Regen, Tempera­tur und Wind­stärke zum Zeit­punkt der Messung.

Bitte hier Klicken, um den Quelltext anzuzeigen
/**
 * Ergebnis der Messung einer Wetterstation.
 */
@Entity
@Table(name = "WETTER")
@CardsPlusSpec                       
public class Wetter extends AbstractEntity {

  /**
   * Die eindeutige Kennung der Wetterstation.
   */
  @Size(max = 50)
  @NotNull
  @Column(name = "KENNUNG")
  private String kennung;

  /**
   * Der Wert ist true, wenn es zum Zeitpunkt
   * der Messung regnet.
   */
  @NotNull
  @Column(name = "REGEN")
  private boolean regen;

  /**
   * Die Temperatur in Grad Celsius zum Zeitpunkt
   * der Messung.
   */
  @NotNull
  @Column(name = "TEMP")
  private double temp;

  /**
   * Die Kategorie der Windstärke zum Zeitpunkt
   * der Messung.
   */
  @NotNull
  @Column(name = "WIND")
  @Enumerated(EnumType.STRING)
  private Windkategorie wind;
}

Neben den primi­tiven Typen String, boolean und double gibt es in diesem Daten­modell auch einen Auf­zählungs­typ.

Bitte hier Klicken, um den Quelltext anzuzeigen
/**
* Enum für die grobe Einteilung der Windstärke in Kategorien.
*/
@CardsPlusSpec(embedded = true)
public enum Windkategorie {
  /**
   * Keine Einschätzung möglich.
   */
  UNBEKANNT,
  /**
   * Windstille, keine Luftbewegung,
   * Rauch steigt senkrecht empor.
   */
  FLAUTE,
  /**
   * Wind ist spürbar, Blätter und
   * dünne Zweige bewegen sich.
   */
  BRISE,
  /**
   * Wind ist hörbar, größere Zweige
   * und Bäume bewegen sich.
   */
  WIND,
  /**
   * Schäden an Häusern und Bäumen
   * möglich.
   */
  STURM,
  /**
   * Schwerste Sturmschäden und Ver-
   * wüstungen möglich.
   */
  ORKAN
}

Die Java-Klasse ist mit Java­doc-Kommen­taren und ver­schiedenen Anno­tationen ver­sehen. Beide Java-Klassen sind zusätz­lich noch mit @CardsPlusSpec anno­tiert. Das ist ein Hin­weis für ein spezielles Doclet, alle Eigen­schaften, wich­tige Anno­tationen und die Jav­doc-Kommen­tare der Java-Klasse als Tabelle in eine Mark­up-Datei zu expor­tieren.

Bitte hier Klicken, um den Quelltext anzuzeigen
||Attribut||Datentyp||Kommentar||
|kennung|String|Die eindeutige Kennung der Wetterstation.
|regen|boolean|Der Wert ist `true`, wenn es zum Zeitpunkt der Messung regnet.|
|temp|double|Die Temperatur in Grad Celsius zum Zeitpunkt der Messung.|
|wind|Windkategorie|Die Kategorie der Windstärke zum Zeitpunkt der Messung.
# UNBEKANNT
# FLAUTE
# BRISE
# WIND
# STURM
# ORKAN|

Die Mark­up-Datei wird bei der Frei­gabe der Imple­mentierung als Unter­seite im Bau­stein Entity in das Wiki hoch­geladen.

Dieser Vor­gang kann natür­lich auch auto­mati­siert und bei­spiels­weise mit dem Abschluss eines Merge-Requests als Aus­löser verbunden werden.


Methode

Spezifi­kation mit Avro

Avro aus dem Apache-Uni­ver­sum ist eine von vielen Lösungen für eine sprach­neu­trale Daten­seriali­sierung. Mit Avro werden Daten mit einem Schema beschrie­ben. Avro unter­stützt primi­tive und komp­lexe Typen und Listen davon. Die Schema-Datei kann wie Quell­text versio­niert werden.

Die Ver­wendung von Avro-Schema­dateien als Spezi­fikation lässt sich am Bei­spiel eines Daten­satzes einer Wetter­station zeigen. Das Nach­richten­objekt beschreibt das Wetter mit Anga­ben zu Regen, Tempera­tur und Wind­stärke zum Zeit­punkt der Messung.

Bitte hier Klicken, um den Quelltext anzuzeigen
{
  "name": "WetterEvent",
  "type": "record",
  "fields": [
    {
        "name": "meta",
        "type": {
          "name": "Meta",
          "type": "record",
          "fields": [
            {
              "name": "id",
              "type": "string"
            },
            {
              "name": "correlation",
              "type": {
                "type": "array",
                "items": "string"
              }
            },
            {
              "name": "created",
              "type": "string"
            }
          ]
        }
      },
    {
      "name": "data",
      "type": {
        "name": "WetterData",
        "type": "record",
        "fields": [
          {
            "name": "kennung",
            "type": "string",
            "doc": "Die eindeutige Kennung der Wetterstation."
          },
          {
            "name": "regen",
            "type": "boolean",
            "doc": "Der Wert ist true, wenn es zum Zeitpunkt der Messung regnet."
          },
          {
            "name": "temp",
            "type": "double",
            "doc": "Die Temperatur in Grad Celsius zum Zeitpunkt der Messung."
          },
          {
            "name": "wind",
            "type": {
              "type": "enum",
              "name": "Windkategorie",
              "symbols": [
                "UNBEKANNT",
                "FLAUTE",
                "BRISE",
                "WIND",
                "STURM",
                "ORKAN"
              ]
            },
            "doc": "Die Kategorie der Windstärke zum Zeitpunkt der Messung.",
            "default": "UNBEKANNT"
          }
        ]
      }
    }
  ]
}

Die Avro-Schema­datei ist bereits eine les­bare Spezi­fikation. Sie kann so wie sie im Code-Reposi­tory vor­liegt im Wiki als Unter­seite im Bau­stein Event ver­öffent­licht werden. Struk­tur und Daten­typen des Events werden im Rahmen der Mög­lich­keiten von Avro syntak­tisch beschrie­ben. Mit dem doc-Ele­ment gibt der Ent­wick­ler noch zusätz­liche seman­tische Infor­mationen. Das default-Element kann auch zur Fest­legung des Stan­dard­ertes ver­wendet werden.


Methode

Spezifi­kation mit Asciidoc

Asciidoc ist eine leicht­gewicht­ige Aus­zeich­nungs­sprache für eine text­basierte Doku­menten­generie­rung. Eine Asciidoc-Datei kann wie Quell­text versio­niert werden.

Asciidoctor ist ein belieb­ter Text­prozessor, der eine Asciidoc-Datei in die For­mate HTML5, EPUB3 und PDF umwan­deln kann. Asciidoctor unter­stützt durch eine Erweiterung auch text­basierte Diagramme mit Mermaid oder PlantUML.

Die Ver­wendung von Ascii­doc als Format für die Spezi­fikation lässt sich am Bei­spiel eines Dienstes mit einem REST-API zum Lesen und Speichern von Daten­sätzen einer Wetter­station zeigen. Das Infor­mations­objekt beschreibt das Wetter mit Anga­ben zu Regen, Tempera­tur und Wind­stärke zum Zeit­punkt der Messung.

Bitte hier Klicken, um den Quelltext anzuzeigen
@RestController
@RequestMapping("/wetter")
public class WetterController {

  @RequestMapping(method = RequestMethod.POST)
  public void createWetter(@RequestBody Wetter wetter) {
    this.wetterRepository.create(wetter);
  }
    
  @RequestMapping(method = RequestMethod.GET)
  public Collection findAllWetter(String kennung) {
    return this.wetterRepository.findAllByKennung(String kennung);
  }        
}

Die Spezifi­kation besteht aus einer zen­tra­len Ascii­doc-Datei. Dort beschrei­ben die Ent­wick­ler Besonder­heiten und Regeln der Imple­mentierung als Text oder sie inklu­dieren les­bare Teile vom Code.

Bitte hier Klicken, um den Quelltext anzuzeigen
= Wetter API

== Konfiguration

[source,text]
----
include::{srcdir}/main/resources/application.properties[]
----

== Operationen

Das Service stellt folgende Operationen zur Verfügung.

|===
|Operation |Name |Funktion |Status

|GET
|/wetter?kennung=<String>
|Die Operation liefert alle Datensätze einer Wetterstation.
|200=ok +
204 (Wetterstation unbekannt) +
404 (Keine Daten)

|POST
|/wetter
|Die Operation speichert einen Datensatz einer Wetterstation.
|200=ok +
204 (Wetterstation unbekannt) +
406 (Falsche Daten)
|===

Es gilt die Regel, dass in jedem Code-Reposi­tory ein Ordner doc und die primäre Ascii­doc-Datei Service.adoc exis­tiert. Im Gegen­satz zu anderen Markup-Sprachen ver­fügt Ascii­doc über ein mäch­tiges Kon­zept zur Modulari­sierung: Den include-Befehl. Damit können Ent­wick­ler Ihre Spezifi­kation auf mehrere Ascii­doc-Dateien auf­teilen. Das erleich­tert die Team­arbeit und ver­bessert die Über­sicht­lich­keit. Die primäre Ascii­doc-Datei wird bei der Frei­gabe der Imple­mentierung als Unter­seite im Bau­stein Service in das Wiki hoch­geladen. Alle durch den include-Befehl referen­zierten Dateien werden in der einen Unter­seite zusam­men­gefasst oder im Fall einer Bild­datei im Anhang der Seite gespei­chert.

Dieser Vor­gang kann natür­lich auch auto­mati­siert und bei­spiels­weise mit dem Abschluss eines Merge-Requests als Aus­löser ver­bunden werden.


Methode

Spezifi­kation mit Spring REST-Docs

Spring REST-Docs kombi­niert hand­geschrie­bene und gene­rierte Ascii­doc-Dateien zu einer API-Doku­mentation. Ein Spring MVC-Test erstellt Ascii­doc-Dateien bei der Aus­führung, die das REST-API voll­stän­dig doku­mentieren. Der Ansatz stellt sicher, dass die Doku­mentation nur erstellt werden kann, wenn der Test erfolg­reich ist. Gleich­zeitig wird sicher­gestellt, dass genau das doku­mentiert wird, was auch imple­men­tiert wurde.

Die Ver­wendung von Spring REST-Docs erwei­tert den Ansatz der Spezifi­kation mit Asciidoc. Die Spezifi­kation besteht aus einer Ascii­doc-Datei als Rah­men­doku­ment. Dort beschrei­ben die Ent­wick­ler Besonder­heiten und Regeln der Imple­mentierung als Text oder sie inkludieren lesbare Teile vom Code. Zusätz­lich werden die von Spring REST-Docs gene­rierten Frag­mente einge­fügt. Der Auf­wand für die Pflege der Spezifi­kation durch das Team wird dadurch mini­miert.

Bitte hier Klicken, um den Quelltext anzuzeigen
= Wetter API

== Konfiguration

[source,text]
----
include::{srcdir}/main/resources/application.properties[]
----

== Operationen

Das Service stellt folgende Operationen zur Verfügung.

=== GET /wetter

Die Operation liefert alle Datensätze einer
Wetterstation.

Der Status-Code ist im Erfolgsfall 200 (ok).

Der Status-Code ist 204 (no content), wenn
die Wetterstation unbekannt ist.

Der Status-Code ist 404 (not found), wenn
keine Daten vorliegen.

==== Request

include::{snippets}/wetter/http-request.adoc[]

==== Response

include::{snippets}/wetter/http-response.adoc[]

==== CURL

include::{snippets}/wetter/curl-request.adoc[]

=== POST /wetter

Die Operation speichert einen Datensatz einer
Wetterstation.

Der Status-Code ist im Erfolgsfall 200 (ok).

Der Status-Code ist 204 (no content), wenn
die Wetterstation unbekannt ist.

Der Status-Code ist 406	(not acceptable),
wenn die Daten fehlerhaft sind.

==== Request

include::{snippets}/wetter/http-request.adoc[]

==== Response

include::{snippets}/wetter/http-response.adoc[]

==== CURL

include::{snippets}/wetter/curl-request.adoc[]

Es gilt die Regel, dass in jedem Code-Reposi­tory ein Ordner doc und die primäre Ascii­doc-Datei Service.adoc exis­tiert. Im Gegen­satz zu anderen Markup-Sprachen ver­fügt Ascii­doc über ein mäch­tiges Kon­zept zur Modulari­sierung: Den include-Befehl. Das nutzt Spring REST-Docs, um im Ordner snippets weitere Ascii­doc-Dateien zu gene­rieren, die das REST-API in unter­schied­lichen Aspek­ten test­getrie­ben spezifi­zieren. Die primäre Ascii­doc-Datei wird bei der Frei­gabe der Imple­mentierung als Unter­seite im Bau­stein Service in das Wiki hoch­geladen. Alle durch den include-Befehl referen­zierten Dateien werden in der einen Unter­seite zusammen­gefasst oder im Fall einer Bild­datei im Anhang der Seite gespei­chert.

Dieser Vor­gang kann natür­lich auch auto­mati­siert und bei­spiels­weise mit dem Abschluss eines Merge-Requests als Aus­löser verbunden werden.