In unserer Rails-Anwendung fügen wir Benachrichtigungen hinzu. Einige davon sind blocking
: Sie stoppen den Fortschritt der hinzugefügten Ressource, da einige Informationen zu dieser Ressource fehlen.
Andere Benachrichtigungen sind einfache Benachrichtigungen, die nur Informationen enthalten.
Heute hatte ich eine Diskussion mit einem anderen Programmierer in unserem Team. Ich habe die Vererbungsstruktur wie folgt erstellt:
Er möchte jedoch lieber, dass ich nur blocking
eine boolesche Rückgabemethode für jede Benachrichtigung hinzufüge und eine Liste von Unterklassen spezifiziere, die innerhalb der übergeordneten Klasse "Benachrichtigung" blockiert werden.
Der Unterschied zwischen diesen Ansätzen ist nicht sehr groß; In meinem Ansatz muss man diese Liste nicht spezifizieren, um die Stammklasse sauberer zu halten. Auf der anderen Seite ist die spezielle Logik, die gerade auftritt, auch Notification::Blocking
nicht sehr groß.
Welche Art von Abstraktion ist für dieses Problem besser geeignet?
Antworten:
Sie möchten vermeiden, dass Basisklassen über abgeleitete Klassen Bescheid wissen. Es führt zu einer engen Kopplung und bereitet Wartungsprobleme, da Sie jedes Mal, wenn Sie eine neue abgeleitete Klasse erstellen, daran denken müssen, die Liste zu erweitern.
Außerdem wird verhindert, dass Sie die Notification-Klasse in ein wiederverwendbares Paket / eine wiederverwendbare Assembly einfügen können, wenn Sie diese Klasse in mehreren Projekten verwenden möchten.
Wenn Sie wirklich eine einzelne Basisklasse verwenden möchten, können Sie dieses Problem auch lösen, indem Sie der Basisklasse Notification eine virtuelle Eigenschaft oder Methode IsBlocking hinzufügen. Abgeleitete Klassen können dies dann überschreiben, um true oder false zurückzugeben. Sie hätten eine Einzelklassenlösung, ohne dass die Basisklasse über abgeleitete Klassen Bescheid weiß.
quelle
Das sieht sehr eigenartig aus und ist ein besonderer Codegeruch.
Ich würde Unterklassen bereitstellen, wenn Sie unterschiedliche Verhaltensweisen zwischen den Klassen aufweisen und alle diese Benachrichtigungen auf dieselbe Weise behandeln möchten (dh mit Polymorphismus ).
quelle
Im Gegensatz zu den vorhandenen Antworten würde ich vorschlagen, dass die boolesche Eigenschaft die beste Option ist, wenn der zu verwendende Modus dynamisch geändert werden muss (z. B. über eine Konfigurationsdatei, die eine Liste der zu blockierenden Typen enthält und welche nicht).
Das heißt, ein besseres Design selbst in dieser Situation könnte darin bestehen, ein Decorator-Objekt zu verwenden.
quelle
Ich würde sagen, es hängt davon ab, wie viel das Besondere an einer Sperrbenachrichtigung ist. Mein erster Gedanke ist jedoch, "beides" zu wählen:
Auf diese Weise können Sie verwenden ,
n.Blocking
odern is BlockingNotification
(alle in Pseudo-Code), obwohl, wenn Sie einer Klasse zu ermöglichen , gehen zu einem kontextsensitiven umzusetzenBlocking
Wert, da Sie jedes Mal, wenn Wert überprüfen müßten, dasBlockingNotification
wird Klasse weniger nützlich.In jedem Fall stimme ich den anderen Antworten zu, bei denen Sie nicht möchten, dass die Basisklassenimplementierung etwas
Blocking
über die abgeleiteten Klassen weiß.quelle
Anstatt zwei Basisklassen und jeweils mehrere Instanzen zu erstellen, erstellen Sie eine Benachrichtigungsklasse mit einem Bool, um anzugeben, ob die Benachrichtigung blockiert ist, und um weitere Informationen zu erhalten, die zur Übermittlung der Benachrichtigung an den Benutzer erforderlich sind.
Auf diese Weise können Sie eine Codemenge zum Verarbeiten und Präsentieren von Benachrichtigungen verwenden und die Komplexität Ihres Codes verringern.
quelle