Geschäftslogik in MVC [geschlossen]


182

Ich habe 2 Fragen:

Q1. Wo genau liegt "Geschäftslogik" im MVC-Muster? Ich bin verwirrt zwischen Model und Controller.

Q2. Ist "Geschäftslogik" dasselbe wie "Geschäftsregeln"? Wenn nicht, was ist der Unterschied?

Es wäre großartig, wenn Sie dies anhand eines kleinen Beispiels erklären könnten.

Antworten:


172

Geschäftsregeln gehen in das Modell ein.

Angenommen, Sie haben E-Mails für eine Mailingliste angezeigt. Der Benutzer klickt auf die Schaltfläche "Löschen" neben einer der E-Mails, der Controller benachrichtigt das Modell, um Eintrag N zu löschen, und benachrichtigt dann die Ansicht, die das Modell geändert hat.

Vielleicht sollte die E-Mail des Administrators niemals von der Liste entfernt werden. Das ist eine Geschäftsregel, dass Wissen in das Modell gehört. Die Ansicht kann letztlich repräsentiert diese Regel irgendwie - vielleicht das Modell eine „IsDeletable“ Eigenschaft aussetzt , die eine Funktion der Geschäftsregel ist, so dass die Löschtaste in der Ansicht für bestimmte Einträge deaktiviert ist - aber die Regel selbst nicht enthalten sind in der Ansicht.

Das Modell ist letztendlich der Gatekeeper für Ihre Daten. Sie sollten in der Lage sein, Ihre Geschäftslogik zu testen, ohne die Benutzeroberfläche zu berühren.


5
Danke für das Beispiel. Können wir den E-Mail-Eintrag des Administrators (der steuert, ob er gelöscht werden kann oder nicht) nicht mit unserem Controller steuern?
hmthur

2
@mud was ist, wenn wir unser Modell in zwei weitere Schichten aufteilen, dh Service-Schicht und Repository ... Service-Schicht ist für die Geschäftslogik verantwortlich und Repository ist für die Datenschicht verantwortlich ...?
Dragon

3
@PeterMatisko "Modelle sollten nur Daten tragen." Sie verstehen nicht, was M in "MVC" bedeutet. V ist reine Präsentation. C ist Klebstoff zwischen Präsentation und Modell. (Tatsächlich werden die "VC" oft zusammen als Präsentationsschicht betrachtet, und beliebte Variationen von MVC wie MVVM - Model View Viewmodel - machen dies noch deutlicher.) Das M ist alles andere : alle Daten und Logik Ihrer Bewerbung. Sie können Daten und Geschäftslogik innerhalb dieser Schicht trennen und den Datenteil dieser Schicht als Ihr "Modell" bezeichnen, aber darauf bezieht sich das "M" in "MVC" nicht.
Schlamm

1
@PeterMatisko "In Laravel werfen die Leute dann alles in die Controller oder Modelle. Schlechte schlechte Architektur." Schlecht wie ? Sei genau. "V" bedeutet "Ansicht". Alles, was keine Ansicht ist, muss in "M" oder "C" stehen. "MVC ist einfach nicht genug, es spricht nicht explizit über Geschäftslogik und wo man es hinstellt " Sicher. "M" ist das Modell Ihrer Anwendung, dh Ihre Daten, die Geschäftslogik und alles andere, was nicht dargestellt wird. "V" und "C" sind Präsentationsschicht, Benutzereingabe und -ausgabe.
Schlamm

2
@Mud Das Problem ist, dass Laravel ein "Modell" nur einen Datenträger nennt. Wenn in Tutorials angegeben wird, dass Laravel MVC verwendet, und Sie dann feststellen, dass 'Model' einen ganz bestimmten Zweck hat, haben Sie keine Ahnung, wo Sie die Geschäftslogik platzieren sollen. Und der einzig vernünftige Ort ist der Controller, der nicht gut ist. Ich denke mir das nicht aus, ich habe nur typische Laravel-Projekte (und Tutorials) kommentiert, die ich oft sehe.
Peter Matisko

