MVC (Model, View, Controller) ist ein Muster zum Organisieren von Code in einer Anwendung, um die Wartbarkeit zu verbessern.
Stellen Sie sich einen Fotografen mit seiner Kamera in einem Studio vor. Ein Kunde bittet ihn, ein Foto von einer Schachtel zu machen.
Nicht-MVC-Architekturen sind in der Regel eng miteinander integriert. Wenn die Box, der Controller und die Kamera ein und dasselbe Objekt wären, müssten wir jedes Mal die Box und die Kamera auseinanderbauen, wenn wir eine neue Ansicht erhalten möchten . Außerdem ist das Fotografieren immer so, als würde man versuchen, ein Selfie zu machen - und das ist nicht immer ganz einfach.
bwaha schrieb:
Der Autor verweist auf mvctree.py in wxPython als Beispiel für das MVC-Design. Ich bin jedoch immer noch zu grün, daher finde ich dieses Beispiel zu komplex und verstehe die vom Autor empfohlene Trennung nicht.
MVC dreht sich alles um die Trennung von Bedenken.
Das Model ist verantwortlich für die Verwaltung der Programmdaten (sowohl der privaten als auch der Kundendaten). Der View / Controller ist dafür verantwortlich, der Außenwelt die Möglichkeit zu geben, mit den Kundendaten des Programms zu interagieren.
Das Modell bietet eine interne Schnittstelle (API), über die andere Teile des Programms mit ihm interagieren können. Der View / Controller verfügt über eine externe Schnittstelle (GUI / CLI / Webformular / High-Level-IPC / usw.), über die das gesamte Programm mit ihm kommunizieren kann.
Das Model ist für die Aufrechterhaltung der Integrität der Programmdaten verantwortlich. Wenn diese beschädigt werden, ist das Spiel für alle vorbei. Der View / Controller ist dafür verantwortlich, die Integrität der Benutzeroberfläche aufrechtzuerhalten, sicherzustellen, dass alle Textansichten aktuelle Werte anzeigen, Menüelemente zu deaktivieren, die nicht für den aktuellen Fokus gelten usw.
Das Modell enthält keinen View / Controller-Code. Keine GUI-Widget-Klassen, kein Code zum Auslegen von Dialogfeldern oder zum Empfangen von Benutzereingaben. Die Ansicht / Steuerung enthält keinen Modellcode. Kein Code zum Überprüfen von URLs oder zum Ausführen von SQL-Abfragen und auch kein ursprünglicher Status: Alle von Widgets gespeicherten Daten dienen nur zu Anzeigezwecken und spiegeln lediglich die im Modell gespeicherten wahren Daten wider.
Hier ist der Test eines echten MVC-Designs: Das Programm sollte im Wesentlichen auch ohne angeschlossenen View / Controller voll funktionsfähig sein. OK, die Außenwelt wird Probleme haben, in dieser Form damit zu interagieren, aber solange man die entsprechenden Modell-API-Beschwörungen kennt, speichert und bearbeitet das Programm die Daten wie gewohnt.
Warum ist das möglich? Nun, die einfache Antwort ist, dass dies alles dank der geringen Kopplung zwischen der Model- und der View / Controller-Ebene möglich ist. Dies ist jedoch nicht die ganze Geschichte. Entscheidend für das gesamte MVC-Muster ist die Richtung, in die diese Verbindung verläuft: ALLE Anweisungen fließen von der Ansicht / Steuerung zum Modell. Das Modell teilt dem View / Controller NIEMALS mit, was zu tun ist.
Warum? Denn in MVC darf der View / Controller zwar etwas über das Modell (insbesondere die API des Modells) wissen, aber das Modell darf überhaupt nichts über den View / Controller wissen.
Warum? Denn bei MVC geht es um eine klare Trennung der Anliegen.
Warum? Damit die Komplexität des Programms nicht außer Kontrolle gerät und Sie, den Entwickler, nicht darunter leiden. Je größer das Programm ist, desto größer ist die Anzahl der Komponenten in diesem Programm. Und je mehr Verbindungen zwischen diesen Komponenten bestehen, desto schwieriger ist es für Entwickler, einzelne Komponenten zu warten, zu erweitern oder zu ersetzen oder sogar nur zu verfolgen, wie das gesamte System funktioniert. Fragen Sie sich Folgendes: Wenn Sie sich ein Diagramm der Programmstruktur ansehen, möchten Sie lieber einen Baum oder die Wiege einer Katze sehen? Das MVC-Muster vermeidet letzteres, indem kreisförmige Verbindungen nicht zugelassen werden: B kann eine Verbindung zu A herstellen, A kann jedoch keine Verbindung zu B herstellen. In diesem Fall ist A das Modell und B die Ansicht / Steuerung.
Übrigens, wenn Sie scharf sind, werden Sie ein Problem mit der soeben beschriebenen 'Einweg'-Beschränkung bemerken: Wie kann das Modell die Ansicht / Steuerung über Änderungen der Benutzerdaten des Modells informieren, wenn das Modell dies nicht einmal darf? Weißt du, dass der View / Controller egal Nachrichten an ihn sendet? Aber keine Sorge: Es gibt eine Lösung dafür, und sie ist ziemlich ordentlich, auch wenn es auf den ersten Blick ein bisschen umständlich zu sein scheint. Wir werden gleich darauf zurückkommen.
In der Praxis kann ein View / Controller-Objekt dann über die API des Modells 1. das Modell anweisen, Dinge zu tun (Befehle auszuführen) und 2. das Modell anweisen, ihm Dinge zu geben (Daten zurückzugeben). Die Ansichts- / Controller-Ebene
überträgt Anweisungen an die Modellebene und ruft Informationen aus der Modellebene ab.
Und das ist , wo Sie Ihr erstes MyCoolListControl Beispiel schief geht, weil die API für diese Klasse erfordert , dass Informationen werden geschoben
hinein, so dass Sie wieder eine Zwei-Wege - Kopplung zwischen den Schichten zu haben, die MVC - Regeln zu verletzen und Sie gleich wieder in die Dumping Die Wiegenarchitektur der Katze, die Sie [vermutlich] vermeiden wollten.
Stattdessen sollte die MyCoolListControl-Klasse dem Ablauf folgen und die benötigten Daten aus der darunter liegenden Ebene abrufen, wenn sie benötigt werden. Bei einem Listen-Widget bedeutet dies im Allgemeinen, dass Sie nach der Anzahl der Werte und anschließend nach jedem dieser Elemente fragen, da dies der einfachste und lockerste Weg ist, um die Kopplung auf ein Minimum zu beschränken. Und wenn das Widget diese Werte beispielsweise dem Benutzer in einer guten alphabetischen Reihenfolge präsentieren möchte, ist dies seine Berechtigung. und seine Verantwortung natürlich.
Nun ein letztes Rätsel, wie ich bereits angedeutet habe: Wie lässt sich die Anzeige der Benutzeroberfläche in einem MVC-basierten System mit dem Status des Modells synchronisieren?
Hier ist das Problem: Viele Ansichtsobjekte sind statusbehaftet, z. B. kann ein Kontrollkästchen aktiviert oder deaktiviert sein, ein Textfeld kann bearbeitbaren Text enthalten. MVC schreibt jedoch vor, dass alle Benutzerdaten in der Modellebene gespeichert werden. Daher müssen alle Daten, die von anderen Ebenen für Anzeigezwecke gespeichert werden (der Status des Kontrollkästchens, der aktuelle Text des Textfelds), eine untergeordnete Kopie dieser primären Modelldaten sein. Wenn sich der Status des Modells ändert, ist die Kopie dieses Status in der Ansicht nicht mehr korrekt und muss aktualisiert werden.
Aber wie? Das MVC-Muster verhindert, dass das Modell eine neue Kopie dieser Informationen in die Ansichtsebene überträgt. Heck, es erlaubt dem Model nicht einmal, der Ansicht eine Nachricht zu senden, die besagt, dass sich sein Status geändert hat.
Naja fast. Okay, die Model-Ebene darf nicht direkt mit anderen Ebenen kommunizieren, da dies voraussetzt, dass sie etwas über diese Ebenen weiß, und MVC-Regeln verhindern dies. Wenn jedoch ein Baum in einen Wald fällt und niemand da ist, um ihn zu hören, macht er dann ein Geräusch?
Wie Sie sehen, besteht die Antwort darin, ein Benachrichtigungssystem einzurichten, das der Model-Ebene einen Ort bietet, an dem sie insbesondere niemandem mitteilen kann, dass sie gerade etwas Interessantes getan hat. Andere Ebenen können dann Listener mit diesem Benachrichtigungssystem veröffentlichen, um auf die Ankündigungen zu warten, an denen sie tatsächlich interessiert sind. Die Model-Ebene muss nichts darüber wissen, wer zuhört (oder auch, wenn überhaupt jemand zuhört!). Es wird nur eine Ankündigung gepostet und diese dann vergessen. Und wenn jemand diese Ansage hört und danach Lust hat, etwas zu tun - wie das Model nach neuen Daten zu fragen, damit es seine Bildschirmanzeige aktualisieren kann - dann großartig. Das Modell listet nur auf, welche Benachrichtigungen es als Teil seiner API-Definition sendet. und was jemand anderes mit diesem Wissen macht, liegt bei ihnen.
MVC bleibt erhalten und alle sind glücklich. Ihr Anwendungsframework bietet möglicherweise ein integriertes Benachrichtigungssystem. Wenn nicht, können Sie auch ein eigenes schreiben (siehe 'Beobachtermuster').
...
Wie auch immer, hoffe das hilft. Sobald Sie die Beweggründe hinter MVC verstanden haben, werden die Gründe, warum die Dinge so gemacht werden, wie sie sind, sinnvoll, auch wenn sie auf den ersten Blick komplexer als nötig erscheinen.
Prost,
hat