ASP.NET MVC - Sollte Geschäftslogik in Controllern vorhanden sein?

97

Derik Whitaker hat vor ein paar Tagen einen Artikel veröffentlicht , der einen Punkt erreicht hat, auf den ich schon seit einiger Zeit neugierig bin: Sollte Geschäftslogik in Controllern existieren?

Bisher haben alle ASP.NET MVC-Demos, die ich gesehen habe, den Repository-Zugriff und die Geschäftslogik in den Controller integriert. Einige werfen dort sogar eine Validierung hinein. Dies führt zu ziemlich großen, aufgeblähten Controllern. Ist dies wirklich der Weg, um das MVC-Framework zu verwenden? Es scheint, dass dies nur zu einer Menge duplizierten Codes und Logik führen wird, die auf verschiedene Controller verteilt sind.

Kevin Pang
quelle
Der Link zum Artikel ist tot - web.archive.org/web/20150906064521/http://devlicio.us/blogs/… ist eine Kopie von archive.org für alle anderen Interessierten.
Stuart Moore

Antworten:

75

Geschäftslogik sollte wirklich im Modell sein. Sie sollten auf fette Modelle und dünne Controller abzielen.

Zum Beispiel anstatt:

public interface IOrderService{
    int CalculateTotal(Order order);
}

Ich hätte lieber:

public class Order{
    int CalculateTotal(ITaxService service){...}        
}

Dies setzt voraus, dass die Steuer von einem externen Dienst berechnet wird, und erfordert, dass Ihr Modell die Schnittstellen zu Ihren externen Diensten kennt.

Dies würde Ihren Controller ungefähr so ​​aussehen lassen:

public class OrdersController{
    public OrdersController(ITaxService taxService, IOrdersRepository ordersRepository){...}

    public void Show(int id){
        ViewData["OrderTotal"] = ordersRepository.LoadOrder(id).CalculateTotal(taxService);
    }
}

Oder etwas ähnliches.

jonnii
quelle
1
Würden Sie dann Services in Ihre Controller anstatt in Repositorys einfügen? Wie kommt in diesem Fall das Prinzip der Arbeitseinheit ins Spiel?
Kevin Pang
Ich habe noch ein paar Sachen geschrieben, ich hoffe das macht mehr Sinn. Vielleicht möchten Sie auch lesen: weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model Auch wenn es um Rails geht, ist es immer noch sehr anwendbar.
Jonnii
Ich würde ein Repository persönlich als Service bezeichnen.
Brad Wilson
Sie sind definitiv eine Art Service, aber speziell für den Datenzugriff. Es ist nur eine Konvention, die ich benutze, nicht etwas, für das ich mich ausdrücklich einsetze.
Jonnii
1
Dadurch wird Ihr Modell eng mit ITaxService gekoppelt. Wenn Sie das Modell in einem anderen Projekt oder einer anderen DLL wiederverwenden möchten, müssen Sie über eine ITaxService-Implementierung oder -Referenz verfügen. Andernfalls wird Ihr Modell beschädigt, was zu einem Verstoß gegen die SOLID-Prinzipien führt. ITaxService sollte eine Referenz Ihres Modells haben. Auf diese Weise können Sie Ihr Modell in einem anderen Projekt wiederverwenden, ohne dass eine ITaxService-Referenz erforderlich ist.
Mehmet Ali Sert
65

Ich mag das Diagramm von Microsoft Patterns & Practices . Und ich glaube an das Sprichwort "Ein Bild sagt mehr als tausend Worte".

Das Diagramm zeigt die Architektur der MVC- und Business-Service-Schichten

AlejandroR
quelle
6
Das ist wirklich nützlich! Können Sie mir sagen, wo auf dieser Site Sie dieses Diagramm gefunden haben?
Rob Church
2
Dies ist aus Microsofts 'Server-Side Implementation' msdn.microsoft.com/en-us/library/hh404093.aspx
Justin
OK, aber beispielsweise in einer MVC-App - wohin geht die Geschäftslogik? Scheint, wir brauchen eine zusätzliche Serviceschicht oder so?!
Niico
14

Das ist eine faszinierende Frage.

Ich finde es interessant, dass eine große Anzahl von MVC-Beispielanwendungen tatsächlich nicht dem MVC-Paradigma folgt, indem die "Geschäftslogik" wirklich vollständig in das Modell aufgenommen wird. Martin Fowler hat darauf hingewiesen, dass MVC kein Muster im Sinne der Gang Of Four ist. Es ist vielmehr ein Paradigma, dass der Programmierer Muster hinzufügen muss , wenn er etwas jenseits einer Spielzeug-App erstellt.

Die kurze Antwort lautet also, dass "Geschäftslogik" in der Tat nicht in der Steuerung leben sollte, da die Steuerung die zusätzliche Funktion hat, sich mit der Ansicht und den Benutzerinteraktionen zu befassen, und wir Objekte mit nur einem Zweck erstellen möchten.

Eine längere Antwort ist, dass Sie sich Gedanken über das Design Ihrer Modellebene machen müssen, bevor Sie die Logik von Controller zu Modell verschieben. Vielleicht können Sie die gesamte App-Logik mit REST verarbeiten. In diesem Fall sollte das Design des Modells ziemlich klar sein. Wenn nicht, sollten Sie wissen, welchen Ansatz Sie verwenden werden, um zu verhindern, dass Ihr Modell aufgebläht wird.

Joe Seelenbringer
quelle
14

Sie können dieses fantastische Tutorial von Stephen Walther lesen , das die Validierung mit einer Service-Schicht zeigt .

Erfahren Sie, wie Sie Ihre Validierungslogik aus Ihren Controller-Aktionen in eine separate Service-Schicht verschieben. In diesem Tutorial erklärt Stephen Walther, wie Sie eine scharfe Trennung von Bedenken aufrechterhalten können, indem Sie Ihre Service-Schicht von Ihrer Controller-Schicht isolieren.

Leniel Maccaferri
quelle
2
Dies ist die richtigste Antwort. Ich persönlich befürworte ferner, keine Dienste für den Controller verfügbar zu machen und stattdessen ein ViewModel-Konzept zu verwenden, wie es im MVVM-Muster zu finden ist. Stellen Sie sich ein Szenario vor, in dem Sie eine Geschäftsanwendung mit einer Desktop-Oberfläche (z. B. Windows Forms oder WPF) und einer Weboberfläche schreiben möchten. Das Lösen dieses Problems führt Sie zu dem "Skinny Controller" -Muster, wie es auch hier empfohlen wird. Fazit: Fügen Sie niemals Geschäftslogik in ein Modell oder einen Controller ein und fügen Sie nichts in einen Controller ein, den Sie nicht haben.
Sam
9

Business Logic sollte nicht in Controllern enthalten sein. Die Controller sollten so dünn wie möglich sein. Befolgen Sie im Idealfall das Muster:

  1. Domain-Entität suchen
  2. Auf Domain-Entität einwirken
  3. Bereiten Sie Daten für die Anzeige / Rückgabe von Ergebnissen vor

Zusätzlich können Controller eine Anwendungslogik enthalten.

Wo lege ich meine Geschäftslogik ab? Im Modell.

Was ist ein Modell? Das ist eine gute Frage. Weitere Informationen finden Sie im Artikel zu Microsoft Patterns and Practices (ein großes Lob an AlejandroR für eine hervorragende Suche). Hier gibt es drei Kategorien von Modellen:

  • Ansichtsmodell : Dies ist einfach eine Datentasche mit minimaler, wenn überhaupt vorhandener Logik zum Übergeben von Daten von und zu Ansichten, die eine grundlegende Feldvalidierung enthält.
  • Domänenmodell : Das Fat-Modell mit Geschäftslogik arbeitet mit einer einzelnen oder mehreren Datenentitäten (dh Entität A in einem bestimmten Zustand als Aktion auf Entität B).
  • Datenmodell : Speicherbewusstes Modell, Logik, die in einer einzelnen Entität enthalten ist, bezieht sich nur auf diese Entität (dh wenn Feld a, dann Feld b)

Natürlich ist MVC ein Paradigma, das es in verschiedenen Varianten gibt. Was ich hier beschreibe, ist, dass MVC nur die oberste Schicht belegt. Siehe diesen Artikel auf Wikipedia

Heute sind MVC und ähnliche Model-View-Presenter (MVP) Designmuster für die Trennung von Bedenken, die ausschließlich für die Präsentationsschicht eines größeren Systems gelten. In einfachen Szenarien kann MVC das primäre Design eines Systems darstellen und direkt in die Datenbank greifen. In den meisten Szenarien sind Controller und Modell in MVC jedoch lose von einer Dienst- oder Datenschicht / -schicht abhängig. Hier dreht sich alles um die Client-Server-Architektur

Jacek Glen
quelle
-1

Wenn Sie Abhängigkeitsinjektoren verwenden, wird Ihre Geschäftslogik zu ihnen gehen und Sie erhalten daher saubere und saubere Controller.

Chandresh Patel
quelle