MVP bei Schachspiel

P@u1

Aktives Mitglied
Hallo zusammen,

ich arbeite zurzeit zusammen mit einem Freund an einem Schachspiel. Die Spiellogik steht schon (abgesehen von ein paar bugs, die wir im Moment beheben).
Im Moment ist auch eine 2d GUI in arbeit und später soll auch eine 3d GUI benutzt werden, also muss das ganze austauschbar sein.

Ich habe mir jetzt ein paar Gedanken zum (Software-)Design dazu gemacht und dafür einiges über MVC und MVP durchgelesen. Ich wollte jetzt MVP benutzen und habe dazu gerade einen Entwurf erstellt:
Anmerkungen: Mit Highlights ist gemeint, dass manche Felder markiert werden, z.B. um anzuzeigen, dass dort Züge möglich sind.
Ich habe beim Diagram Assozitationen erstmal rausgelassen.
Hier werden nicht alle vorhandenen Klassen und Methoden dargestellt, sondern nur die wichtigsten.
dlftb5xp.png


Das oben dargestellte Package "ChessLogic" existiert schon und funktioniert auch ganz gut.
Das package unten "Presentation" ist bisher nur ein Entwurf. Ich habe schon eine einfache 2d GUI angefangen, aber bisher ist das alles in eine Klasse gepackt.

Die Idee war jetzt, eine abstrakte klasse/interface (Abstract)ChessView zu erstellen, für die es dann für 2d und 3d und evtl. später für web konkrete implementierungen gibt.
Alle views können dann aber den selben Presenter und das selbe Model verwenden.

Wenn bei der View auf ein Feld geklickt wird, ruft die View beim Presenter OnFieldSelected() auf und der Presenter führt dann entsprechende Aktionen bei den Logikobjekten aus.

Als Model habe ich nicht das ChessBoard direkt gewählt, weil ich zusätzlich noch die oben erwähnten Highlights brauche und die mit in das ViewModel getan habe.
Wird dann ein Zug ausgeführt, wird vom Model oder vom Presenter (das weiß ich noch nicht genau) bei der View die Methode MoveExecuted() aufgerufen, wodurch sich die View dann updated. Entsprechendes gilt auch für HighlightsChanged().

Ein Problem ist auch noch, wie die ganzen Objekte nachher erzeugt werden.
Presenter, View und Model haben ja untereinander einige Beziehungen, deswegen bin ich mir nicht sicher, in welcher Reihenfolge die Objekte erzeugt werden sollten und welche Argumente den jeweiligen Konstruktoren dann übergeben werden sollten. Habt ihr da Ideen?


Was haltet ihr von dem Design? Würdet ihr das auch so machen? Habt ihr Verbesserungsvorschläge/Anmerkungen?

Vielen Dank schonmal für eure Hilfe!

Edit: Evtl. passt das auch besser ins allgemeine Forum, als ins AWT, Swing & SWT, bin mir aber nicht sicher.
 
Zuletzt bearbeitet:
M

Marcinek

Gast
Ich würde das Board als eindimensionales Array machen. Das macht Berechnungen einfacher.

Bei dem Move fehlt noch die Figur. Wobei man das auch von Board her ablesen kann.

Du erzeugst den Controller. Dieser erzeugt das Modell und zeigt es an.

Gruß,

Martin
 

P@u1

Aktives Mitglied
Ich würde das Board als eindimensionales Array machen. Das macht Berechnungen einfacher.

Warum macht das die Berechnungen einfacher?
Ich finde es einfacher, direkt mit [5][4] zuzugreifen, als erst einen index ausrechnen zu müssen.
Das könnte man zwar in einem getter kapseln, aber einen vorteil sehe ich da trotzdem nicht.

Bei dem Move fehlt noch die Figur. Wobei man das auch von Board her ablesen kann.

Genau, wir lesen das vom board ab.

Du erzeugst den Controller. Dieser erzeugt das Modell und zeigt es an.

