Clean Code
Kommentare

Grundprinzip: Separation of Concerns
Ein weiteres Prinzip, das uns dem architektonischen Ziel, lose gekoppelte Systeme zu haben, näher bringt, ist es, die „Angelegenheiten“ oder „Belange“ von Objekten

Grundprinzip: Separation of Concerns

Ein weiteres Prinzip, das uns dem architektonischen Ziel, lose gekoppelte Systeme zu haben, näher bringt, ist es, die „Angelegenheiten“ oder „Belange“ von Objekten bzw. Klassen zu trennen. Solche „Concerns“ sind Absichten oder Zwecke, die oft orthogonal zueinander oder zum Hauptzweck, der Geschäftslogik eines Objekts stehen.

Belange, die oft mit der Hauptfunktion einer Einheit vermischt werden, sind Logging, Tracing, Persistenz, Caching, Transaktionsbehandlung etc. In der aspektorientierten Programmierung kennt man sie auch als „Aspekte“. Klassen, die nur einen Belang verfolgen, weisen eine deutlich höhere Kohäsion auf, sind also deutlich fokussierter und wirken „zusammengehöriger“. Sie sind dadurch wartbarer. Zum anderen weisen solche Klassen auch niedrigere Kopplung auf. Kohäsion und Kopplung sind in der Regel gegenläufig.

SOLID-Prinzip: Single responsibility Principle (SRP)

Robert Martin hat in seinem Buch „Agile Software Development: Principles, Patterns and Practices“ [8] fünf Prinzipien beschrieben, deren Einhaltung für deutlich besseren Code sorgt. Sie sind für Clean Code zu einem wichtigen Wissensbestandteil von agilen Entwicklern geworden.

Die Grundidee des Single-Responsibility-Prinzips ist sehr einfach. Es besagt, dass eine Klasse nur eine Verantwortung haben soll, sich also nur um eine Sache „kümmern“ soll. Tut sie das nicht und trägt sie mehrere Verantwortungen, entsteht zwischen den einzelnen Verantwortungen, oder besser gesagt, den zugehörigen Codeteilen, eine hohe Kopplung. Wenn der Code der einen Verantwortung geändert wird, betrifft das auch den Code der anderen Verantwortungen, sodass hier auch Änderungen notwendig werden, oder es verletzt darin sogar Funktionalitäten.

Handelt es sich bei einer Verantwortung um eine allgemeinere, häufig verwendete, so würde es helfen, eine Verantwortung in eine Basisklasse zu verlegen und für die zweite Verantwortung eine davon abgeleitete Klasse zu nehmen. Ein Beispiel hierfür ist eine Klasse, die geometrische Figuren, wie Rechteck, Dreieck etc. zeichnen (erste Verantwortung) und für sie auch mathematische Berechnungen, wie Fläche oder Umfang, anstellen kann (zweite Verantwortung). Durch diese hohe Kopplung entsteht ein zerbrechliches Design, das auf unterschiedlichste und unerwartete Weise „zerfällt“, wenn Änderungen an der einen Verantwortung notwendig werden. Man erkennt diese hohe Kopplung auch daran, dass es in der Regel mehrere Gründe gibt, an solch einer Klasse Änderungen vorzunehmen.

Das Single-Responsibility-Prinzip hilft uns, hohe Kopplung zu entdecken und diesen Code Smell zu beheben, indem wir die Verantwortungen einer Klasse (oder auch einer Funktion) in mehrere aufteilen. Der erste Weg führt uns zu „Extract Class“. Eine weitere Möglichkeit, diesen Code Smell los zu werden, wäre es, eine Schnittstelle für jede Verantwortung einzuführen („Extract Interface“), wenn es aus bestimmten Gründen nicht gelingt, die Implementierung aufzutrennen. In diesem Fall ist die Kopplung in der Implementierung zwar noch vorhanden, es hängen jedoch keine anderen Klassen von dieser Implementierung ab (bzw. sie ist nicht mehr sichtbar).

SOLID-Prinzip: Open Closed Principle (OCP)

Das zweite Prinzip besagt, dass Softwaremodule (Klassen, Funktionen etc.) offen für Erweiterung, jedoch geschlossen für Modifikation sein sollen. Offenheit bedeutet dabei, dass das Verhalten eines Softwaremoduls erweitert werden kann. Der zweite Teil, die Geschlossenheit, bedeutet, dass das Verhalten in abgeleiteten Klassen nicht mit einer anderen Semantik belegt werden darf. Solche Abstraktionen sind normalerweise Schnittstellen oder Vererbung. Java-EE-Programmierer kennen das Problem – wenn ein Client eine bestimmte Funktionalität eines Servers benutzt, muss er die Schnittstelle des Servers kennen. Es reicht aus, sie zu kennen, eine Benutzungsrelation zwischen den beiden wäre zu viel „Intimität“ und eine Verletzung des OCP bei der Serverklasse (der Implementierung der Schnittstelle). Durch die Schnittstelle wird es möglich, die Serverklasse auszutauschen, ohne die Clients zu beeinträchtigen.

Ein anderes, deutlich gebräuchlicheres Beispiel für das Open-Closed-Prinzip ist eine Schnittstelle, die die Java-Klassenbibliothek für Listen sortierter Objekte verwendet. Eine sortierte Liste benötigt Vergleichsoperatoren, um für das Sortieren festzustellen, ob ein Objekt kleiner, gleich oder größer zu einem anderen ist. Die Art und Weise, wie dies von der Java-Bibliothek gelöst wird, ist es, eine Schnittstelle „Comparable“ einzuführen, die genau diesen Vergleichsoperator definiert. Die Elemente, die in so einer Liste sortiert werden sollen, müssen sie implementieren. Somit müssen in der Liste die Elemente, die darin sortiert werden sollen, bzw. deren Typ nicht bekannt sein. Dadurch ist die Kopplung zwischen diesen Objekten bzw. Klassen deutlich geringer als würde die Liste alle Typen „kennen“ müssen.

Auch wenn diese Beispiele offensichtlich klingen, die allgemeine Anwendung dieses Prinzips auf alle Klassen einer Anwendung ist schwer. Nur wenn man sich die Zeit nimmt und das Design zum Beispiel im Code-Review im Hinblick auf diese Prinzipien untersucht, eröffnen sich viele Möglichkeiten, den Code zu refaktorisieren. Oft fällt eine Verletzung des OCP selbst während einer TDD-Sitzung nicht unmittelbar auf. Es wird offensichtlich, dass es sinnvoll ist, den Code laufend explizit hinsichtlich der Einhaltung der SOLID-Prinzipien zu untersuchen.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -