2010-06-17 14 views
6

Ich habe Kommandoklassen, die die ICommand {Execute} -Schnittstelle implementieren. Mehrere Befehle enthalten doppelte Codeabschnitte. Ich habe mehrere Optionen, wie trocken:Hilfsklasse (n) vs funktionale Vererbung. Best Practice

  • erstellen statische Hilfsklasse (n) und doppelten Code bewegen dort
  • Befehle erstellen Vererbung mit geschützten Hilfsmethoden

Was würden Sie vorschlagen, und warum?

HINZUGEFÜGT Vielen Dank an alle, die geantwortet haben, viele Antworten waren gleich und nützlich!

Antwort

3

Es hängt vollständig von der Art Ihres doppelten Code ab.

Was sind die Eingänge/Ausgänge Ihrer Hilfsfunktionen? Funktionieren sie auf logisch zusammenhängenden Variablen? Dann - ja, Sie sollten besser eine Basisklasse mit diesen Variablen als Mitglieder und verwandte Gruppe von Hilfsfunktionen erstellen.

Andernfalls, wenn die Parameter in Ihren Hilfsfunktionen nicht kohärent sind, würden Sie diese Funktionen trotzdem als statische Funktionen implementieren, oder? Ich sehe keine Gründe, die Dinge mit der Vererbung in diesem Fall zu verkomplizieren, und ich würde es nur mit Hilfsfunktionen tun (oder, wenn Ihre Sprache keine Funktionen als erstklassige Bürger behandelt, verwenden Sie die statische Hilfsklasse).

3

Wenn es eine Chance gibt, dass die doppelte Logik auch von anderen Klassen außerhalb der Hierarchie benötigt wird, würde ich es in statische Hilfsklassen setzen. Sonst in der Basisklasse mit geschützter Vererbung.

2

Meiner Meinung nach würde ich den doppelten Code in die Basisklasse einfügen, wenn er sich nur auf diese Klassenhierarchie bezieht und nicht außerhalb davon verwendet wird. Wenn die Möglichkeit besteht, dass der Code für verschiedene Klassen verwendet wird, verschieben Sie ihn in eine Hilfsklasse innerhalb eines gemeinsamen Projekts.

Viel Spaß!

5

Anstelle von statischen Klassen besteht eine weitere Möglichkeit darin, den allgemeinen Code in eine neue Klasse zu stellen und die Abhängigkeitsinjektion zu verwenden, um die Hilfsklasse in die Befehle zu injizieren. Dies gilt auch für die Komposition über den Vererbungsbegriff.

+0

Oder umgekehrt: Machen Sie die Hilfsklasse zu einem Dekorator und injizieren Sie die Befehlsklasse in die Hilfsklasse. – Ozan

+2

+1 Denken Sie bei der Wiederverwendung von Code nicht an "Vererbung", sondern an "Aggregation". –

1

Es gibt wahrscheinlich keine richtige/falsche Antwort hier, obwohl ich denke, dass Sie es sicherlich schlecht implementieren könnten. Es ist wahrscheinlich sehr abhängig von Ihren tatsächlichen Anforderungen und wie Ihre Befehle zueinander verwandt sind. Im Allgemeinen würde ich wahrscheinlich mit einer Basisklassenimplementierung und Vererbungshierarchie gehen, unter der Annahme, dass die Befehle verwandt sind und der Code sich direkt auf die Befehle selbst bezieht, nicht auf irgendeine externe Entität, die eine eigene Klasse sein sollte. Sicherlich sind sie dadurch verbunden, dass sie Befehle sind und die Basisklasse dies widerspiegeln kann.

Wenn Sie Code haben, der nur Teilmengen von nicht verwandten Befehlen gemeinsam ist, würde das Erstellen einer Vererbungshierarchie eine Beziehung erzwingen, die nicht existiert, und dann eine "helper" -Klasse hinzufügen (nicht statisch, if möglich, um die Testbarkeit zu verbessern) wäre eine vollkommen natürliche Möglichkeit, das Problem anzugehen. Sie können feststellen, dass Sie die "Helfer" -Methoden natürlich in eigene Klassen gruppieren können. Wenn beispielsweise mehrere Methoden mit Ihrem Authentifizierungs-Subsystem interagieren müssen, verfügen Sie möglicherweise über einen AuthenticationMediator für diese Methoden. Ich sehe auch keine Konflikte mit einigen von beiden.

