Was ist ein Wrapper in der Programmierung?

Das englische Wort „Wrapper“ bezeichnet z. B. Verpackungen oder Buchumschläge. Im Zusammenhang mit Software steht der Begriff für Programme oder Codes, die andere Programmkomponenten umgeben. Für den Einsatz von Wrappern gibt es unterschiedliche Gründe: Oft geschieht es im Hinblick auf Kompatibilität oder Interoperabilität zwischen verschiedenen Software-Strukturen oder auch aus Gründen der optischen Darstellung, wie etwa bei HTML- oder CSS-Wrappern. Bei einem Wrapper kann es sich um einzelne Software-Komponenten, eigenständige Software-Produkte, Software-Architekturen, Klassen in der objektorientierten Programmierung oder Frameworks handeln.

Sollen innerhalb eines Programms Funktionen oder Programmblöcke einer anderen Programmiersprache genutzt werden, kann man diese mit einem Wrapper „umhüllen“. Das Hauptprogramm kommuniziert ausschließlich mit dem Wrapper, der die Befehle an das umhüllte Programm weiterleitet und umgekehrt die Ergebnisse zurückliefert. Der Wrapper selbst ist die einzige Komponente, die direkt mit beiden Programmteilen kommuniziert.

Wrapper lassen sich in der Programmierung und Software-Entwicklung vielfältig einsetzen. Wie ein Wrapper genau funktioniert und welche unterschiedlichen Aufgaben er übernimmt, zeigen die folgenden Anwendungsbeispiele.

Wrapper als Übersetzer für Benutzereingaben

Formulare in Programmen oder Webanwendungen erwarten Eingaben, die das Programm verarbeiten kann. So geht man bei Programmen aus dem britischen Raum oft fast selbstverständlich davon aus, dass Zahlen mit Dezimalpunkt statt Komma und Maße in Fuß und Zoll eingegeben werden. Nicht immer besteht bei der Nutzung solcher Programmkomponenten in eigenen Anwendungen die Möglichkeit, diese an die hierzulande üblichen Benutzereingaben anzupassen, was unweigerlich zu falschen Ergebnissen oder sogar Programmfehlern führt.

In solchen Fällen bietet sich ein Wrapper an. Das Eingabeformular leitet die Eingaben nicht direkt an das externe Programm weiter, sondern an den Wrapper. Dieser wertet die Eingaben aus und übersetzt sie in gültige Eingaben für das externe Programm, ohne dass es verändert werden muss.

Wrapper beim Zugriff auf Datenbanken

Datenbanken unterschiedlicher Hersteller lassen sich normalerweise kaum zusammen nutzen, da Datentabellen, Abfragen oder Abfragesprachen nicht kompatibel zueinander sind. Auch hier kann ein Wrapper die Lösung sein. Wie bei jeder Art von Wrappern geht es darum, Inkonsistenzen zwischen verschiedenen Software-Schnittstellen zu erkennen und mit dem Wrapper zu überbrücken.

Die Java Database Connectivity (JDBC), eine Datenbank-Schnittstelle aus der Oracle-Java-Plattform, ist ein typisches Beispiel für einen Wrapper. Die JDBC ermöglicht in ihrer Funktion als Wrapper den Zugriff auf relationale Datenbanken unterschiedlicher Software-Anbieter. JDBC baut die Verbindung zu den einzelnen Datenbanken über spezielle Treiber auf. SQL-Anfragen von Programmen richten sich ausschließlich an JDBC und nicht an die Datenbanken selbst. JDBC setzt die Anfragen in die von der jeweiligen Datenbank verwendete Abfragesprache um und liefert das Ergebnis in einer Java-kompatiblen Form zurück. So erhält das abfragende Programm die Daten immer in einem einheitlichen Format, unabhängig von der verwendeten Datenbank.

Wrapper in der objektorientierten Programmierung

In der objektorientierten Programmierung nutzt man verschiedene Strukturmuster, die unabhängig von der tatsächlich verwendeten Programmiersprache prinzipiell immer gleich funktionieren. Die Entwurfsmuster (Design Patterns) Adapter und Dekorator gehören zur Kategorie der Strukturmuster und werden als Wrapper bezeichnet.

Ein Adapter verhüllt zueinander inkompatible Schnittstellen zwischen einzelnen Klassen. Durch die Übersetzung einer Schnittstelle in eine andere können die Klassen wieder miteinander kommunizieren. Das ist besonders wichtig, wenn Klassen oder ganze Klassenbibliotheken in neuen Projekten weiterverwendet werden sollen. Diese Bibliotheken nutzen eindeutige, standardisierte Schnittstellen, die nicht verändert werden dürfen, da sie für eine Vielzahl an Programmen gültig sein sollen. Der Wrapper – hier der Adapter – stellt bei der Kommunikation das entscheidende Zwischenglied dar.

Ein Dekorator ermöglicht es, eine Klasse um zusätzliche Funktionen zu erweitern, ohne die Klasse selbst zu verändern. Der Dekorator hat gegenüber dem aufrufenden Programmobjekt dieselbe Schnittstelle wie die Originalklasse. Auf diese Weise muss im aufrufenden Objekt nichts verändert werden. Der Dekorator gibt als Wrapper die Aufrufe an die Klasse weiter. Neue Funktionen, die in der Klasse nicht enthalten sind, arbeitet der Dekorator direkt ab. Die Ergebnisse gibt er auf eine solche Weise zurück, dass sie dem aufrufenden Objekt wie Ergebnisse der dekorierten Klasse angezeigt werden.

Wrapper zur Gestaltung von HTML-Dokumenten

Bei der (Um-)Gestaltung von Websites mit HTML und CSS kommen häufig Wrapper zum Einsatz. Sonst müsste man auch bei einzelnen Anpassungen, z. B. beim Ändern der Abstände am Rand des Browserfensters, mehrere Stylesheets ändern und darauf achten, dass diese anschließend wieder zusammenpassen.

Einfacher ist es, einen Wrapper in Form eines DIV-Containers um den gesamten Inhalt der Seite zu legen wie im folgenden Beispiel:

<html>
  <head>
  ...
  </head>
  <body>
    <div class="wrapper">
    …
    </div>
    </body>
</html>

Innerhalb dieses Wrapper-Containers steht dann der eigentliche Inhalt der Seite.

In der zugehörigen CSS-Datei wird der Wrapper als Stylesheet definiert:

body {
  margin: 0;
  padding: 0
}
.wrapper {
  width: 500px;
  margin: 25px auto;
}

In diesem Beispiel wird dem Container über den Parameter width: eine Breite von 500 Pixel zugeordnet. Die Ränder oben und unten werden über den Parameter margin: auf 25 Pixel festgelegt. Die Ränder links und rechts ergeben sich automatisch aus der Breite des Browserfensters und der Breite des Containers.

Durch einfache Veränderung des Wrappers lassen sich die Seitenränder leicht anpassen, ohne weiter in den HTML- oder CSS-Code einzugreifen.

TCP-Wrapper in Linux-Systemen

Der Hintergrunddienst inetd in Linux und anderen auf UNIX basierten Betriebssystemen läuft als TCP-Wrapper. inetd hört Netzwerk-Sockets ab und nimmt Verbindungsanfragen an. Eine Konfigurationsdatei legt fest, welche Ports berücksichtigt werden sollen. Die Anfragen werden ausgewertet, und der jeweils in der Konfigurationsdatei angegebene inetd-Dienst wird für diesen Port gestartet. In den meisten Fällen handelt es sich bei diesen Programmen um Daemons, die im Hintergrund laufen.

Wird die Verbindung beendet, stoppt inetd den gestarteten Dienst automatisch wieder. Durch das Starten bei Bedarf kann man die Systemressourcen deutlich einsparen gegenüber dem automatischen Starten von eventuell gar nicht benötigten Netzwerkdiensten. inetd arbeitet als Wrapper, an den alle Programme ihre Netzwerkanfragen stellen, ohne mit den einzelnen Diensten direkt zu kommunizieren.

TCP-Wrapper können auch dafür eingesetzt werden, unerwünschte Zugriffe aus einem Netzwerk zu unterbinden. Der TCP-Wrapper wird dabei von inetd oder spezieller Server-Software abgefragt. Die zulässigen oder abzulehnenden Hosts und Computer werden in den beiden Dateien /etc/hosts.allow und /etc/hosts.deny eingetragen.