Die Zeit, in der Sie eine Klasse in Betracht ziehen müssen, die erweitert werden soll, ist die Zeit, in der Sie eine echte Planung für die Zukunft durchführen. Lassen Sie mich Ihnen ein reales Beispiel aus meiner Arbeit geben.
Ich verbringe viel Zeit damit, Schnittstellen-Tools zwischen unserem Hauptprodukt und externen Systemen zu schreiben. Wenn wir einen neuen Verkauf abschließen, besteht eine große Komponente aus einer Reihe von Exporteuren, die in regelmäßigen Abständen ausgeführt werden und Datendateien mit den Ereignissen an diesem Tag erstellen. Diese Datendateien werden dann vom System des Kunden verwendet.
Dies ist eine hervorragende Gelegenheit, den Unterricht zu erweitern.
Ich habe eine Export-Klasse, die die Basisklasse jedes Exporteurs ist. Es kann eine Verbindung zur Datenbank herstellen, herausfinden, wo sie zuletzt ausgeführt wurde, und Archive der von ihr generierten Datendateien erstellen. Es bietet auch die Verwaltung von Eigenschaftendateien, die Protokollierung und einige einfache Ausnahmebehandlungen.
Darüber hinaus habe ich einen anderen Exporteur, der mit den einzelnen Datentypen arbeitet. Möglicherweise gibt es Benutzeraktivitäten, Transaktionsdaten, Cash-Management-Daten usw.
Auf diesen Stapel lege ich eine kundenspezifische Ebene, die die vom Kunden benötigte Datendateistruktur implementiert.
Auf diese Weise ändert sich der Basis-Exporteur sehr selten. Die wichtigsten Exportprogramme für Datentypen ändern sich manchmal, aber selten, und normalerweise nur, um Datenbankschemaänderungen zu verarbeiten, die ohnehin an alle Kunden weitergegeben werden sollten. Die einzige Arbeit, die ich jemals für jeden Kunden erledigen muss, ist der Teil des Codes, der für diesen Kunden spezifisch ist. Eine perfekte Welt!
Die Struktur sieht also so aus:
Base
Function1
Customer1
Customer2
Function2
...
Mein wichtigster Punkt ist, dass ich durch die Architektur des Codes auf diese Weise die Vererbung hauptsächlich für die Wiederverwendung von Code nutzen kann.
Ich muss sagen, ich kann mir keinen Grund vorstellen, über drei Schichten hinauszugehen.
Ich habe oft zwei Ebenen verwendet, um zum Beispiel eine gemeinsame Table
Klasse zu haben, die Abfragen von Datenbanktabellen implementiert, während Unterklassen Table
die spezifischen Details jeder Tabelle implementieren, indem sie ein verwenden enum
, um die Felder zu definieren. Das enum
Implementieren einer in der Table
Klasse definierten Schnittstelle zuzulassen, ist in jeder Hinsicht sinnvoll.
Open/Closed principle
, nicht dasClosed Principle.