189

Faust von allem:
Ich glaube, dass Sie das MVC-Muster und die n-Tier-basierten Designprinzipien verwechseln.

Die Verwendung eines MVC-Ansatzes bedeutet nicht, dass Sie Ihre Anwendung nicht überlagern sollten.
Es kann hilfreich sein, wenn Sie MVC eher als Erweiterung der Präsentationsebene sehen.

Wenn Sie Nicht-Präsentationscode in das MVC-Muster einfügen, kann dies sehr bald zu einem komplizierten Design führen.
Daher würde ich vorschlagen, dass Sie Ihre Geschäftslogik in eine separate Geschäftsschicht einteilen.

Schauen Sie sich das an: Wikipedia-Artikel über mehrschichtige Architektur

Es heißt:

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.

Wie auch immer ... wenn es sich um eine Unternehmenswebanwendung handelt, sollten die Aufrufe von der Benutzeroberfläche an die Geschäftslogikschicht innerhalb des (Präsentations-) Controllers platziert werden.

Dies liegt daran, dass der Controller die Aufrufe einer bestimmten Ressource tatsächlich verarbeitet, die Daten durch Aufrufe der Geschäftslogik abfragt und die Daten (das Modell) mit der entsprechenden Ansicht verknüpft.

Mud hat Ihnen gesagt, dass die Geschäftsregeln in das Modell einfließen.
Das ist auch wahr, aber er hat das (Präsentations-) Modell (das 'M' in MVC) und das Datenschichtmodell eines tierbasierten Anwendungsdesigns verwechselt.
So gilt es Ihre Datenbank bezogenen Geschäft zu platzieren Regeln im Modell (Datenschicht) der Anwendung.
Sie sollten sie jedoch nicht in das Modell Ihrer MVC-strukturierten Präsentationsebene einfügen, da dies nur für eine bestimmte Benutzeroberfläche gilt.

Diese Technik ist unabhängig davon, ob Sie ein domänengesteuertes Design oder einen auf Transaktionsskripten basierenden Ansatz verwenden.

Lassen Sie mich das für Sie visualisieren:


Präsentationsschicht: Modell - Ansicht - Controller


Geschäftsschicht: Domänenlogik - Anwendungslogik


Datenschicht: Datenrepositorys - Datenzugriffsschicht


Das oben gezeigte Modell bedeutet, dass Sie über eine Anwendung verfügen, die MVC, DDD und eine datenbankunabhängige Datenschicht verwendet.
Dies ist ein gängiger Ansatz zum Entwerfen einer größeren Unternehmenswebanwendung.

Sie können es aber auch verkleinern, um eine einfache Nicht-DDD-Geschäftsschicht (eine Geschäftsschicht ohne Domänenlogik) und eine einfache Datenschicht zu verwenden, die direkt in eine bestimmte Datenbank schreibt.
Sie können sogar die gesamte Datenschicht löschen und direkt von der Geschäftsschicht aus auf die Datenbank zugreifen, obwohl ich dies nicht empfehle.

Das ist der Trick ... Ich hoffe das hilft ...

[Hinweis:] Sie sollten sich auch der Tatsache bewusst sein, dass heutzutage mehr als nur ein "Modell" in einer Anwendung vorhanden ist. Im Allgemeinen hat jede Ebene einer Anwendung ein eigenes Modell. Das Modell der Präsentationsebene ist ansichtsspezifisch, jedoch häufig unabhängig von den verwendeten Steuerelementen. Die Geschäftsschicht kann auch ein Modell haben, das als "Domänenmodell" bezeichnet wird. Dies ist normalerweise der Fall, wenn Sie sich für einen domänengesteuerten Ansatz entscheiden. Dieses "Domänenmodell" enthält sowohl Daten als auch Geschäftslogik (die Hauptlogik Ihres Programms) und ist normalerweise unabhängig von der Präsentationsschicht. Die Präsentationsschicht ruft normalerweise die Geschäftsschicht bei einem bestimmten "Ereignis" (Taste gedrückt usw.) auf, um Daten von der Datenschicht zu lesen oder in diese zu schreiben. Die Datenschicht verfügt möglicherweise auch über ein eigenes Modell, das normalerweise datenbankbezogen ist.

Die Frage ist: Wie passt das in das MVC-Konzept?

Antwort -> nicht!
Nun - das tut es irgendwie, aber nicht vollständig.
Dies liegt daran, dass MVC ein Ansatz ist, der Ende der 1970er Jahre für die Programmiersprache Smalltalk-80 entwickelt wurde. Zu dieser Zeit waren GUIs und PCs ziemlich ungewöhnlich und das World Wide Web wurde nicht einmal erfunden! Die meisten heutigen Programmiersprachen und IDEs wurden in den 1990er Jahren entwickelt. Zu dieser Zeit waren Computer und Benutzeroberflächen völlig anders als in den 1970er Jahren.
Sie sollten dies berücksichtigen, wenn Sie über MVC sprechen.
Martin Fowler hat einen sehr guten Artikel über MVC, MVP und die heutigen GUIs geschrieben.


10
+1 für die korrekte Auflistung des Unterschieds zwischen MVC- und N-Tier-App. Die meisten von mir entwickelten Unternehmensanwendungen haben n-Tier und verwenden mvc nur als Präsentationsschicht.
Retired_User

Nehmen wir an, 1) Zeigen Sie Modelle in MVC (Presentation Layer) an. 2) Einige C # -Technologien (Business Layer) für autorisierte Transaktionen, Core Business Rules Logic. 3) Repository und Arbeitseinheit in (Datenzugriffsschicht) Bitte führen Sie einige Technologien (oder Best Practices Patterns) durch, die zum Erstellen der Geschäftsschicht verwendet werden können. Diese sollte die Freiheit bieten, Modell- und Repository-Zugriff vom Controller in der Präsentationsschicht (oben) zuzulassen und verfügbar zu machen Schicht). Grundsätzlich glaube ich, dass Hinzufügen, Löschen, Aktualisieren und deren Kombination als Geschäftslogik unter Transaktionen aufbewahrt werden sollte. Bitte verbreiten Sie etwas zusätzliches Licht darauf.
Mark Macneil Bikeio

Hallo Rahul, wenn ich dich richtig verstehe, dann hast du recht. CRUD-Operationen sind im Wesentlichen atomare Bestandteile von Geschäftstransaktionen. Ich persönlich bevorzuge es, einen leistungsstarken OR-Mapper wie Hibernate als Repository zu verwenden, anstatt meinen eigenen zu erstellen. Dies liegt daran, dass der Ruhezustand das Muster der Arbeitseinheit bereits intern implementiert. Außerdem lege ich normalerweise Geschäftstransaktionen in separate Geschäftsdienste.
Frank

Für das Ansichtsmodell kann ich Ihnen folgendes Beispiel geben: Nur Bild Sie haben eine GUI mit einer Dual-List-Ansicht. Diese Dual-List-Ansicht verwendet ein Dual-List-View-Modell als Datenmodell. Dieses Datenmodell besteht nur aus zwei einfachen Listen. Das Dual-List-View-Modell hängt also von der Implementierung der Präsentationsschicht ab, da es im Gegensatz zu den beiden einfachen Listen, die zum Erstellen des View-Modells verwendet werden, nicht Teil Ihres Domänenmodells ist. Abhängig von der GUI, die Sie erstellen möchten, gibt es mehrere Fälle, in denen Sie möglicherweise ein ansichtsspezifisches Modell an eine Ansicht anstelle Ihres Domänenmodells binden möchten.
Frank

