Frage

Ich bin etwas über einen Absatz in dem Code komplettes Buch verwirrt.

Im Abschnitt „Klassen zu vermeiden,“ heißt es:

„Vermeiden Klassen benannt nach Verben Eine Klasse, die nur das Verhalten hat aber keine Daten ist in der Regel nicht wirklich eine Klasse. Betrachten wir eine Klasse wie DatabaseInitialization () oder Stringbuilder () in eine Routine auf einer anderen Klasse drehen“

Mein Code besteht hauptsächlich aus Verbklassen ohne Daten. Es gibt invoicereaders, pricecalculators, messagebuilders usw. ich dies tun jeder die Klassen eine Aufgabe zu konzentrieren. Dann füge ich Abhängigkeiten zu anderen Klassen für andere Funktionen.

Wenn ich den Absatz richtig verstehe ich möchte verwenden Code

class Webservice : IInvoiceReader, IArticleReader {
    public IList<Invoice> GetInvoices();
    public IList<Article> GetArticles();
}

statt

class InvoiceReader : IInvoiceReader {
    public InvoiceReader(IDataProvider dataProvider);
    public IList<Invoice> GetInvoices();
}

class ArticleReader : IArticleReader {
    public ArticleReader(IDataProvider dataProvider);
    public IList<Article> GetArticles();
}

Bearbeiten Vielen Dank für die Antworten.

Meine Schlussfolgerung ist, dass mein aktueller Code ist mehr SRP als OO aber, dass es leidet auch unter dem „anämischen Domänenmodell“.

Ich bin sicher, Thesen Einblicke mir in Zukunft helfen werden.

War es hilfreich?

Lösung

Klassennamen wie InvoiceReader, Preiskalkulator, MessageBuilder, ArticleReader, InvoiceReader sind nicht wirklich Verb Namen. Sie sind „Nomen Agent-Substantiv“ Klassennamen wirklich. Siehe Agent Substantive .

Ein Verb Klassenname so etwas wie Validate wäre, Operate, verwalten usw. Offensichtlich ist diese besser als Verfahren verwendet, und würde als Klassennamen ziemlich unangenehm sein.

Das größte Problem mit „Nomen Agent-Substantiv“ Namen Klasse ist, dass sie sehr wenig Bedeutung geben, was die Klasse tatsächlich tut (zB Usermanager, Datenprozessor etc.). Als Ergebnis sind sie eher aufgebläht sein und den inneren Zusammenhalt zu verlieren. (Siehe Einzel Prinzip Verantwortung ).

Deshalb ist die WebService-Klasse mit den IInvoiceReader und IArticleReader Schnittstellen ist wahrscheinlich das klare und aussagekräftiges OO-Design.

Das gibt Ihnen den einfachen, offensichtlichen Substantiv Klassennamen „WebService“, zusammen mit „Nomen Agent-Substantiv“ Interface-Namen, die eindeutig werben, was die WebService-Klasse für Anrufer tun kann.

Sie könnten wahrscheinlich auch mehr Bedeutung für die eigentliche Klasse geben, indem ein anderes Substantiv, zum Beispiel PaymentWebService prefixing.

Allerdings ist die Schnittstellen sind immer besser als ein einziger Klasse-Name bei der Beschreibung genauer gesagt, was die Klasse für Anrufer tun. Da die Klasse können komplexe, neue Schnittstellen wächst auch mit aussagekräftigen Namen hinzugefügt werden.

Andere Tipps

ich diese „Regel“ ignorieren, persönlich. Der .NET Framework selbst ist voll von "Verb" Klassen: TextReader, BinaryWriter, XmlSerializer, CodeGenerator, StringEnumerator, HttpListener, TraceListener, ConfigurationManager, TypeConverter, RoleProvider ..., wenn Sie denken, dass der Rahmen ist schlecht konzipiert, dann mit allen Mitteln, verwenden Sie keine Namen wie diese.

Steve Absicht ist verständlich. Wenn Sie sich Dutzende auf Dutzende von Klassen zu schaffen nur eine bestimmte Aufgabe zu erfüllen, ist es wahrscheinlich ein Zeichen für eine anämisch Domain Modell , wo die Objekte, die sollte der Lage sein, diese Dinge selbst zu tun sind es nicht. Aber irgendwann muss man eine Wahl treffen zwischen „reinen“ OOP und die SRP .

Mein Vorschlag wäre dies: Wenn Sie sich selbst ein „Verb“ Klasse finden erstellen, die auf einer einzigen „Nomen“ Klasse handelt, denken ehrlich darüber, ob oder nicht die „Nomen“ -Klasse die Aktion selbst durchführen kann. Aber nicht starten Gott Objekte oder kommen mit sinnloser Schaffung / irreführende Namen für den alleinigen Zweck der die verb-Klasse zu vermeiden.

folgen keinen Rat blind. Dies sind nur Richtlinien.

Das heißt, Substantive machen sehr gute Klassennamen , solange sie logische Objekte modellieren. Da die „Person“ Klasse ein Entwurf für alle „Person“ Objekte ist, nannte es „Person“ ist sehr praktisch, weil es Ihnen zu Grund wie dies ermöglicht: „Ich habe eine Person aus der Eingabe des Benutzers erstellen werden, aber zuerst ich brauche zu validieren es ... "

Bitte beachten Sie die Verwendung des Wortes „zu vermeiden“. Es ist nicht zu beseitigen, oder auszurotten, oder in der Hölle brennen, wenn Sie jemals sie verwenden.

Was bedeutet der Autor ist, dass, wenn Sie sich mit einem Bündel von Klassen finden Sie alle nach Verben benannt und alles, was Sie tun passieren zu statisch thoses Klassen erstellen, rufen Sie eine Funktion und vergessen Sie über sie, es ist wahrscheinlich ein Zeichen dafür, dass Sie ein bisschen zu viel Klasse Bedenken zu trennen.

