MVP Entwurfsmuster richtig anwenden
MVP Entwurfsmuster richtig anwenden
hi leute,
ich mache gerade meine ersten schritte mit qt und möchte in naher zukunft eine komplexere applikation mit dem framework bauen. als architektur habe ich versucht das gängige mvc muster anzuwenden. das model soll die datenhaltung und die geschäftslogik übernehmen, der controller zur steuerung dienen und letztendlich das view die daten anzeigen. soviel zur threorie....
..weitere recherchen haben ergeben das qt von haus aus kein echtes mvc unterstützt, sondern eine art model/view architektur benutzt. der controller und das view verschmelzen miteinander. nun versuche ich das muster nachzuvollziehen und stoße auf einige hürden. so wie ich das verstanden habe wird in der view klasse die form initialisiert. eine weitere klasse namens viewdelegate soll dann alle fkten beinhalten die die view verändern können. das model soll die daten aus bspw. einer datei ziehen und in objekte ablegen und fkten zur verfügung stellen, damit man aud diese daten zugreifen kann. wird also versucht ein datensatz in einem textedit auszugeben, ruft viewdelegate eine funktion im model auf um an den datensatz ranzukommen und eine zweite fkt um diese im view darzustellen.
eigentlich wollte ich strikt model und view trennen und alle funktionsaufrufe in einer separaten controllerklasse machen, würdet ihr mehr zu solch einer klassischen variante oder zu qts hausgemachten tendieren ?
ich mache gerade meine ersten schritte mit qt und möchte in naher zukunft eine komplexere applikation mit dem framework bauen. als architektur habe ich versucht das gängige mvc muster anzuwenden. das model soll die datenhaltung und die geschäftslogik übernehmen, der controller zur steuerung dienen und letztendlich das view die daten anzeigen. soviel zur threorie....
..weitere recherchen haben ergeben das qt von haus aus kein echtes mvc unterstützt, sondern eine art model/view architektur benutzt. der controller und das view verschmelzen miteinander. nun versuche ich das muster nachzuvollziehen und stoße auf einige hürden. so wie ich das verstanden habe wird in der view klasse die form initialisiert. eine weitere klasse namens viewdelegate soll dann alle fkten beinhalten die die view verändern können. das model soll die daten aus bspw. einer datei ziehen und in objekte ablegen und fkten zur verfügung stellen, damit man aud diese daten zugreifen kann. wird also versucht ein datensatz in einem textedit auszugeben, ruft viewdelegate eine funktion im model auf um an den datensatz ranzukommen und eine zweite fkt um diese im view darzustellen.
eigentlich wollte ich strikt model und view trennen und alle funktionsaufrufe in einer separaten controllerklasse machen, würdet ihr mehr zu solch einer klassischen variante oder zu qts hausgemachten tendieren ?
Zuletzt geändert von marvel am 9. August 2009 20:04, insgesamt 3-mal geändert.
ich habe mich jetzt durch unzählige internetseiten und foren durchgelesen und muss feststellen das das mvc/mvp in der theorie leicht zu verstehen ist, nur leider keine konkreten beispiele für die praxis gibt. deshalb habe ich anhand meines bisherigen verständnissen ein kleines beispiel implementiert, indem ein string aus dem model in einem textedit ausgebeben wird und wollte euch bitten dies mit mir mal durchzugehen.
im model wird der string angelegt, soll also nur eine triviales beispiel für einen datenbezug darstellen und kann per getMethode erreicht werden.
in der view wird per set Methode ins textEdit geschrieben.
da qt nach erstellung einer form den erzeugten quellcode in einer seperaten datei ablegt, in diesem fall ui_view.h, muss ich erstmal per get an das textEdit rankommen, um dann damit arbeiten zu können.
der controller legt 2 instanzen an, das model und das view. der controller ist also das verbindungsstück zwischen model und view. model und view kennen sich nicht !
std main fkt um die applikation zu starten
......................................................
weitere überlegungen :
mein beispiel hat nur ein anzeigelement, das textEdit, sollte es aber mal eingabeelemente geben so müsste nach meiner überlegung nach einer eingabe das view ein signal an den controller senden, der dann wiederum die eingebenen daten an das model weiterreicht.
mfg
marvel
Code: Alles auswählen
[b]model.h:[/b]
#ifndef MODEL_H
#define MODEL_H
#include <QObject>
#include <QString>
class Model : public QObject
{
public:
Model();
QString* getString();
private:
QString string;
};
#endif // MODEL_H
[b]model.cpp:[/b]
#include "model.h"
Model::Model()
{
string = "Hallo Welt!";
}
QString* Model::getString()
{
return &string;
}
Code: Alles auswählen
[b]view.h:[/b]
#ifndef VIEW_H
#define VIEW_H
#include "ui_view.h"
class View : public QMainWindow
{
Q_OBJECT
public:
View(QWidget *parent = 0);
QTextEdit* getTextEdit();
void setTextEdit(QString *string);
private:
Ui::View m_ui;
};
#endif // VIEW_H
[b]view.cpp:[/b]
#include "view.h"
View::View(QWidget *parent): QMainWindow(parent)
{
m_ui.setupUi(this);
}
QTextEdit* View::getTextEdit()
{
return m_ui.textEdit;
}
void View::setTextEdit(QString *string)
{
getTextEdit()->setText(*string);
}
da qt nach erstellung einer form den erzeugten quellcode in einer seperaten datei ablegt, in diesem fall ui_view.h, muss ich erstmal per get an das textEdit rankommen, um dann damit arbeiten zu können.
Code: Alles auswählen
[b]controller.h:[/b]
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <QObject>
#include <QApplication>
#include "model.h"
#include "view.h"
class Controller : public QObject
{
public:
Controller();
void initialize();
private:
Model *model;
View *view;
};
#endif // CONTROLLER_H
[b]controller.cpp:[/b]
#include "controller.h"
Controller::Controller()
{
model = new Model();
view = new View();
}
void Controller::initialize()
{
view->setTextEdit(model->getString());
view->show();
}
Code: Alles auswählen
#include <QApplication>
#include "controller.h"
int main( int argc, char* argv[])
{
QApplication a(argc, argv);
Controller *c = new Controller();
c->initialize();
return a.exec();
}......................................................
weitere überlegungen :
mein beispiel hat nur ein anzeigelement, das textEdit, sollte es aber mal eingabeelemente geben so müsste nach meiner überlegung nach einer eingabe das view ein signal an den controller senden, der dann wiederum die eingebenen daten an das model weiterreicht.
mfg
marvel
wie ich gerade herausgefunden habe entspricht mein codebeispiel dem sog. Model-View-Presenter Entwurfsmuster. Die Schwierigkeit liegt darin es von dem klassischen MVC zu trennen, da die Begrifflichkeiten oftmals durcheinandergeworfen werden. Hier nochmal ein paar Erklärungen zu den Unterschieden:
http://de.wikipedia.org/wiki/Model_View_Presenter
http://msdn.microsoft.com/de-de/magazin ... #id0080083
nochmal zur verdeutlichung eine grafik, links das MVP in meiner Variante und rechts das klassische MVC