Der Teil mit den Geschäftsregeln / der Logik ist etwas schwierig zu erklären. Um eine Datenverarbeitung zu starten, rufen Sie eine Methode von einem Ihrer Dienste auf. Das heißt, Sie starten grundsätzlich eine Transaktion. Wenn diese Methode die Geschäftslogik enthält, wird sie als "Transaktionsskript" bezeichnet. Das ist normalerweise eine schlechte Sache, da es kaum wiederverwendbar ist. Es wäre besser, wenn diese Methode die Geschäftslogik Ihres Domänenmodells aufruft. Dies bedeutet, dass Ihr Domain-Modell so entworfen werden muss, dass es die Geschäftslogik enthalten kann. Dieser domänengesteuerte Ansatz funktioniert nicht mit einem unvollständigen oder falschen Domänenmodell.
Frank

73

Der Begriff Geschäftslogik ist meiner Meinung nach keine genaue Definition. Evans spricht in seinem Buch Domain Driven Design über zwei Arten von Geschäftslogik:

  • Domänenlogik.
  • Anwendungslogik.

Diese Trennung ist meiner Meinung nach viel klarer. Und mit der Erkenntnis, dass es verschiedene Arten von Geschäftsregeln gibt, kommt auch die Erkenntnis, dass nicht alle notwendigerweise an den gleichen Ort gehen.

Domänenlogik ist eine Logik, die der tatsächlichen Domäne entspricht. Wenn Sie also eine Buchhaltungsanwendung erstellen, sind Domänenregeln Regeln für Konten, Buchungen, Steuern usw. In einem agilen Software-Planungstool sind die Regeln beispielsweise die Berechnung von Veröffentlichungsdaten basierend auf Geschwindigkeit und Story-Punkten im Backlog. etc.

Für beide Anwendungstypen könnte der CSV-Import / Export relevant sein, aber die Regeln für den CSV-Import / Export haben nichts mit der tatsächlichen Domäne zu tun. Diese Art von Logik ist Anwendungslogik.

Die Domänenlogik geht mit Sicherheit in die Modellschicht. Das Modell würde auch der Domänenschicht in DDD entsprechen.

Die Anwendungslogik muss jedoch nicht unbedingt in der Modellebene platziert werden. Dies kann direkt in den Controllern platziert werden, oder Sie können eine separate Anwendungsebene erstellen, in der diese Regeln gehostet werden. Was in diesem Fall am logischsten ist, hängt von der tatsächlichen Anwendung ab.


1
Das ist sehr wahr! Hier gibt es zwei Modelle: Ihr Ansichtsmodell und Ihr Domänenmodell. Ich finde es fast bedauerlich, dass das Layout von MVC-Projekten Anfänger dazu bringt, zu glauben, dass sie ihren Code einfach in das Ansichtsmodell packen sollten.
Jonathan

1
Fand Ihre Antwort akzeptabler und verständlicher. Vielen Dank.
Revo

27

A1 : Business Logic geht zum ModelTeil MVC. Die Rolle von Modelbesteht darin, Daten und Geschäftslogik zu enthalten. ControllerAuf der anderen Seite ist er dafür verantwortlich, Benutzereingaben zu erhalten und zu entscheiden, was zu tun ist.

A2 : A Business Ruleist ein Teil von Business Logic. Sie haben eine has aBeziehung. Business Logichat Business Rules.

Schau es dir an Wikipedia entry for MVC. Gehen Sie zur Übersicht, in der der MVCMusterfluss erwähnt wird.

Schauen Sie sich auch an Wikipedia entry for Business Logic. Es wird erwähnt, dass Business Logicaus Business Rulesund besteht Workflow.


16

Wie einige Antworten gezeigt haben, gibt es meines Erachtens einige Missverständnisse zwischen der mehrschichtigen und der MVC-Architektur.

Bei einer mehrschichtigen Architektur wird Ihre Anwendung in Ebenen / Ebenen unterteilt (z. B. Präsentation, Geschäftslogik, Datenzugriff).

MVC ist ein Architekturstil für die Präsentationsschicht einer Anwendung. Bei nicht trivialen Anwendungen sollte Geschäftslogik / Geschäftsregeln / Datenzugriff nicht direkt in Modellen, Ansichten oder Controllern platziert werden. Dies würde bedeuten, dass Geschäftslogik in Ihre Präsentationsebene eingefügt wird und somit die Wiederverwendung und Wartbarkeit Ihres Codes verringert wird.

