Frage

Bevor jemand Dupe schreit, fiel es mir schwer, es in einem einfachen Titel zusammenzufassen. Ein anderer Titel könnte "Was ist der Unterschied zwischen einem Domänenmodell und einem MVC -Modell?" oder "Was ist ein Modell?"

Konzeptionell verstehe ich ein Modell als die Daten, die von den Ansichten und dem Controller verwendet werden. Darüber hinaus scheint es viel unterschiedliche Meinungen darüber zu geben, was das Modell ausmacht. Was ist ein Domänenmodell im Vergleich zu einem App -Modell, im Vergleich zu einem Ansichtsmodell, im Vergleich zu einem Dienstmodell usw.

Zum Beispiel wurde mir in einer kürzlich von mir gestellten Frage nach dem Repository -Muster Punkt leer mitgeteilt, dass das Repository Teil des Modells ist. Ich habe jedoch andere Meinungen gelesen, dass das Modell vom Persistenzmodell und der Geschäftslogikschicht getrennt werden sollte. Ist das Repository -Muster nicht, um die konkrete Persistenzmethode aus dem Modell zu entkoppeln? Andere Leute sagen, dass es einen Unterschied zwischen dem Domänenmodell und dem MVC -Modell gibt.

Nehmen wir ein einfaches Beispiel. Der AccountController, der im MVC -Standardprojekt enthalten ist. Ich habe mehrere Meinungen gelesen, die der enthaltene Account -Code von schlechtem Design, verstößt gegen SRP usw. usw. Wenn man ein "ordnungsgemäßes" Mitgliedschaftsmodell für eine MVC -Anwendung entwerfen würde, was wäre das?

Wie würden Sie die ASP.NET -Dienste (Mitgliedsanbieter, Rollenanbieter usw.) aus dem Modell trennen? Oder würdest du überhaupt?

So wie ich es sehe, sollte das Modell "rein" sein, vielleicht mit Validierungslogik. Angenommen, Sie haben eine Geschäftsregel, die besagt, dass jemand per E -Mail gesendet werden muss, wenn ein neues Konto erstellt wird. Das gehört meiner Ansicht nach nicht wirklich in das Modell. Wo hing es also?

Möchte jemand etwas Licht in dieses Problem werfen?

War es hilfreich?

Lösung

Ich habe es getan - und ich sage nicht, dass es richtig oder falsch ist, meine Ansicht und dann ein Modell, das für meine Ansicht gilt. Dieses Modell hat nur das, was für meine Ansicht relevant ist - einschließlich Datenanmerkungen und Validierungsregeln. Der Controller beherbergt nur Logik für den Bau des Modells. Ich habe eine Serviceschicht, die alle Geschäftslogik beherbergt. Meine Controller rufen meine Serviceschicht an. Darüber hinaus ist meine Repository -Ebene.

Meine Domain -Objekte sind separat untergebracht (eigentlich in ihrem eigenen Projekt). Sie haben ihre eigenen Datenanmerkungen und Validierungsregeln. Mein Repository bestätigt die Objekte in meiner Domäne, bevor sie sie in der Datenbank speichert. Da jedes Objekt in meiner Domäne eine Basisklasse erbt, in der die Validierung eingebaut ist, ist mein Repository generisch und validiert alles (und erfordert es von der Basisklasse).

Sie könnten denken, dass zwei Modelssätze die Duplizierung von Code sind und in gewissem Maße. Es gibt jedoch völlig vernünftige Fälle, in denen das Domänenobjekt für die Ansicht nicht geeignet ist.

Ein typisches Beispiel ist bei der Arbeit mit Kreditkarten - ich muss bei der Bearbeitung einer Zahlung ein CVV benötigen, aber ich kann das CVV nicht speichern (es ist eine Geldstrafe von 50.000 US -Dollar, dies zu tun). Ich möchte aber auch, dass Sie Ihre Kreditkarte bearbeiten können - Änderung der Adresse, Namen oder Ablaufdatum. Aber Sie geben mir beim Bearbeiten nicht die Nummer oder den CVV, und ich werde Ihre Kreditkartennummer auf die Seite auf jeden Fall nicht in einen Klartext einfügen. Meine Domain enthält diese Werte, die für das Speichern einer neuen Kreditkarte erforderlich sind, da Sie sie mir geben, aber mein Bearbeitungsmodell enthält nicht einmal die Kartennummer oder CVV.

Ein weiterer Vorteil für so viele Schichten besteht darin, dass Sie bei korrekter Architektur Structuremap oder einen anderen IOC -Container verwenden und Teile ausgetauscht haben, ohne dass Sie Ihre Anwendung nachteilig beeinflussen.

Meiner Meinung nach sollte der Controller -Code nur Code auf die Ansicht sein. Zeigen Sie dies, verbergen Sie das usw. Die Serviceschicht sollte die Geschäftslogik für Ihre App unterbringen. Ich mag es, alles an einem Ort zu haben, damit es einfach ist, eine Geschäftsregel zu ändern oder zu optimieren. Die Repository -Ebene sollte relativ dumm sein - ohne Geschäftslogik und nur Ihre Daten abfragen und Ihre Domänenobjekte zurückgeben. Durch die Trennung der Ansichtsmodelle vom Domänenmodell haben Sie viel mehr Flexibilität, wenn es um benutzerdefinierte Validierungsregeln geht. Dies bedeutet auch, dass Sie nicht jedes Daten in Ihre Ansicht in versteckten Feldern ablegen und sie zwischen Client und Server hin und her schieben oder im Backend wieder aufbauen). In Ihrem Ansichtsmodell wird dann nur die für die Ansicht relevanten Informationen untergebracht - und es kann so angepasst werden

