Sollte eine Ansicht und ein Modell kommunizieren oder nicht?
33
Gemäß der Wikipedia-Seite für die MVC-Architektur kann die Ansicht vom Modell benachrichtigt werden und es kann auch der aktuelle Status des Modells abgefragt werden. Gemäß Paul Hegartys Kurs zu iOS 5 in Stanford, Vorlesung 1, Seite 18 muss jedoch jede Interaktion über den Controller erfolgen, wobei sich Model und View niemals kennen sollten. Es ist mir nicht klar, ob Hegartys Aussage als Vereinfachung des Kurses gedacht sein muss, aber ich bin versucht zu sagen, dass er das Design als solches beabsichtigt.
Wie erklären Sie diese beiden gegensätzlichen Sichtweisen?
Dies ist ein kontroverses Thema in MVC / MVVM. Einige sagen, es ist in Ordnung, dass die Ansicht direkt auf die Modelle zugreift, andere sagen, Sie sollten die Modelle in ViewModels einschließen, um sie aus der Ansicht zu entfernen. Ich persönlich bin kein Fan von beiden Ansätzen.
Eines der Hauptziele von MVC / MVVM ist die Entkopplung von Benutzeroberfläche, Geschäftslogik und Daten. Unter Berücksichtigung dieses Konzepts entsteht eine Abhängigkeit, die Sie möglicherweise nicht haben möchten, wenn Sie der Ansicht den direkten Zugriff auf die Modelle ermöglichen. Andererseits ist das Umschließen der Modelle in ViewModels oft mühsam und nicht sehr nützlich, da die ViewModels in der Regel nur als Durchgang zu den Modellen fungieren.
Mir gefällt der Ansatz, dass Ihre Models eine bestimmte Schnittstelle implementieren. Nennen wir sie IModel. Ihre ViewModel-Klasse kann dann Instanzen von Objekten anbieten, die IModel for View-Verbrauch implementieren. Die Ansicht weiß einfach, dass sie mit IModel-Objekten funktioniert, die sie vom ViewModel erhält. Dadurch wird der irrelevante ViewModel-Wrappercode entfernt und die konkrete Implementierung von IModel wird aus der Ansicht ausgeblendet. Sie können später eine Implementierung von IModel gegen eine andere austauschen, ohne die Ansicht zu beeinträchtigen.
In Bezug auf die langwierigen Aspekte der Zuordnung eines Modells zu einem Ansichtsmodell sollte beachtet werden, dass Tools zur Verfügung stehen, die den Mapping-Schmerz lindern können. EG: (.NET AutoMapper) (Java Modelmapper)
Jesse
+1 Tolle Antwort! Dies ist ein großartiger Ansatz, der von der Komplexität Ihres Modells abhängt . Die meisten heutigen Modelle sind jedoch vom anämischen Typ. Da es sich bei den Elementen des Modells kaum um mehr als verhaltenslose Datenobjekte handelt, sehe ich wenig oder gar keine Notwendigkeit für eine solche Abstraktion und eine geringe Gefahr darin, dass Ihre Ansicht direkt auf Ihr Modell zugreifen kann.
maple_shaft
2
Ich höre, was du sagst. Die meisten IModel-Schnittstellen enthalten lediglich eine Reihe von Eigenschaftsdeklarationen und einige (wenn überhaupt) Methodendeklarationen. Aber auch wenn die Modelle anämisch sind, entkoppelt die Benutzeroberfläche die Ansicht von ihrer konkreten Implementierung. Diese Trennung ist möglicherweise nicht für jedes Projekt erforderlich, aber es ist immer eine gute Idee, Ihre Optionen offen zu halten.
Raymond Saltrelli
1
Ich bin verwirrt, wenn Sie eine Reihe völlig unterschiedlicher Ansichten haben, wie können Sie sich dann auf eine Benutzeroberfläche verlassen, ohne sie zu überladen? Ich denke, View Models sind fantastisch. Sie erstellen Models, die generisch genug sind, um in Ihrer Anwendung verwendet zu werden, und Sie erstellen View Models, um ein oder mehrere Models zu konsumieren und zusätzlich Operationen zu implementieren, die nur von dieser View verwendet werden.
The Muffin Man
12
Im Web nennt jeder seine Entkopplungs-MVC.
Einige Technologien, wie z. B. C #, verwenden MVVM, da keine Verknüpfung zwischen der Ansicht und einer anderen besteht. Alles läuft über den Service Locator und bindet die Variablen.
Bei reiner MVC kommuniziert die Ansicht direkt mit dem Modell und umgekehrt. Der Controller ist nur dort, wenn Änderungen auftreten.
Und dann gibt es noch die PAC (Presentation Abstraction Control). In dieser Architektur sprechen die Ansicht und das Modell nicht miteinander. Der Controller ist der einzige, der irgendetwas mit der Ansicht oder dem Modell machen darf. Leute verwechseln dies oft mit MVC.
Das grundlegende Ziel einer Architektur ist für mich, zukünftige Umgestaltungsversuche nicht zu behindern. Normalerweise sind Ansichten, die direkt mit Modellen interagieren, von dieser Anforderung betroffen, und es ist relativ klar, wenn dies nicht der Fall ist.
Wenn eine Ansicht mit einem Modell zu intim wird, kann ein ViewModel eine schöne Sache sein, aber für mich ist es normalerweise so, dass die Fälle, in denen dies erforderlich ist, in der Minderheit liegen.
In MVC ist Paul Hegarty falsch. Bei Controller geht es um Benutzerereignisse, nicht um Kommunikation zum Anzeigen des Modells. In der klassischen MVC beobachten die Ansichten das Modell (Beobachtermuster).
Wenn der Typ zwischendurch die Mediation durchführt, sollte das Muster MVP heißen , und tatsächlich ist das meiste, was heutzutage als MVC dargestellt wird, tatsächlich näher an MVP.
Dann gibt es MVVM, das etwas ähnlich und doch etwas anders ist und schon lange existiert hat. Am besten ist es, es als zwei MVCs / MVPs anzusehen, die durch ein viewmodel-Objekt miteinander verbunden sind - der "Client" MVC hat viewmodel als sein Modell und der "Server" MVC hat das Ansichtsmodell als seine Ansicht.
Heute (Anfang 2014) erscheint mir (mit meinem Knoten und meinem Angular Stack) diese Unterscheidung zwischen "Client" -MVC und "Server" -MVC sehr relevant und irgendwie aufschlussreich. (danke)
Slacktracer
4
Da Sie insbesondere in diesen Stanford-Vorlesungen nach dem Material fragen, sollten Sie zwei Aspekte in Bezug auf Hegartys Haltung berücksichtigen:
Wie Sie bereits erwähnt haben, unterrichtet er einen 100-Level-Computer Sci-Kurs. In seinen Vorlesungen gibt es viele Stellen, an denen er vereinfacht, Details beschönigt oder "mach es einfach so" sagt, wie man es beim Unterrichten der Grundlagen wahrscheinlich tun muss, dh man muss die Regeln beherrschen, bevor man sie brechen kann.
Ich habe mit dem iOS-SDK die Erfahrung gemacht, dass es, wenn es keine strikte Trennung zwischen Ansicht und Modell erzwingt , stark auf dieses Muster ausgerichtet ist. Insbesondere beim Schreiben von iOS-Apps können Sie Code schreiben, der den Erwartungen des Frameworks entspricht. Ich würde zögern, Hegartys Aussagen auf die Entwicklung auf anderen Plattformen oder allgemein zu verallgemeinern.
Ich stimme Paul Hegarty zu und glaube, dass die Ansicht nichts über das Modell wissen darf. Es ist nicht so schwer zu erreichen, bringt aber zusätzliche Vorteile für Ihr Design und Ihre zukünftige Flexibilität.
In kleinen Anwendungen (normalerweise Desktop), in denen ich "Dummy" -ViewModel-Klassen vermeiden und die Dinge einfach halten möchte, verwende ich auch die IModel-Schnittstelle (siehe Antwort oben) und achte darauf, dass Model keine Ahnung von der Ansicht hat (verwende Abonnenten) wie im klassischen MVC).
Auch in diesem Fall ist der Controller so eingestellt, dass er gut mit der Ansicht gekoppelt ist, und der Einfachheit halber trenne ich sie nicht immer klar voneinander ab.
Der zweite vereinfachte Ansatz ist in Ordnung, wenn Sie möglicherweise mehrere Ansichten für dasselbe Modell haben. Ich würde ihn jedoch nicht empfehlen, wenn Sie dieselbe Ansicht für verschiedene Modelle verwenden möchten. Unter "anders" verstehe ich "von Natur aus anders" und nicht nur JUnit-Testklassen, die dem Hauptmodell "folgen".
Ich glaube, dass es keine feste Regel dafür gibt, es hängt völlig von Ihren Bedürfnissen ab.
Sie werden Menschen mit unterschiedlichen Überzeugungen finden. Architekturen sind Konzepte zum Entwerfen besserer Lösungen.
Abgesehen von der Kommunikation über die Modellsicht gibt es einen weiteren Widerspruch zur Geschäftslogik in MVC. Viele Leute glauben, dass die gesamte Geschäftslogik ein Modell sein sollte (siehe diese SO-Frage ), andererseits besagt die von Florian (in seiner Antwort) geteilte Verknüpfung, dass die Geschäftslogik auf dem Controller sein sollte.
Außerdem besteht die Möglichkeit, die Geschäftslogik in Anwendungslogik (Controller) und Domänenanmeldung (Modell) zu unterteilen.
Die Moral der Geschichte ist also, dass MVC bedeutet, dass Modell, Ansicht und Steuerung getrennt sein sollten. Davon abgesehen, was auch immer am besten zu Ihnen passt.
Benutzer füllt das Aktualisierungsformular aus (Ansicht)
Benutzer sendet Formular
Controller bindet Formulardaten an UserUpdateDTO
DTO und UserModel sind POJOs, aber DTO hat keine ID und keinen Benutzernamen, da wir den Benutzernamen nicht aktualisieren können.
Ein weiterer Unterschied ist, dass die Modellklasse Relationen und Assoziationen hat, aber DTO nur Daten speichert und wir können JSR 303-Validatoren hinzufügen
Controller sagen es der Serviceebene zu, um zu sparen
Die Service-Schicht fordert die DAO-Schicht auf, die Daten beizubehalten
Ich bin mit dem Lager, das sagt, dass die Ansicht nie mit dem Modell kommunizieren sollte. Der Controller muss immer der Ansprechpartner für alles sein. Er entscheidet dann, was zu tun ist (validieren, Daten vom Modell anfordern usw.).
Ich sehe es eher als organisatorisches Problem als irgendetwas anderes.
Wie viele werden vorgeschlagen, warum und wie View & Model in verschiedenen Kontexten frei interagieren müssen, aber der Hauptgrund für die Herstellung von Controller in iOS ist, dass zwischen ihnen keine Model & View-Abhängigkeiten in Ihrer Codebasis bestehen und wir sie wiederverwenden können Entweder Modell oder Ansicht entsprechend den Anforderungen mit der Entwicklung von iOS.
Da wir möglicherweise Aktualisierungen für unsere Apps in UI / UX oder Model oder in einigen Fällen in beiden Fällen vornehmen müssen, sollte kein Modusabhängigkeitscode zwischen model & view erstellt werden. Wenn Sie die Präsentationsebene Ihrer App ändern möchten, gehen Sie einfach und Wenn Sie es ändern, können Sie dasselbe Modell immer noch wiederverwenden und umgekehrt.
Obwohl ich damit einverstanden bin, dass MVC in iOS riesige ViewController mit vielen verschiedenen Logiken erstellt und alle Arten von Dingen verarbeitet, die nicht für das vorgesehen sind. Daher ist es besser, MVVM oder Presentation Controls zu verwenden, um die Codebasis flexibler und einfacher zu gestalten lesbar und wartbar mit kleineren ViewControllern.
Dies kann hilfreich sein, wenn Sie nach kleineren ViewControllern für iOS suchen:
Im Web nennt jeder seine Entkopplungs-MVC.
Einige Technologien, wie z. B. C #, verwenden MVVM, da keine Verknüpfung zwischen der Ansicht und einer anderen besteht. Alles läuft über den Service Locator und bindet die Variablen.
Bei reiner MVC kommuniziert die Ansicht direkt mit dem Modell und umgekehrt. Der Controller ist nur dort, wenn Änderungen auftreten.
Und dann gibt es noch die PAC (Presentation Abstraction Control). In dieser Architektur sprechen die Ansicht und das Modell nicht miteinander. Der Controller ist der einzige, der irgendetwas mit der Ansicht oder dem Modell machen darf. Leute verwechseln dies oft mit MVC.
Eine bessere Erklärung finden Sie hier: http://www.garfieldtech.com/blog/mvc-vs-pac
quelle
Das grundlegende Ziel einer Architektur ist für mich, zukünftige Umgestaltungsversuche nicht zu behindern. Normalerweise sind Ansichten, die direkt mit Modellen interagieren, von dieser Anforderung betroffen, und es ist relativ klar, wenn dies nicht der Fall ist.
Wenn eine Ansicht mit einem Modell zu intim wird, kann ein ViewModel eine schöne Sache sein, aber für mich ist es normalerweise so, dass die Fälle, in denen dies erforderlich ist, in der Minderheit liegen.
quelle
In MVC ist Paul Hegarty falsch. Bei Controller geht es um Benutzerereignisse, nicht um Kommunikation zum Anzeigen des Modells. In der klassischen MVC beobachten die Ansichten das Modell (Beobachtermuster).
Wenn der Typ zwischendurch die Mediation durchführt, sollte das Muster MVP heißen , und tatsächlich ist das meiste, was heutzutage als MVC dargestellt wird, tatsächlich näher an MVP.
Dann gibt es MVVM, das etwas ähnlich und doch etwas anders ist und schon lange existiert hat. Am besten ist es, es als zwei MVCs / MVPs anzusehen, die durch ein viewmodel-Objekt miteinander verbunden sind - der "Client" MVC hat viewmodel als sein Modell und der "Server" MVC hat das Ansichtsmodell als seine Ansicht.
quelle
Da Sie insbesondere in diesen Stanford-Vorlesungen nach dem Material fragen, sollten Sie zwei Aspekte in Bezug auf Hegartys Haltung berücksichtigen:
quelle
Ich stimme Paul Hegarty zu und glaube, dass die Ansicht nichts über das Modell wissen darf. Es ist nicht so schwer zu erreichen, bringt aber zusätzliche Vorteile für Ihr Design und Ihre zukünftige Flexibilität.
In kleinen Anwendungen (normalerweise Desktop), in denen ich "Dummy" -ViewModel-Klassen vermeiden und die Dinge einfach halten möchte, verwende ich auch die IModel-Schnittstelle (siehe Antwort oben) und achte darauf, dass Model keine Ahnung von der Ansicht hat (verwende Abonnenten) wie im klassischen MVC).
Auch in diesem Fall ist der Controller so eingestellt, dass er gut mit der Ansicht gekoppelt ist, und der Einfachheit halber trenne ich sie nicht immer klar voneinander ab.
Der zweite vereinfachte Ansatz ist in Ordnung, wenn Sie möglicherweise mehrere Ansichten für dasselbe Modell haben. Ich würde ihn jedoch nicht empfehlen, wenn Sie dieselbe Ansicht für verschiedene Modelle verwenden möchten. Unter "anders" verstehe ich "von Natur aus anders" und nicht nur JUnit-Testklassen, die dem Hauptmodell "folgen".
quelle
Ich glaube, dass es keine feste Regel dafür gibt, es hängt völlig von Ihren Bedürfnissen ab.
Sie werden Menschen mit unterschiedlichen Überzeugungen finden. Architekturen sind Konzepte zum Entwerfen besserer Lösungen.
Abgesehen von der Kommunikation über die Modellsicht gibt es einen weiteren Widerspruch zur Geschäftslogik in MVC. Viele Leute glauben, dass die gesamte Geschäftslogik ein Modell sein sollte (siehe diese SO-Frage ), andererseits besagt die von Florian (in seiner Antwort) geteilte Verknüpfung, dass die Geschäftslogik auf dem Controller sein sollte.
Außerdem besteht die Möglichkeit, die Geschäftslogik in Anwendungslogik (Controller) und Domänenanmeldung (Modell) zu unterteilen.
Die Moral der Geschichte ist also, dass MVC bedeutet, dass Modell, Ansicht und Steuerung getrennt sein sollten. Davon abgesehen, was auch immer am besten zu Ihnen passt.
quelle
Ich benutze DTO für die Model-View-Kommunikation.
Zum Beispiel:
quelle
Ich bin mit dem Lager, das sagt, dass die Ansicht nie mit dem Modell kommunizieren sollte. Der Controller muss immer der Ansprechpartner für alles sein. Er entscheidet dann, was zu tun ist (validieren, Daten vom Modell anfordern usw.).
Ich sehe es eher als organisatorisches Problem als irgendetwas anderes.
quelle
Wie viele werden vorgeschlagen, warum und wie View & Model in verschiedenen Kontexten frei interagieren müssen, aber der Hauptgrund für die Herstellung von Controller in iOS ist, dass zwischen ihnen keine Model & View-Abhängigkeiten in Ihrer Codebasis bestehen und wir sie wiederverwenden können Entweder Modell oder Ansicht entsprechend den Anforderungen mit der Entwicklung von iOS.
Da wir möglicherweise Aktualisierungen für unsere Apps in UI / UX oder Model oder in einigen Fällen in beiden Fällen vornehmen müssen, sollte kein Modusabhängigkeitscode zwischen model & view erstellt werden. Wenn Sie die Präsentationsebene Ihrer App ändern möchten, gehen Sie einfach und Wenn Sie es ändern, können Sie dasselbe Modell immer noch wiederverwenden und umgekehrt.
Obwohl ich damit einverstanden bin, dass MVC in iOS riesige ViewController mit vielen verschiedenen Logiken erstellt und alle Arten von Dingen verarbeitet, die nicht für das vorgesehen sind. Daher ist es besser, MVVM oder Presentation Controls zu verwenden, um die Codebasis flexibler und einfacher zu gestalten lesbar und wartbar mit kleineren ViewControllern.
Dies kann hilfreich sein, wenn Sie nach kleineren ViewControllern für iOS suchen:
http://blog.xebia.com/simplification-of-ios-view-controllers-mvvm-or-presentation-controls/
quelle