Ich arbeite derzeit als Solo-Entwickler an meinem aktuellen Projekt. Ich habe das Projekt von einem anderen Entwickler geerbt, der das Unternehmen inzwischen verlassen hat. Es ist eine Webanwendung im Model-View-Controller-Stil in C #. Es verwendet Entity Framework für die objektrelationale Zuordnung. Und es gibt zwei verschiedene Klassen für die Typen im Domänenmodell. Ein Satz wird für die Interaktion mit dem ORM verwendet, der andere als Modell im MVC-System. Beispielsweise kann es zwei Klassen geben:
public class Order{
int ID{get;set;}
String Customer{get;set;}
DateTime DeliveryDate{get;set;}
String Description{get;set;}
}
und
public class OrderModel{
String Customer{get;set;}
DateTime DeliveryDate{get;set;}
String Description{get;set;}
public OrderModel( Order from){
this.Customer= from.Customer;
// copy all the properties over individually
}
public Order ToOrder(){
Order result =new Order();
result.Customer = this.Customer;
// copy all the properties over individually
}
}
Ich kann mir einige Nachteile dieses Ansatzes vorstellen (mehr Orte, an denen Code geändert werden kann, wenn sich etwas ändert, mehr Objekte im Speicher, mehr Zeit für das Kopieren von Daten), aber ich bin mir nicht sicher, welche Vorteile hier liegen. Mehr Flexibilität für die Modellklassen, nehme ich an? Aber ich könnte das erreichen, indem ich auch die Entitätsklassen unterklassifiziere. Meine Neigung wäre, diese beiden Klassengruppen zusammenzuführen oder möglicherweise die Modellklassen Unterklassen der Entitätsklassen zu sein. Vermisse ich hier etwas Wichtiges? Ist dies ein allgemeines Designmuster, das mir nicht bekannt ist? Gibt es gute Gründe, den Refactor, über den ich nachdenke, nicht durchzugehen?
AKTUALISIEREN
Einige der Antworten hier lassen mich erkennen, dass meiner anfänglichen Beschreibung des Projekts einige wichtige Details fehlten. Es gibt auch eine dritte Gruppe von Klassen im Projekt: die Seitenmodellklassen. Sie werden tatsächlich als Modell für die Seite verwendet. Sie enthalten auch Informationen, die für die Benutzeroberfläche spezifisch sind und nicht mit einer Bestellung in der Datenbank gespeichert werden. Eine beispielhafte Seitenmodellklasse könnte sein:
public class EditOrderPagelModel
{
public OrderModel Order{get;set;}
public DateTime EarliestDeliveryDate{get;set;}
public DateTime LatestAllowedDeliveryDate{get;set;}
}
Ich sehe den Nutzen dieser dritten Gruppe hier völlig anders und habe nicht vor, sie mit etwas anderem zusammenzuführen (obwohl ich sie vielleicht umbenennen könnte).
Die Klassen in der Modellgruppe werden derzeit auch von der API der Anwendung verwendet. Ich würde mich auch für Eingaben interessieren, ob dies eine gute Idee ist.
Ich sollte auch erwähnen, dass der Kunde, der hier als Zeichenfolge dargestellt wird, das Beispiel vereinfachen sollte, nicht weil es tatsächlich so im System dargestellt wird. Das tatsächliche System hat den Kunden als einen bestimmten Typ im Domänenmodell mit seinen eigenen Eigenschaften
quelle
Antworten:
JA
Während diese wie dasselbe aussehen und dasselbe in der Domäne darstellen, sind sie nicht dieselben (OOP) Objekte.
Einer ist der
Order
durch den Datenspeicher bekannte Teil des Codes. Die andere ist dieOrder
der Benutzeroberfläche bekannte. Es ist zwar ein angenehmer Zufall, dass diese Klassen die gleichen Eigenschaften haben, dies ist jedoch nicht garantiert .Oder betrachten Sie das Prinzip der Einzelverantwortung, um es aus einer anderen Perspektive zu betrachten. Der Hauptmotivator hier ist, dass "eine Klasse einen Grund hat, sich zu ändern". Insbesondere beim Umgang mit allgegenwärtigen Frameworks wie einem ORM- und / oder UI-Framework müssen Ihre Objekte gut isoliert sein, da Änderungen am Framework häufig dazu führen, dass sich Ihre Entitäten ändern.
Indem Sie Ihre Entitäten an beide Frameworks binden , machen Sie es noch schlimmer.
quelle
Der Zweck des Ansichtsmodells besteht darin, die Entkopplung auf zwei Arten bereitzustellen: durch Bereitstellen von Daten in der für die Ansicht erforderlichen Form (unabhängig vom Modell) und (insbesondere in MVVM) durch Zurückschieben eines Teils oder der gesamten Ansichtslogik aus der Ansicht zum Ansichtsmodell.
In einem vollständig normalisierten Modell würde der Kunde im Modell nicht durch eine Zeichenfolge, sondern durch eine ID dargestellt. Wenn das Modell den Namen des Kunden benötigt, sucht es den Namen in der Tabelle "Kunden" unter Verwendung der Kunden-ID in der Tabelle "Bestellungen".
Ein Ansichtsmodell hingegen interessiert sich möglicherweise mehr für
Name
den Kunden, nicht für die ID. Die ID ist nur erforderlich, wenn der Kunde im Modell aktualisiert wird.Darüber hinaus kann und wird das Ansichtsmodell normalerweise eine andere Form annehmen (es sei denn, es handelt sich um reines CRUD ). Ein Rechnungsansichtsmodellobjekt verfügt möglicherweise über Kundennamen, Adressen und Werbebuchungen, das Modell enthält jedoch Kunden und Beschreibungen.
Mit anderen Worten, Rechnungen werden normalerweise nicht so gespeichert, wie sie angezeigt werden.
quelle
In gewisser Hinsicht haben Sie Recht: Beide beziehen sich auf dasselbe Domainobjekt, das aufgerufen wird
order
. Aber Sie liegen insofern falsch, es ist keine echte Vervielfältigung als eine andere Darstellung - die aus unterschiedlichen Zwecken stammt. Wenn Sie Ihre Bestellung beibehalten möchten, möchten Sie z. B. Zugriff auf jede einzelne Spalte. Aber das wollen Sie nicht nach außen lecken. Außerdem ist es nicht das, was Sie wirklich wollen , ganze Entitäten durch den Draht zu schieben . Ich kenne Fälle, in denen eine Sammlung von MBsorders
an den Kunden gesendet wurde, in denen ein paar KB ausreichen würden.Um es kurz zu machen - hier sind die Hauptgründe, warum Sie das tun möchten:
1) Kapselung - Informationen, die Ihre Anwendung verbergen
2) Kleine Modelle sind schnell zu serialisieren und einfach zu übertragen
3) Sie dienen unterschiedlichen Zwecken, obwohl sie sich überlappen, und daher sollten unterschiedliche Objekte vorhanden sein.
4) Manchmal ist es sinnvoll, für verschiedene Abfragen unterschiedliche Wertobjekte zu haben . Ich weiß nicht, wie es in C # ist, aber in Java ist es möglich, ein POJO zu verwenden, um Ergebnisse zu sammeln. Wenn ich eine einzelne benötige, verwende
order
ich die Order -Entity. Wenn ich jedoch nur einige Spalten mit Datenmengen benötige, ist die Verwendung kleinerer Objekte effizienter.quelle
(Haftungsausschluss: Ich habe nur gesehen, dass es auf diese Weise verwendet wird. Ich habe möglicherweise den eigentlichen Zweck falsch verstanden. Behandeln Sie diese Antwort mit Argwohn.)
Hier ist ein weiteres fehlendes Bit: die Konvertierung zwischen
Order
undOrderModel
.Die
Order
Klasse ist an Ihr ORM gebunden, während dieOrderModel
an das Design Ihres Ansichtsmodells gebunden ist.In der Regel werden die beiden Methoden "auf magische Weise" bereitgestellt (manchmal als DI, IoC, MVVM oder noch etwas anderes bezeichnet). Das heißt, anstatt diese beiden Konvertierungsmethoden als Teil von zu implementieren
OrderModel
, gehören sie stattdessen zu einer Klasse, die sich der gegenseitigen Konvertierung dieser Dinge widmet. Diese Klasse wird irgendwie beim Framework registriert, so dass das Framework es leicht nachschlagen kann.Der Grund dafür ist, dass Sie bei jedem Übergang von der
OrderModel
nachOrder
oder umgekehrt wissen, dass einige Daten aus ORM geladen oder in ORM gespeichert wurden.quelle