<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) && 
    Model.SomeObject.SomeInt == 3 && ...) { %>

Während sich alles verteilt und überleuchtet erscheint, hat es den Zweck, auf diese Weise architektiert zu werden. Ist es perfekt? nicht wirklich. Aber ich bevorzuge es einigen früheren Designs von Rufnotorien vom Controller und der Geschäftslogik im Controller, des Repositorys und des Modells.

Andere Tipps

Ich habe mich zu oft gefragt, wie genau die MVC -Elemente in eine herkömmliche Webanwendungsstruktur passen, in der Sie Ansichten (Seiten), Controller, Dienste und Datenobjekte (Modell) haben. Wie Sie sagten, gibt es viele Versionen davon.

Ich glaube, die Verwirrung besteht aufgrund der oben genannten, weithin anerkannten Architektur, die das "anämische Domänenmodell" (angeblich) -Aanti-Muster verwendet. Ich werde nicht auf viele Details über das "Anti-Muster" des anämischen Datenmodells eingehen (Sie können mir die Anstrengungen ansehen, um Dinge zu erklären hier (Java-basiert, aber für jede Sprache relevant)). Kurz gesagt, dies bedeutet jedoch, dass unser Modell nur Daten enthält und die Geschäftslogik in Diensten/Managern aufgestellt wird.

Aber nehmen wir an, wir haben Domänengesteuerte Architektur, und unsere Domain -Objekte sind so, wie sie erwartet werden, dass sie sowohl die staatliche als auch die Geschäftslogik haben. Und in dieser domänengesteuerten Perspektive kommen die Dinge zusammen:

  • Die Ansicht ist die Benutzeroberfläche
  • Der Controller versammelt die Eingaben der Benutzeroberfläche, ruft Methoden auf das Modell auf und sendet eine Antwort an die Benutzeroberfläche zurück
  • Das Modell ist unsere Geschäftskomponenten - die Daten hält, aber auch Geschäftslogik.

Ich denke, das beantwortet Ihre Hauptfragen. Die Dinge werden kompliziert, wenn wir weitere Ebenen hinzufügen, wie die Repository -Ebene. Es wird oft vermutet, dass es von der im Modell aufgenommenen Geschäftslogik aufgerufen werden sollte (und daher hat jedes Domänenobjekt einen Hinweis auf ein Repository). In meinem von mir verlinkten Artikel habe ich argumentiert, dass dies nicht ganz eine beste Praxis ist. Und dass es tatsächlich keine schlechte Sache ist, eine Serviceschicht zu haben. Das domänengesteuerte Design schließt übrigens die Serviceschicht nicht aus, aber es soll "dünn" sein und nur Domain-Objekte koordinieren (also keine Geschäftslogik dort).

Für das Paradigma des anämischen Datenmodells, das weit verbreitet ist (für immer oder für schlecht), wäre das Modell sowohl die Serviceschicht als auch Ihre Datenobjekte.

Meiner Meinung nach,

Modell -

Sollte keine Geschäftslogik enthalten, sollte es steckbar sein (WCF -ähnliches Szenario). Es wird verwendet, um an die Anzeige zu binden. Es sollte also Eigenschaften haben.

Geschäftslogik -

Es sollte in "Domain Services Layer" platziert werden, es handelt sich insgesamt separate Ebenen. Außerdem fügt hier eine weitere Ebene "Anwendungsdienste" hinzu.

App Services spricht mit Domain Services Layer, um die Geschäftslogik anzuwenden und dann das Modell zuletzt zurückzugeben.

Daher wird Controller den Anwendungsdienst nach Modell fragen und der Fluss wird wie:

    Controller->Application Services(using domain services)->Model

Das MVC -Muster und das ASP.NET -Framework unterscheiden nicht, was das Modell sein sollte.

Die eigenen Beispiele von MS enthalten Persistenzklassen im Modell. Ihre Frage zur Mitgliedschaft im Modell. Das hängt davon ab. Sind Klassen in Ihrem Modell im Besitz von etwas? Gibt es eine Verbindung zwischen dem, wer sich anmeldet und welche Daten angezeigt werden? Gibt es die Filterung des Datenteils eines Berechtigungssystems, das bearbeitetbar ist? Ist wer zuletzt einen Objektteil Ihrer Domain aktualisiert oder bearbeitet, wie es in jemand anderem es sehen muss oder etwas für die Unterstützung von Backends?

Das E -Mail -Beispiel ist auch es hängt davon ab. Kennen Sie sich insbesondere mit Domain Eventing oder Eventing? Haben Sie einen separaten Service zum Senden von E -Mails? Ist das Gesetz des Sendens eines E -Mail -Teils Ihrer Domain oder ist es ein Antrag auf Bewerbungsebene außerhalb des Rahmens Ihres Systems? Muss die Benutzeroberfläche wissen, ob eine E -Mail erfolgreich gesendet wurde oder nicht? Benötigen E -Mails, die keine Wiederholungen senden? Muss der Inhalt der gesendeten E -Mail für Support- oder Kundendienstanforderungen gespeichert werden?

Diese Arten von Fragen sind übermäßig breit und subjektiv, aber ich beantworte, damit Sie und jeder, der Sie gewählt hat, dies verstehen können.

Ihre Anforderungen/Zeitpläne/Ressourcen entlüften alle in die Architektur Ihres Systems. Sogar die Erlösmodell kann einen Effekt haben. Sie müssen auch das Muster berücksichtigen, für das Sie fotografieren. DDD unterscheidet sich stark von den Anwendungen als Persistenz-As-Model, und der gesamte Slop dazwischen ist auch für bestimmte Apps gültig. Schießen Sie, um die App zu testen? All dies wirkt sich aus.

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