Softwarearchitektur verstehen und entscheiden

Aaron KreisÜber mich
Anwendungsarchitektur

Adapter

Unpassende Schnittstelle übersetzen

Die Idee und ihr Nutzen

Die Schadenanwendung einer Versicherung soll vor dem Anlegen eines Schadens prüfen, ob die Adresse des Kunden stimmt. Dafür steht ein alter Adressdienst bereit, der die Adresse aber in einer anderen Form erwartet und statt „gültig“ oder „ungültig“ einen Prüfwert von 0 bis 100 zurückgibt. Der Prüfwert gibt an, wie genau die eingegebene Adresse zu einer Adresse passt, die der alte Adressdienst kennt: 100 bei genauer Übereinstimmung, weniger bei einem Tippfehler im Straßennamen oder einer unbekannten Hausnummer, nahe 0, wenn es keine ähnliche Adresse gibt. Ein kleines zusätzliches Programmstück zwischen beiden Programmen nimmt die Anfrage der Schadenanwendung entgegen, formt sie für den alten Adressdienst um und macht aus dem Prüfwert „gültig“ oder „ungültig“: Erreicht der Prüfwert einen Grenzwert, den die Fachabteilung festlegt, gilt die Adresse als gültig. Dieses Übersetzungsstück heißt Adapter.

Bausteine: Schadenanwendung: bleibt unverändert; Adapter: übersetzt in beide Richtungen; Alter Adressdienst: bleibt unverändert. Verbindungen: Schadenanwendung — Adapter (Adresse als ein Objekt); Schadenanwendung — Adapter („gültig“ oder „ungültig“); Adapter — Alter Adressdienst (Straße, Postleitzahl, Ort einzeln); Adapter — Alter Adressdienst (Prüfwert 0 bis 100). Der Adapter übersetzt Aufruf und Antwort zwischen Schadenanwendung und altem Adressdienst.

Wie funktioniert es?

Eine Sachbearbeiterin erfasst in der Schadenanwendung einen Wasserschaden für die Adresse Lindenstraße 12, 40210 Düsseldorf. Die Schadenanwendung ruft beim Adapter pruefe(adresse) auf und übergibt ein Adressobjekt, also Straße, Postleitzahl und Ort als ein zusammengehöriges Datenpaket. Der Adapter zerlegt das Adressobjekt, weil der alte Adressdienst die drei Angaben einzeln verlangt, und ruft damit validateAddress(street, zip, city) auf. Der alte Adressdienst antwortet mit dem Prüfwert 92. Der Adapter vergleicht ihn mit dem Grenzwert 80 und meldet der Schadenanwendung „gültig“. Die Sachbearbeiterin kann den Schaden anlegen.

Den Aufruf pruefe(adresse) hat das Team der Schadenanwendung festgelegt: So will die Schadenanwendung eine Adresse prüfen lassen, mit einem Adressobjekt als Eingabe und „gültig“ oder „ungültig“ als Antwort. Eine solche vereinbarte Form eines Aufrufs, also sein Name, die übergebenen Angaben und die Art der Antwort, heißt Schnittstelle. Der Adapter bietet genau diese Schnittstelle an und ruft seinerseits die Schnittstelle des alten Adressdienstes auf. Dass der Adapter dafür den alten Adressdienst aufruft, wie dessen Schnittstelle aussieht und was der Prüfwert bedeutet, steht ausschließlich im Code des Adapters und lässt sich dort testen. Die Schadenanwendung erfährt davon nichts. Den Grenzwert legt der Adapter nicht selbst fest, er wendet ihn nur an. Geschrieben und gepflegt wird der Adapter vom Team der Schadenanwendung.

Hat sich die Sachbearbeiterin bei der Postleitzahl vertippt, findet der alte Adressdienst nur eine ähnliche Adresse und liefert zum Beispiel den Prüfwert 45. Der Adapter meldet dann „ungültig“, und die Schadenanwendung bittet die Sachbearbeiterin, die Adresse zu korrigieren. Fällt der alte Adressdienst aus, meldet der Adapter einen Fehler und nicht „ungültig“. Sonst sähe ein Ausfall des alten Adressdienstes aus wie eine falsche Adresse.

Adapter: Adressprüfung in beide Richtungen übersetzen

Beteiligte: Sachbearbeiterin: erfasst einen Wasserschaden; Schadenanwendung: kennt nur den Aufruf pruefe(adresse); Adapter: übersetzt Aufruf und Antwort, kennt Grenzwert 80; Alter Adressdienst: kennt nur validateAddress, liefert 0 bis 100. Ablauf: 1. Die Sachbearbeiterin erfasst einen Wasserschaden mit der Adresse Lindenstraße 12, 40210 Düsseldorf. 2. Die Schadenanwendung ruft beim Adapter pruefe(adresse) auf und übergibt das Adressobjekt, so wie sie es immer tut. 3. Der Adapter zerlegt das Adressobjekt in drei Angaben, weil der alte Adressdienst nur Straße, Postleitzahl und Ort als einzelne Angaben annimmt. 4. Der alte Adressdienst liefert einen Prüfwert zwischen 0 und 100, hier 92: Die Adresse passt fast genau zu einer bekannten Adresse. 5. Der Adapter vergleicht den Prüfwert mit dem Grenzwert 80 der Fachabteilung. 92 bedeutet „gültig“; ein technischer Fehler würde als Fehler gemeldet, nicht als „ungültig“. 6. Die Schadenanwendung erhält die Antwort „gültig“ in der Form, die sie erwartet. 7. Die Sachbearbeiterin legt den Schaden an. Bei einem Prüfwert von 45 hätte die Schadenanwendung sie gebeten, die Adresse zu korrigieren.

