MVC-Architektur - Wie viele Controller benötige ich?

54

Ich habe für eine Weile codiert, aber meistens Skripte und einfache Anwendungen. Ich bin in eine neue Rolle gewechselt, in der es darum geht, Web-Apps zu entwickeln und eine ordnungsgemäße MVC-Architektur zu verwenden. Daher versuche ich verzweifelt, das alles sehr schnell zu lernen.

Ich hoffe, diese Frage ähnelt nicht zu sehr " Best Practices for MVC Architecture ", aber während ich ein paar verschiedene Tutorials durcharbeite, habe ich festgestellt, dass einige mehrere Controller für verschiedene Dinge haben.

Wie viele Controller benötigt eine einzelne Web-App?

Mir ist klar, dass dies ohne ein Beispiel schwer zu beantworten ist, daher werde ich eines bereitstellen:

Anwendung:

  1. Benutzer meldet sich an.
  2. Der Benutzer hat drei Möglichkeiten :
    a) Eine Datei hochladen (in einer Mongodb-Datenbank mit Metadaten gespeichert).
    b) Suchen Sie nach einer Datei.
    c) Abmelden.

Meine Frage ist allgemein, aber ich habe das Beispiel gegeben, um jedem zu helfen, der versucht zu antworten.

Jeff
quelle
8
Eine sehr schön gestellte Frage.
Daniel Hollinrake

Antworten:

34

Für Ihr Beispiel würde ich zwei Controller erstellen:

  • Sessions Controller zum An- und Abmelden (Sitzung für REST-ähnliches Layout erstellen und löschen)
  • Files Controller für alle Dateien (Index = Suchen und Erstellen = Hochladen)

Im Allgemeinen gibt Ihnen ein RESTful-Ansatz, bei dem Sie über alles nachdenken, was als Ressource angezeigt, erstellt, bearbeitet und zerstört werden kann, eine gute Vorstellung davon, wie Sie Dinge strukturieren können. Wie Sie meinen Beispielen entnehmen können, halte ich mich nicht an jedes einzelne Verb in REST.

Wahrscheinlich benötigen Sie mehr Controller für weitere Funktionen. Zum Beispiel ein Benutzer-Controller, auf dem Benutzer neue Konten erstellen können. Außerdem benötigen Sie eine Administrationsoberfläche, über die Sie die Ressourcen mit höheren Berechtigungen bearbeiten können. In einem solchen Fall ist es durchaus üblich, dass fast jeder Controller dupliziert wird.

Eine sehr sehr grobe Schätzung, um einen ersten Eindruck zu bekommen, könnte ein Controller für jede Tabelle in Ihrer Datenbank sein, auf die Benutzer zugreifen können. Aber das ist wirklich nur eine sehr grobe Messung.

thorsten müller
quelle
3
Nehmen Sie Ihr Admin-Beispiel: Würde der Admin-Controller den allgemeinen Benutzer erweitern oder würden Sie alle Methoden komplett neu definieren? Zum Beispiel können möglicherweise alle Benutzer hochladen und suchen, aber nur Administratoren können löschen. Würde die Admin-Controller-Klasse nur alle allgemeinen Benutzermethoden erben?
Jeff
4
Dies hängt sehr stark von der tatsächlichen Funktionalität ab. Im Allgemeinen schreibe ich jedoch einfach einen zweiten Controller ohne jegliche Vererbung. Nach dem 'Thin Controller'-Prinzip sollte in einem Controller sowieso nicht viel Code sein. Und der Admin-Controller kann besonders einfach sein. Alle wichtigen Funktionen fließen in das Modell ein. (Wenn z. B. das Löschen eines Benutzers bedeutet, dass alle seine Dateien ebenfalls gelöscht werden sollen, übernimmt das Modell dies. Im Controller ist hierfür keine einzige Zeile vorhanden.)
thorsten müller
6

Das hängt wirklich von der Web-App ab. In Ihrem Beispiel ist wahrscheinlich einer ausreichend. Wenn Sie eine umfassende E-Commerce-App mit Versand, Steuern, Bestandsverwaltung, Staffelpreisen usw. implementieren möchten, möchten Sie vielleicht noch ein paar mehr.

Wenn Ihr Controller an einem oder mehreren Code-Gerüchen leidet (insbesondere an Large Class oder God Object ), wissen Sie, dass Sie wahrscheinlich den Punkt überschritten haben, an dem nur einer ausreicht.

Dan Pichelman
quelle
5

Es hängt wirklich von Ihren Anwendungsanforderungen und der Architektur der Geschäftsmodule ab.

Als allgemeine Faustregel hängt die Anzahl der erforderlichen Controller von einer Reihe von Modulen und Untermodulen in der Web-App ab.

