Anmeldung Registrierung
Auto Hell Dunkel
Erweiterte Suche
  1. Startseite
  2. Podcasts
  3. IT-Berufe-Podcast Podcast
  4. Interface Segregation Principle (ISP) – Wissenshäppchen #6
Interface Segregation Principle (ISP) – Wissenshäppchen #6

Interface Segregation Principle (ISP) – Wissenshäppchen #6

IT-Berufe-Podcast vor 7 Jahren
Zu Sammlung hinzufügen

Du hast noch keine Sammlungen.

Herunterladen (rechte Maustaste) Teilen Fundstellen Kommentare
0:00
15:55
Das sechste Wissenshäppchen hat das Interface Segregation Principle
als Thema. TL;DR Mit dem Interface Segregation Principle (ISP)
halte ich die Schnittstellen, von denen mein Code abhängt, so
klein, wie es die jeweilige Aufgabe erlaubt. Am Beispiel von List
und Iterable in Java zeige ich dir, wie eine passende Schnittstelle
den Zugriff auf Methoden begrenzt und deinen Code für weitere
Datenstrukturen öffnet. Kleine Interfaces erleichtern Tests und
verringern den Aufwand, wenn sich andere Teile des Codes ändern.
Dabei entstehen mehr einzelne Schnittstellen, die sich mit modernen
IDEs gezielt finden lassen. Kapitelmarken [00:00:20] Das vierte
SOLID-Prinzip: Interface Segregation [00:00:44] Kleine Interfaces
und passende Abhängigkeiten [00:01:47] Große Interfaces und das
Liskov Substitution Principle [00:02:35] Beispiel: Eine Liste
durchlaufen [00:04:12] Iterable als passende Schnittstelle
[00:05:25] Fachliche Aufgaben trennen und das Single Responsibility
Principle [00:06:42] Mehrere kleine Interfaces in einer Klasse
implementieren [00:07:32] Änderungen an ungebrauchten Methoden und
erneutes Kompilieren [00:08:55] Einfachere Tests mit kleinen
Interfaces [00:10:06] Duck Typing und explizite Abhängigkeiten
[00:11:45] Vorteile kleiner Schnittstellen [00:12:46] Mehr
Komponenten und der Umgang mit vielen Dateien [00:13:59]
Schnittstellen klein halten [00:14:55] Ausblick, Codebeispiel und
weiterführende Links 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#)
Zusammenfassung Was das Interface Segregation Principle bedeutet
Wenn ich eine Schnittstelle für meinen Code auswähle, soll sie
genau die Methoden anbieten, die er für seine Aufgabe braucht. Das
Interface Segregation Principle (ISP) ist das vierte der fünf
SOLID-Prinzipien. Es fordert, die Schnittstelle zwischen einer
Klasse und ihrer Abhängigkeit möglichst klein zu halten. Für dich
bedeutet das: Wähle ein Interface, dessen Methoden zur jeweiligen
Aufgabe passen. Jede zusätzliche Methode erweitert die
Möglichkeiten des aufrufenden Codes und schafft eine weitere
Abhängigkeit. Beispiel: Eine Liste durchlaufen Ich möchte eine
Liste mit Mitarbeiter:innen durchlaufen und ihre Daten ausgeben.
Erwartet meine Methode dafür das Java-Interface List, erhält sie
auch Zugriff auf Methoden wie clear(). Damit könnte sie die
übergebene Liste leeren, obwohl ihre Aufgabe lediglich darin
besteht, die Elemente zu durchlaufen. Außerdem erschweren die
vielen angebotenen Methoden den Überblick. Für diese Aufgabe reicht
Iterable aus. Über dessen Methode iterator() erhält mein Code den
Iterator, den er zum Durchlaufen braucht. Die Schnittstelle bietet
ihm damit genau den passenden Zugriff. Dadurch kann ich auch andere
Objekte übergeben, die Iterable implementieren. Eine selbst
geschriebene Collection-Klasse muss dafür lediglich die
entsprechende Methode anbieten. Mein Code kann so mit weiteren
Datenstrukturen arbeiten. Fachlich passende Schnittstellen bilden
Bei einem Repository, das Benutzer:innen und Artikel sowie
Bestellungen aus der Datenbank lädt, treffen mehrere fachliche
Aufgaben zusammen. Code, der eine Bestellung bearbeitet, erhält
über eine gemeinsame Schnittstelle möglicherweise auch Zugriff auf
Methoden für Benutzer:innen. Solche großen Interfaces können darauf
hinweisen, dass das Single Responsibility Principle verletzt wird.
Die Methoden gehören dann zu unterschiedlichen Aufgaben und lassen
sich auf kleinere Schnittstellen verteilen. Das ISP betrifft auch
Basisklassen, die zu viele Funktionen anbieten. Ich kann für die
einzelnen Aufgaben eigene Interfaces definieren und sie weiterhin
in einer gemeinsamen Repository-Klasse implementieren. Der
aufrufende Code erwartet jeweils die fachlich passende
Schnittstelle. Sie wirkt wie ein kleines Fenster auf die Klasse,
durch das nur die benötigten Methoden sichtbar sind. Was große
Interfaces nach sich ziehen Wenn sich eine Methode einer großen
Schnittstelle ändert, kann davon auch Code betroffen sein, der
andere Methoden dieser Schnittstelle aufruft. Im
Repository-Beispiel muss der Code für Artikel unter Umständen
erneut kompiliert werden, sobald sich die gemeinsame Schnittstelle
für Benutzer:innen ändert. Getrennte Interfaces begrenzen solche
Abhängigkeiten und den damit verbundenen Aufwand. Auch die Klasse,
die ein Interface implementiert, muss alle vorgegebenen Methoden
anbieten. Braucht sie fachlich nur einen Teil davon, entstehen
zusätzliche Methoden ohne sinnvolle Aufgabe. Wer dort lediglich
Exceptions wirft, riskiert einen Verstoß gegen das Liskov
Substitution Principle: Der Compiler erkennt die Methode, beim
Aufruf zur Laufzeit scheitert sie. Tests mit kleinen Interfaces
Wenn ich eine Abhängigkeit im Test durch einen selbst geschriebenen
Stub oder Mock ersetze, muss dieser alle Methoden des Interfaces
implementieren. Bei einer großen Schnittstelle entsteht dadurch
viel Boilerplate-Code für Methoden, die mein Test gar nicht
aufruft. Mit einer kleinen Schnittstelle beschränkt sich diese
Arbeit auf die benötigten Methoden. Moderne Mocking-Frameworks
können die Methoden automatisch bereitstellen und nehmen dir damit
einen Teil dieses Aufwands ab. Duck Typing und sichtbare
Abhängigkeiten Beim Duck Typing kann ich einer Methode ein Objekt
übergeben, das die aufgerufenen Methoden bereitstellt. Ein
ausdrücklich implementiertes Interface ist dafür entbehrlich. Das
erleichtert es, passende Objekte zu übergeben. Welche Methoden der
aufrufende Code erwartet, lässt sich dabei erst durch einen Blick
in den Code erkennen. Fehlt eine davon, zeigt sich der Fehler zur
Laufzeit....
Episode melden

