Donnerstag, 24. April 2014

Abstraktheit - was bleibt übrig von den Abstraktionen?

Im vorhergehenden Blogartikel über abstrakte Klassen und Interfaces haben wir den Nutzen von Abstraktionen beim Entwurf von Typen im Detail betrachtet. Wir haben festgestellt, dass dieser Nutzen im Wesentlichen aus
  • der Möglichkeit zu unvollständiger und verzögerter Implementierung
  • dem Zwang zur Implementierung konkreter Klassen und Methoden
  • der Verhinderung der Instanzerzeugung und
  • der Entkopplung der Klienten von konkreten Klassen
besteht. Im vorliegenden Artikel soll nun überlegt werden, ob sich diese nützlichen Eigenschaften auf Mengen von Typen, von denen einzelne abstrakt sind, übertragen lassen. Der Einfachheit halber soll im weiteren Artikel immer von "Komponenten" gesprochen werden, wenn solche Mengen von Typen gemeint sind. In der Realität kann es sich um verschiedene Konzepte zur Zusammenfassung von Typen handeln, wie Packages, Bundles, deploymentfähige Einheiten usw.

Abstraktheit und unvollständige Implementierung

Wenn einzelne Klassen einer Komponente unvollständig implementiert sind, so ist offensichtlich auch die gesamte Komponente unvollständig implementiert. Abstraktheit sagt in dieser Hinsicht etwas über das Ausmaß der Unvollständigkeit aus. Wenn allerdings dieselbe Komponente auch konkrete Subklassen der Abstraktion bereitstellt und damit also die Implementierung vervollständigt, so wird dies durch die Abstraktheit nicht erfasst. Als Maß der Unvollständigkeit ist Abstraktheit daher allenfalls schwach geeignet.

Abstraktheit und erzwungene Implementierung

Möchte man innerhalb einer Komponente erzwingen, dass zur Nutzung einer bestimmten Funktionalität zunächst bestimmte Methoden oder Klassen implementiert werden müssen, so kann man dies durch die Abstraktion dieser Methoden oder Klassen erreichen. Die Aussage, dass es möglich ist, bestimmte Implementierungen für eine Komponente zu erzwingen, ist also korrekt. Durch bloße Ansicht der Abstraktheit kann allerdings nicht entschieden werden, ob dies tatsächlich auch erforderlich ist, denn die Komponente könnte zusätzlich zur Abstraktion auch eine oder mehrere konkrete Implementierungen zur Verfügung stellen. In diesem Fall wäre eine Implementierung nicht mehr erzwungen, sondern es muss lediglich noch die gewünschte Instanzerzeugung herbeigeführt werden. Das Abstraktheitsmaß macht also keine sinnvolle Aussage über die Erfordernis konkreter Implementierungen.

Abstraktheit und verhinderte Instanzerzeugung

Wir haben besprochen, dass die Verhinderung der Instanzerzeugung von Abstraktionen mit  folgenden zwei Vorteilen einhergeht:
  • Der Klient darf sich nur auf die öffentliche Schnittstelle der Abstraktion verlassen.
  • Die Verantwortlichkeit für die Erzeugung der gewünschten Instanz geht vom Klienten auf eine passendere Einheit über.
Ob diese Vorteile auch für die Gesamtkomponente gelten, die Abstraktionen enthält, hängt allerdings davon ab, ob die konkreten Implementierungen innerhalb der Komponente tatsächlich auch Subtypen der Abstraktionen sind - oder alternativ, ob sie ausschließlich von den Abstraktionen verwendet werden. Ist dies nicht der Fall, so existiert für diese Implementierungen also weder eine abstrakte öffentliche Schnittstelle, noch liegt ihre Instantiierung außerhalb der eigentlichen Klienten nahe.

Die Abstrakheit erlaubt demnach ohne Zusatzinformationen zur Vererbungshierarchie sowie zur Sichtbarkeit der konkreten Klassen in der Komponente keine sinnvolle Aussage darüber, ob die Vorteile der verhinderten Instanzerzeugung tatsächlich auch genutzt werden können.

Abstraktheit und Entkopplung von konkreten Klassen

Das Argument des vorhergehenden Abschnitts trifft auch auf die gewünschte Entkopplung von konkreten Klassen zu. Betrachten wir die folgenden beiden Konstellationen und ermitteln die Abstraktheit wie von Martin vorgeschlagen über die Anzahl der abstrakten Klassen im Verhältnis zur Gesamtzahl der Klassen. Die weitere Argumentation ist davon unabhängig, ob dieses Maß noch durch Gewichte verfeinert wird oder man es z. B. nicht von der Anzahl der abstrakten Klassen, sondern von der Anzahl der abstrakten Methoden abhängig macht.
Während die konkreten Klassen von Komponente1 vom Klienten entkoppelt sind, so gilt dies nicht für die konkreten Klassen von Komponente2

Man kann nun argumentieren, dass auch in Komponente2 die beiden abstakten Klassen für eine Entkopplung stehen, da die konkreten Implementierungen zu diesen Abstraktionen offensichtlich an einem anderen Ort bereitgestellt werden müssen. Nichtsdestotrotz besteht eine enge Kopplung von Klient2 zu den konkreten Klassen von Komponente2, und diese Kopplung wird durch das bloße Vorhandensein der beiden abstrakten Klassen im Abstraktheitsmaß abgemildert, obwohl diese Abstraktionen gar nichts mit den betroffenen konkreten Klassen zu tun haben. Das Abstraktheitsmaß betrachtet nicht, welche konkreten Abhängigkeiten eigentlich bestehen, und kann daher auch nicht zu sinnvollen Kopplungsaussagen herangezogen werden. Um dies tun zu können, müsste eher eine Art "Ausmaß der Verwendung von Abstraktionen" definiert werden.

Das Beispiel zeigt, dass Abstraktheit keine Aussage darüber erlaubt, wie gut die Interna einer Komponente von externen Klienten entkoppelt sind.

Zusammenfassung

Die vorhergehenden Abschnitte haben folgende Ergebnisse bzgl. der Aussagekraft der Abstraktheit hinsichtlich der vier Haupt-Nutzenbereiche von Abstraktionen erbracht:
  • Abstraktheit erlaubt nur eine schwache Aussage über das Ausmaß der unvollständigen Implementierung einer Komponente.
  • Abstraktheit macht keine sinnvolle Aussage über die Erfordernis konkreter Implementierungen.
  • Ohne Zusatzinformationen zur Vererbungshierarchie sowie zur Sichtbarkeit der konkreten Klassen in der Komponente ermöglicht Abstraktheit keine sinnvolle Aussage darüber, ob die Vorteile der verhinderten Instanzerzeugung tatsächlich auch genutzt werden können.
  • Abstraktheit ermöglicht keine zuverlässige Aussage darüber, wie gut die Interna einer Komponente von externen Klienten entkoppelt sind.
Insgesamt ist der Bedeutungsgehalt des Konzepts der Abstraktheit von Komponenten gegenüber demjenigen der Abstraktion einzelner Typen so stark vermindert, dass er kaum mehr als relevant einzustufen ist. Das Konzept der Abstraktheit taugt daher kaum für mehr als eine grobe Beurteilung, ob und in welchem Ausmaß Abstraktionen in einer Menge von Klassen überhaupt vorkommen.