Ergänzend wäre es hilfreich, die Controller in Bereiche zu unterteilen . Das Konzept der Bereiche ist in das ASP.NET MVC-Framework integriert und vereinfacht die Organisation von Controllern, die ein Modul bedienen.

Es gibt eine Reihe von Diskussionen zu diesem Thema:

EL Yusubov
quelle
1
Tolle Referenzen! Ich werde sie mir auf jeden Fall ansehen!
Jeff
Sicher kein Problem.
EL Yusubov
4

Ich mag Apples Arbeitsweise.

Jede Ansicht wird von nur einem Ansichtscontroller gesteuert. ~ Controller-Programmierhandbuch für iOS anzeigen

Die Idee ist, dass Sie in der Lage sein sollten, Ansichten leicht auszutauschen. IMO, indem nur 1 Controllerpro Viewes macht es einfacher, dies zu erreichen. Ich bin mir jedoch sicher, dass Sie einen Controller mit mehreren Ansichten haben und dennoch so gestalten können, dass Sie die Ansichten wechseln können, ohne die Programmlogik zu ändern.

Korey Hinton
quelle
Das ist ein guter Punkt, aber benötigen Sie für jede Ansicht einen Controller sowie zusätzliche, um sich um Dinge wie Benutzer zu kümmern? Ich denke auch, wenn mein Projekt größer wäre, wäre es sinnvoller, mehr Controller zu haben.
Jeff
Models sollten die Benutzer im Auge behalten. So können bei Bedarf mehrere Controller alle dasselbe Modellobjekt verwenden.
Korey Hinton
2
Ein Controller verfügt also über ein Model-Objekt und ein View-Objekt. Der Controller fragt das Modellobjekt nach Informationen (z. B. Benutzerinformationen) und legt die Ansicht entsprechend fest. Das Modell sollte über den größten Teil der Programmlogik verfügen, während der Controller nur über die Logik verfügt, um zwischen der Ansicht und dem Modell hin und her kommunizieren zu können.
Korey Hinton
2
Ein Controller pro Ansicht ist sehr eingeschränkt, da Ihr Controller für verschiedene Zustände des Modells keine unterschiedlichen Ansichtsmodelle anzeigen kann.
EL Yusubov
1
@ElYusubov Ich kann sehen, wo es verwirrend sein könnte. In iOS hat jede Ansicht nur einen Ansichtscontroller und jeder Ansichtscontroller hat nur eine aktive Ansicht (und diese Ansicht kann Unteransichten haben), aber dieser Ansichtscontroller kann auch Verweise auf eine beliebige Anzahl von Ansichten enthalten.
Korey Hinton
2

Ein Beispiel, das mir gefällt, ist der Gedanke an einen Thermostat. Ein Thermostat eignet sich hervorragend zum Anzeigen des MVC-Musters.


Auf einem älteren analogen Thermostat können Sie sich Folgendes vorstellen:

Ansicht - Der Temperaturleser, der die aktuelle Temperatur anzeigt.

Controller - Das Einstellrad, mit dem Sie die Temperatur ändern

Modell - Die Teile im Inneren, die vom Controller aufgerufen werden und eine Temperaturänderung verursachen.


Sie sollten sich immer an Konstruktionen halten, die eine lose Kopplung ermöglichen und Modelle und die zugehörigen Steuerungen auf eine einzige Aufgabe beschränken . Sie sollten so viele Module / Steuerungen verwenden, wie Sie benötigen . Abhängig von der Größe Ihrer Anwendung haben Sie möglicherweise weitaus weniger Ansichten als Modelle und Controller. Dies ist bei großen Anwendungen zu erwarten. Gute objektorientierte Programmierung zeichnet sich durch lose Kopplung, Verkapselung, Vererbung und Polymorphismus aus. Nicht alle Sprachen unterstützen Polymorphismus in gleichem Maße (Funktion, Methode, Operatorüberladung / -überschreibung).

Wenn Sie ein besseres Verständnis für die ordnungsgemäße Verwendung der MVC-Architektur haben möchten, lesen Sie in der GoF-Dokumentation "Design Patterns: Elements of Reusable ... Software" nach, in der C ++ und SmallTalk als Beispielcode verwendet werden. Dieses Buch ist nicht das A und O, aber es ist sicherlich ein Anfang!

Viel Glück!

Charles Addis
quelle
1

Ich gehe davon aus, dass sich Ihr Beispiel zu einem komplexen System entwickeln wird.

Anwendung:

Benutzer meldet sich an:

  • LoginController

Es liegt in seiner alleinigen Verantwortung, die Anmeldungen zu bearbeiten, den Benutzer umzuleiten oder ihn über das Ergebnis zu informieren.

Eine Datei hochladen

  • UploadController

