Ich versuche zu verstehen, wie eine gute Entkopplung zwischen einer Benutzeroberfläche und dem Modell implementiert werden kann, habe aber Probleme, genau herauszufinden, wo die Linien aufgeteilt werden müssen.
Ich habe mir Model-View-Presenter angesehen, bin mir aber nicht sicher, wie ich es implementieren soll. Beispielsweise verfügt meine Ansicht über mehrere Dialogfelder.
- Sollte es eine View-Klasse mit Instanzen der einzelnen Dialogfelder geben? Wie sollten dann in diesem Fall die Dialoge mit dem Präsentator interagieren? dh Wenn ein einzelner Dialog Daten vom Modell über den Presenter anfordern muss, wie soll der Dialog einen Verweis auf den Presenter erhalten? Über einen Verweis auf die Ansicht, die ihr beim Bau gegeben wurde?
- Ich dachte, vielleicht sollte die Ansicht eine statische Klasse sein? Dann die Dialoge GetView und dort den Presenter holen ...
- Ich hatte darüber nachgedacht, den Presenter mit dem Besitz der Ansicht und des Modells einzurichten (im Gegensatz dazu, dass die Ansicht den Presenter und den Presenter mit dem Modell hat) und der Presenter Rückrufe für Ereignisse in der Ansicht registriert, aber das lässt es sehr erscheinen mehr gekoppelt (oder zumindest sprachabhängig)
Ich versuche zu:
- machen Sie dies so entkoppelt wie möglich
- Im Idealfall ist es möglich, den Presenter / das Model mit Ansichten anderer Sprachen zu koppeln. (Ich habe nicht viele Dinge zwischen den Sprachen erledigt, aber ich weiß, dass es möglich ist, insbesondere, je mehr
void(void)
ich mich an eine C # -Anwendung halten kann.) C ++ Bibliothek ... - Halten Sie den Code sauber und einfach
Also .. irgendwelche Vorschläge, wie mit den Interaktionen umgegangen werden soll?
design-patterns
ui
interfaces
trycatch
quelle
quelle
Antworten:
Willkommen auf einer rutschigen Piste. Sie haben zu diesem Zeitpunkt festgestellt, dass es eine endlose Vielfalt aller Modellsicht-Interaktionen gibt. MVC, MVP (Taligent, Dolphin, Passive View), MVVM, um nur einige zu nennen.
Das Model View Presenter-Muster ist wie die meisten Architekturmuster vielfältig und experimentierfreudig. Allen Variationen gemeinsam ist die Rolle des Moderators als "Mittelsmann" zwischen Sicht und Modell. Die beiden häufigsten sind die Passive View und der Supervising Presenter / Controller - [ Fowler ]. Passive View behandelt die Benutzeroberfläche als eine sehr flache Schnittstelle zwischen dem Benutzer und dem Präsentator. Es enthält sehr wenig oder gar keine Logik und überträgt so viel Verantwortung an einen Moderator. Supervising Presenter / Controllerversucht, die in vielen UI-Frameworks integrierte Datenbindung zu nutzen. Die Benutzeroberfläche verwaltet die Datensynchronisation, aber der Präsentator / Controller sorgt für eine komplexere Logik. In beiden Fällen bilden das Modell, die Ansicht und der Präsentator eine Triade
Dafür gibt es viele Möglichkeiten. Es ist sehr verbreitet, dies zu sehen, indem jedes Dialogfeld / Formular als eine andere Ansicht behandelt wird. Oft besteht eine 1: 1-Beziehung zwischen Ansichten und Moderatoren. Dies ist keine feste Regel. Es ist durchaus üblich, dass ein Moderator mehrere verwandte Ansichten verwaltet oder umgekehrt. Es hängt alles von der Komplexität der Ansicht und der Komplexität der Geschäftslogik ab.
Wie Ansichten und Moderatoren einen Bezug zueinander herstellen, wird manchmal als Verkabelung bezeichnet . Sie haben drei Möglichkeiten:
Die Ansicht enthält einen Verweis auf den Präsentator.
Ein Formular oder ein Dialogfeld implementiert eine Ansicht. Das Formular verfügt über Ereignisbehandlungsroutinen, die über direkte Funktionsaufrufe einen Moderator ansprechen:
Da der Präsentator keinen Verweis auf die Ansicht hat, muss die Ansicht die Daten als Argumente senden. Der Präsentator kann über Ereignisse / Rückruffunktionen, auf die die Ansicht achten muss, mit der Ansicht kommunizieren.
Der Presenter enthält einen Verweis auf die Ansicht.
In diesem Szenario werden in der Ansicht die Eigenschaften der Daten angezeigt, die dem Benutzer angezeigt werden. Der Präsentator wartet auf Ereignisse und bearbeitet die Eigenschaften der Ansicht:
Beide haben einen Bezug zueinander und bilden eine kreisförmige Abhängigkeit.
Dieses Szenario ist tatsächlich einfacher zu bearbeiten als die anderen. Die Ansicht reagiert auf Ereignisse, indem sie Methoden im Presenter aufruft. Der Präsentator liest / ändert Daten aus der Ansicht über offen gelegte Eigenschaften.
Bei den MVP-Mustern müssen noch andere Probleme berücksichtigt werden. Erstellungsreihenfolge, Objektlebensdauer, wo die Verkabelung stattfindet, Kommunikation zwischen MVP-Triaden, aber diese Antwort ist schon lange genug gewachsen.
quelle
Wie jeder gesagt hat, gibt es Dutzende von Meinungen und keine einzige davon ist richtig oder falsch. Ohne auf die Vielzahl von Mustern einzugehen und sich nur auf MVP zu konzentrieren, hier einige Vorschläge zur Implementierung.
Halte sie getrennt. Die Ansicht sollte eine Schnittstelle implementieren, die die Verbindung zwischen der Ansicht und dem Präsentator herstellt. Die Ansicht erstellt einen Präsentator und injiziert sich in den Präsentator und macht die Methoden verfügbar, die der Präsentator für die Interaktion mit der Ansicht bietet. Die Ansicht ist dafür verantwortlich, diese Methoden oder Eigenschaften nach Belieben zu implementieren. Im Allgemeinen haben Sie eine Ansicht: einen Moderator, aber in einigen Fällen können Sie mehrere Ansichten haben: einen Moderator (Web, WPF usw.). Der Schlüssel hierbei ist, dass der Präsentator nichts über UI-Implementierungen weiß und nur über die Benutzeroberfläche mit der Ansicht interagiert.
Hier ist ein Beispiel. Zuerst haben wir eine Ansichtsklasse mit einer einfachen Methode, um dem Benutzer eine Nachricht anzuzeigen:
Hier ist der Moderator. Beachten Sie, dass der Präsentator eine IView in seinen Konstruktor aufnimmt.
Hier ist die eigentliche Benutzeroberfläche. Dies kann ein Fenster, ein Dialog, eine Webseite usw. sein. Beachten Sie, dass der Konstruktor für die Ansicht den Präsentator erstellt, indem er sich selbst einfügt.
Der Präsentator kümmert sich nicht darum, wie die Ansicht die Methode implementiert, die sie gerade ausführt. Soweit der Moderator weiß, wird möglicherweise in eine Protokolldatei geschrieben und diese dem Benutzer nicht einmal angezeigt.
In jedem Fall arbeitet der Präsentator am Backend mit dem Modell und möchte den Benutzer irgendwann darüber informieren, was los ist. Jetzt haben wir also irgendwo im Presenter eine Methode, die die InformUser-Nachricht views aufruft.
Hier bekommen Sie Ihre Entkopplung. Der Moderator hat nur einen Verweis auf eine Implementierung von IView und kümmert sich nicht wirklich darum, wie diese implementiert ist.
Dies ist auch eine schlechte Implementierung von Mans, da Sie in der Ansicht einen Verweis auf den Presenter haben und Objekte über Konstruktoren festgelegt werden. In einer robusteren Lösung möchten Sie wahrscheinlich die Inversion von Steuerungscontainern (IoC) wie Windsor, Ninject usw. untersuchen, die die Implementierung von IView zur Laufzeit auf Abruf für Sie auflösen und damit noch weiter entkoppeln.
quelle
Ich denke, es ist wichtig, sich daran zu erinnern, dass der Controller / Presenter der Ort ist, an dem die Aktion wirklich stattfindet. Eine Kopplung im Controller ist zwangsläufig erforderlich.
Der Kernpunkt des Controllers besteht darin, dass sich das Modell nicht ändern muss, wenn Sie eine Änderung an der Ansicht vornehmen, und umgekehrt (wenn sich das Modell ändert, muss auch die Ansicht nicht geändert werden), da der Controller das übersetzt Modell in die Ansicht und wieder zurück. Der Controller ändert sich jedoch, wenn Modell- oder Ansichtsänderungen vorgenommen werden, da Sie innerhalb des Controllers effektiv übersetzen müssen, wie das Modell angezeigt werden soll, um Änderungen in der Ansicht wieder in den Modus zu übernehmen.
Das beste Beispiel, das ich geben kann, ist, dass ich beim Schreiben einer MVC-App nicht nur Daten in der GUI-Ansicht haben kann, sondern auch eine Routine schreiben kann, die Daten, die aus dem Modell gezogen wurden, in eine Routine schiebt
string
, die im Debugger angezeigt werden soll (und als Erweiterung in eine reine Textdatei). Wenn ich Modelldaten nehmen und frei in Text übersetzen kann, ohne die Ansicht oder das Modell und nur den Controller zu ändern , bin ich auf dem richtigen Weg.Abgesehen davon müssen Sie Referenzen zwischen den verschiedenen Komponenten haben, damit alles funktioniert. Der Controller muss die Ansicht kennen, um Daten zu übertragen, und der View muss die Ansicht kennen, um sie zu informieren, wenn eine Änderung vorgenommen wurde (z. B. wenn der Benutzer auf "Speichern" oder "Neu ..." klickt). Der Controller muss über das Modell Bescheid wissen, um die Daten abzurufen, aber ich würde argumentieren, dass das Modell über nichts anderes Bescheid wissen sollte.
Einschränkung: Ich komme aus einem komplett Mac, Objective-C, Cocoa-Hintergrund, der Sie wirklich in das MVC-Paradigma einführt, ob Sie wollen oder nicht.
quelle
Im Allgemeinen soll Ihr Modell alle Interaktionen mit diesem Modell kapseln. Beispielsweise sind Ihre CRUD-Aktionen (Erstellen, Lesen, Aktualisieren, Löschen) Teil des Modells. Gleiches gilt für Sonderberechnungen. Dafür gibt es ein paar gute Gründe:
In Ihrem Controller (MVC-App) müssen Sie nur die Modelle sammeln, die Sie in Ihrer Ansicht verwenden müssen, und die entsprechenden Funktionen für das Modell aufrufen. Alle Änderungen am Modellstatus werden in dieser Ebene vorgenommen.
In Ihrer Ansicht werden nur die von Ihnen vorbereiteten Modelle angezeigt. Im Wesentlichen liest die Ansicht nur das Modell und passt die Ausgabe entsprechend an.
Abbildung des allgemeinen Prinzips auf tatsächliche Klassen
Denken Sie daran, dass Ihre Dialoge Ansichten sind. Wenn Sie bereits eine Dialogklasse haben, gibt es keinen Grund, eine weitere "View" -Klasse zu erstellen. Die Presenter-Ebene bindet das Modell im Wesentlichen an die Steuerelemente in der Ansicht. Die Geschäftslogik und alle wichtigen Daten sind im Modell gespeichert.
quelle