Ich habe eine Klasse, die das jährliche Nettoeinkommen der Arbeiter berechnet. Es hat eine Konstante, die einen Steuerprozentsatz darstellt. Aber eines Tages hat sich der Steuersatz geändert, daher muss ich den Code korrigieren.
Zeigt das Festlegen dieser Konstante einen Verstoß gegen das Open-Closed-Prinzip an , da postuliert wird, dass eine Klasse für Änderungen geschlossen werden sollte?
object-oriented
object-oriented-design
solid
Analyse Paradisys
quelle
quelle
Antworten:
Das OCP kann besser verstanden werden, wenn man an Klassen oder Komponenten denkt, die von einem Anbieter A in einer Art Black-Box-Bibliothek zur Verwendung durch die Benutzer B, C und D bereitgestellt werden (beachten Sie, dass dies nur ein mentales Modell ist, das ich aus Gründen der Klarheit verwende). Es spielt keine Rolle, ob in Wirklichkeit der einzige Benutzer der Klasse A selbst ist.
Wenn B, C und D die bereitgestellten Klassen für verschiedene Anwendungsfälle verwenden oder wiederverwenden können, ohne dass der Quellcode der Bibliothek geändert werden muss, erfüllt die Komponente die OCP ( in Bezug auf eine Kategorie von Anwendungsfällen ). Es gibt verschiedene Mittel, um dies zu erreichen, wie z
Vererbbarkeit der Klasse (normalerweise in Verbindung mit dem Muster der Vorlagenmethode oder dem Strategiemuster)
durch Bereitstellen von "Injektionspunkten" für die Abhängigkeitsinjektion
durch Bereitstellen von Konfigurationsparametern für die Klasse oder Komponente (z. B. durch einen Konstruktorparameter "Steuerprozentsatz" wie in Ihrem Fall oder durch Verwendung eines anderen Konfigurationsmechanismus)
möglicherweise andere Mittel, abhängig von der Programmiersprache oder dem Ökosystem
Die typischen Beispiele, die Sie in Lehrbüchern finden, sind oft vom ersten oder zweiten Typ (ich denke, weil der dritte Typ in den Augen der Autoren dieses Buches zu trivial ist, um erwähnt zu werden).
Wie Sie sehen, hat dies nichts damit zu tun, eine Änderung des Quellcodes durch Anbieter A zu verbieten (z. B. zur Fehlerbehebung, Optimierung oder zum Hinzufügen abwärtskompatibler neuer Funktionen), die in keiner Beziehung zum OCP steht. In der OCP geht es darum, wie A die Schnittstelle und die Granularität der Komponenten in der Bibliothek gestaltet, sodass unterschiedliche Wiederverwendungsszenarien (wie die Wiederverwendung mit unterschiedlichen Steuersätzen) nicht automatisch Änderungsanforderungen hervorrufen.
Trotz allem, was Ihnen hier gesagt wird, lautet die Antwort eindeutig "Ja" . Dies wäre eine Verletzung der OCP.
BEARBEITEN: Zwischendurch hat jemand einen detaillierten Blog-Beitrag zu genau diesem Thema geschrieben. Obwohl Teile davon besser formuliert sein könnten (wie Derek Elkins betonte), scheint der Autor im Allgemeinen meinen Standpunkt zu teilen, dass "Erfüllung der OCP" keine absolute Eigenschaft ist, sondern etwas, das nur im Zusammenhang mit bestimmten bewertet werden kann Kategorien von Anforderungsänderungen.
quelle
Wie andere sagen, würde die Arbeitereinkommensklasse im Idealfall die Parametrisierung der Konstante ermöglichen, wodurch diese Klasse von diesem Wert unabhängig wird.
Letztendlich kann die aufrufende Anwendung auch eine Parametrisierung in Bezug auf die externe Konfiguration (z. B. eine Datei) ermöglichen. Sobald wir eine externe Konfiguration haben, können wir den Steuersatz ändern. Beachten Sie jedoch, dass die Anwendung neu gestartet werden muss, wenn die Konfigurationsdatei beim Start nur einmal gelesen wird, damit die aktualisierten Steuerprozentsätze wirksam werden Verstand. Wir könnten eine Anwendungsfunktion bereitstellen, um die Konfiguration erneut zu lesen, wenn Sie dazu aufgefordert werden, oder wir könnten einen komplizierteren Mechanismus bereitstellen, der feststellt, wenn sich die Konfigurationsdatei ändert ...
Langfristig können Sie feststellen, dass die Steuerprobleme mehr als nur einen Prozentsatz erfordern - zum Beispiel, dass die Steuergesetze eines Tages komplexer sind und mehrere Prozentsätze und einige Konstanten erfordern (z. B. der Betrag unter 10.000 USD, der mit X% besteuert wird, während die Rest besteuert mit Y%).
Dies legt im Wesentlichen die Verwendung eines Strategiemusters nahe, bei dem die hier fragliche Hauptklasse ein Strategieobjekt zur Berechnung der Steuer akzeptiert.
Die verschiedenen Strategien (sowie die Konstanten% und $) sollten aus der Konfigurationsdatei ausgewählt werden können. Zum Hinzufügen einer neuen Strategie muss nun neuer Code hinzugefügt werden, der vorhandene Code muss jedoch nicht unbedingt aktualisiert werden.
Jede Strategie kann möglicherweise ihre eigenen externen Konfigurationsargumente analysieren / interpretieren sowie die tatsächliche Steuer berechnen.
Dynamisch kann die Steuer außerdem vom maßgeblichen Gebietsschema abhängen, sodass das Gebietsschema möglicherweise mit dem Einkommen oder mit Mitarbeitern (oder beiden) verknüpft ist. In der externen Konfiguration können wir das Gebietsschema mit der Steuerstrategie verknüpfen.
Siehe auch Abhängigkeitsinjektion , wo wir diese Dinge explizit verwalten.
quelle
Wenn Sie die Klasse ändern müssen, um den Steuerwert zu ändern, verstößt ihr Design tatsächlich gegen OCP. Das geeignete Design für das, was Sie bisher beschrieben haben, besteht darin, dass die Rechnerklasse den Steuerwert als Parameter verwendet.
Wenn Ihre Klasse instanziiert ist (was bedeutet, dass es sich nicht um eine statische Klasse handelt), indem Sie die Steuervariablen-Klasseneigenschaft festlegen, deren Wert über den Konstruktor eingefügt wird, verbessern Sie auch den Klassenzusammenhalt.
Kurz gesagt, Ihr aktuelles Design lässt Ihre Klasse von einem konstanten Wert abhängen, der nicht wirklich eine Konstante ist (Konstante als Wert definieren, der sich niemals ändern würde, egal was passiert, wie der Wert von PI). Es verstößt gegen OCP. Ändern Sie das Design, um den Steuerwert als Konstruktorargument zu erhalten.
quelle
Stimmen Sie @Becuzz voll und ganz zu, und ich möchte dies nur zusammenfassen: Bei OCP geht es darum, wiederverwendete (daher nützliche) Abstraktionen zu finden, die in eine Klasse eingefügt werden. Das Verhalten der Klasse wird also nicht geändert, indem der Code geändert wird, sondern indem verschiedene Implementierungen bereitgestellt werden. Dies wird in Robert Martins Buch " Agile Softwareentwicklung, Prinzipien, Muster und Praktiken " kristallklar gemacht. Lesen Sie das entsprechende Kapitel "Das Open-Closed-Prinzip", "Abstraktion ist der Schlüssel", Unterkapitel. Es verdeutlicht ein weiteres Missverständnis, dass Verhalten nur durch Vererbung geändert werden kann. Es war Bertrand Meyer, der 1988 in seinem Buch „ Object Oriented Software Construction “ vorschlug , nicht Robert Martin.
quelle
So wie ich es sehe, verstößt es nicht gegen das Open-Closed-Prinzip. Die Tatsache, dass sich etwas, das sich mit der Zeit ändern muss (z. B. der Steuerprozentsatz), als Konstante darstellt, ist jedoch ein Konstruktionsfehler: Sie sollten nicht den Wert der Konstante ändern, sondern wie Sie mit dem Steuerprozentsatz umgehen. Dies sollte eine Einstellung sein, die geändert werden kann, ohne das Ganze neu zu kompilieren.
quelle