Artikelformat

Das Vertragsmodell

Heute gab es wieder ein interessantes Gespräch und dies drehte sich um das Vertragsmodell in der Softwareentwicklung. Dies war dann für mich Anlass das Thema etwas zu recherchieren und hier vorzustellen.

Das Vertragsmodell (oder auch Design by Contract oder Programming by Contract) wurde von Bertrand Meyer zusammen mit der Programmiersprache Eiffel entworfen. Es dient dazu einzelne Module und Klassen miteinander interagieren zu lassen und eine gewisse Robustheit und Korrektheit der Software zu gewährleisten.

Wenn man nun 2 Klassen betrachtet, wobei eine Klasse A die Funktionalität einer Klasse B nutzt so ist Klasse B Dienstleister für die Klasse A. Und andersherum ist Klasse A Kunde oder Klient von Klasse B.

Jetzt gibt es 3 Arten von Bedingungen, die man betrachtet: Vorbedingung, Nachbedingung und Invarianten.

Vorbedigungen:
Vorbedingungen sind Zusicherungen, die Klasse A (der Aufrufer) einzuhalten hat. D.h. Parameter müssen in einem definierten Wertebereich liegen und vom richtigen Typ sein. PHP hat hier einen kleinen Nachteil, da die Typkorrektheit gesondert geprüft werden muss. TypeHinting hilft hier aber sehr.

Nachbedingungen:
Der Dienstleister macht eine Zusicherung über die Leistung und dass diese auch in einem festen Wertebereich und von korrektem Typ ist. Hier ist PHP noch ein Tick komplizierter, da TypeHinting bei return-Werten nicht vorhanden ist. Aber da man den Wertebereich eh zusichern muss, ist der Typ dann nur eine weiter Überprüfung.

Invarianten:
Hierbei handelt es sich um Zusicherungen zum Zustand einer Klasse. Gewisse Korrelationen zwischen Klassenattributen werden hier abgebildet und geprüft, sodass die Klasse keinen inkonsistenten Zustand einnehmen kann.

Die Gesamtaussage ist nun: Wenn ich als Klasse A eine Klasse B aufrufe und dabei alle Vorbedingungen einhalte, so wird diese auch Ergebnisse liefern, die den Nachbedingungen genügen. Während des Lebenszyklus von B ist die Klasse in sich selbst auch konsistent.

Überprüfung
Wie kann man nun diese Bedingungen überprüfen. Einerseits kann man hier TypeHinting nutzen, was eine sehr rudimentäre Form ist. Weiter sind assert-Statements sehr nützlich. In der Java-Welt kann man das JWAM-Framework nutzen, dass eine Contract-Klasse mit entsprechenden statischen Methoden zur Verfügung stellt. An dieser Stelle der Aufruf an die PHP-Spezialisten, die dieses Verfahren nutzen: Gibt es so etwas für PHP? Ich habe hier leider nichts gefunden.

Das Java Framework arbeitet mit den Methoden require, ensure und check. Wobei Vor-, Nachbedingung und Invariante geprüft werden.

abgeleitete Klassen:
Wenn man nun eine Klasse von B ableitet, muss man gewisse Dinge beachten. Die Vorbedingungen werden aufgeweicht, da man nun weiter Vorbedingungen mit oder anfügen muss. Die Nachbedingungen hingegen werden eingeschränkt, da diese mit und mit neuen Bedingungen verknüpft sein müssen. Dies gilt ebenfalls für die Invarianten.

Warum dies so ist, kann man sich ganz leicht überlegen. Die Invariante der Elternklasse muss gelten und es kommen neue Attribute hinzu die ebenfalls in die Korrelation der Attribute mit aufgenommen werden müssen, also gilt die Invariante der Elternklasse und zusätzlich die der Kindklasse. Dies gilt ebenfalls für die Nachbedingung. Vorbedingungen werden deswegen verodert, weil sich die Bedingungen bei abgeleiteten Klassen unterscheiden können.

Exceptions:
Eine Frage die man sich nun stellt wird wohl sein, was denn mit Exceptions ist und wie diese Ausnahmen zu behandeln sind, wenn man den Kontext des Vertragsmodells betrachtet. Exceptions dürfen aus einem Submodul „ausbrechen“, aber sie dürfen die Invarianten nicht verletzen. Verbietet man dies und erlaubt nur lokale Exceptions, so muss man darauf achten, dass Invarianten und Nachbedingungen eines Methodenaufrufs erfüllt sind.

Fazit:
Das Vertragsmodell ist eine interessante Art, um Robustheit und Korrektheit einer Software sicher zustellen. Durch feste Ausdrücke wie assert oder eine Contract-Klasse wird die Lesbarkeit gegenüber if-then-else und try-catch-finally erhöht. Und gegenüber dem if-then-else-Konstrukt hat man keinen Code, den man dann wieder extra testen muss.

3 Kommentare

    • Na klar doch. PHP bietet einiges … man muss es nur suchen UND finden 🙂

      Danke für den Link, hatte den vergessen einzufügen 😛

  1. Insgesamt scheint es mir, dass PHP in der kommenden Generation einiges der Java-Welt entnehmen kann und muss (und ja auch bereits hat; PHPUnit, Frameworks, Enterprise Patterns, …).

    Abgesehen davon ist es schön mal diese Sichtweise zusammengestellt zu lesen. Gerade bei PHP ist es üblich den gegenteiligen Weg zu gehen und bspw. flexibel übergebene Argumente zu casten und zu transformieren um Anwendungsfehler zu korrigieren. Nicht Schnittstellen-konforme Anwendungen gehören strikt abgeschmettert. Damit es dazu nicht kommt ist eine saubere Doku von Nöten – PHPDoc und Doxygen sind ja auch durch die Java-typische Dokumentationsweise geprägt.

    Antworten

Schreibe einen Kommentar

Pflichtfelder sind mit * markiert.