Interface Segregation Principle (ISP) – Wissenshäppchen #6
Das sechste Wissenshäppchen hat das Interface Segregation Principle
als Thema. Inhalt Das ISP ist das vierte SOLID-Prinzip. The
dependency of one class to another one should depend on the
smallest possible interface.
16 Minuten
Podcast
Podcaster
Beschreibung
vor 6 Jahren
Das sechste Wissenshäppchen hat das Interface Segregation
Principle als Thema.
Inhalt
Das ISP ist das vierte SOLID-Prinzip.
The dependency of one class to another one should depend on the
smallest possible interface.
Im Prinzip kann man das ISP so zusammenfassen: Verwende immer nur
die kleinstmögliche Schnittstelle zu deinen Abhängigkeiten. Je
mehr Funktionen eine Komponente an ihren Abhängigkeiten aufrufen
kann, desto abhängiger wird sie von ihr. Wenn sich diese
Funktionen nämlich ändern (z.B. die Signatur einer Methode), muss
die nutzende Komponente neu kompiliert werden. Außerdem können
Funktionen aufgerufen werden, die die nutzende Komponente weder
benötigt, noch anwenden soll, z.B. die clear()-Methode einer
Liste, die sie eigentlich nur durchlaufen soll. Zuletzt müssen
auch implementierende Klassen von zu großen Interfaces für sie
unnötige Methoden implementieren, nur um der Schnittstelle zu
entsprechen.
Erklärung
Zu große Interfaces oder Basisklassen bieten evtl. Zugriff
auf verschiedene Funktionalitäten, die nicht zusammengehören
(z.B. Repository.getUser() und Repository.getArticle()), oder
über das benötigte/erlaubte Verhalten hinausgehen (z.B.
Repository.deleteUser()).
Komponenten, die von diesen Schnittstellen abhängen, können
mit ihnen „zu viel“ machen und müssen angepasst (mind.
rekompiliert) werden, wenn sich diese ändern, auch wenn sie die
geänderte Funktionalität gar nicht nutzen.
Komponenten, die die vorgegebenen Schnittstellen anbieten
möchten, müssen mehr implementieren, als sie eigentlich wollen
(oder dies nicht tun und das LSP mit einer
NotImplementedException verletzen).
Tests von Komponenten, die Abhängigkeiten auf große
Schnittstellen haben, werden schwieriger, da viele eigentlich
unnötige Funktionen gestubbt oder gemockt werden müssen.
Auch eine „große“ Klasse kann mehrere „kleine“ Interfaces
anbieten und damit wohldefinierte „Fenster“ auf ihre
Funktionalität anbieten.
Beispiel
Die Methode printEmployees() im folgenden Beispiel erwartet eine
List, obwohl sie diese lediglich durchlaufen
können muss. Durch das „zu große“ Interface kann sie darüber
hinaus jetzt auch die Liste leeren, was für den Aufrufer unschöne
Konsequenzen hat.
public class ISP { public static void main(String[] args) {
List employees = new ArrayList();
employees.add(new Employee("Stefan", "Macke")); employees.add(new
Employee("Karl", "Meier")); employees.add(new Employee("Hans",
"Georg")); printEmployees(employees);
System.out.println(employees.size()); } private static void
printEmployees(List employees) {
for (var employee : employees) { System.out.println(employee); }
employees.clear(); } } // Ausgabe: // Stefan Macke // Karl Meier //
Hans Georg // 0
Die Methode sollte stattdessen das kleinstmögliche Interface
benutzen, das sie braucht, um ihre Aufgabe erfüllen zu können. In
Java wäre das z.B. ´Iterable´:
private static void printEmployees(Iterable
employees) { for (var employee : employees) {
System.out.println(employee); } }
Der restliche Code funktioniert wie vorher, aber es sind nun
keine modifizierenden Aufrufe mehr möglich, da das kleinere
Interface die Methoden nicht anbietet.
Dynamisch typisierte Sprachen haben hier einen Vorteil, da sie
dank Duck-Typing ohnehin kaum Basisklassen oder gar Interfaces
benötigen. Sie rufen einfach nur die Methoden auf, die sie
brauchen. Das kann allerdings auch zu impliziten Abhängigkeiten
führen, die nicht vom Compiler geprüft werden, da der Zugriff auf
die Klasse nicht durch ein Interface „geschützt“ ist.
Vorteile
Kleinere Komponenten machen uns das Entwicklerleben einfach:
klare Zuständigkeiten, einfachere Tests, weniger unnötige
Abhängigkeiten.
Durch klar definierte Schnittstellen wird die fehlerhafte
oder unerlaubte Verwendung von Funktionen verhindert.
Kleinere Schnittstellen entsprechen dem Single Responsibility
Principle.
Nachteile
Insgesamt steigt die Anzahl der Typen im System durch kleine
Schnittstellen an (siehe auch SRP).
Literaturempfehlungen
Es wird schon langweilig: Auch beim vierten SOLID-Prinzip
empfehle ich wieder Uncle Bobs Clean Code*.
*
Links
Permalink zu dieser Podcast-Episode
RSS-Feed des Podcasts
Interface Segregation Principle
ArticleS.UncleBob.PrinciplesOfOod (Artikel von Uncle Bob,
Beispiel in C++)
Interface-Segregation-Prinzip – Wikipedia
Das Interface Segregation Principle (Deutsches Beispiel in
C#)
Weitere Episoden
5 Minuten
vor 3 Wochen
11 Minuten
vor 4 Monaten
8 Minuten
vor 4 Monaten
8 Minuten
vor 4 Monaten
10 Minuten
vor 5 Monaten
In Podcasts werben
Kommentare (0)