Ich habe eine App, die MVC verwendet, aber ich habe ein wenig Probleme damit, wie der Controller aufgebaut sein soll. In der Ansicht werden beispielsweise nur einige Teilmengen der Modelldaten gleichzeitig angezeigt. Ich bin mir jedoch nicht sicher, wie genau das geregelt werden soll. Ist es normal, dass die Ansicht oder das Modell zum Beispiel Funktionen auf dem Controller direkt aufruft? Über irgendeine Schnittstelle? Oder sind sie vollständig gekapselt und kennen sich nie mit dem Controller aus?
Nur als Bearbeitung; Dies ist eine benutzerdefinierte App, die nicht in einem Webframework geschrieben ist. Daher suche ich hier nicht nach Framework-spezifischen Details und habe die Freiheit, meine eigene Wahl zu treffen.
Antworten:
Die Steuerung steuert den Aktivitätsfluss. Der Benutzer führt diese Aktion aus, der Controller übergibt die Anzeigedaten an die Domäne, die alles Erforderliche tut. Anschließend teilt der Controller dem Framework anhand der Antwort (en) mit, welche Ansicht als Nächstes angezeigt werden soll (und gibt ihm genügend Daten zur Verfügung so).
Der Controller muss also zum Teil an das Domain-Modell gekoppelt sein. dh Sie könnten eine Service-Schicht dazwischen legen, die jedoch per strenger Definition Teil der Domäne wird.
Es ist auch mit den Ansichtsdaten gekoppelt, jedoch nicht mit der Ansicht selbst. dh Es heißt einfach "Kundenansicht mit diesem Kundendetail anzeigen". Das Framework entscheidet dann, wo es diese Ansicht finden soll.
Jetzt sollte es Ihnen möglich sein, das Domänenmodell von der Ansicht zu entkoppeln, indem Sie ein Ansichtsmodell mit denselben Daten verwenden. Einige Entwickler tun dies, andere nicht, und ich denke, es ist größtenteils eine Frage der persönlichen Präferenz.
In Rails werden Sie sehr ermutigt, die Domänenobjekte (ActiveRecord) in die Ansicht zu verschieben und darauf zu vertrauen, dass die Ansicht diesen Zugriff nicht nutzt (z. B. sollten Sie customer.save nicht aus der Ansicht heraus aufrufen, obwohl dies der Fall ist wäre verfügbar).
In der .NET-Welt neigen wir dazu, das Risiko zu verringern, indem wir Dinge, die nicht passieren sollten, nicht zulassen. Aus diesem Grund scheint mir das Modell der getrennten Ansicht populärer zu sein.
quelle
Anmerkung: Robert C. Martin (auch bekannt als Onkel Bob) erklärt dies in seiner Keynote „ Architecture the Lost Years“ auf eine viel bessere und humorvollere Weise . Ein bisschen lang, bringt aber viele gute Konzepte bei.
tl; dr: Denken und planen Sie Ihre App nicht in Bezug auf MVC. Das MVC-Framework ist nur ein Implementierungsdetail.
Das verwirrendste an MVC ist, dass die Entwickler versuchen, alle zusammengeklebten Komponenten zu verwenden.
Versuchen Sie, in den Begriffen eines Programms zu denken, nicht in den Begriffen des Frameworks.
Ihr Programm hat einen Zweck. Es nimmt einige Daten auf, erledigt Dinge mit Daten und gibt einige Daten zurück.
Auf diese Weise ist das
controller
der Lieferungsmechanismus Ihres Programms.$user->addToCart($product)
addToCart
Funktion desuser
Objekts) erledigt die beabsichtigte Arbeit und gibt eine Antwort zurück (sagen wir malsuccess
)view
: z. im Controller-Objekt$this->render($cartView('success')
Auf diese Weise werden die Steuerungen vom Programm entkoppelt und als Liefermechanismus verwendet. Sie wissen nicht, wie Ihr Programm funktioniert, sondern nur, welcher Teil des Programms für die Anforderungen aufgerufen werden muss.
Wenn Sie ein anderes Framework verwenden möchten, muss Ihre App nicht geändert werden. Sie müssen lediglich relevante Controller schreiben, um Ihr Programm für Anforderungen aufzurufen.
Wenn Sie eine Desktop-Version erstellen möchten, bleibt Ihre App unverändert. Sie müssen lediglich einen Übermittlungsmechanismus vorbereiten.
Und die
Model
. Stellen Sie es sich als einen Persistenzmechanismus vor.Auf die OO-Weise gibt es Objekte in Ihrem Programm, die die Daten enthalten.
Wenn Sie einen Artikel in den Warenkorb zu legen, können Sie das addieren ,
product::id
um dieuser::shoppingCart
.Wenn Sie die Daten beibehalten möchten, können Sie den
model
Teil des Frameworks verwenden, der im Allgemeinen aus einem ORM besteht, um die Klassen den Datenbanktabellen zuzuordnen.Wenn Sie den von Ihnen verwendeten ORM ändern möchten, bleibt Ihr Programm unverändert, nur die Zuordnungsinformationen ändern sich. Wenn Sie die Datenbanken alle zusammen vermeiden möchten, können Sie die Daten einfach in Nur-Text-Dateien schreiben, und Ihre App bleibt unverändert.
Schreiben Sie also zuerst Ihr Programm. Wenn Sie mit der 'OO'-Methode programmieren, verwenden Sie einfache alte Objekte der Sprache. Denken Sie zunächst nicht an MVC.
quelle
MVC
ist. Deshalb habe ich geschriebenMVC Framework
.Martin Fowler beschreibt das MVC-Paradigma sehr gut. Hier ist ein Link zu seinem Artikel darüber http://martinfowler.com/eaaDev/uiArchs.html
Beachten Sie sein Zitat zu Separated Presentation "Die Idee hinter Separated Presentation ist eine klare Trennung zwischen Domänenobjekten, die unsere Wahrnehmung der realen Welt modellieren, und Präsentationsobjekten, die die GUI-Elemente darstellen, die wir auf dem Bildschirm sehen."
quelle
Hier ist ein einfaches Beispiel, wie MVC in einer typischen Java-Swing-Anwendung verwendet werden kann ...
Angenommen, Sie haben ein Bedienfeld mit einer Schaltfläche und einem Textfeld. Wenn die Taste gedrückt wird, wird ein Ereignis ausgelöst, das zu einer Statusänderung in der Anwendung führt. Sobald die Statusänderung registriert ist, wird das TextField deaktiviert.
Dies wäre dann der typische Ansatz einer einfachen MVC-Anwendung ...
Der Controller registriert sich als Listener der View-Ereignisse. Wenn Sie auf die Schaltfläche klicken, wird das Ereignis von der Ansicht selbst nicht verarbeitet. der Controller tut. Der Controller ist Swing-spezifisch, da er Swing-bezogene Ereignisse verarbeiten muss.
Der Controller erhält diese Benachrichtigung und muss entscheiden, wer damit umgehen muss (Die Ansicht oder das Modell). Da dieses Ereignis den Status der Anwendung ändert, werden die Informationen an das Modell weitergeleitet, das für die Daten- und Programmlogik verantwortlich ist. Einige machen den Fehler, Programmlogik in der Steuerung zu platzieren, aber in OOP repräsentieren Modelle sowohl Daten als auch Verhalten. Lesen Sie dazu Martin Fowler.
Die Nachricht wird vom Modell im richtigen Kontext empfangen. Das heißt, es gibt keinerlei Verweise auf Swing oder andere GUI-spezifische Verweise. Diese Nachricht spricht das Modell und NUR das Modell an. Wenn Sie feststellen, dass Sie javax.swing-Anweisungen in das Modell importieren, codieren Sie das Modell nicht richtig.
Das Modell setzt dann seinen Status auf "deaktiviert" und benachrichtigt alle interessierten Parteien über diese Modelländerung. Die Ansicht, die an dieser Veranstaltung interessiert ist, hat sich bereits als Beobachter für Modelländerungen registriert. Sobald das Model-Statusänderungsereignis von der Ansicht erfasst wurde, wird das TextField deaktiviert. Es ist auch zulässig, dass die Ansicht schreibgeschützte Informationen direkt von ihrem Modell abruft, ohne dass der Controller (in der Regel über eine bestimmte Schnittstelle, die vom Modell für solche Aktivitäten verfügbar gemacht wird) darauf zugreifen muss.
Wenn Sie eine solche lose Kopplung zwischen der Präsentations- und der Geschäftslogik- und der Datenebene fördern, können Sie Ihren Code viel besser verwalten. Wenn die Systeme wachsen, wächst auch Ihre Einstellung zu MVC. Beispielsweise ist Hierarchical MVC eine Erweiterung, die häufig verwendet wird, um MVC-Triaden zu großen unternehmensweiten Systemen zu verbinden, ohne Subsysteme miteinander zu koppeln
quelle
Die Kopplung (die Art, die Sie vermeiden möchten) beinhaltet eine gegenseitige Abhängigkeit zwischen zwei Klassen. Das heißt, ein Foo hängt von einem Balken ab, und ein Balken hängt von einem Foo ab, sodass Sie einen nicht wirklich ändern können, ohne den anderen zu ändern. Das ist eine schlechte Sache.
Sie können es jedoch nicht wirklich vermeiden, einige Abhängigkeiten zu haben. Die Klassen müssen ein wenig voneinander wissen, sonst würden sie nie kommunizieren.
Im MVC-Muster steuert der Controller die Kommunikation zwischen dem Domänenmodell und der Präsentationsansicht. Als solches muss der Controller genug über das Modell wissen, um es aufzufordern, das zu tun, was es tun soll. Der Controller muss auch genug über die Ansicht wissen, um sie dem Client oder den Benutzern präsentieren zu können. Der
ModelController hat also Abhängigkeiten von beiden. Die Ansicht kann jedoch auch ohne den Controller existieren - es besteht keine Abhängigkeit. Ebenso hat das Modell keine Abhängigkeiten zum Controller - es ist einfach das, was es ist. Schließlich sind das Modell und die Ansicht vollständig voneinander getrennt.Im Wesentlichen ist der Controller die Indirektionsebene, die die Ansicht vom Modell entkoppelt, sodass sie sich nicht gegenseitig kennen müssen.
quelle
Nach meiner Erfahrung hängt das Modell im Allgemeinen nur von einer Ansicht ab, nicht von einer bestimmten, oft als Beobachter ... wenn es überhaupt eine solche Kopplung aufweist.
Die Ansicht ist in der Regel mit dem verbunden, was gerade angezeigt wird, was Sinn macht. Es ist schwer, eine Ansicht zu finden, die von der Ansicht abgekoppelt werden kann ... aber manchmal kann es zu einer partiellen Kopplung kommen.
Der Controller neigt häufig dazu, mit beiden zu koppeln. Dies ist auch sinnvoll, da es die Aufgabe ist, Ansichtsereignisse in Modelländerungen umzuwandeln.
Natürlich ist dies nur eine Tendenz, die ich beobachtet habe und zu keinem konkreten Beispiel wirklich etwas aussagt.
Um zu verstehen, was MVC ist und wie die Kopplungsbeziehung aussehen könnte, sollten Sie untersuchen, wie MVC entstanden ist. In der Umgebung, in der MVC erstellt wurde, gab es keine "Widgets" als Formularelemente, mit denen Sie Dialoge erstellen können. Eine "Ansicht" war eine Schachtel und es zeichnete Sachen. Eine Textansicht wäre ein Feld, das Text zeichnet. Eine Listenansicht war eine Box, die eine Liste zeichnen würde. Der "Controller" hat alle Maus- und Tastaturereignisse vom UI-System empfangen, die in dieser Ansicht stattgefunden haben. Es gab keine "textChanged" - oder "selectionChanged" -Ereignisse. Der Controller würde all diese Low-Level-Ereignisse aufnehmen und eine Interaktion mit dem Modell erzeugen. Das Modell würde, wenn es geändert wird, seine Ansichten mitteilen; wir sind seitdem gekommen, um diese Beziehung als "Beobachter" zu sehen und es '
DAS ist die Essenz des MVC-Musters. Da diese Art der UI-Programmierung auf niedriger Ebene im Allgemeinen nicht mehr durchgeführt wird, hat sich die MVC in viele verschiedene Richtungen entwickelt. Manche Dinge, die heute so heißen, sind kaum etwas wie die MVC und sollten eigentlich etwas anderes heißen. Es kann dennoch im Sinne eines Dialogs als Ganzes verwendet werden, der mit einem größeren Objekt interagiert. Es gibt jedoch viele bessere Alternativen.
Grundsätzlich geschieht alles, was die MVC lösen sollte, jetzt in Widgets und wir müssen es nicht mehr verwenden.
Für diejenigen, die glauben, es besser zu wissen:
http://www.codeproject.com/Articles/42830/Model-View-Controller-Model-View-Presenter-and-Mod
http://msdn.microsoft.com/en-us/library/ff649643.aspx
Ich bin mir sicher, dass es noch mehr gibt, aber diese stehen bei Google nur ganz oben auf der Liste. Wie Sie sehen, hängt das Modell in vielen Implementierungen stark von einer Ansichtsschnittstelle ab. Im Allgemeinen ist ein Modell beobachtbar und die Ansicht ist ein Beobachter.
Aber warum sollten Fakten im Weg stehen ...
Ein Artikel, der bereits in einer anderen Antwort veröffentlicht wurde, unterstützt auch meine Aussagen:
http://martinfowler.com/eaaDev/uiArchs.html
Wenn die Leute weiterhin sagen wollen, dass JEDER in der Designbranche Unrecht hat, dann ist das in Ordnung.
quelle
Wenn der Controller eng mit einer Ansicht verbunden war, befinden wir uns in einer Welt von Webformularen. Sie verfügen über einen Code, der an eine Vorlagendatei gebunden ist (gilt für ASP.NET-Webformulare).
Aus diesem Grund ist der Controller nicht an ein Modell oder eine Ansicht gekoppelt. Es ist nur ein Mechanismus zum Verarbeiten von Anfragen und zum Senden von Antworten.
Die Ansicht ist eng an ein Modell gekoppelt. Wenn Sie Änderungen an Ihrem Modell vornehmen (z. B. die Eigenschaft ändern), müssen Sie Änderungen an Ihrer Ansicht vornehmen.
Das Modell ist nicht eng mit einer Ansicht verbunden. Wenn Sie Änderungen an einer Ansicht vornehmen, hat dies keine Auswirkungen auf ein Modell.
Das Modell weiß nichts über Controller oder Ansichten, in denen es verwendet werden kann. Daher ist das Modell nicht eng an eine Ansicht oder einen Controller gekoppelt.
Eine andere Art, darüber nachzudenken:
Nehmen Sie Änderungen an einem Controller vor - Ansicht und Modell bleiben davon unberührt
Vornehmen von Änderungen an einem Modell - Die Ansicht wird unterbrochen, da sie von einem Modell abhängt
Nehmen Sie Änderungen an einer Ansicht vor - Modell und Controller bleiben davon unberührt
Diese lose Kopplung in MVC-Projekten erleichtert den Komponententest.
quelle