0

Wenn die Logik arbeitet an Schnittstelle Mitglieder, im Gegensatz zu Implementierung Mitglieder, dann eine Hilfsmethode [oder Erweiterungsmethode] Schreiben wird empfohlen.

public IRandom 
{ 
    byte NextByte(); 
} 

public static class IRandomExtensions 
{ 
    // logic that acts against public interface IRandom 
    // may be applied to all implementations 
    public static int GetNextUnbiasedInteger (this IRandom random) { } 
    public static IEnumerable<T> Shuffle<T> (
     this IRandom random, 
     IEnumerable<T> items) { } 
} 

Wenn Business-Logik arbeitet gegen Implementierung Mitglieder,

public class SomeCommand : ICommand 
{ 
    // an implementation-specific member, NOT a member 
    // of ICommand 
    public int SomeControlCount { get; set; } 
} 

// a method that references implementation-speciic 
// details. where should this go? 
public void DoSomething() 
{ 
    SomeCommand command; 
    int count = command.SomeControlCount; 
} 

dann wahrscheinlich sollten wir stärker binden diese an die implementierende Klasse. Wenn dies häufig vorkommt, kann eine Basisklasse sinnvoll sein.

Persönlich, komplexe Hierarchien sind mehr Mühe, als sie wert sind, verwenden Sie Ihr eigenes Urteil in Bezug auf Wartbarkeit, Lesbarkeit und Wiederverwendung, und Sie sollten in Ordnung sein!

Hoffe, das hilft! :)

0

Staatenlosen Code verwenden Helfer.

Statusabhängiger Code mit mehreren Methoden verwendet Vererbung. Zum Beispiel, wenn mehrere Methoden eine gemeinsame Membervariable verwenden und somit einen gemeinsamen Status beibehalten.

Das Ziel ist es, die Menge an doppeltem Code zu reduzieren, und es hängt davon ab, welche Art von Code es ist. Allerdings hasse ich es wirklich, wenn Leute dies übertreiben und super abstrakte Klassen oder Hilfsfunktionen machen, die 7 Sprünge zu anderem strangle abstrakten Code machen, die so etwas wie "Executor" "Invoker" "DataConveyer" "DataManager" "SharedCode" genannt werden. Und das irgendwie am Ende von all diesen Sprüngen hat tatsächlich geschafft, die Arbeit zu tun, die es angenommen wurde, aber ist so miteinander verbunden, dass Sie nicht sicher sind, wo man die neuen Änderungen macht, um diese neue Eigenschaft hinzuzufügen. Soll ich DataConveyer machen oder sollte ich das in DataManager machen?

Also sollte das goldene Ziel eher sein, behalte es einfach.

1

Verwendung von Helfern in Ihrem eigenen Code ist eine schlechte Praxis, die aus Faulheit kam.

Die einzig mögliche Situation, die Sie wirklich brauchen Helfer - ist das Verhalten der versiegelten Klassen von 3rd-Party-Bibliotheken wie Selen usw.

Was Helfer zu verlängern? Es ist eine statische Methode, die aus der Klasse selbst stammt.

Welche Probleme bekommen wir?

  1. statische Methode. Hat Probleme mit Unit-Tests. Zum Beispiel haben unsere Entwickler den Helfern Caching hinzugefügt. Infolgedessen gab es keine Möglichkeit, diese Methoden einfach zu verspotten, während ich zu viel Logik nur für das einfache Spotten hinzufügen musste. Ja, es gibt eine Möglichkeit der falschen Verwendung der statischen Methode ... aber am Anfang hat niemand erwartet, dem Helfer einen Zustand hinzuzufügen.
  2. Ort. Die Methode befindet sich in einer anderen Klasse, weit entfernt von der grundlegenden Logik. Es ist eine falsche Vorstellung von Code-Design.

Wann Helfer zu verwenden? Wenn Sie die Bibliothek von Drittanbietern erweitern müssen, ohne die Möglichkeit zu haben, sie zu erben. Ansonsten vererbe nur lib.

Wann keine Helfer? Um doppelten Code zu reduzieren. Sie müssen diesen Code in einen anderen Dienst verschieben.Lesen Sie über DDD, um Refactoring-Fähigkeiten zu verbessern und Service am besten zu organisieren