Das Modell ist eine sehr vernünftige Wahl, um Geschäftslogik zu platzieren. Ein besserer / wartbarerer Ansatz besteht jedoch darin, Ihre Präsentationsschicht von Ihrer Geschäftslogikschicht zu trennen, eine Geschäftslogikschicht zu erstellen und bei Bedarf einfach die Geschäftslogikschicht aus Ihren Modellen aufzurufen. Die Geschäftslogikschicht ruft wiederum die Datenzugriffsschicht auf.

Ich möchte darauf hinweisen, dass es nicht ungewöhnlich ist, Code zu finden, der Geschäftslogik und Datenzugriff in einer der MVC-Komponenten mischt, insbesondere wenn die Anwendung nicht mit mehreren Ebenen erstellt wurde. In den meisten Unternehmensanwendungen finden Sie jedoch häufig mehrschichtige Architekturen mit einer MVC-Architektur innerhalb der Präsentationsschicht.


2
Beste Antwort in dieser Angelegenheit. Sollte höher gewählt werden. Die schlechteste Antwort wird als akzeptiert markiert.
Peter Matisko

Beste Antwort .. kein Zweifel
Salman

Hängt dies von der Größe der Daten und der Anwendung ab? Für eine kleine App schätze ich, dass die gesamte Logik ohne Verwirrung in Modelle fließen könnte. Wenn ja, wie hoch ist der Größenschwellenwert, um mit der Trennung in eine separate Schicht zu beginnen?
mLstudent33

15

Dies ist eine beantwortete Frage, aber ich gebe meinen "einen Cent":

Geschäftsregeln gehören in das Modell. Das "Modell" besteht immer aus (logisch oder physikalisch getrennt):

  • Präsentationsmodell - eine Reihe von Klassen, die sich gut für die Verwendung in der Ansicht eignen (sie sind auf eine bestimmte Benutzeroberfläche / Präsentation zugeschnitten).
  • Domänenmodell - der UI-unabhängige Teil des Modells und
  • Repository - der speicherbewusste Teil des "Modells".

Geschäftsregeln leben im Domänenmodell, werden in einer für die Präsentation geeigneten Form dem "Präsentations" -Modell ausgesetzt und manchmal in der "Datenschicht" dupliziert (oder auch erzwungen).


5

Es ist nicht sinnvoll, Ihre Geschäftsschicht in das Modell für ein MVC-Projekt aufzunehmen.

Sagen Sie, dass Ihr Chef beschließt, die Präsentationsebene in etwas anderes zu ändern, Sie wären fertig! Die Geschäftsschicht sollte eine separate Baugruppe sein. Ein Modell enthält die Daten, die von der Geschäftsschicht stammen, die zur Anzeige an die Ansicht übergeben wird. Beim Binden beispielsweise bindet das Modell an eine Personenklasse, die sich in der Geschäftsschicht befindet, und ruft PersonBusiness.SavePerson (p) auf. Dabei ist p die Personenklasse. Folgendes mache ich (BusinessError-Klasse fehlt, würde aber auch in den BusinessLayer aufgenommen werden):Geben Sie hier die Bildbeschreibung ein


Würden Sie diese Aussage klarstellen? "Ein Modell enthält die Daten, die von der Geschäftsschicht stammen , die zur Anzeige an die Ansicht übergeben wird."
Anthony Rutledge

2

Q1:

Geschäftslogiken können in zwei Kategorien betrachtet werden:

  1. Domänenlogiken wie Steuerelemente für eine E-Mail-Adresse (Eindeutigkeit, Einschränkungen usw.), Abrufen des Rechnungspreises eines Produkts oder Berechnen des Gesamtpreises des Einkaufswagens anhand seiner Produktobjekte.

  2. Breitere und kompliziertere Workflows, die als Geschäftsprozesse bezeichnet werden, wie die Steuerung des Registrierungsprozesses für den Schüler (der normalerweise mehrere Schritte umfasst und unterschiedliche Prüfungen erfordert und kompliziertere Einschränkungen aufweist).

