PRAXIS


Praxis

Spezifi­kation mit Include

Mit Ascii­doc und der include-Direk­tive ist es sehr ein­fach, ganze Dateien oder Teile des Codes in die Pro­dukt­doku­men­tation im Wiki ein­zu­betten. Die Datei application.yaml einer Spring-Boot-An­wen­dung zeigt die Grundkonfi­guration der An­wen­dung. Das Deploy­ment einer An­wen­dung wird durch die yml-Datei der In­gress-Kon­figu­ration sehr gut ge­zeigt. Das sind nur zwei Beispiele. Prak­tisch jede gut les­bare Quell­datei kann zu einer aus­sage­kräf­tigen Spezi­fi­kation wer­den.

Mit die­sen Fähig­kei­ten hebt sich das For­mat Ascii­doc von ande­ren Mark­down-Dialekten ab. Code und Code-Frag­men­te wer­den dort um er­klären­de Hin­weise er­gänzt, wo der Code alleine nicht klar ge­nug ist. Oft reichen da­für Links zu On­line-Hil­fen im Inter­net.

Bitte hier Klicken, um den Quelltext anzuzeigen
  = Wetter API
  
  == Konfiguration

  Das Service hat folgende Grundeinstellungen:
  
  [source,text]
  ----
  include::{srcdir}/main/resources/application.properties[]
  ----

  TIP: Siehe
  https://spring.io/projects/spring-boot
  für mehr Informationen.
  
  == Deployment
  
  Das Service stellt folgende Operationen zur Verfügung:
  
  [source,text]
  ----
  include::{srcdir}/helm/templates/ingress.yml[tag=path]
  ----
  
  TIP: Siehe
  https://helm.sh
  für mehr Informationen.
          

Es gilt die Regel, dass in jedem Code-Reposi­tory ein Ordner doc und die primäre Ascii­doc-Datei service.adoc exis­tiert. 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.

Das Ergeb­nis ist eine Pro­dukt­doku­men­tation, die in einem gro­ßen Maß aus Code be­steht. Code, der in der ver­öffent­lich­ten Form tat­säch­lich als Teil der Soft­ware aus­ge­führt wird. Hin­weise und Er­läuterun­gen im Wiki er­klä­ren, wa­rum es den Code gibt. Der Code selbst zeigt, wie die kon­krete Lö­sung aus­sieht.

Asciidoc(tor).
Für Qualität.


Praxis

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 bei der Aus­führung Ascii­doc-Frag­mente , 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 war. 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 Ascii­doc. 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.

Bitte hier Klicken, um den Quelltext anzuzeigen
  = Wetter API
  
  == Konfiguration

  Das Service hat folgende Grundeinstellungen:
  
  [source,text]
  ----
  include::{srcdir}/main/resources/application.properties[]
  ----

  TIP: Siehe
  https://spring.io/projects/spring-boot
  für mehr Informationen.
  
  == 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. Die Spezifi­­kation für den Dienst besteht aus der pri­mären Ascii­­doc-Datei als Rah­men­­doku­­ment, in der alle mit Spring REST Docs erzeugten Ascii­doc-Frag­mente an passen­der Stelle ein­gefügt wurden. 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.

Der Auf­­wand für die Pflege der Spezifi­­kation durch das Team wird dadurch redu­ziert. Gleich­zeitig steigt die Quali­tät der Spezifi­kation, weil sie nicht nur zu gro­­ßen Tei­­len auto­matisch gene­riert, sondern auch getes­tet wurde.


Praxis

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 automatisch 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­taren als Spezi­fikation lässt sich am Bei­spiel eines Infor­mations­objek­tes für die Daten einer Wetter­station zeigen. Es 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")                   
  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;
  }

Es gilt die Regel, dass in jedem Code-Reposi­tory ein Ordner doc und eine primäre Ascii­doc-Datei für jedes Infor­mations­objekt exis­tiert. Die Spezifi­­kation für das Infor­mations­objekt besteht aus der pri­mären Ascii­­doc-Datei als Rah­men­­doku­­ment, in der alle von einem Doclet erzeug­ten Ascii­doc-Frag­mente an passen­der Stelle ein­gefügt wurden. Die primäre Ascii­doc-Datei wird bei der Frei­gabe der Imple­mentierung als Unter­seite im Bau­stein Entity in das Wiki hoch­geladen.

Der Auf­­wand für die Pflege der Spezifi­­kation durch das Team wird dadurch redu­ziert. Gleich­zeitig steigt die Quali­tät der Spezifi­kation, weil Wissen direkt aus dem Code über­nommen wird.


Praxis

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.

Der Auf­­wand für die Pflege der Spezifi­­kation durch das Team wird dadurch mini­­miert. Gleich­zeitig steigt die Quali­tät der Spezifi­kation, weil Code direkt als Doku­mentation über­nommen wird.