 |
(14.05.04 07:47)
Das Geheimnisprinzip in der Objektorientierung ist etwas sehr schönes. Es gibt uns die Möglichkeit, all die kleinen Details, die für die Lösung eines Problems von Bedeutung sind, hinter einer Schnittstelle zu verbergen. So entstehen Abstraktionen, die ein Verständnis auf höherer Ebene ermöglichen. Aber wenn die Schnittstelle eines Objektes uns nicht sagt, was wir wissen müssen, um das Objekt effektiv zu verwenden, dann verkehrt sich der Nutzen zum Nachteil: Wir sind gezwungen, den objektorientierten Bohrer anzusetzen und ein Loch in die öffentliche Schnittstelle zu treiben, um uns die internen Implementierungsdetails anzusehen; der meiste Nutzen der Kapselung geht dadurch verloren. Als Gedankenarbeiter kämpfen wir ständig mit kognitiver Überlastung: Wird die Zahl der zu berücksichtigenden Fakten zu gross, dann fällt es uns schwer, uns auf das Wesentliche zu konzentrieren. Je mehr Implementierungsdetails einer Komponente wir bei ihrer Verwendung berücksichtigen müssen, desto mehr werden wir von der eigentlichen Arbeit abgelenkt, uns über die Verwendung Gedanken zu machen. Unser Verstand ist gezwungen, ständig zwischen zwei Orten der Aufmerksamkeit hin und her zu schalten: Komponenten-Implementierung und Verwendung.
Wenn wir die Implementierung einer Komponente bei ihrer Verwendung berücksichtigen müssen, dann geht der Nutzen der Kapselung verloren. Wenn wir gezwungen sind, den Zweck einer Klasse oder einer Methode aus der Implementierung abzuleiten, dann riskieren wir, dass dieser Zweck von der Klasse lediglich zufällig erfüllt wird. Entspricht dieser Zweck nicht dem vom Implementierer tatsächlich beabsichtigten, dann besteht die Gefahr, dass unsere Verwendung nur momentan korrekt ist; Verwender und Entwickler – selbst wenn es sich um die gleiche Person handelt – arbeiten in entgegen gesetzte Richtung.
Gute Schnittstellen, die ihre Verwendung offensichtlich machen – Eric Evans (Domain-Driven Design) nennt sie Intention Revealing Interfaces, zu Deutsch etwa aufschlussreiche Schnittstellen – beschreiben einen wohl definierten Zweck. Sie sind schmal und robust und machen ihre korrekte Verwendung offensichtlich. Gute Namen – sowohl für die Schnittstelle selbst als auch für ihre Methoden – sind ein wichtiges Hilfsmittel, um die Mitteilungskraft und Ausdrucksstärke eines Entwurfes zu verbessern. Die Namen von Typen, Methoden und Argumenten sollte so gewählt werden, dass sie Zweck und Effekt klar und unmissverständlich zum Ausdruck bringen. In diesem Zusammenhang ist übrigens eine einheitliche – systemweit allgegenwärtige - Sprache unabdingbar; so sollte die z.B. Operation für das Löschen eines Elementes in einer Elementsammlung immer delete oder remove heissen und nicht einmal remove und an einer anderen Stelle delete.
Gute Namen sind aber nicht genug. Wir müssen auch sorgfältig darauf achten, dass unsere Schnittstellen nicht zur missbräuchlichen Verwendung einladen oder gar dazu zwingen. Gift sind zum Beispiel Methoden, die den Zugriff auf intern verwendete Objekte erlauben. Sie legen den Samen für eine gefährliche Frucht: Methodenketten. Das Gesetz von Demeter hilft uns, diesen Fehler zu verhindern und sorgt dafür, dass unsere Schnittstellen sauber bleiben. Zudem sollten unsere Schnittstellen nach dem Prinzip Tell, don't ask entworfen sein, um zu verhindern, dass die Verwender der Schnittstelle gezwungen sind, sich Status und damit letztlich Implementierungsdetails des verwendeten Objektes zu merken.
Eine gute Möglichkeit, um aufschlussreiche Schnittstellen zu entwerfen, ist für mich die tetsgetriebene Entwicklung: Indem der Test-Code geschrieben wird, bevor wir uns um die Implementierung kümmern, nehmen wir gedanklich die Rolle des Verwenders ein, da wir uns ständig fragen, was ein Objekt für uns tun soll, und wir uns erst in zweiter Linie darum kümmern, wie das Objekt dies tut. Das erhöht die Chancen, aufschlussreiche Schnittstellen zu erhalten. Und die sind die Voraussetzung für den Erhalt der intellektuellen Beherrschabrkeit einer Software.
-nemo :-)
Über diesen Artikel diskutieren.
|
 |