Allerdings gibt es Situation, in Klassen zu schaffen eine Aktion zu implementieren ist eine gute Sache, wie wenn Sie verschiedene Strategien für die gleiche Wirkung haben. Ein sehr gutes Beispiel ist IComparer <>. Alles, was es tut, ist zwei Dinge vergleichen, aber es gibt mehrere Art, die Dinge zu vergleichen.

Wie der Autor vorgeschlagen, in diesen Fällen eine gute Möglichkeit, dies zu tun, ist durch eine Schnittstelle zu schaffen und sie zu implementieren. IComparer <> kommt wieder in den Sinn.

Eine weitere häufige Situation ist, wenn die Aktion einen schweren Stand hat, wie zum Beispiel das Laden von Dateien. Es könnte sich gerechtfertigt, den Staat in einer Klasse zu kapseln.

Im Wesentlichen das Buch, was zu sagen ist, dass OO-Design ist es, die Objekte zu extrahieren (die Substantive) und die Identifizierung die Operationen (die Verben), die auf und zwischen diesen Objekten auftreten.

Die Substantive die Objekte werden, werden die Verben die Methoden, die auf diesen Objekten arbeiten.

Die Idee ist, dass die

  

näher Programm Modelle der realen   Weltproblem ist, desto besser das Programm   sein wird.

In der Praxis das nützlichste, was mit einem Objekt ist, dass es einen bestimmten Zustand darstellen kann. Dann können Sie verschiedene Instanzen dieser Klasse haben jeweils einen anderen Zustand zu halten, um einen Aspekt des Problems darstellen.

Bei der InvoiceReader Klasse

  • Sie werden nur eine Instanz zu erschaffen
  • der einzige Staat, repräsentiert es ist, dass ein Datenprovider
  • zu enthalten,
  • es enthält nur eine Methode

Es gibt keinen Vorteil, um es in einem Objekt platzieren.

Die Anweisung Eine Klasse, die nur das Verhalten hat aber keine Daten ist in der Regel nicht wirklich eine Klasse. ist schlicht falsch.

Verhalten in eine separate Klasse Extrahierung ist eine gute und gemeinsame Sache in Refactoring zu tun. Es kann Zustand, aber auch nicht braucht, einen zu haben. Sie müssen sauber Schnittstellen haben, und setzen sie dich trotzdem für notwendig erachten.

Auch sind staatenlos Klassen groß für Berechnungen brauchen Sie nur für einen kurzen Zeitraum. Sie instanziiert sie (oder fordern Sie eine Fabrik von einer Art, sie zu erhalten), tun die notwendigen Berechnungen und sie dann zu Müll werfen. Sie können die entsprechende „Version“ Ihres Verhaltens zur Verfügung überall und jederzeit haben.

Normalerweise finde ich, dass verschiedene Implementierungen einer Schnittstelle einig Zustand (Set im Konstruktor, zum Beispiel), aber manchmal die Art Ihrer Klasse kann sein Verhalten vollständig bestimmen.

Beispiel:

public interface IExporter
{
    /// <summary>
    /// Transforms the specified export data into a text stream.
    /// </summary>
    /// <param name="exportData">The export data.</param>
    /// <param name="outputFile">The output file.</param>
    void Transform(IExportData exportData, string outputFile);
}

implementiert werden kann als

class TabDelimitedExporter : IExporter { ... }
class CsvExporter : IExporter { ... }
class ExcelExporter : IExporter { ... }

von IExportData Export implementieren (was auch immer das sein mag) in eine CSV-Datei, müssen Sie wahrscheinlich keinen Staat überhaupt. ExcelExporter, auf der anderen Seite könnten verschiedene Eigenschaften für den Export-Optionen haben, könnte aber auch staatenlos sein.

[Bearbeiten]

Umzug GetInvoices und GetArticles in die WebService Klasse bedeutet, dass Sie ihre Implementierung auf den WebService-Typ binden wird. sie in getrennten Klassen Having ermöglicht es Ihnen, verschiedene Implementierungen sowohl für Rechnungen und Artikel zu haben. Insgesamt scheint es besser, sie zu trennen hat.

weniger auf den Namen. Die Vorschrift über den Namen ist nur ein Regel-of-Daumen Indikator für eine schlechte Praxis. Der wichtige Punkt ist:

  

Eine Klasse, die nur das Verhalten hat aber keine Daten ist in der Regel nicht wirklich eine Klasse

In Ihrem Fall sieht es so aus, als ob Ihre Klassen beiden Daten und Verhalten, und dass sie auch „Rechnung“ genannt werden können und „Artikel“.

Es hängt davon ab. Viele Klassen existieren nach Lese- und Schreib Verben benannt, weil die Klassen auch erstellen, pflegen und eine Verbindung mit der Datenquelle sie lesen oder Schreiben von darstellen. Wenn Ihre Klassen das tun, ist es wahrscheinlich am besten, um sich zu trennen.

Wenn der Reader-Objekte nur enthalten Logik Parsen, dann die Klassen in Utility-Methoden Drehen ist der Weg zu gehen. Ich würde gehen mit einem aussagekräftigeren Namen als Webservice though.

ich glaube, das Buch ein Design wie die folgenden schlägt vor:

class Article : IIArticleReader
{
    // Article data...

    public IList<Article> GetArticles(); 
}

Hier ist ein klassisches Nehmen auf 'Verb vs Substantiv' in OO:

http: // steve-Yegge .blogspot.com / 2006/03 / Ausführungs-in-Reich-of-nouns.html

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top