Start / Seminare / Java SE in der Praxis
Modul
Externe Web-API
7 Kapitel in diesem Modul-Video · Laufzeit
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
Externe Web-API
0:00 Im ersten Modul haben wir ein Fundament gebaut: ein Projekt, das sauber baut, eine Klasse, die ihre Eingaben prüft, und eine ordentliche Protokollierung. Ehrlicherweise macht diese Anwendung damit noch nichts, was irgendjemanden beeindrucken würde. Das ändert sich jetzt. In diesem Modul holt Kursradar zum ersten Mal echte Daten — aus einer fremden Schnittstelle, über das Netz, im Format JSON.
0:23 Und mit diesem einen Schritt tauchen fast alle Fragen auf, die den Alltag in echten Projekten ausmachen: Wie spricht man mit fremden Systemen? Was, wenn sie nicht antworten? Und wie wird aus Text ein Objekt?
Externe Web-API
0:36 Sieben Stationen liegen vor uns. Zuerst der Aufruf selbst, mit Bordmitteln von Java. Dann die Frage, was passiert, wenn der Server etwas anderes als ein freundliches Ja zurückgibt. Danach modellieren wir die Daten als eigenen Typ, binden JSON darauf, filtern die Ergebnisse und ergänzen die erste kleine Fachlogik. Und weil wir dann zum ersten Mal Code haben, der wirklich etwas entscheidet, schreiben wir zum Abschluss auch die ersten Tests.
1:01 Sie werden merken: Ab jetzt fühlt sich das Projekt spürbar nach Anwendung an. Vier Ziele. Erstens: eine fremde HTTP-Schnittstelle ansprechen, ohne dafür eine Zusatzbibliothek zu brauchen — das geht seit einigen Java-Versionen erstaunlich gut. Zweitens: JSON in eigene Datentypen überführen und dabei bewusst nur das nehmen, was Sie wirklich brauchen. Drittens: die Fachlogik von der Anbindung trennen.
1:26 Das klingt nach Architekturlehre, hat aber einen sehr praktischen Grund — nur so lässt sie sich später prüfen. Und viertens genau das: die ersten Tests, und zwar so geschrieben, dass sie nicht bei jedem neuen Fall vervielfacht werden müssen.
Aufrufe mit Javas HttpClient
1:41 Fangen wir mit dem Aufruf an. Wer Java schon länger begleitet, erinnert sich vielleicht daran, dass HTTP-Aufrufe früher entweder umständlich oder nur mit externer Bibliothek machbar waren. Das hat sich geändert, und es lohnt sich, das einmal zu sehen — denn eine Abhängigkeit, die man gar nicht erst braucht, muss man auch nie pflegen.
2:00 Der HttpClient gehört seit einigen Versionen fest zu Java. Er beherrscht moderne HTTP-Aufrufe, kommt mit Weiterleitungen zurecht und arbeitet auf Wunsch auch asynchron. Für uns heißt das: keine zusätzliche Bibliothek, kein Pflegeaufwand, kein Sicherheitsrisiko von außen. Kursradar fragt damit die Kurskatalog-Schnittstelle nach den Kursen einer Autorin. Was zurückkommt, behandeln wir zunächst bewusst stiefmütterlich — als reine Zeichenkette.
2:27 Das ist ein Zwischenschritt, und er ist Absicht: Erst soll die Verbindung stehen, dann kümmern wir uns darum, was der Text eigentlich bedeutet. Man könnte den Aufruf einfach in die Einstiegsklasse schreiben. Zehn Zeilen, fertig. Und genau so entstehen die Klassen, die man später niemand mehr anfassen mag. Deshalb bekommt die Anbindung eine eigene Klasse mit einem Namen, der sagt, wofür sie zuständig ist.
2:52 Der Gewinn zeigt sich an drei Stellen: Der Einstiegspunkt bleibt frei von Netzwerkdetails. Die Anbindung ist an einer Stelle austauschbar, wenn die fremde Schnittstelle sich ändert — und das tut sie irgendwann. Und die Fachlogik lässt sich testen, ohne dass jemand ein Netz braucht. Das ist keine Architekturästhetik, das ist Alltagsnutzen.
3:12 Zwei Dinge stehen hier als Konstanten. Die Adresse mit einem Platzhalter, in den später die Kennung der Autorin eingesetzt wird — das ist bequemer und weniger fehleranfällig als Zeichenketten zusammenzukleben. Und der Client selbst. Der ist bewusst nur einmal angelegt, denn er ist threadsicher und kann von vielen Aufrufen geteilt werden.
3:32 Wer ihn stattdessen für jeden Aufruf neu erzeugt, verschenkt Verbindungen und Zeit — und merkt es erst unter Last. Das ist ein Muster, das auch für andere Objekte gilt: teuer im Aufbau, ungefährlich in der Wiederverwendung. Hier sehen Sie zwei typische Java-Muster auf einmal. Das erste ist der Baustil: Sie setzen die Anfrage Schritt für Schritt zusammen und schließen sie am Ende ab.
3:54 Das liest sich fast wie ein Satz und ist deutlich übersichtlicher als ein Konstruktor mit sechs Argumenten. Das zweite betrifft die Ausnahmebehandlung. Der Aufruf kann auf zwei Arten scheitern, und weil wir auf beide gleich reagieren, fangen wir sie gemeinsam ab. Wichtig ist die Meldung, die wir daraus machen: Wenn diese Zeile nachts im Protokoll auftaucht, soll klar sein, welches System nicht erreichbar war.
4:18 Vier Punkte, die alle im Alltag vorkommen. Für jeden Aufruf einen neuen Client bauen — funktioniert, kostet aber unnötig Ressourcen. Die Kennung ungeprüft in die Adresse einsetzen; wer schon einmal Sonderzeichen in einer URL hatte, weiß, warum. Geprüfte Ausnahmen einfach schlucken, weil man gerade weiterkommen will — damit verschwindet der Fehler, nicht die Ursache.
4:39 Und der vierte ist eigentlich ein Tipp: Die Dokumentation zur Standardbibliothek ist gut und liegt in Ihrer Entwicklungsumgebung einen Tastendruck entfernt. Sie zu ignorieren und stattdessen zu raten, ist der langsamste Weg.
Antworten robust behandeln
4:53 Bisher haben wir stillschweigend angenommen, dass der Server freundlich antwortet. Das tut er meistens — aber eben nicht immer. Schauen wir uns an, was passiert, wenn die Antwort anders ausfällt, und wie man das behandelt, ohne den Code mit Verzweigungen zu überziehen. Ein Server antwortet mit einem Statuscode, und der ist mehr als eine Zahl im Protokoll — er ist eine Entscheidung.
5:15 Kursradar unterscheidet drei Fälle: Alles gut, der Autor ist unbekannt, oder etwas ist passiert, mit dem wir nicht gerechnet haben. Für so etwas gibt es in neueren Java-Versionen ein passendes Sprachmittel: einen Switch, der selbst einen Wert liefert. Der Clou daran ist weniger die kürzere Schreibweise, sondern dass der Compiler darauf besteht, dass Sie alle Möglichkeiten abdecken. Vergessen ist damit keine Option mehr.
5:40 Bisher haben wir den Client mit Standardeinstellungen genommen, und die sind vernünftig. Trotzdem lohnt sich hier eine Einstellung: dem Weiterleiten folgen. Warum? Schnittstellen ziehen um. Ein Anbieter richtet dann eine Weiterleitung ein und geht davon aus, dass die Aufrufer ihr folgen. Ein Browser tut das selbstverständlich, ein HTTP-Client nur, wenn man es ihm sagt. Diese eine Zeile kann Ihnen also in zwei Jahren einen Ausfall ersparen — und sie kostet nichts.
6:09 Das ist ein gutes Verhältnis für eine Vorsichtsmaßnahme. Lesen Sie das einmal wie einen Satz: Bei Erfolg wandeln wir die Antwort um, bei einem unbekannten Autor geben wir eine leere Liste zurück, in allen anderen Fällen brechen wir ab. Genau diese Klarheit ist der Gewinn. Zwei Details sind wichtig. Erstens der Standardzweig — er ist hier keine Höflichkeit, sondern Pflicht, weil der Ausdruck jeden möglichen Wert abdecken muss.
6:34 Zweitens die Fehlermeldung: Der tatsächliche Statuscode steht darin. Das klingt nach einer Kleinigkeit und ist bei der Fehlersuche später die halbe Miete. Der Kern dieser Entscheidung ist: Ein leeres Ergebnis und ein Fehler sind nicht dasselbe. Wenn ein Autor keine Kurse hat, ist das ein gültiges Ergebnis — eine leere Liste.
6:54 Wenn der Server dagegen mit einem unerwarteten Code antwortet, ist etwas kaputt, und das darf nicht als leeres Ergebnis durchgehen. Genau diese Verwechslung führt zu den unangenehmsten Fehlern überhaupt: Die Anwendung läuft weiter, zeigt aber stillschweigend nichts an, und niemand merkt es tagelang. Mit dem Statuscode als bewusster Verzweigung schließen Sie diese Lücke.
7:15 Ihre Aufgabe: Bauen Sie diese Fallunterscheidung selbst und prüfen Sie sie. Rufen Sie die Schnittstelle einmal mit einer Kennung auf, die es nicht gibt, und schauen Sie, was Ihre Anwendung daraus macht. Erfolgreich sind Sie, wenn ein unbekannter Autor eine leere Liste liefert und ein Serverfehler mit einer Meldung abbricht, in der der Statuscode steht.
7:35 Wichtig ist der zweite Teil: Es reicht nicht, dass es nicht abstürzt. Sie müssen an der Meldung erkennen können, was passiert ist, ohne den Code zu öffnen.
Daten modellieren mit Records
7:44 Wir haben jetzt eine Zeichenkette voller JSON. Damit lässt sich schlecht arbeiten. Bevor wir sie umwandeln, brauchen wir also ein Ziel — einen Java-Typ, der die Daten aufnimmt. Und dafür bietet Java inzwischen etwas an, das genau für diesen Zweck gemacht ist. Ein Record ist ein Datentyp, der nur aus Daten besteht. Sie schreiben auf, welche Bestandteile er hat — und Java erzeugt daraus den Konstruktor, die Zugriffsmethoden, den Vergleich und die lesbare Ausgabe.
8:13 Wer früher solche Klassen von Hand geschrieben oder generieren lassen hat, weiß, wie viel Rauschen damit verschwindet. Für uns ist noch etwas anderes wichtig: Wir bilden nur die fünf Felder ab, die wir wirklich brauchen — nicht die zwanzig, die der Katalog liefert. Ein Datentyp beschreibt, was Ihre Anwendung interessiert, nicht was das fremde System alles weiß.
8:34 Achten Sie auf den Namen: Dieser Typ heißt nicht einfach Kurs, sondern trägt den Katalog im Namen. Das ist Absicht. Er ist eng an die fremde Schnittstelle gebunden — ändert sie sich, ändert er sich mit. In Modul drei bekommt Kursradar deshalb einen zweiten, eigenen Kurstyp für die Domäne. Zwei ähnliche Typen zu haben, fühlt sich zunächst nach Doppelung an. Es ist aber das Gegenteil: Es ist die Naht, an der fremde und eigene Welt getrennt bleiben.
9:02 Die Annotation ganz oben erklärt sich gleich von selbst. Der eigentliche Punkt dieser Übersicht: Sie schreiben eine Zeile und bekommen vier Dinge geschenkt, die Sie sonst pflegen müssten. Und Pflege ist hier das Stichwort. Vergessene Anpassungen an Vergleichsmethoden gehören zu den fiesesten Fehlern in Java-Projekten, weil sie erst dann auffallen, wenn Objekte in Mengen oder Zuordnungen landen.
9:24 Bei einem Record kann das nicht passieren, weil die Bestandteile die einzige Quelle sind. Die lesbare Ausgabe wiederum werden Sie schon in wenigen Minuten zu schätzen wissen, wenn wir uns die geholten Kurse im Protokoll ansehen. Der häufigste Fehler ist, den Katalogtyp zum Allzwecktyp zu machen und ihn durch die ganze Anwendung zu reichen. Dann hängt am Ende auch die Datenbank an der fremden Schnittstelle.
9:47 Der zweite: alle Felder abbilden, weil sie ja da sind — das ist Arbeit ohne Gegenwert und bindet Sie an Details, die Sie nicht brauchen. Der dritte betrifft die Unveränderlichkeit: Ein Record ist nur so unveränderlich wie das, was in ihm steckt. Legen Sie eine veränderliche Liste hinein, ist die Zusicherung dahin. Und viertens: Fachlogik gehört hinein, wenn sie sich auf die eigenen Daten bezieht — sonst nicht.
JSON binden mit Jackson
10:11 Jetzt schließen wir die Lücke zwischen Zeichenkette und Objekt. Anders als beim HTTP-Aufruf hilft uns die Standardbibliothek hier nicht — für JSON gibt es in Java keine eingebaute Lösung. Also binden wir zum zweiten Mal eine Bibliothek ein, diesmal eine, die praktisch jedes Java-Projekt kennt. Jackson ist in der Java-Welt so etabliert, dass man es fast als Standard bezeichnen kann.
10:34 Die zentrale Figur ist der ObjectMapper: Sie geben ihm einen Text und sagen, welchen Typ Sie erwarten, und er liefert das Objekt. Eine Feinheit gibt es, und die ist typisch Java. Wenn Sie eine Liste von etwas erwarten, reicht die Angabe der Klasse nicht — zur Laufzeit ist nämlich nicht mehr sichtbar, wovon die Liste eine Liste ist.
10:53 Man nennt das Typlöschung. Für diesen Fall braucht Jackson eine etwas ausführlichere Typangabe. Zwei Bausteine, und das hat einen Grund: Der eine erledigt die Umwandlung, der andere bringt die Annotationen mit, über die man sie steuert. Sie sehen außerdem, dass die Versionen hier nicht ausgeschrieben stehen, sondern über Eigenschaften kommen — dasselbe Muster wie beim Protokollieren im ersten Modul.
11:17 Ich empfehle Ihnen ausdrücklich, die aktuellen Versionen selbst nachzuschlagen, statt eine Zahl von einer Folie abzuschreiben. Eine Folie veraltet still; die Suche in Maven Central sagt Ihnen, was heute gilt. In Modul fünf heben wir diese Angaben dann noch an eine gemeinsame Stelle. Der Umweg über die Typfabrik wirkt beim ersten Lesen umständlich, und das ist er auch.
11:39 Der Grund ist die eben erwähnte Typlöschung: Zur Laufzeit weiß niemand mehr, dass die Liste Kurse enthalten soll. Also sagen wir es explizit — Behälter und Elementtyp getrennt. Merken Sie sich vor allem die Fehlermeldung, die Sie sonst bekommen: Sie erhalten tatsächlich eine Liste, aber gefüllt mit etwas anderem als erwartet, und der Fehler fällt erst später auf.
12:00 Der zweite Punkt hier: Diese Umwandlung steht in einer eigenen kleinen Methode. Das hält den Verzweigungscode von vorhin lesbar. Der erste Punkt tritt beim ersten Lauf garantiert ein: Jackson meldet ein unbekanntes Feld und bricht ab. Der Grund ist gutgemeint — die Bibliothek warnt, dass die Daten nicht zum Typ passen. Da wir absichtlich nur einen Ausschnitt abbilden, sagen wir ihr, dass sie den Rest ignorieren soll.
12:24 Der zweite Punkt betrifft mitgezogene Bibliotheken: Wenn Sie einen Typ im Code verwenden, gehört dessen Baustein in Ihre Projektdatei — sich darauf zu verlassen, dass ihn jemand anderes mitbringt, geht irgendwann schief. Der dritte und vierte sind Aufräumhinweise: Den Mapper einmal anlegen und die Umwandlung nicht in die Verzweigung quetschen.
12:44 Jetzt bauen Sie die Brücke selbst. Binden Sie die Antwort an Ihren Katalogtyp und lassen Sie sich im Protokoll ausgeben, wie viele Kurse zurückkamen. Erfolgreich ist die Aufgabe, wenn zwei Dinge stimmen: Sie bekommen eine Liste echter Objekte statt einer Zeichenkette — und ein zusätzliches Feld in der Antwort bringt Ihre Anwendung nicht mehr aus dem Tritt.
13:03 Der zweite Teil ist der wichtigere. Fremde Schnittstellen wachsen, und wenn jede Erweiterung auf der Gegenseite Ihre Anwendung stoppt, haben Sie ein Problem, das Sie nicht kontrollieren.
Kurse filtern mit Streams
13:13 Wir haben jetzt eine Liste echter Objekte. Damit lässt sich endlich arbeiten. Und die erste fachliche Entscheidung ist naheliegend: Ausgemusterte Kurse wollen wir gar nicht erst weiterreichen. Ein kleiner Schritt — aber ein guter Anlass, sich die Streams anzuschauen. Die Streams-API beschreibt, was passieren soll, statt wie es abläuft.
13:33 Statt einer Schleife mit Zählvariable und Zwischenliste sagen Sie: aus dieser Liste, gefiltert nach dieser Bedingung, wieder als Liste. Wer das zum ersten Mal sieht, findet die Schleife oft vertrauter — verständlich. Der Gewinn zeigt sich, sobald mehrere Schritte zusammenkommen: filtern, sortieren, umwandeln. Dann liest sich der Stream wie eine Beschreibung der Absicht, während die Schleife zu einem Block wird, den man Zeile für Zeile nachvollziehen muss, um zu verstehen, was er eigentlich tut.
14:02 Hier stehen zwei Fassungen desselben Gedankens nebeneinander. Oben mit einer kleinen anonymen Funktion, unten mit einer Methodenreferenz und einer Umkehrung. Ich sage bewusst nicht, dass die zweite besser ist. Sie ist kürzer, wirkt für viele aber auch abstrakter — vor allem die Umkehrung liest sich rückwärts. Wichtig ist, dass Sie beide erkennen, denn beide begegnen Ihnen in fremdem Code. Und wichtig ist die Haltung dahinter: Lesbarkeit schlägt Kürze.
14:29 Wenn im Team die Hälfte bei einer Schreibweise stockt, ist sie im Zweifel die falsche. Der erste Stolperstein trifft fast jeden einmal: Ein Stream tut nichts, solange am Ende kein abschließender Schritt steht. Sie bauen die Kette, weisen das Ergebnis nicht zu — und wundern sich, dass die Liste unverändert ist. Der zweite ist fachlich: Erst speichern und dann filtern heißt, die Altlasten sind schon in der Datenbank. Filtern gehört an die Stelle, an der die Daten hereinkommen.
14:58 Der dritte betrifft die eben erwähnte Lesbarkeit. Und der vierte ist eine Gewohnheit aus älteren Java-Ständen — für den einfachen Fall gibt es inzwischen einen kürzeren Weg.
Fachlogik ergänzen
15:09 Bis jetzt haben wir Daten transportiert und umgeformt. Jetzt kommt zum ersten Mal Code, der etwas entscheidet — eine kleine Berechnung. Und damit haben wir auch zum ersten Mal etwas, das man sinnvoll testen kann. Das ist kein Zufall, sondern hängt zusammen. Der Katalog liefert die Laufzeit eines Kurses als Text, in einem Zeitformat mit Stunden, Minuten, Sekunden und manchmal Millisekunden. Wir brauchen eine Zahl.
15:34 Jetzt könnte man den Text selbst zerlegen — und das ist genau der Moment, in dem in Projekten die kleinen, hartnäckigen Fehler entstehen. Stattdessen nutzen wir die Zeit-Bibliothek von Java: Sie liest das Format und rechnet den Abstand zu Mitternacht aus. Das ist ein kleiner gedanklicher Trick, denn eine Laufzeit ist keine Uhrzeit. Er trägt weit — aber nicht unbegrenzt.
15:57 Vier Zeilen, und trotzdem lohnt der Blick auf die Fußnote. Wir behandeln die Laufzeit als Uhrzeit. Das funktioniert prima, solange kein Kurs länger als vierundzwanzig Stunden ist. Der Punkt ist nicht, dass diese Grenze schlimm wäre — sie ist völlig vertretbar. Der Punkt ist, dass wir sie kennen und benennen. Genau das unterscheidet eine bewusste Vereinfachung von einem versteckten Fehler. Schreiben Sie solche Annahmen auf, im Code oder im Kommentar.
16:24 Der Kollege, der in zwei Jahren einen seltsamen Wert sieht, wird es Ihnen danken. Es geht hier nicht um Bequemlichkeit, sondern um Fehlerquellen. Das Zeitformat ist genormt, und der Parser dafür ist geschrieben, getestet und millionenfach im Einsatz. Millisekunden, führende Nullen, Stunden — alles fällt ohne Sonderfall mit ab.
16:44 Wer denselben Text selbst zerlegt, schreibt am Anfang zehn Zeilen und pflegt danach jahrelang Ausnahmen nach, weil immer wieder ein Format auftaucht, an das niemand gedacht hat. Weniger eigener Code heißt weniger eigene Fehler. Und die Einschränkung, die wir uns einhandeln, ist bekannt und benannt statt zufällig und still.
17:04 Der erste Punkt ist der eben besprochene: Zeichenketten von Hand zerlegen und dann Sonderfälle nachziehen. Der zweite betrifft die Dokumentation der Annahme — eine Grenze, die niemand kennt, ist eine Falle. Der dritte ist verwandt: Wir schneiden Sekunden ab, statt zu runden. Auch das ist in Ordnung, solange es jemand entschieden hat und nicht der Zufall. Und der vierte ist eine Frage der Zuständigkeit.
17:27 Diese Berechnung gehört an den Datentyp, denn sie rechnet mit dessen eigenen Daten. Im Service wäre sie heimatlos — und schwerer zu testen.
Erste Tests mit JUnit
17:36 Und damit sind wir beim Testen. Wir haben jetzt Code, der eine Umrechnung vornimmt, und die Frage lautet: Woher wissen wir, dass sie stimmt? Einmal ausprobieren und hinschauen ist eine Antwort. Sie hält nur nicht, sobald jemand den Code ändert. JUnit ist die Testbibliothek der Java-Welt. Sie markieren Methoden, JUnit führt sie aus und meldet, was durchgelaufen ist und was nicht.
18:00 Wichtig ist der Geltungsbereich, den wir der Abhängigkeit geben: nur für Tests. Damit ist technisch ausgeschlossen, dass jemand versehentlich Testbibliotheken im Produktionscode benutzt — was öfter passiert, als man denkt, und was Sie dann bis in die ausgelieferte Anwendung mitschleppen. Dasselbe Prinzip wie bei der Protokoll-Umsetzung im ersten Modul: Der Geltungsbereich ist keine Formalie, er zieht eine Grenze, an die man sich nicht aus Versehen hinwegsetzen kann.
18:27 Sechs Zeilen, und eine davon ist die interessante — die mit dem Geltungsbereich. Alles andere kennen Sie schon aus dem ersten Modul. Was Sie beim ersten Einbinden vielleicht überrascht: JUnit bringt eine ganze Reihe weiterer Bausteine mit. Das ist normal, und sie tragen alle denselben Geltungsbereich, also landet nichts davon in Ihrer Anwendung.
18:46 Ein guter Moment, sich das in der Entwicklungsumgebung einmal anzusehen — die Ansicht der externen Bibliotheken zeigt Ihnen sehr anschaulich, was ein einzelner Eintrag in der Projektdatei tatsächlich nach sich zieht. Diese fünf Schritte enthalten einen, der befremdlich wirkt: die Erwartung bewusst falsch setzen. Der Grund ist wichtig.
19:06 Ein Test, der noch nie fehlgeschlagen ist, beweist nichts — er könnte auch gar nicht ausgeführt werden oder am falschen Objekt prüfen. Erst wenn Sie ihn einmal rot gesehen haben, wissen Sie, dass er tatsächlich hinschaut. Danach korrigieren Sie die Erwartung, und Grün bedeutet etwas. Der letzte Schritt ist ebenso wichtig: einmal über die Kommandozeile bauen. Ein Test, den nur Ihre Entwicklungsumgebung kennt, schützt das Projekt nicht.
19:33 Hier passiert etwas Nützliches. Statt drei fast identische Testmethoden zu schreiben, steht der Testkörper einmal da, und die Fälle stehen als Daten daneben — Eingabe und Erwartung, Zeile für Zeile. Drei Fälle: normale Minuten, mehr als eine Stunde mit Millisekunden, und die Null als Randfall. Der Gewinn zeigt sich beim vierten Fall: Sie fügen eine Zeile hinzu, nicht eine Methode.
19:56 Kopierte Tests dagegen driften auseinander — jemand bessert einen aus und übersieht die anderen beiden. Das ist die Sorte Fehler, die man nur schwer wiederfindet. Ihre Aufgabe ist, genau diese drei Fälle abzudecken, ohne den Testkörper zu vervielfachen. Erfolgreich sind Sie, wenn der Build über die Kommandozeile drei Läufe ohne Fehler meldet.
20:17 Und dann kommt der interessantere Teil, der freiwillig ist: Ergänzen Sie eine Laufzeit von mehr als vierundzwanzig Stunden. Sie werden feststellen, dass unsere Umsetzung an dieser Stelle nicht mehr trägt. Entscheiden Sie dann bewusst, was passieren soll — ein Fehler, ein anderer Ansatz, oder die Grenze bleibt und wird dokumentiert. Alle drei Antworten sind vertretbar.
20:39 Keine Antwort ist es nicht. Der erste Punkt ist der, der Projekten wirklich schadet: Tests laufen nur in der Entwicklungsumgebung. Dann prüft niemand sie beim Bauen, und irgendwann sind sie kaputt, ohne dass es auffällt. Der zweite ist die Frage des Geltungsbereichs, die wir gerade hatten. Der dritte ist Aufwand ohne Nutzen — Zugriffsmethoden zu testen, die Java selbst erzeugt hat, prüft nur, ob Java funktioniert.
21:04 Und der vierte sind die kopierten Tests, deren Varianten getrennt veralten. Testcode ist Code. Er verdient dieselbe Sorgfalt wie der Rest, sonst wird er zur Last statt zur Absicherung.
Kursradar holt Daten
21:16 Machen wir Bilanz. Kursradar spricht jetzt mit einem fremden System, und zwar mit Bordmitteln, sauber getrennt von der übrigen Anwendung. Es versteht die Antwort — nicht als Text, sondern als eigene Datentypen, bei denen es sich bewusst auf das Nötige beschränkt. Es hat eine erste Fachlogik, und die ist mit Tests abgesichert, die auch im Build laufen. Was fehlt, ist offensichtlich: Sobald das Programm endet, sind die Daten weg.
21:41 Genau da setzt das nächste Modul an — wir bringen die Kurse in eine Datenbank, und dafür schneiden wir das Projekt neu.
Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →