Start / Seminare / Moderne API-Entwicklung mit REST, OpenAPI und Contract Testing

Modul

Ressourcen und Endpunkte modellieren

4 Kapitel in diesem Modul-Video · Laufzeit

Vertonung mit synthetischer Stimme · Inhalte redaktionell verantwortet · © 2026 HECKER CONSULTING, alle Rechte vorbehalten

Transkript

Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.

Ressourcen und Endpunkte modellieren

0:00 Im ersten Modul haben wir geklärt, warum eine API ein Versprechen ist. Jetzt geht es an die Substanz dieses Versprechens: Welche Dinge gibt es in Ihrer Schnittstelle überhaupt, und unter welchen Adressen sind sie zu finden? Das klingt nach einer Fingerübung und ist in Wahrheit die folgenreichste Stunde im ganzen Projekt. Denn URIs sind das, was am längsten hält.

0:21 Code können Sie umschreiben, Datenbanken migrieren — eine Adresse, gegen die fremde Systeme programmiert haben, bleibt. In diesem Modul geht es darum, sie so zu wählen, dass Sie das nicht bereuen.

Ressourcen und Endpunkte modellieren

0:33 Drei Fragen strukturieren dieses Modul. Erstens: Wie kommt man vom Geschäftsprozess zu Ressourcen, ohne einfach die Datenbank abzuschreiben? Zweitens: Was macht man mit Vorgängen, die keine Dinge sind — Stornieren, Umbuchen, Freigeben? Und drittens: Wie hält man Listen beherrschbar, bevor sie zu groß werden? Am Ende steht ein Ressourcenmodell für die Hofkiste, mit dem wir am zweiten Tag weiterarbeiten.

Von Geschäftsprozessen zu Ressourcen

0:59 Der Anfang jeder API-Modellierung ist eine Sprachübung, keine technische. Bevor wir über Pfade reden, klären wir, worüber die Fachseite eigentlich spricht — und was davon ein eigenständiges Ding ist. Denn was die Fachseite beim Namen nennt, überlebt Umbauten an der Datenbank. Was aus der Datenbank stammt, überlebt sie meistens nicht.

1:20 Eine gute Faustregel lautet: Eine Ressource ist etwas, das die Fachseite beim Namen nennt und über das man einen Satz sagen kann, der einen Zustand beschreibt. Die Bestellung ist bestätigt. Das Lieferfenster ist ausgebucht. Der Unterschied zum Datenmodell ist entscheidend. Ihre Datenbank ist nach Speichereffizienz und Normalisierung geschnitten, und beides interessiert Ihre Consumer nicht.

1:43 Wenn Sie diesen Schnitt nach außen tragen, dann friert er ein — und jede spätere Änderung an der Speicherung wird zu einer Änderung am Vertrag. Genau das wollen wir vermeiden. Der Trick an diesem Vorgehen ist der zweite Schritt. Substantive zu markieren ist leicht — jeder Prozesstext ist voller Substantive. Die eigentliche Arbeit ist die Frage, welche davon eigenständig gelesen, geändert und berechtigt werden. Was diese Prüfung nicht besteht, ist kein Ding, sondern ein Feld.

2:11 Und der letzte Schritt steht bewusst am Schluss: Adressen zu vergeben ist verlockend, weil es sich nach Fortschritt anfühlt. Aber wer zuerst die URIs schreibt, hat die Modellierungsentscheidung schon getroffen, ohne sie diskutiert zu haben. Schauen Sie auf das Muster, nicht auf die einzelnen Zeilen. Sie sehen hier drei verschiedene Beziehungen.

2:32 Die Lieferungen stehen unter dem Abo, weil sie ohne Abo nicht existieren — das ist eine echte Subressource. Das Lieferfenster steht für sich, obwohl es zu Bestellungen gehört, denn es hat einen eigenen Lebenszyklus und eine eigene Berechtigung: Die Disposition sperrt es, nicht der Kunde. Und die Bestellung wird angelegt, nicht in eine Collection gepresst. Wichtig ist außerdem, was Sie nicht sehen: kein einziges Verb im Pfad. Die Methode trägt die Handlung.

3:00 Der zweite Punkt lohnt eine kurze Warnung, weil er sich anfangs richtig anfühlt. Tiefe Verschachtelung wirkt ordentlich — alles hängt sauber an seinem Elternteil. Nach der dritten Ebene ist die Ressource aber nur noch über einen langen Pfad erreichbar, und wer sie direkt braucht, kann sie nicht adressieren. Zwei Ebenen sind eine gute Obergrenze.

