Angenommen, ich habe verschiedene Entitäten in meinem Modell (mit EF), z. B. Benutzer, Produkt, Rechnung und Bestellung.
Ich schreibe ein Benutzersteuerelement, das die Zusammenfassungen von Entitätsobjekten in meiner Anwendung drucken kann, in denen die Entitäten zu einer vorab festgelegten Menge gehören. In diesem Fall sage ich, dass Zusammenfassungen von Benutzer und Produkt zusammengefasst werden können.
Die Zusammenfassungen haben alle nur eine ID und eine Beschreibung, daher erstelle ich eine einfache Schnittstelle dafür:
public interface ISummarizableEntity {
public string ID { get; }
public string Description { get; }
}
Dann erstelle ich für die fraglichen Entitäten eine Teilklasse, die diese Schnittstelle implementiert:
public partial class User : ISummarizableEntity
{
public string ID
{
get{ return UserID.ToString(); }
}
public string Description
{
get{ return String.Format("{0} {1} is from {2} and is {3} years old", FirstName, LastName, Country, Age); }
}
}
public partial class Product: ISummarizableEntity
{
public string ID
{
get{ return ProductID.ToString(); }
}
public string Description
{
get{ return String.Format("{0} weighs {1}{2} and belongs in the {3} department", ProductName, WeightValue, WeightUnit, Department); }
}
}
Auf diese Weise kann meine Benutzersteuerung / Teilansicht nur an eine Sammlung von ISummarizableEntity gebunden werden und muss überhaupt nicht an der Quelle interessiert sein. Mir wurde gesagt, dass Schnittstellen nicht als Datentypen verwendet werden sollten, aber ich habe nicht mehr Informationen erhalten. Soweit ich sehen kann, obwohl Schnittstellen normalerweise das Verhalten beschreiben, ist die bloße Verwendung von Eigenschaften an sich kein Anti-Pattern, da Eigenschaften ohnehin nur syntaktischer Zucker für Getter / Setter sind.
Ich könnte einen konkreten Datentyp erstellen und diesen die Entitäten zuordnen, aber ich kann den Nutzen nicht erkennen. Ich könnte die Entitätsobjekte von einer abstrakten Klasse erben lassen und dann die Eigenschaften definieren, aber dann sperre ich die Entitäten für keine weitere Verwendung, da wir keine Mehrfachvererbung haben können. Ich bin auch offen dafür, dass jedes Objekt ISummarizableEntity ist, wenn ich wollte (natürlich würde ich die Schnittstelle umbenennen).
Die Lösung, die ich in meinem Kopf verwende, ist wartbar, erweiterbar, testbar und ziemlich robust. Kannst du das Anti-Muster hier sehen?
EntitySummary
,User
undProduct
jeder eine Methode hatpublic EntitySummary GetSummary()
?Antworten:
Schnittstellen beschreiben kein Verhalten. Im Gegenteil, manchmal.
Schnittstellen beschreiben Verträge, z. B. "Wenn ich dieses Objekt einer Methode anbieten möchte, die eine ISummarizableEntity akzeptiert, muss dieses Objekt eine Entität sein, die sich selbst zusammenfassen kann" - in Ihrem Fall wird dies als Rückgabe von a definiert Zeichenfolgen-ID und eine Zeichenfolgenbeschreibung.
Das ist eine perfekte Verwendung von Schnittstellen. Kein Anti-Muster hier.
quelle
List
einer Liste tun , die sich nicht wie eine Liste verhält?Sie haben den besseren Pfad für dieses Design gewählt, weil Sie einen bestimmten Verhaltenstyp definieren, der für mehrere unterschiedliche Objekttypen erforderlich ist. Vererbung würde in diesem Fall eine gemeinsame Beziehung zwischen den Klassen implizieren, die tatsächlich nicht existiert. In diesem Fall wird die Kompositionsfähigkeit der Vererbung vorgezogen.
quelle
Schnittstellen, die nur Eigenschaften tragen, sollten vermieden werden, da:
Hier mischen Sie zwei Bedenken:
Eine Zusammenfassung besteht aus zwei Zeichenfolgen: einer ID und einer Beschreibung. Dies sind einfache Daten:
Nachdem Sie definiert haben, was eine Zusammenfassung ist, möchten Sie einen Vertrag definieren:
Beachten Sie, dass die Verwendung von Intelligenz in Gettern ein Anti-Muster ist und vermieden werden sollte: Sie sollte sich stattdessen in Funktionen befinden. So sehen Implementierungen aus:
quelle