Die erste Kategorie gehört zum Modell und die zweite gehört zum Controller . Dies liegt daran, dass die Fälle in der zweiten Kategorie eine breite Anwendungslogik sind und das Einfügen in das Modell die Abstraktion des Modells mischen kann (zum Beispiel ist nicht klar, ob wir diese Entscheidungen in die eine oder andere Modellklasse einordnen müssen, da sie zusammenhängen an beide!).

In dieser Antwort finden Sie eine spezifische Unterscheidung zwischen Modell und Controller, in diesem Link sehr genaue Definitionen und auch in diesem Link ein schönes Android-Beispiel.

Der Punkt ist, dass die oben von "Mud" und "Frank" erwähnten Notizen sowohl wahr als auch "Pete" sein können (Geschäftslogik kann je nach Art der Geschäftslogik in ein Modell oder einen Controller eingefügt werden).

Beachten Sie schließlich, dass MVC von Kontext zu Kontext unterschiedlich ist. In Android-Anwendungen werden beispielsweise einige alternative Definitionen vorgeschlagen, die sich von webbasierten unterscheiden (siehe beispielsweise diesen Beitrag ).


Q2:

Die Geschäftslogik ist allgemeiner und (als "Decyclone" oben erwähnt) haben wir die folgende Beziehung zwischen ihnen:

Geschäftsregeln ⊂ Geschäftslogik


0

Warum führen Sie keine Service-Schicht ein? Dann ist Ihr Controller schlank und besser lesbar. Dann sind alle Controller-Funktionen reine Aktionen. Sie können die Geschäftslogik innerhalb der Serviceschicht beliebig zerlegen. Die Wiederverwendbarkeit von Code ist hoch. Keine Auswirkungen auf Modelle und Repositorys.


-5

Modell = Code für CRUD-Datenbankoperationen.

Controller = reagiert auf Benutzeraktionen und übergibt die Benutzeranforderungen zum Abrufen oder Löschen / Aktualisieren von Daten an das Modell, vorbehaltlich der organisationsspezifischen Geschäftsregeln. Diese Geschäftsregeln können in Hilfsklassen implementiert werden oder, wenn sie nicht zu komplex sind, direkt in den Controller-Aktionen. Der Controller fordert die Ansicht schließlich auf, sich selbst zu aktualisieren, um dem Benutzer Feedback in Form einer neuen Anzeige oder einer Meldung wie "aktualisiert, danke" usw. zu geben.

Ansicht = Benutzeroberfläche, die basierend auf einer Abfrage im Modell generiert wird.

Es gibt keine festen Regeln, wohin Geschäftsregeln gehen sollen. In einigen Designs werden sie modelliert, in anderen sind sie im Controller enthalten. Aber ich denke, es ist besser, sie beim Controller zu behalten. Lassen Sie das Modell sich nur um die Datenbankkonnektivität kümmern.


Wenn Sie Geschäftsregeln in den Controller einfügen und viele, viele Aktionen ausführen, werden Sie die Geschäftsregeln viele, viele Male replizieren? Nein. Sie werden es in einer Hilfsmethode oder einer Klasse trennen. Setzen Sie das "Ding" in das Modell ein, wo es hingehört.
G. Stoynev

3
MVC ist kein Anwendungsmuster für CRUD-Datenbankoperationen (obwohl es auf diese Weise verwendet werden kann), daher kann Model kein "Code für CRUD-Datenbankoperationen" sein. Das Modell definiert die Entitäten der Anwendung, einschließlich der Daten und der Geschäftsregeln. Der Controller koordiniert die Interaktion zwischen der Ansicht und dem Modell. Die Ansicht ist die Benutzeroberfläche, die das Modell und die verfügbaren Operationen in den vom Controller bereitgestellten Modellen verfügbar macht.
Jon Davis
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.