Heißt "und zeigt es an", dass der Controller (Presenter) auch noch die View erstellt?
Oder wird die View dem Controller übergeben?

Sieht das dann ungefähr so aus?
[Java]
public class Presenter
{
private View view;
private Model model;

public Presenter(/*View übergeben?*/)
{
this.model = new Model();
this.view = new View(this, model);
}
}
[/Java]

Ich denke, es wäre schon sinnvoll, die View zu übergeben, damit man ohne den Presenter zu ändern, verschiedene Interfaces (2d / 3d) benutzen kann.
Dann muss man nur Nachträglich per setter dem view das model und den presenter übergeben.
Die View braucht ja das model, um den Zustand abfragen zu können und es braucht den Controller(Presenter), um wenn ein Feld angeklickt wird, dem Controller(Presenter) bescheid zu sagen (das würde auch per observer gehen, aber warum umständlich wenns auch direkt geht).

Und ansonsten ist das so alles ok?
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Ob das ein 1D-Array ist oder nicht, sieht man am Interface nicht mehr - es würde ja schon reichen, die Zeile mit dem [][] 2D-Array aus dem Diagramm zu entfernen - WIE eine Klasse ein Interface impelementiert, bleibt ihr überlassen.

Ansonsten... bisher sieht man da nicht viel, was falsch sein könnte. Der Punkt, dass man die V an den P übergibt, weil das flexibler sein könnte, stimmt. Aber ist im Moment IMHO erstmal nur ein Detail... :bahnhof:
 

P@u1

Aktives Mitglied
Vielen Dank für eure Hilfe!

Wenn ich später Netzwerkfunktionialität hinzufügen will und dann den nächsten zug vom gegner empfangen will, dann wird das vom ChessPresenter aus gemacht, richtig?

Ich hab jetzt nochmal ein paar etwas allgemeinere Fragen zu MVP:

-Was ist dabei das Model? Benutzt man dafür normalerweise ein Objekt aus der Anwendungsdomäne (bei mir wäre das ChessBoard), oder erstellt man ein PresentationModel, das genau auf die Bedürfnisse der View abgestimmt ist (und möglicherweise intern ein Objekt aus der Anwendungsdomäne benutzt)? Oder mal so und mal so?
Ich habe da ja die zweite Variante gewählt und eine Model-Klasse erstellt, die intern auf ChessBoard und ChessLogic zugreift, aber auch speziell für die View aufbereitete Informationen bereitstellt (die Highlights).

-Wie funktioniert die ganze Initialisierung, wenn ich einen GUI-Editor benutze, um die Oberfläche zu erstellen? So wie ich das kenne, kann man dann dem Konstruktor keine Parameter übergeben und die GUI wird als ganzes erstellt.

Ich stelle mir das dann so vor, dass ich erstmal die gesamte GUI erstelle.
Dann erstelle ich alle Presenter, die jeweils ihre models erstellen und übergebe die Presenter dann in irgendeiner Containerklasse an die GUI, die dann an die jeweiligen unterviews die entsprechenden Presenter weitergibt. Die Presenter rufen dann bei ihren jeweiligen Views eine Initialize-Methode auf, bei der sie eine Referenz auf sich selbst und das zugehörige Model übergeben.
 
M

Marcinek

Gast
Ich würde das so machen, dass mein Programm funktioniert.

Diese ganze MVC und MVP Sache wird föllig überbewertet. Das einzige, wass du machen musst ist:

Modell, Logik und die Darstellung zu trennen. Damit du eines davon ausstauschen kannst, ohne das Programm neu zu machen.

Wenn nun dein GUI Builder keine parametirerten Konstruktoren erlaubt. Tja, dann entweder von Hand machen oder GUI Builder wechseln. Wenn iwelche Konventionen aus einem Buch oder von WIKI dagegen sprechen, dann Konvention ignorieren.

Wenn deine GUI Zugriff auf das Model oder den Controller benötigt, dann wirst du eine Referenz übergeben müssen.

Ich mache das immer so:

new Controller();

Controller.loadModell();

Controlleer.showGUI();

ende.
 

P@u1

Aktives Mitglied
Im Prinzip hast du Recht.

Aber trotzdem muss ich um "Modell, Logik und die Darstellung zu trennen" ja erstmal genau wissen, was ein Modell ist.
Im Internet finde ich da verschiedene Ansätze zu.
Manchmal werden Domänenobjekte als Modell benutzt, manchmal aber auch spezielle Modelle, die auf die view abgestimmt sind.

Und "Logik" ist mmn auch nicht ganz klar. Ich versuche immer alle Domänenlogik in eigenen Klassen unterzubringen. Ich nehme mal an, dass du mit Logik jetzt Präsentationslogik meinst.
 

DanZ

Bekanntes Mitglied
Ich würde Marcinek zustimmen, wichtig ist Modell, Logik und Darstellung zu trennen, Patterns werden überwertet :). Als Modell würd ich hier tatsächlich die Klassen zur Datenkapselung sehen, deine Hauptmodellklasse wäre also Chessboard. Die Modellklassen sollten meiner Meinung nach dann aber auch keine Logik enthalten sondern wirklich nur die Daten halten und geeignet zur Verfügung stellen Sie kann natürlich noch Util-methoden haben, um e.g. eine Figur zu verschieben. Diese Methode sollte dann aber nicht checken, ob der Zug korrekt ist oder sowas. Auch sollte die View nicht auf diese Methoden zugreifen (können). Das sollte meiner Meinung nach komplett von der Logik gekapselt werden (e.g. View sagt "User will Stein verschieben" -> Logik überprüft, ob dieser Zug möglich ist und teilt es wenn ja dem Modell mit).

Noch was anderes: Wieso hast du jede Figur einzelnd als enum definiert. Wäre doch viel einfacher Typ und Farbe zu trennen. E.g. haben doch beide Könige die selbe Logik um die möglichen Züge zu berechnen aber mit deiner momentanen Methode kannst du garnicht feststellen, dass es sich um die selbe Figur handelt und nur die Farbe unterschiedlich ist.
 
M

maki

Gast
MVP ist ein konkretes Muster, im Gegensatz zu MVC, bei MVP ist dementsprechend auch nix "überbewertet", ist ja schliesslich kein allgemeines Blabla wie MVC.

Allerdings muss MVP von der "Plattform" unterstützt werden in form eines Frameworks/API, wie zB. bei SWT/JFace und GWT, einfach mal so aus dem Stand zu sagen "Ich mach jetzt mal MVP" geht schlicht nicht, ausser man schreibt sich sein eigenes Framework..

View und Model werden an den Presenter übergeben, weder Model noch View wissen etwas über den Presenter, das Model weiss natürlich auch nix über die View. Der Presenter kümmert sich u.a. um das "Binding" zwischen View und Model.
 

P@u1

Aktives Mitglied
Wenn ich als Model einfach nur das ChessBoard nehme, dann sehe ich da aber eine paar Probleme.

Erstmal muss ich dann in eine Domänenklasse das Observerpattern reintun, was ich nicht besonders schön finde, aber durchaus machbar ist.

Und dann muss die Logik dazu, wo welche Markierungen hinkommen (mögliche züge anzeigen, zurzeit angeklickte figur usw.), irgendwo anders hin.

In die View wäre schlecht, weil ich die selbe Logik dann doppelt schreiben müsste (für 2D und 3D ansicht).

Dann bleibt also nur der Presenter/Controller. Der hätte dann allerdings 2 verschiedene Aufgaben: Reagieren auf Benutzereingabe (beim klick auf nen feld ggf. ein zug durchführen) und aufbereitung der Rohdaten für die View. Das würde dann aber das Single Responsibility Prinzip verletzen.

Zu dem mit MVC vs. MVP: Eigentlich geht es mir nicht speziell um MVP, aber ich möchte von den Beschränkungen bei MVC loskommen, dass alles über observer synchronisiert werden muss und der Controller nicht direkt auf die view zugreifen darf. Außerdem kam mir MVP irgendwie moderner vor. Aber ich seh das auch so, dass das alles ähnliche Sachen sind. Im Prinzip ist es mir auch egal, ob wirs MVC oder MVP nennen.
Ich suche einfach nach einer Möglichkeit ein solches Muster bei dem Schachspiel mal anzuwenden um damit Erfahrung zu sammeln und es dann später auch bei anderen Sachen anwenden zu können.
 
Zuletzt bearbeitet:

Michael...

Top Contributor
Zu dem mit MVC vs. MVP: Eigentlich geht es mir nicht speziell um MVP, aber ich möchte von den Beschränkungen bei MVC loskommen, dass alles über observer synchronisiert werden muss und der Controller nicht direkt auf die view zugreifen darf.
Wo steht das? Der Controller darf eine direkte Assoziation auf die View besitzen. Oft wird ein Controller speziell für eine View entwickelt.
 

P@u1

Aktives Mitglied
Ich dachte, ich hätte es irgendwo gelesen.

Aber meinetwegen, dann mach ich halt MVC und nicht MVP (ich mach das gleiche und nenn es ab jetzt anders).

Für die Sache mit der Highlightlogik und dem Modell bin ich mir aber immer noch unsicher, wie ich das am besten umsetze.

Zum einen würde es sich ja anbieten, dass ChessBoard als Modell zu nehmen. Dafür könnte ich auch Observer einbaun, das würde soweit gehen.

Dann gibt es darüber hinaus aber auch noch die Highlights, die anzeigen, welche Züge möglich sind. Diese sind von ChessBoard nicht direkt abfragbar. Dafür braucht man bei unserer implementierung ein ChessLogics objekt, das auf einem ChessBoard-objekt arbeitet. Und dann muss man die ChessMoves noch in Punkte, die markiert werden sollen umwandeln.

Die alternative wäre, dass mit ins model zu packen und das modell dann das ChessBoard aggregieren zu lassen.
Hier wurde aber genannt, dass das Modell keine logik enthalten sollte usw.

Gehört eurer Meinung nach diese Logik dann eher in den controller oder ins modell?
Wenn in den controller, wie wird dem Modell dann bescheid gesagt, einfach mit setHighlights() oder sowas?
 

P@u1

Aktives Mitglied
Ok und das modell speichert dann das chessboard als privates attribut um die Belegung des felds zurückgeben zu können und dazu werden dann weitere attribute für die highlights hinzugefügt?

Und wie mach ich das eigentlich, wenn da jez noch mehr komponenten hinzukommen?
Folgendes soll in kürze dazukommen:
-eine chatbox
-eine anzeige der geschlagenen figuren
-eine statusanzeige
-ein Dialog zum einloggen und suchen eines spiels

Wieviele Models/Views/Controller benutze ich dafür dann am besten?

Ich könnte mir z.B. vorstellen, dass die Anzeige der geschlagenen figuren, die statusanzeige und die schachfeldanzeige sich ein modell teilen. Oder ist das eher schlecht?

Die statusanzeige und die liste der geschlagenen figuren brauchen keinen controller, weil sie nur ausgabe machen.

Und für die Chatbox würde ich dann einen controller benutzuen, der das eingegebene per internet verschiockt und nachrichten übers internet empfängt. Eine explizite view würde ich mir dann dafür sparen, weil es ja einfach nur eine textbox ist.

Und für den dialog zum einloggen und suchen vom spiel dann wieder ein model,view,controller trippel. Und der controller davon muss dann mit anderen controllern kommunizieren (z.B. dem der das schachspiel managed, damit dieser das gestartete spiel ausführen kann).

Und ich würde die controller gerne so halten, das ich für die 2d gui und die 3d gui die selben controller benutzen kann und nur neue views brauche. Das ist doch so machbar, oder?
 

P@u1

Aktives Mitglied
Es wurde ja vorher genannt, das das Modell NUR daten enthalten soll und keine Logik.

Ich habe dazu nochmal ein bischen nachgelesen und z.B. sagt das englische Wikipedia:
The model manages the behavior and data of the application domain
. Einige andere Seiten sagen ähnliches.

Und ich finde das auch sinnvoll, da logik drin zu haben. Es existieren ja im Normalfall sowieso schon objekte aus der anwendungsdomäne die daten und logik beinhalten, die als Modell oftmals zu gebrauchen sind (domain model).

Das Problem ist nur, was man mit zusätzlichen Daten, wie z.B. Selektionen usw. macht.
Man könnte entweder als Modell einen Wrapper um das domain model bauen und dann zusätzlich noch selectionen und so weiter hinzufügen.
Oder man packt das mit in den controller oder in die view.
Beides hört sich nicht so besonders toll an.
 
M

Marcinek

Gast
Hast du überhaupt mal eine Variante implementiert??

Einen Satz zusammenhanglos hier zu Posten bringt dich nicht viel weiter. Welche probleme auftauche können sieht man auch mal, wenn man mal angefangen hat das zu tippen, was man ellenlang im Forum diskutiert ;).
 

P@u1

Aktives Mitglied
Ja, ich habe das implementiert, indem ich einen Wrapper um das Domainmodel geschrieben habe.
Das Domain-Model ist ChessField und den Wrapper, der als Modell für die View fungiert habe ich ChessViewModel genannt. Dort werden zusätzlich noch informationen zu Selektionen abgespeichert.

Es geht mir aber nicht dadrum, das irgendwie fertig zu kriegen, sondern zu lernen, wie ich MVC sinnvoll anwenden kann um das auch bei späteren Projekten nutzen zu können.
Und ich habe bisher nicht viel dazu gefunden, wo Sachen wie Selektionen reingehören.
Falls es ins Modell rein soll, dann muss man ja einen solchen Wrapper schreiben, wie ich es gemacht habe.
Es gibt da aber noch andere Möglichkeiten.

Und Probleme an dem Entwurf werden erst sichtbar, sobald das Projekt größer ist. Bei einem kleinen Projekt kann man auch problemlos alles in eine Klasse packen. Sobald das Projekt aber wächst, kriegt man früher oder später Probleme.
Außerdem bin ich ein Freund der Theorie :)
Deswegen würde ich gerne schon jetzt über den Entwurf diskutieren.

Und jetzt steht ja auch gerade eine Erweiterung an und da bin ich mir ja auch nicht sicher, in wieviele (kleine oder große) controller, modells und views ich das am besten zerlegen sollte.
Ich kann jetzt natürlich wieder einfach irgendeine Variante implementieren, aber wenn ihr da bereits Erfahrung habt, könnt ihr mir ja vielleicht auch im Vorraus ein paar Tipps dazu geben.

Wenn ihr irgendwelche guten Tutorials/Videos/Bücher/Beispiele zu MVC kennt, dann wäre das auch sehr hilfreich.
An Beispielen find ich immer nur sehr kleine Sachen, die so abgespeckt sind, dass sie im Prinzip nichts nützen.
 
Zuletzt bearbeitet:

Michael...

Top Contributor
Die Implementierung einen MVC Patterns ist immer anwendungspezifisch. Es gibt m.M. hier kein richtig oder falsch. Als Vorlage/Inspiration könnte man sich ja Java eigene Implementierungen anschauen, zumindest für den Model-View-Anteil wäre so was wie die JTable mit ihrem TableModel und ListSelectionModel eine mögliche Basis.
 
Ähnliche Java Themen

Ähnliche Java Themen


Oben