Wann ist es sinnvoll und wann nicht?

Ein Adapter lohnt sich

  • Der alte Adressdienst lässt sich nicht ändern. Andere Programme nutzen ihn in seiner heutigen Form, oder er gehört einem anderen Team.
  • Mehrere Programmteile der Schadenanwendung prüfen Adressen. Ohne Adapter müsste jeder von ihnen das Adressobjekt selbst zerlegen und den Prüfwert selbst deuten.
  • Der alte Adressdienst soll später durch einen neuen ersetzt werden. Dann schreibt das Team der Schadenanwendung nur einen neuen Adapter, und die Schadenanwendung bleibt unverändert. Liefert der neue Adressdienst statt einer Zahl „bestätigt“, „unsicher“ oder „unbekannt“, muss allerdings die Fachabteilung entscheiden, wie eine „unsichere“ Adresse behandelt wird.

Ein Adapter ist nicht das Richtige

  • Beide Programme stammen vom selben Team, und ihre Schnittstellen lassen sich mit wenig Aufwand angleichen. Dann ist es einfacher, eine der beiden Schnittstellen anzupassen, als dauerhaft einen Adapter zu pflegen.
  • Die Schadenanwendung muss für eine einzige Aufgabe mehrere Aufrufe in der richtigen Reihenfolge machen, etwa erst den Vertrag prüfen und dann den Schaden speichern. Die Schnittstellen passen, es sind nur viele Schritte. Dafür gibt es die Facade, die diese Aufrufe hinter einem einzigen Aufruf zusammenfasst.
  • Beide Programme verwenden dieselben Begriffe mit verschiedener Bedeutung, etwa „Kunde“ einmal für eine Person und einmal für einen Vertrag. Das Umformen von Aufrufen löst diesen Widerspruch nicht. Dafür gibt es den Anti Corruption Layer, der auch Begriffe und Regeln des fremden Programms übersetzt.
  • Der alte Adressdienst ist zu langsam oder fällt häufig aus. Daran ändert ein Adapter nichts; dagegen helfen Timeout und Circuit Breaker.

Nachteile und typische Fehler

Jeder Adapter ist zusätzlicher Code, den das Team der Schadenanwendung pflegen und testen muss. Ändert der alte Adressdienst seine Aufrufe, muss auch der Adapter geändert werden. Der Adapter übersetzt nur: Ist der alte Adressdienst langsam oder ausgefallen, bemerkt die Schadenanwendung das weiterhin.

Typische Fehler und woran man sie erkennt:

  • Fehler als fachliche Antwort: Der Adapter meldet bei einem Ausfall des alten Adressdienstes „ungültig“ statt eines Fehlers. Sachbearbeiter korrigieren dann richtige Adressen. Erkennbar ist das an vielen abgelehnten Adressen zur selben Zeit, in der der alte Adressdienst Fehler meldet.
  • Verlorene Information: Die Schadenanwendung erfährt nur „gültig“ oder „ungültig“, nicht ob der Prüfwert 81 oder 99 war. Braucht sie später doch den genauen Wert, etwa um zweifelhafte Adressen von Hand prüfen zu lassen, fehlt er. Erkennbar ist das, wenn Fachabteilungen nach Angaben fragen, die der alte Adressdienst liefert, die Schadenanwendung aber nicht kennt.
  • Versteckter Grenzwert: Der Grenzwert 80 ist eine fachliche Entscheidung, steht aber nur im Code des Adapters. Ändert die Fachabteilung ihre Vorgabe, arbeitet der Adapter weiter mit dem alten Wert, und niemand bemerkt es. Deshalb gehört der Grenzwert dokumentiert und mit der Fachabteilung abgestimmt.
  • Verkettete Adapter: Mehrere Adapter sind hintereinandergeschaltet und übersetzen die Angaben jeweils erneut. Ein fehlerhaftes Ergebnis lässt sich dann schwer dem Adapter zuordnen, der es verursacht hat.

Weiterführend

Verwandte Ansätze

  • Hexagonal Architecture: baut eine ganze Anwendung so auf, dass jede Technik wie Datenbank, Webformular oder E-Mail über einen eigenen Adapter angebunden ist.
  • Message Translator: wendet dieselbe Übersetzungsidee auf Nachrichten an, die Programme einander schicken.

Werkzeuge und Umsetzungen

Der Adapter ist ein Entwurfsmuster, also eine bewährte Bauweise, die Entwickler selbst programmieren. Es gibt kein Produkt, das man dafür installiert. Die folgenden Projekte sind nach dem Muster gebaut oder erleichtern das Schreiben von Adaptern:

  • SLF4J: Java-Programme schreiben ihre Protokolleinträge über eine einheitliche Schnittstelle. SLF4J leitet sie über ein eingebundenes Adaptermodul an eine gewählte Protokollbibliothek wie Logback oder Log4j weiter.
  • Apache Camel: enthält mehrere hundert Komponenten. Jede Komponente bindet ein fremdes System oder Protokoll, etwa einen Dateiserver, eine Datenbank oder einen Nachrichtendienst, an die einheitliche Verarbeitung von Camel an.
  • MapStruct: erzeugt Java-Code, der Werte von einem Datenobjekt in ein anderes überträgt. Solcher Umwandlungscode wird in Adaptern häufig gebraucht. Die Entwickler müssen fachliche Deutungen wie den Grenzwert 80 weiterhin selbst programmieren.

Quellen