Ich gehe hier davon aus, dass Sie einen beliebigen Dateityp hochladen möchten. Wenn Sie sich zu einem späteren Zeitpunkt für das Hochladen von MP3s und PDFs entscheiden, verfügen Sie über einen UploadController, einen MP3UploadController und einen PDFUploadController.

Suchen Sie nach einer Datei.

  • SearchFileController

Dies würde für eine Grundvoraussetzung ausreichen. Sie können zu einem späteren Zeitpunkt mehrere Suchcontroller haben, je nachdem, wie komplex die Suchlogik wird. Das Letzte, was Sie haben möchten, ist ein einzelner SearchController mit 20 Aktionsmethoden, die verschiedene Suchvorgänge ausführen.

Ausloggen.

-LogoutController .

Man könnte das für einen Overkill halten, aber ich denke nicht, dass es so ist. Ich denke es ist sauber und schön getrennt.

Wenn ich mir diese Projektstruktur ansehen würde, würde ich sofort wissen, was sie macht und wie sie strukturiert ist. Um noch einen Schritt weiter zu gehen, würde ich LoginControllerund LogoutControllerin einen separaten Bereich setzen.

Ich habe so etwas schon einmal entwickelt und es hat sehr gut funktioniert.

CodeART
quelle
Danke für die Eingabe! Hast du einen funktionierenden Code? in ein paar Dingen stecken bleiben.
Jeff
Welche Probleme haben Sie?
CodeART
Ich kann einen Betreff und ein Datum (im Zeichenfolgenformat) hochladen, aber die Datei selbst nicht hochladen (siehe stackoverflow.com/questions/18344614/… ).
Jeff
Ich bin ein .NET-Entwickler. Entschuldigung, ich kann dir nicht helfen.
CodeART
1

Der größte Teil Ihres Codes würde in einer Geschäftsschicht ablaufen, oder? Wenn dies der Fall ist, geben Sie in Ihrem Controller nur Daten an die Ansicht zurück.

Ich bin mir nicht sicher, ob ich ein Fan davon bin, die Controller in Untertypen zu unterteilen. Während Sie die Trennung von Bedenken beibehalten sollten, gehen die Untertypen meiner Meinung nach etwas zu weit. Sie müssen auch vorsichtig sein, wenn schwere Objekte im Konstruktor oder einer Steuerung initialisiert werden. Beispiel: In Ihrem Beispiel möchten Sie, dass ein schweres Objekt, das nur zum Suchen / Hochladen von Dateien verwendet wird, freigegeben wird, wenn sich der Benutzer auf der Anmeldeseite befindet.

Es ist besser, einen Controller pro Logikeinheit zu haben, zum Beispiel AccountController (Anmelden, Registrieren, Abmelden), FileController (Suchen, Hochladen) und so weiter.

Harsha
quelle
0

Im Allgemeinen kann man sagen, dass jedes MODELL seine eigenen CONTROLLER und dedizierten VIEWs hat. Mit "allgemein" meine ich, dass dies die beste Vorgehensweise ist.

Anwendungsaspekte (wie die Benutzerverwaltung) sollten in den Anwendungsdienst übersetzt werden und vom Controller selbst aufgerufen werden oder Ihren Controller umschließen (z. B. mithilfe von Attributen, die die Controller-Funktionalität entsprechend der Benutzerrolle der Anforderung "sichtbar" machen).

Denken Sie daran, dass alle Controller grundsätzlich CRUD-Operationen über das Modell hinweg ausführen und unterschiedliche Ansichten für unterschiedliche Filter verwenden sollten.

Meiner Meinung nach ist einer der Hauptvorteile von MVC als Muster, dass es die beste Möglichkeit bietet, Modelle und Ansichten zu verknüpfen.

Zu dem von Ihnen hinzugefügten Beispiel: Ich würde zwei Controller erstellen: einen für die Anmeldung aller Benutzer (Registrieren, Anmelden, Abmelden usw.) und einen für Dateioperationen (Hochladen und Suchen). Beachten Sie, dass der erste auch mit Aspekten der Anmeldefunktionalität gesichert werden sollte und der zweite ein gewöhnlicher Controller ist

Saturn Technologies
quelle
Ohne eine Erklärung kann diese Antwort für den Fall unbrauchbar werden, dass jemand anders eine gegenteilige Meinung äußert. Wenn zum Beispiel jemand eine Behauptung wie "Benutzerrollen verwalten und Autorisierung sollte nicht über dem Controller liegen" postet , wie würde diese Antwort dem Leser helfen, zwei gegensätzliche Meinungen zu ermitteln? Überlegen Sie , ob Sie es in eine bessere Form bringen
möchten
1
@gnat Ich akzeptiere Ihren Kommentar, siehe bearbeitete Antwort
Saturn Technologies