3:19 Der letzte Punkt ist der unauffälligste: Beziehungen nur als Fremdschlüssel zu liefern zwingt jeden Consumer, sich die Zieladresse selbst zusammenzubauen. Damit haben Sie den Pfad faktisch zum Vertragsbestandteil gemacht, ohne es zu merken.

Aktionen und Granularität

3:33 Jetzt kommt der Teil, an dem sich die Geister scheiden. Nicht alles, was eine API tun soll, lässt sich als Ding beschreiben. Stornieren, Umbuchen, Freigeben — das sind Vorgänge. Sehen wir uns an, welche Wege es gibt und wie fein man überhaupt schneiden sollte. Und wir klären, wie fein man überhaupt schneiden sollte — eine Frage, die am Ende die Consumer beantworten.

3:57 Hier hilft ein Bild aus dem Alltag. Eine Überweisung ist kein Zustand Ihres Kontos, sondern ein Vorgang — und deshalb bekommt sie einen eigenen Beleg, den man später nachlesen kann. Genauso können Sie ein fachliches Kommando behandeln: als eigene Ressource, die den Vorgang festhält. Die Alternative ist der Zustandsübergang auf der bestehenden Ressource.

4:18 Beide Wege sind legitim. Die Frage ist nur, ob Sie den Vorgang später noch brauchen — für Nachvollziehbarkeit, für eine eigene Berechtigung, für eine Auswertung. Die Gegenüberstellung zeigt einen Zielkonflikt, den man nicht auflösen, sondern nur entscheiden kann. Links bleibt der Vorgang nachlesbar und kann eigene Rechte tragen — die Stornierung darf jemand anderes auslösen als die Bestellung. Der Preis sind mehr Endpunkte.

4:44 Rechts ist es kompakter, aber Sie sehen später nur das Ergebnis: Die Bestellung ist storniert. Wer, wann und warum, ist verloren, sofern Sie es nicht anderswo mitschreiben. Meine Empfehlung: Fragen Sie zuerst die Fachseite, ob der Vorgang selbst eine Bedeutung hat. Die Granularität ist keine Stilfrage, sondern eine Kostenfrage — und die Kosten liegen auf beiden Seiten.

5:06 Ein sehr feiner Schnitt bedeutet viele Aufrufe, und über eine mobile Verbindung merkt das jeder Nutzer. Ein sehr grober Schnitt liefert bei jedem Aufruf Felder mit, die niemand liest, und macht jede Änderung breiter, als sie sein müsste. Der wichtigste Satz steht an dritter Stelle: Der Zuschnitt richtet sich nach dem Bedarf der Consumer. Nicht nach Symmetrie, nicht nach Schönheit des Modells.

5:30 Und Bulk-Operationen baut man, wenn jemand danach fragt — nicht vorher. Der erste Punkt beschreibt eine Falle, in die viele Teams unter Zeitdruck tappen: Ein Sammelendpunkt, der alles liefert, löst das aktuelle Problem sofort. Er wird nur nie wieder kleiner. Der zweite Punkt ist ein echter Betriebsschmerz — eine Bulk-Operation, die bei einem Fehler komplett abbricht, zwingt den Consumer zu raten, was durchgelaufen ist.

5:55 Und der vierte ist der langfristig teuerste: Wer seinen Schnitt an der Oberfläche der ersten App ausrichtet, hat eine App-API gebaut, keine Schnittstelle. Beim zweiten Consumer merkt man das.

Collections beherrschbar halten

6:06 Kommen wir zu einem Thema, das in fast jedem Projekt zu spät angefasst wird. Jede Liste wächst — und irgendwann wird aus der bequemen Abfrage aller Bestellungen ein Problem für Datenbank, Netz und Client. Sehen wir uns an, wie man das von Anfang an vermeidet. Merken Sie sich diesen einen Satz: Seitenaufteilung nachzurüsten ist ein Bruch. Der Grund ist unangenehm logisch.

6:29 Bisher lieferte Ihr Aufruf alles; sobald er nur noch die ersten fünfzig Einträge liefert, bekommen bestehende Consumer stillschweigend unvollständige Daten. Sie bemerken es nicht einmal — es gibt keinen Fehler, keinen Statuscode, nichts. Die Liste ist einfach kürzer. Diese Sorte Bruch ist die gefährlichste, weil sie leise passiert.

