Anmeldung Registrierung
Auto Hell Dunkel
Erweiterte Suche
  1. Startseite
  2. Podcasts
  3. IT-Berufe-Podcast Podcast
  4. Open Closed Principle (OCP) – Wissenshäppchen #4
Open Closed Principle (OCP) – Wissenshäppchen #4

Open Closed Principle (OCP) – Wissenshäppchen #4

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

Du hast noch keine Sammlungen.

Herunterladen (rechte Maustaste) Teilen Fundstellen Kommentare
0:00
22:17
Mein viertes Wissenshäppchen hat das Open Closed Principle zum
Thema. TL;DR Mit dem Open-Closed-Principle (OCP) erweitere ich
Software um neue Funktionen, während der bestehende Code
unverändert bleibt. Durch Polymorphie und Interfaces kannst du
zusätzliche Klassen einbinden; typabhängige Abfragen mit instanceof
oder switch weisen auf Stellen hin, die bei jeder neuen Klasse
angepasst werden müssen. Das Prinzip senkt das Risiko, Fehler in
funktionierenden Code einzubauen. Wie viel zusätzliche Architektur
dafür sinnvoll ist, wäge ich anhand der erwarteten Anforderungen
und des YAGNI-Prinzips ab. Kapitelmarken [00:00:00] Einstieg in das
Open-Closed-Principle [00:00:53] Bedeutung des OCP und Motivation
[00:02:42] Ursprung bei Bertrand Meyer [00:03:33] Vererbung und
Polymorphie [00:04:27] Grenzen der Vererbung [00:05:41] Das OCP mit
Interfaces umsetzen [00:07:14] Typabhängige Abfragen als Code Smell
[00:10:34] Replace Conditional with Polymorphism [00:11:16]
Beispiel: Tiere durch eigene Methoden beruhigen [00:13:24] Ruby und
Duck Typing [00:14:21] Beispiel: Boni für Mitarbeiter:innen
berechnen [00:15:43] Vorteile des Open-Closed-Principle [00:17:05]
Overengineering vermeiden und YAGNI beachten [00:18:55] Rückblick
auf das OCP [00:20:50] Codebeispiele und weiterführende Quellen
Inhalt Das OCP ist das zweite der SOLID-Prinzipien. Es wurde vor
Robert "Uncle Bob" Martin bereits 1988 von Bertrand Meyer
definiert: Software entities (classes, modules, functions, etc.)
should be open for extension, but closed for modification.
Ursprünglich ging es darum, durch Vererbung die Anpassung
("modification") bereits bestehender Klassen zu verhindern, indem
Subklassen abgeleitet werden, die die vorhandene Funktionalität
erweitern ("extension"). Heutzutage ist Vererbung aber eher nicht
mehr so gerne gesehen, da es eine starke Kopplung an die
Basisklasse zur Folge hat, was das Design inflexibel macht.
Stattdessen sollte man besser von vornherein Interfaces mit
potentiell verschiedenen Implementierungen einsetzen. Erklärung Bei
Änderungen an einem Programm sollen bestehende Komponenten
bestenfalls gar nicht angepasst werden müssen, da diese Anpassungen
Fehler nach sich ziehen können, die auch das bereits bestehende
Verhalten betreffen. Neue Funktionalität wird dem Programm immer
durch neue Komponenten hinzugefügt, also z.B. indem neue Klassen
oder Methoden ergänzt werden. Fallunterscheidungen auf Basis von
Typen (z.B. mit instanceof in Java) oder Enumerations (insb. wenn
diese in einem switch verwendet werden) sind oft ein Hinweis auf
Verletzung des OCP und sollten durch Polymorphie ersetzt werden.
Beispiel class Manager end class Developer end class Payroll def
self.calculate_bonus(employee) if employee.is_a?(Manager) return
1000 end if employee.is_a?(Developer) return 500 end end end puts
Payroll.calculate_bonus(Manager.new) # 1000 puts
Payroll.calculate_bonus(Developer.new) #500 Wenn diese
Bonusberechnung um einen neuen Mitarbeitertyp Administrator
erweitert werden soll, muss die bestehende Implementierung von
calculate_bonus() angepasst werden: def
self.calculate_bonus(employee) if employee.is_a?(Manager) return
1000 end if employee.is_a?(Developer) return 500 end if
employee.is_a?(Administrator) return 250 end end Stattdessen sollte
von Anfang an die Berechnung des Bonuses an die Mitarbeiterklassen
delegiert werden. class Manager def bonus 1000 end end class
Developer def bonus 500 end end class Payroll def
self.calculate_bonus(employee) employee.bonus end end puts
Payroll.calculate_bonus(Manager.new) # 1000 puts
Payroll.calculate_bonus(Developer.new) # 500 Dadurch ist eine
spätere Erweiterung um neue Mitarbeitertypen ohne Anpassung des
bisherigen Codes möglich: class Administrator def bonus 250 end end
puts Payroll.calculate_bonus(Administrator.new) # 250 In dynamisch
typisierten Sprachen (wie im Beispiel Ruby) ist das OCP übrigens
meist noch einfacher umzusetzen als in statisch typisierten, da
durch das Duck-Typing umfangreiche Klassenhierarchien oder
Interfaces unnötig werden. Dies sieht man auch im Beispiel oben:
Manager und Developer haben keinerlei Beziehung zueinander.
Trotzdem funktioniert der Code, da beide Klassen die Methode
bonus() anbieten. Vorteile Bei Erweiterungen der Funktionalität
sinkt die Wahrscheinlichkeit, Fehler in den bereits
funktionierenden Code einzubauen. Klassen behalten ihre Aufgabe
"ein Leben lang". Abhängige Klassen können sich darauf verlassen,
dass sich die Funktionalität nicht ändert. Erweiterungen sind ggfs.
einfacher zu implementieren, da nicht an mehreren Stellen Code
angepasst, sondern "nur" neuer Code geschrieben werden muss.
Nachteile Meist ist gar nicht im Voraus bekannt, welche Stellen im
Code später einmal erweitert werden müssen. Einfach nur noch mit
Abstraktionen zu arbeiten, macht den Code aber schwer verständlich.
Außerdem verletzten wir damit das YAGNI-Prinzip.
Literaturempfehlungen Da Uncle Bob die SOLID-Prinzipien so schön
aufgeschrieben hat, kann ich wieder einmal seinen Klassiker Clean
Code* empfehlen. * Links Permalink zu dieser Podcast-Episode
RSS-Feed des Podcasts Open Closed Principle
ArticleS.UncleBob.PrinciplesOfOod (Artikel von Uncle Bob, Beispiel
in C++) Open-Closed-Prinzip – Wikipedia SOLID – Das Open Closed
Principle | Informatik Aktuell (ausführliche Diskussion der
Nachteile, Beispiel in C#) SOLID Design Principles Explained – The
Open/Closed Principle with Code Examples (Beispiel in Java)
Zusammenfassung Was das Open-Closed-Principle bedeutet Wenn du ein
bestehendes System um neue Funktionen ergänzt, sollen seine
vorhandenen Komponenten unverändert bleiben können. Das
Open-Closed-Principle (OCP) beschreibt dieses Ziel mit "offen für
Erweiterungen, geschlossen für Änderungen". Es ist das zweite der
fünf SOLID-Prinzipien und steht für das O in SOLID. Jeder Eingriff
in funktionierenden Code birgt das Risiko, Fehler einzubauen. Indem
ich neue Funktionen in zusätzlichen Klassen unterbringe, bleibt das
bisherige Verhalten erhalten. Ursprung und Vererbung Bereits 1988
formulierte Bertrand Meyer das Prinzip. Robert C. Martin griff es
später im Zusammenhang mit SOLID auf. Die ursprüngliche Idee setzte
auf Vererbung: Eine fertige Basisklasse wird durch Unterklassen
ergänzt, die zusätzliche Funktionen mitbringen. Durch Polymorphie
kann eine Unterklasse überall dort eingesetzt werden, wo die
Basisklasse erwartet wird. In meiner Ausbildung empfehle ich
Vererbung dann, wenn vorhandener Code wiederverwendet werden soll.
Eine Hierarchie aus der Realität allein ist für mich kein
ausreichender Anlass. In Java und C# kann eine Klasse nur von einer
einzigen Basisklasse erben, wodurch sie sich eng an diese bindet.
Das OCP mit Interfaces umsetzen Für Java und C# bevorzuge ich
Interfaces als Grundlage. Eine Klasse kann mehrere Interfaces
implementieren. Wenn dein bestehender Code mit einem Interface
arbeitet, kannst du passende Klassen austauschen oder ergänzen. Für
eine neue Funktion schreibst du eine weitere Klasse, die das
erwartete Interface implementiert. Der aufrufende Code arbeitet
weiterhin mit derselben Schnittstelle, während die neue Klasse das
zusätzliche Verhalten mitbringt. Typabhängige Abfragen als
Warnsignal Wenn du konkrete Klassen mit instanceof prüfst und davon
abhängig unterschiedliche Aktionen ausführst, deutet das auf einen
Verstoß gegen das OCP hin. Solche Fallunterscheidungen können in
if-Abfragen oder switch-Anweisungen stecken. In meinem Beispiel
bekommt eine Methode ein Objekt vom Typ Tier. Prüft sie
ausdrücklich auf Hund und Katze, braucht sie beim späteren
Hinzufügen eines Pferd einen weiteren Zweig. Damit musst du
bestehenden Code ändern. Je mehr solcher Stellen vorhanden sind,
desto mehr Stellen musst du bei einer neuen Tierart bearbeiten.
Fallunterscheidungen durch Polymorphie ersetzen Martin Fowler
beschreibt in seinem Buch Refactoring das passende Vorgehen als
Replace Conditional with Polymorphism. Dabei wandert das
typabhängige Verhalten in die jeweiligen Klassen. Für das Beispiel
aus einer Tierarztpraxis erhält Tier eine Methode beruhige. Die
aufrufende Klasse ruft diese Methode am übergebenen Tier auf. Jede
konkrete Tierklasse legt selbst fest, wie das Tier beruhigt wird.
Ergänzt du später ein Meerschweinchen mit einer eigenen Methode
beruhige, kann der bestehende Aufruf damit arbeiten. Ruby und Duck
Typing In meinem Ruby-Beispiel genügt es, dass ein übergebenes
Objekt die aufgerufene Methode anbietet. Ruby ist dynamisch
typisiert; ein ausdrücklich implementiertes Interface ist dafür
entbehrlich. Dieses Konzept heißt Duck Typing. Entscheidend ist, ob
das Objekt das benötigte Verhalten bereitstellt. Das Beispiel
behandelt Boni für Mitarbeiter:innen. Die jeweiligen Klassen für
Manager:innen und Entwickler:innen bestimmen ihren Bonus selbst.
Auch Administrator:innen erhalten eine eigene Klasse. Die
aufrufende Methode fragt den Bonus über get Bonus ab. Eine
zusätzliche Klasse für Reinigungskräfte kann denselben Aufruf mit
einer eigenen Bonusberechnung unterstützen. Was dir das Prinzip
bringt Weil bestehender Code unverändert bleibt, sinkt das Risiko,
dort neue Fehler einzubauen. Klassen behalten ihre Aufgaben und ihr
Verhalten, sodass sich aufrufender Code weiterhin darauf verlassen
kann. Neue Funktionen lassen sich in zusätzlichen Klassen
unterbringen. Dadurch entfällt die Suche nach verstreuten
Fallunterscheidungen, die du sonst erweitern müsstest. Aufwand und
YAGNI abwägen Bei meinen Beispielen lässt sich leicht vorstellen,
welche Klassen später hinzukommen. Im Alltag ist oft unklar, welche
Teile eines Systems künftig erweitert werden müssen. Zusätzliche
Interfaces und Abstraktionsschichten kosten Aufwand und machen den
Code schwerer verständlich. Überflüssige Komplexität kann
ihrerseits Fehler begünstigen; außerdem kann der
Episode melden

„Open Closed Principle (OCP) – Wissenshäppchen #4“

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