Fette Modelle und dünne Controller klingen wie das Erstellen von Gottmodellen [geschlossen]

91

Ich habe viele Blogs gelesen, die sich für den Ansatz von Fat Models und Skinny Controllern einsetzen , insb. das Rails Camp. Infolgedessen finden die Router im Grunde nur heraus, welche Methode auf welchem ​​Controller aufgerufen werden soll, und die Controller-Methode ruft lediglich die entsprechende Methode im Modell auf und ruft dann die Ansicht auf. Ich habe hier zwei Bedenken, die ich nicht verstehe:

  1. Der Controller und der Router erledigen wirklich keine anderen Aufgaben als das Aufrufen einer Methode für das gottähnliche Modell basierend auf der Route.
  2. Models machen zu viel. Senden von E-Mails, Erstellen von Beziehungen, Löschen und Ändern anderer Modelle, Einreihen von Aufgaben usw. Grundsätzlich haben Sie jetzt gottähnliche Objekte, die alles tun sollen, was mit dem Modellieren und Behandeln von Daten zu tun hat oder nicht.

Wo ziehst du die Grenze? Fällt das nicht einfach in das Gottesmuster?

Dschungeljäger
quelle

Antworten:

136

Es ist möglicherweise nicht die beste Idee, Rails als Grundnahrungsmittel für MVC-Designmuster zu betrachten. Dieser Rahmen wurde mit einigen inhärenten Mängeln erstellt (ich habe ihn in einem anderen Beitrag näher ausgeführt ), und die Community hat gerade erst begonnen, sich mit den Folgen zu befassen. Sie könnten die DataMapper2- Entwicklung als ersten großen Schritt betrachten.

Eine Theorie

Menschen, die diesen Rat geben, scheinen von einem weit verbreiteten Missverständnis betroffen zu sein. Lassen Sie mich zunächst klarstellen: Das Modell ist im modernen MVC-Entwurfsmuster KEINE Klasse oder kein Objekt. Modell ist eine Schicht.

Die Kernidee hinter dem MVC-Muster ist die Trennung von Bedenken, und der erste Schritt darin ist die Trennung zwischen Präsentationsschicht und Modellebene. So wie die Präsentationsschicht in Controller (Instanzen, die für die Benutzereingabe verantwortlich sind), Ansichten (Instanzen, die für die Benutzeroberflächenlogik verantwortlich sind) und Vorlagen / Layouts unterteilt ist, ist auch die Modellebene unterteilt.

Die Hauptteile, aus denen die Modellebene besteht, sind:

  • Domänenobjekte

    Auch als Domänenentitäten, Geschäftsobjekte oder Modellobjekte bekannt (letzterer Name gefällt mir nicht, weil er nur zur Verwirrung beiträgt). Diese Strukturen werden normalerweise fälschlicherweise als "Modelle" bezeichnet. Sie sind dafür verantwortlich, Geschäftsregeln zu enthalten (die gesamte Mathematik und Validierung für eine bestimmte Einheit der Domänenlogik).

  • Speicherabstraktionen:

    Wird normalerweise mithilfe eines Data Mapper- Musters implementiert (nicht mit ORMs verwechseln , die diesen Namen missbraucht haben). Diese Instanzen werden normalerweise mit dem Speichern und Abrufen von Informationen in den Domänenobjekten beauftragt. Jedes Domänenobjekt kann mehrere Mapper haben, genau wie es verschiedene Arten von Speicher gibt (DB, Cache, Sitzung, Cookies, / dev / null).

  • Dienstleistungen:

    Strukturen, die für die Anwendungslogik verantwortlich sind (dh Interaktion zwischen Domänenobjekten und Interaktion zwischen Domänenobjekten und Speicherabstraktionen). Sie sollten wie die "Schnittstelle" wirken, über die die Präsentationsschicht mit der Modellebene interagiert. Dies ist normalerweise das, was in Rails-ähnlichem Code in den Controllern landet.

Es gibt auch verschiedene Strukturen in den Räumen zwischen diesen Gruppen: DAOs , Arbeitseinheiten und Repositories .

Oh ... und wenn wir (im Kontext des Webs) über einen Benutzer sprechen , der mit der MVC-Anwendung interagiert, ist dies kein Mensch. Der "Benutzer" ist eigentlich Ihr Webbrowser.

Was ist also mit Gottheiten?

Anstatt mit einem beängstigenden und monolithischen Modell zu arbeiten, sollten Controller mit Diensten interagieren. Sie übergeben Daten von Benutzereingaben an einen bestimmten Dienst (z. B. MailServiceoder RecognitionService). Auf diese Weise ändert der Controller den Status der Modellschicht, dies erfolgt jedoch mithilfe einer klaren API und ohne Probleme mit internen Strukturen (was zu einer undichten Abstraktion führen würde).

Solche Änderungen können entweder eine sofortige Reaktion hervorrufen oder nur die Daten betreffen, die die Ansichtsinstanz von der Modellebene anfordert, oder beides.

Jeder Dienst kann mit einer beliebigen Anzahl (normalerweise nur eine Handvoll) von Domänenobjekt- und Speicherabstraktionen interagieren. Zum Beispiel RecogitionServicekönnte es die Speicherabstraktionen für die Artikel nicht weniger interessieren.

Schlussnotizen

Auf diese Weise erhalten Sie eine Anwendung, die auf jeder Ebene einem Unit-Test unterzogen werden kann, eine geringe Kopplung aufweist (bei korrekter Implementierung) und eine klar verständliche Architektur aufweist.

Beachten Sie jedoch: MVC ist nicht für kleine Anwendungen gedacht. Wenn Sie eine Gästebuchseite mit MVC-Muster schreiben, machen Sie es falsch. Dieses Muster dient zur Durchsetzung von Recht und Ordnung in großen Anwendungen.

Für Personen, die PHP als Primärsprache verwenden, ist dieser Beitrag möglicherweise relevant. Es ist eine etwas längere Beschreibung der Modellebene mit ein paar Codeausschnitten.

tereško
quelle
Sehr nützliche und vollständige Antwort! Kennen Sie ein Buch, das das MVC-Architekturmuster etwas genauer erklärt? Insbesondere bei den Modellen denkt jeder fälschlicherweise: "Das Modell repräsentiert die Daten und tut nichts anderes." und das klingt eher nach der Idee eines Domänenobjekts
thermz
1
@thermz, afaik , es gibt wirklich keine Bücher, die sich ausschließlich mit MVC-Mustern befassen. Normalerweise sage ich den Leuten nur, sie sollen PoEAA lesen und dann graben gehen. Vielleicht könnte diese Liste von Links nützlich sein. Ich finde, wenn die Leute die OOP-Prinzipien und -Konzepte gut verstehen, wird das Muster ziemlich leicht zu verstehen.
Tereško
@ tereško schöne Antwort. Erreicht Hibernate dies? Ich bin nicht überzeugt von den Antworten hier -> stackoverflow.com/questions/1308096/…
Ankan-Zerob
@ Ankan-Zerob Wie Sie vielleicht bemerken, bin ich kein Java-Entwickler, aber nach dem, was ich über den Ruhezustand weiß, bietet es ein vollständiges Toolset für die Persistenzschicht. Sie erhalten einen Teil der dort beschriebenen Informationen, jedoch keine vollständige Modellebene.
Tereško
3
@ Johnny nicht so weit ich weiß. Die meisten der sogenannten "MVC-Frameworks" von PHP sind Variationen von Rails. Und als Teil des Kurses werden die meisten von ihnen mit aktiven, auf Datensätzen basierenden ORM-Lösungen geliefert (diese Dinge sind für DB-Änderungen notorisch anfällig). Sie können so etwas mit SF2.x oder ZF2.x implementieren, aber der Sinn eines Frameworks besteht nicht darin, eine bestimmte Architektur zu implementieren / durchzusetzen, sondern Tools bereitzustellen. Wenn es um MVC geht, wird es durch den Anwendungscode und nicht durch das Framework implementiert .
Tereško
5

Wenn die "Modell" -Klassen schlecht implementiert sind, ist Ihr Anliegen relevant. Eine Modellklasse sollte keine E-Mail (Infrastrukturaufgaben) ausführen.

Die eigentliche Frage ist, was das Modell in MVC bedeutet. Es ist nicht auf POCO-Klassen mit einigen Methoden beschränkt. Modell in MVC bedeutet Daten- und Geschäftslogik. Behandeln Sie es als eine Obermenge klassischer POCO-Kernmodelle.

Ansicht ==== Controller ==== Modell ---> Geschäftsprozessschicht -> Kernmodelle

Wenn Sie Infrastruktur-Assemblys und Datenzugriffsschichten einfügen und diese mithilfe der Injektion in die BPL übergeben, verwendet Ihr Prozess MVC wie vorgesehen.

BPL kann UoW / Respository-Muster aufrufen, Geschäftsregeln ausführen und Infrastrukturfunktionen über injizierte Objekte oder Schnittstellenmuster aufrufen.

Die Empfehlung, einen Controller dünn zu halten, bedeutet also nicht, dass die "Personen" -Klasse in einem klassischen Core-Modell über 50 Methoden verfügen und E-Mail direkt anrufen sollte. Sie haben Recht zu denken, dass dies falsch ist.

Der Controller muss möglicherweise weiterhin Infrastrukturklassen instanziieren und in die BPL oder die Kernschicht einfügen, wenn er direkt aufgerufen wird. Es sollte eine Business-Schicht oder zumindest Klassen geben, die Aufrufe über Classic Object-Modellklassen hinweg orchestrieren. Na das ist sowieso meine "Ansicht" ;-)

Für eine generische Version von MVC die Wiki-Beschreibung http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

Ein kleiner Blog, der über das "M" in MVC spricht. http://www.thedeveloperday.com/skinny-controllers/

Phil Soady
quelle
1
Wenn Sie nicht einverstanden sind, seien Sie zumindest höflich genug, um Ihre Ansicht zu rechtfertigen
phil soady
-1

Ich denke, Sie können zwischen einem einzelnen Fettmodell (möglicherweise App oder Anwendung genannt) und mehreren Fettmodellen unterscheiden, die in logische Gruppen unterteilt sind (Geschäft, Kunde, Bestellung, Nachricht). Letzteres ist die Strukturierung meiner Apps, und jedes Modell entspricht in etwa einer Datenbanktabelle in einer relationalen Datenbank oder einer Sammlung in einer Dokumentendatenbank. Diese Modelle behandeln alle Aspekte des Erstellens, Aktualisierens und Manipulierens der Daten, aus denen das Modell besteht, unabhängig davon, ob es mit der Datenbank kommuniziert oder eine API aufruft. Der Controller ist sehr dünn für wenig mehr verantwortlich, als das entsprechende Modell aufzurufen und eine Vorlage auszuwählen.

Bryan Young
quelle