http://de.wikipedia.org/wiki/Model_View_ControllerKlassisches MVC:
In MVC interagiert der Benutzer mit der Ansicht, und Aktionen (z. B. ein Schaltflächenklick) werden von der Ansicht aufgezeichnet und zum Controller weitergeleitet. Der Controller entscheidet, was zu tun ist, und führt dies durch eine Interaktion mit dem Modell aus. Das Modell ist im Grunde die Geschäftsschicht plus einige zusätzliche Funktionen. Insbesondere benachrichtigt das Modell die Ansicht über Änderungen, die gegebenenfalls eine Aktualisierung der Benutzeroberfläche erfordern.
Das Modell kennt keine Details der Ansicht, aber zwischen dem Modell und der Ansicht besteht eine „Beobachter“-Beziehung. Anders gesagt, die Ansicht enthält einen Verweis zum Modell und meldet sich im Modell an, um eine Benachrichtigung über Änderungen zu erhalten. Wenn die Benachrichtigung empfangen wird, ruft die Ansicht neue Daten vom Modell ab und aktualisiert die Benutzeroberfläche.
MVP basierend auf MVC:
Die ursprüngliche Formulierung von MVC hat einen großen Schwachpunkt: die Methode, durch die die Ansicht aktualisiert wird. Der Informationsfluss zeigt, dass die Ansicht dem Controller die Benutzereingabe mitteilt, aber eine Änderungsbenachrichtigung vom Modell empfängt. Als Nächstes muss die Ansicht ihre detaillierte Kenntnis des Modells nutzen, um aktualisierte Daten aufzugreifen und sich zu aktualisieren. MVP ist eine Variante von MVC, das die Elemente der Triade deutlicher trennt.
In MVP leitet die Ansicht die Benutzereingabe an den Presenter weiter, und vom Presenter erhält es neue Daten für Aktualisierungen. Der Presenter wiederum bearbeitet die Anforderung durch eine Interaktion mit dem Modell.
Im ursprünglichen MVC gibt es keinen expliziten Vertrag, in dem angegeben wird, welche Zustände die Ansicht benötigt. In MVC enthält die Ansicht einen Verweis auf das Modell und führt ihre eigene Logik aus, um die benötigten Daten auszuwählen und sie in Benutzeroberflächenelemente einzuarbeiten. Ausgestattet mit dieser Logik ist die Ansicht nicht so passiv wie sie für Testzwecke sein sollte. Außerdem hängt die Ansicht gewissermaßen von der zugrunde liegenden Benutzeroberflächenplattform ab.
In MVP ist der Presenter im Grunde der Vermittler zwischen Endbenutzern und Anwendungen. Der Presenter hat die Berechtigung, die Ansicht zu rendern und mit dem Modell zu interagieren. Deshalb befindet sich ein Großteil der Darstellungslogik im Presenter. Weil der Presenter eine einfache Klasse ohne Benutzeroberfläche ist, ist es eine inhärent besser prüfbare Klasse.
In MVP implementiert die Ansicht eine Schnittstelle, und der Presenter kommuniziert mit der Ansicht, indem er nur die Member bei der Schnittstelle verwendet. Deshalb liest der Presenter zum Beispiel Eingabedaten in der Ansicht, indem er Methoden und Getter in der Schnittstelle verwendet, und legt neue Werte für die Ansicht festlegt, indem er Methoden und/oder Setter in der Schnittstelle verwendet.
http://de.wikipedia.org/wiki/Model_View_Presenter
http://msdn.microsoft.com/de-de/magazin ... #id0080083
nochmal zur verdeutlichung eine grafik, links das MVP in meiner Variante und rechts das klassische MVC

Das Veschmelzen von View/Model und Controller ist bei Qt kein Problem, da den Controllerpart Qts Signal/Slot-Mechanismus übernimmt. Da wäre eine weitere Klasse zuviel des Guten.
Dein Beispiel mit den Eingabeelementen, also im prinzip ne simple Form, hat in meinen Augen nix mit MVC zu tun, da du genau einen Datensatz hast. MVC macht eigentlich erst Sinn, wenn man mehrere Datensätz verwaltet.
Qt Model/View Framework ist mittlerweile in so vielen Projekten angekommen, dass eine Verweigerung kaum Sinn macht. Und als Grund "ich will das als reines MVC implementieren" find ich an der Praxis vorbei
Es funktioniert perfekt und es macht nicht wirklich viel Arbeit ein eigenes Model zu implementieren. Also schaus dir einfach mal an, bevor du dich dagegen entscheidest...
Dein Beispiel mit den Eingabeelementen, also im prinzip ne simple Form, hat in meinen Augen nix mit MVC zu tun, da du genau einen Datensatz hast. MVC macht eigentlich erst Sinn, wenn man mehrere Datensätz verwaltet.
Qt Model/View Framework ist mittlerweile in so vielen Projekten angekommen, dass eine Verweigerung kaum Sinn macht. Und als Grund "ich will das als reines MVC implementieren" find ich an der Praxis vorbei
Es funktioniert perfekt und es macht nicht wirklich viel Arbeit ein eigenes Model zu implementieren. Also schaus dir einfach mal an, bevor du dich dagegen entscheidest...
hallo erstmal,
ich bin neu auf dem gebiet und versuche mich nur schlau zu machen welcher ansatz der sinnvollere ist. ich habe mich noch nicht entschieden, sondern versuche durch einen informationsaustausch vorteile/nachteile abzuwägen und mich am ende für eine variante zu entscheiden.
ich bin neu auf dem gebiet und versuche mich nur schlau zu machen welcher ansatz der sinnvollere ist. ich habe mich noch nicht entschieden, sondern versuche durch einen informationsaustausch vorteile/nachteile abzuwägen und mich am ende für eine variante zu entscheiden.
da geb ich dir vollkommen recht, nur sollte mein beispiel der reinen veranschaulichung dienen und keinesfalls den wriklichen datenbestand wiedergeben. meine applikation soll später mehrere 100 datensätze verwalten können.Dein Beispiel mit den Eingabeelementen, also im prinzip ne simple Form, hat in meinen Augen nix mit MVC zu tun, da du genau einen Datensatz hast. MVC macht eigentlich erst Sinn, wenn man mehrere Datensätz verwaltet.
nun, ich habe wie oben beschrieben meine applikation nach dem MVP aufgebaut, das bedeuted das model und view getrennt sind und im presenter die eigentliche abläufe passieren. model und view haben nur getter und setter, die der presenter benutzt. könntest du mir anhand eines beispiels oder mit etwas erläuterung zeigen wie man es mit den qt gegebenen mitteln macht ?Das Veschmelzen von View/Model und Controller ist bei Qt kein Problem, da den Controllerpart Qts Signal/Slot-Mechanismus übernimmt. Da wäre eine weitere Klasse zuviel des Guten.
Schau dir doch mal die Examples zum Thema an:marvel hat geschrieben:könntest du mir anhand eines beispiels oder mit etwas erläuterung zeigen wie man es mit den qt gegebenen mitteln macht ?
http://doc.trolltech.com/4.5/examples.html#item-views
Da wirst du schlauer...
Zum Bauen lädst du dir den Qt-Source runter (ich glaub aber auch beim Win-bin sind die dabei) und gehst in Richtung "examples/itemviews" und baust einfach was dich interessiert.
nun danke erstmal für die prompte hilfe...ich denke ich bin in der lage das vorgegebene architekturmuster von qt zu erlernen, jedoch zielte mein thread eher darauf die unterschiede herauszukristallisieren. so wäre es beispielsweise interessant in erfahrung zu bringen, ob model und view ohne weiteres voneinander zu trennen sind und ob man die views austauschen kann etc.
Wenn du dir die Beipiele anschaust sollte es doch klar sein!marvel hat geschrieben:so wäre es beispielsweise interessant in erfahrung zu bringen, ob model und view ohne weiteres voneinander zu trennen sind und ob man die views austauschen kann etc.
Man KANN natürlich model/views austauschen, deshalb überhaupt der abstrakte Ansatz. QDirModel kannst du mit nem QListView und QTreeView anzeigen, du kannst ein eigenes Model implementieren und gleich eine Qt-eigene View verwenden. Du kannst hergehen und mehrere eigene spezialisierte Views implementieren und ein einziges Model-Objekt in allen views anzeigen. Bei Änderung in dem Model werden alle Views aktualisiert. Usw. Aber eigentlich ist die Doku + Examples so ausführlich, dass sich das alles von selber erklären sollte.