6:49 Deshalb gehören Filter, Sortierung und Seitenaufteilung von Anfang an in den Entwurf, auch wenn die Tabelle heute zwölf Zeilen hat. Die entscheidende Zeile ist die zweite. Beim Offset-Verfahren sagen Sie: Gib mir die Einträge fünfzig bis hundert. Wenn zwischen zwei Abfragen jemand einen Eintrag einfügt, verschiebt sich alles um eine Position — Sie sehen einen Eintrag doppelt oder gar nicht.

7:12 Beim Cursor-Verfahren merkt sich der Server, wo Sie stehen, und dieses Problem verschwindet. Der Preis ist, dass Sie nicht auf Seite vierzig springen können. Deshalb die praktische Regel: Oberflächen mit Seitenzahlen bekommen Offset, große Datenmengen und Synchronisation bekommen Cursor. Hier sehen Sie ein Prinzip, das über die Seitenaufteilung hinausgeht. Statt dem Consumer zu erklären, wie er die nächste Adresse baut, schicken Sie ihm die Adresse mit.

7:40 Er folgt einer Relation namens next, und Sie behalten die Freiheit, das Verfahren später zu ändern — der Consumer merkt nichts davon. Das ist genau der Punkt, den RFC 9205 mit Link-Relationen meint, und Sie sehen ihn hier in seiner einfachsten Form. Wer stattdessen die Parameter dokumentiert, hat sie zum Vertragsbestandteil gemacht.

8:00 Der zweite Punkt verdient eine Warnung, weil er verlockend klingt. Eine freie Abfragesprache anzubieten wirkt großzügig und spart Diskussionen über Filter. Nur bekommen Sie sie nie wieder eingefangen: Jede denkbare Kombination ist ab sofort zugesagt, und Ihre Datenbank muss sie aushalten. Der dritte Punkt ist ein Klassiker der stillen Fehler — ohne festgelegte Standardsortierung entscheidet der Ausführungsplan, und der ändert sich mit den Daten.

8:26 Der Consumer sieht dann plötzlich eine andere Reihenfolge, ohne dass irgendetwas deployt wurde.

Übung

8:32 Jetzt sind Sie dran. Wir bauen das Ressourcenmodell der Hofkiste — und zwar so, dass es die nächsten elf Module trägt. Nehmen Sie sich Zeit für die Sprache; die Pfade sind danach schnell geschrieben. Und achten Sie darauf, wie viel von dieser Arbeit eigentlich Sprache ist und wie wenig davon Technik. Ihre Aufgabe ist ein vollständiges Ressourcenmodell für den Bestellprozess der Hofkiste: Abonnements, Bestellungen und Lieferfenster.

8:58 Für jede Ressource brauchen wir eine URI, eine Zuständigkeit und einen Lebenszyklus — wer legt sie an, wer beendet sie. Und die Bestellliste soll von Anfang an gefiltert, sortiert und blätterbar sein. Als Zusatz modellieren Sie das Umbuchen eines Lieferfensters zweimal: einmal als eigener Vorgang, einmal als Zustandsänderung.

9:17 Danach entscheiden Sie sich für einen Weg und können begründen, warum. Beachten Sie, dass die URIs erst im dritten Schritt kommen. Die ersten beiden Schritte sind reine Spracharbeit — den Prozess aufschreiben, Substantive prüfen. Das fühlt sich langsam an und spart Ihnen später Diskussionen. Im vierten Schritt legen Sie Filter, Sortierung und Seitenaufteilung fest, und zwar bewusst sparsam: nur, was ein Consumer tatsächlich braucht.

9:43 Der letzte Schritt ist die Gegenprobe gegen die Design-Smells von eben. Erfahrungsgemäß findet dabei jede Gruppe mindestens einen. Die drei Punkte sind aus der Praxis dieser Übung gegriffen. Die Tour des Fahrers unter die Bestellung zu hängen, wirkt naheliegend — bis die Disposition eine Tour ohne Bezug zu einer einzelnen Bestellung braucht.

10:03 Das Lieferfenster nur als Feld zu führen, rächt sich in dem Moment, in dem jemand es sperren will: Was kein Ding ist, kann man nicht sperren. Und der dritte Punkt ist die häufigste Übertreibung: Filter für jedes denkbare Feld vorzusehen, bevor ein Consumer danach gefragt hat.

Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →