Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   MVP richtig in Delphi implementieren? (https://www.delphipraxis.net/167787-mvp-richtig-delphi-implementieren.html)

normancz 18. Apr 2012 11:18

MVP richtig in Delphi implementieren?
 
Hallo,
ich möchte meine Formulare mit Hilfe vom Spring-Framework mehr in Richtung MVP/MVC/MVVM aufbauen. Aber irgendwie drehe ich mich dabei im Kreis, da die ganzen gegoogelten Infos in D2010 mangels Bindings, GC, etc. nicht so einfach zu implementieren sind.

Als Beispiel soll mal ein einfacher modaler Dialog dienen: dem User wird ein gegebener ganzzahliger Geldbetrag angezeigt und er soll ihn über Eingabefelder in 1, 2, 5 und 10EUR Stücke aufteilen. Direkt bei der Eingabe (OnChange) soll eine Summe und der Restbetrag aktualisiert werden. Beim Verlassen der Eingabefelder (OnExit) sollen diese Rot angezeigt werden, wenn z.B. negativ oder über ein gegebenes Limit.

Der Anwendungsentwickler erhält also irgendein Interface mit Properties für den Betrag, die Limits der einzelnen Felder, eine Execute-Methode und weitere Properties für die zurückgelieferten Eingabewerte. Nun die erste Frage: Was steckt nun hinter diesem Interface? Ist es der Presenter oder sollte es eher eine "Überklasse" sein, welche die MVP-Triad enthält?


So was brauche ich also:
- Eine Model-Klasse, angesprochen über IModel
Ist soweit klar: es enthält die nötigen Daten für den Dialog, also die ganzen Properties. Diese würde ich dann auch dem Anwendungsentwickler, z.B. über den Presenter, als Model-Property rausreichen.


- Eine View-Klasse, angesprochen über IView
Ich möchte eigentlich nicht die einzelnen Eingabeelemente als MVP-Klassen runterbrechen. Für Listen macht das vielleicht noch sinn, aber ein Eingabefeld als Integer-View welche über ein Integer-Presenter mit einem Integer-Model als Observer verbunden wird?

Ich dachte mehr an eine Art passiven View, wobei ich hier die Controls über Wrapper-Klassen als Interfaces rausreiche (wie hier) und die Events bzw. anonyme Methoden dann auch nur das Interface als Sender sehen.

Aber hier taucht schon das nächste Problem auf: ein Formular als Interface hat keine Referenzzählung. Damit kann ich es zwar leicht im Konstruktor des Presenter über DI einbinden, muss dann aber daran denken es im Destruktor wieder frei zu geben. Wenn ich das View irgendwann mal gegen ein referenzgezähltes View (oder eine einfache Mock-Klasse) austausche dann knallt es.

Alternativ könnte ich das Formular auch in eine Wrapper Klasse einbinden und dort die Control-Interfaces erzeugen. Nur dann können dies nicht für einfache Validierungen im Formular genutzt werden. Was wäre die bessere Lösung?


- Eine Presenter-Klasse, angesprochen über IPresenter
Ist soweit auch klar: Diese erhält IView und IModel über DI vom Konstruktor und sorgt für den Datenaustausch zwischen Model und View, sowie macht die nötigen Validierungen und Berechnungen selbst bzw. über das Model.

Hier habe ich das Problem, dass das View bei komplexeren Dingen den Presenter kennen sollte. Nur wenn ich den Presenter direkt als Interface (und nicht als Pointer) verlinke, dann kann ich den Presenter nicht dem Anwendungsentwickler zur Verfügung stellen da er nie freigegeben wird. Zudem bekomme ich dann Probleme mit zirkulären Units.


Unterm Strich weiss ich nicht so richtig wie ich anfangen soll. Entweder habe ich viel Code für Wrapper/Zusatzlayer und "Überklassen" oder ich muss zu viel tricksen (Interfaces über Pointer, Freigabe des View-Interfaces) und hoffen das mir das nicht mal später um die Ohren fliegt.

Die MVVM-Lösung mit DSharp gefällt mir, aber mein Delphi 2010 ist davon nicht so begeistert und wirft interne Fehler oder stellt die Arbeit gleich ganz ein.

Wie also am besten vorgehen?

Danke, und Ciao
Norman

stahli 24. Apr 2012 20:03

AW: MVP richtig in Delphi implementieren?
 
*foreign push*
(hoffe, das ist erlaubt ;-))

Stevie 29. Apr 2012 02:41

AW: MVP richtig in Delphi implementieren?
 
Ich wünschte, jedesmal, wenn irgendjemand nen Post schreibt, in dem DSharp vorkommt, bekomm ich ne PM oder so ;)

Erstmal mein ehrliches tiefes Beileid, dass du Delphi 2010 nutzt. Dort DSharp (bzw allgemein Source mit Generics etc) zum Laufen zu bringen, ist auch für mich das eine oder andere Mal ein Graus. :evil:

Ich muss nochmal nachfragen: möchtest du "nur" eine Trennung von GUI und Businesslogik oder auch noch die Steuerung über einen DI Container?
Zweites gestaltet sich zugegebenermaßen nicht immer so einfach durch die Gegenspieler TComponent und IInterface (bzgl der Steuerung ihrer lifetime).

Ich gehe hier erstmal auf den ersten Punkt ein, da er imo einfacher zu realisieren ist. Ich würde hier eine Art MVVM ohne extra ViewModel benutzen. Also eine Klasse, die die "Geldaufteillogik" und die entsprechenden Properties: wie viele 1, 2, 5, 10 Euro und Gesamtbetrag beinhaltet.

Diese sind mit Bindings ganz einfach an dein View knüpfbar. So weit, so gut. Man kann nun die unterschiedlichen Beträge einstellen.

Die Visualisierung kannst du unterschiedlich gestalten. Eine Möglichkeit wäre ein extra ViewModel, in der du die Eigenschaften, die du visuell darstellen willst (rot markierte Controls, Warnsymbol, ausgegrauter OK Button, etc) extra definierst und sie bei Änderung der einzustellenden Properties (die Anzahl der Geldbeträge in dem Beispiel)

Eine andere Möglichkeit, wäre mit Bindings und ValueConvertern. Zum Beispiel ein negativer Betrag auf clRed oder ähnliches.


Ob du nun das ganze händisch zusammen baust oder über einen DI Container, ist die anschließende Entscheidung. Auch, inwieweit der DI Container genutzt wird. Dient er nur als Container für einige Teile oder wird er schon von Anwendungsstart (wie z.B. im ContactManager Beispiel von DSharp) an genutzt. Davon hängt nämlich dann ab, wie du mit der "TComponent vs Interfaces" Sache umgehst (hab gerade keinen Link, aber die Sache haben wir hier im Forum auch schonmal besprochen). Auch die Art und Weise, wie du dann View und (View)Model zusammen setzt, hängt davon ab.

BlackSeven 20. Mai 2012 11:34

AW: MVP richtig in Delphi implementieren?
 
Hallo Stevie!

Wie kann ich mit DSharp/MVVM auf die Ereignisse verschiedener VCL-Controls bzw. Drag & Drop reagieren und bearbeiten?
Was ist da die beste Herangehensweise?


Gruß

Stevie 23. Mai 2012 10:05

AW: MVP richtig in Delphi implementieren?
 
Außer beim TreeviewPresenter gibt es keine eingebaute Logik, die das abhandelt.

Ich würde je nach Anwendungsfall empfehlen, zwar die entsprechenden Events zu benutzen, aber so wenig wie möglich auf die Controls bezogen zu sein.

Als Beispiel sollen mal 2 Listen dienen, bei denen ich aus der linken Liste Elemente auswählen kann und sie in die rechte Liste packen kann. Unabhängig von Drag&Drop wird es eine Methode im VM geben, um dies zu tun (so in der Art: RightList.Add(LeftList.SelectedItems)). Diese Methode kann man also im entsprechenden Event aufgerufen werden. Andere Events, die z.B. steuern, ob ich überhaupt ein Element auf ein Control droppen kann etc können analog dazu implementiert werden.

BlackSeven 23. Mai 2012 10:28

AW: MVP richtig in Delphi implementieren?
 
Gibt es dafür ein einfaches Beispiel?
MVVM/MVP ist für mich relativ neu.

Stevie 24. Mai 2012 08:50

AW: MVP richtig in Delphi implementieren?
 
Ich hab grad mal unter Samples\MVVM\DragDrop ein kleines Beispiel commited.

BlackSeven 24. Mai 2012 08:56

AW: MVP richtig in Delphi implementieren?
 
Danke.

Deine Hilfsbereitschaft weiß ich sehr zu schätzen!


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:16 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz