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.
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
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
- Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Design Patterns. Elements of Reusable Object-Oriented Software: Buch von 1994, in dem der Adapter als Entwurfsmuster zuerst beschrieben wurde.
- Refactoring Guru: Adapter: erklärt das Muster mit Bildern und unterscheidet den Adapter, der das fremde Objekt umhüllt, vom Adapter, der durch Vererbung entsteht.