„Interface Segregation Principle (ISP) – Wissenshäppchen #6“

Worum geht es? Danach fragen wir noch nach dem Grund.

Teilen

Mein Archiv

Deine Privatkopie der Folgen, die du nicht verlieren willst.

Podcast-Folgen verschwinden. Feeds werden auf die letzten Episoden gekürzt, Hoster räumen alte Dateien ab, Formate wechseln den Anbieter und lassen ihr Archiv zurück. Mit „Mein Archiv“ sichert podcast.de die Folgen deiner Podcasts für dich — angefangen bei den ältesten, denn die sind zuerst weg.

  • Deine gesicherten Folgen bleiben hörbar, auch wenn das Original offline geht.
  • Auch Folgen, die im heutigen Feed gar nicht mehr stehen — podcast.de kennt sie noch.
  • Herunterladen bleibt möglich, solange die Folge beim Podcaster liegt. Der zählt seine Abrufe wie bisher.
Startet bald

Sei beim Start von Mein Archiv dabei

Mein Archiv ist fast fertig. Trag dich ein, dann bekommst du eine E-Mail, sobald es losgeht – und bist von Anfang an dabei. Wir schreiben dir nur zum Start, keine Werbung, keine Weitergabe deiner Daten.

Du bekommst zuerst eine Bestätigungsmail. Abmelden geht jederzeit. Datenschutz