Montag, 26. Mai 2014

Program to an Interface - notwendig partielle Interfaces

"Program to an interface, not an implementation." Erstes Prinzip des objektorientierten Entwurfs, [GOF1995].
In einem einleitenden Artikel hatten wir Interfaces in vier Kategorien unterteilt. Für drei dieser Kategorien haben wir inzwischen besprochen, worin die Motivation für deren Einsatz besteht, welche Alternativen es gibt und wann ggf. von einem Einsatz abzusehen ist:
Im vorliegenden Artikel möchte ich mich nun der verbleibenden Kategorie der notwendig partiellen Interfaces widmen. 

Notwendig partielle Interfaces als Platzhalter

Das Wesentliche notwendig partieller Interfaces besteht darin, dass die Aufgerufenen zur Implementierungszeit des Aufrufers noch nicht (vollständig) bekannt sind. Im Kontext des Aufrufers existiert jedoch offensichtlich bereits Kenntnis über ein bestimmtes Verhalten, das in die eigene Ablauflogik eingebettet werden soll. Die Verwendung des Interfaces wirkt in dieser Situation wie ein Platzhalter
  • Das Interface ermöglicht die Umsetzung des Aufrufers ohne Kenntnis irgendeiner konkreten Implementierung.
  • Selbst wenn einzelne Implementierungen bereits bekannt sein sollten, so können später beliebig viele hinzugefügt werden.
Für diese Betrachtungsweise ist es irrelevant, ob das Interface im Sinne von [Steimann2005] eher anbietender Natur ist oder eher ermöglichender Natur. Ebenfalls spielt es keine Rolle, ob es später lediglich eine Implementierung geben wird oder mehrere. Aus der Sicht des Aufrufers ist das zentrale Argument für den Einsatz eines notwendig partiellen Interfaces die Tatsache, dass er zwar die Eigenschaften des oder der Aufgerufenen vollständig kennt, die zur Erfüllung seiner eigenen Funktion erforderlich sind, nicht aber den oder die Aufgerufenen selbst.

Zusatznutzen

Neben der Platzhalter-Funktion notwendig partieller Interfaces kann je nach konkreter Ausprägung zusätzlicher Nutzen entstehen, der mit dem Nutzen der anderen Interface-Kategorien vergleichbar ist:
  • Wenn nur eine einzige Implementierung erfolgen soll (notwendig partielles 1:1-Interface), so tritt ein ähnlicher Zusatznutzen ein wie für totale 1:1-Interfaces: Ein arbeitsteiliger Entwicklungsprozess wird ermöglicht, modellgetriebene Entwicklungstechnologien können eingesetzt werden, das Deployment wird potentiell entkoppelt.
  • Sind mehrere Implementierungen geplant oder ist die Zahl der künftigen Implementierungen gar potentiell unbeschränkt (notwendig partielles 1:n-Interface), so tritt der Zusatznutzen totaler 1:n-Interfaces ein: redundanzfreie Fallunterscheidungen (Single Choice Prinzip) und Offenheit für Erweiterungen (Open-Closed Prinzip)
  • Und schließlich teilen sich notwendig partielle Interfaces mit freiwillig partiellen Interfaces die positiven Eigenschaften, die sich aus der Zugriffsbeschränkung auf die Aufgerufenen ergeben, d. h. insbesondere Schutz vor Fehlnutzung, bessere Verständlichkeit sowie Einhaltung des Interface Segregation Prinzips.

Alternativen

Welche Alternativen in Betracht kommen, hängt vom speziellen Charakter des Interfaces ab. Ich komme hier auf die Steimann'sche Unterscheidung zwischen anbietenden und ermöglichenden Interfaces zurück [Steimann2005]:
  • Ein anbietendes Interface stellt dem Aufrufer eine Dienstleistung zur Verfügung. Als Platzhalter für eine solche Dienstleistung kommen auch andere Mechanismen in Betracht wie beispielsweise ein Funktions-Repository, die dynamische Konstruktion und Evaluierung von Ausdrücken in Interpreter-basierten Sprachen oder Ähnliches. Bei der Abwägung dieser Alternativen ist zu fragen, ob der Auswahlmechanismus für die Dienstleistung, die zur Implementierungszeit des Aufrufers noch nicht bekannt war, aus konkreten Gründen einem Interface vorzuziehen ist.
  • Ein ermöglichendes Interface geht insofern über ein anbietendes Interface hinaus als es nicht einfach um den Aufruf einer Dienstleistung im Sinne einer Funktion geht, sondern um eine komplexere Behandlung, die dem Aufrerufenen zu Teil wird. Betrachten wir beispielsweise das Java-Inteface Comparable, so wäre es vergleichsweise sinnlos, irgendeine compareTo(...)- und eine equals(...)-Methode über ein Funktions-Repository zur Verfügung zu stellen, die in der Lage ist, zwei Datenstrukturen miteinander zu vergleichen. Vielmehr ist mit dieser Vergleichsmöglichkeit ein umfangreiches Dienstleistungspaket verbunden, das es u. a. ermöglicht, Listen der aufgerufenen Objekte zu sortieren usw. Um den Aufgerufenen derart umfangreiche Dienste zur Verfügung ohne Nutzung von Interfaces zur Verfügung stellen zu können, bedarf es sehr konkreter Lösungen, die im Einzelfall freilich eine gute Begründung haben können. 
In Programmiersprachen, die nicht statisch typisiert sind oder die Formen von Duck-Typing anbieten, muss freilich auch kein Platzhalter-Problem gelöst werden. Der Aufruf der jeweiligen Methode kann in diesen Sprachen auch ohne Interface erfolgen. Freilich wird diese Möglichkeit mit einem generellen Verzicht auf die Leistungen eines entsprechenden Typsystems erkauft. Auf diese oftmals ideologisch geprägte Diskussion kann hier aber nicht näher eingegangen werden.

Zusammenfassung

Zusammenfassend kann gesagt werden, dass die Nutzung notwendig partieller Interfaces als Platzhalter eine natürliche Möglichkeit objektorienterter Programmiersprachen ist, den Aufrufer ohne Kenntnis des oder der künftigen Aufgerufenen vollständig zu implementieren. Der Rückgriff auf alternative Möglichkeiten in Sprachen, die Interfaces anbieten, sollte sehr konkrete Gründe haben. Bei diesen Möglichkeiten wird ggf. auch auf den Zusatznutzen verzichtet, der je nach der konkreten Ausprägung des Interfaces neben der Platzhalter-Funktion durch den Einsatz eines Interfaces entstehen kann.

Siehe auch

Alle Artikel der Serie "Program to an Interface ...":

Einführung
Kategorisierung von Interfaces
Totale 1:n-Interfaces
Totale 1:1-Interfaces
Freiwillig partielle Interfaces
Notwendig partielle Interfaces
Fazit und Gegenbeispiele
Interface oder abstrakte Klasse?
Werkzeugunterstützung
Das Prinzip

Quellen

[GOF1995] - Design Patterns - Elements of Reusable Software, E. Gamma, R. Helm, R. Johnson, J. Vlissides, (Addison‐Wesley, 1995)
[Steimann2005] - Patterns of interface‐based programming, F. Steimann, P. Mayer, Journal of Object Technology 4:5, 75–94 (2005), http://www.jot.fm/issues/issue_2005_07/article1.pdf