![]() |
AW: Konzeptfrage: Interface oder Messages
und noch ein wenig Code zum Beispiel, in welche Richtung hier meine Gedanken gehen:):
Dat Interface:
Delphi-Quellcode:
Da Master
TYPE
TMasterData = record id : integer; status : integer; text : String; end; IDetail = INTERFACE; IMaster = Interface PUBLIC function getItem(index:integer):TMasterData; procedure setItem(const index:integer;const data:TMasterdata); Property Items[index:integer]:TMasterData read getItem write setItem; procedure setDetail(element:IDetail); Property Detail:IDetail write setDetail; Procedure NewElement(data:TMasterdata); Procedure DeleteElement(data:TMasterdata); End; IDetail = Interface PUBLIC Procedure SetMaster(element:IMaster); Property Master:IMaster write setMaster; Procedure AddNew(); Procedure Edit(id:integer); procedure Delete(id:integer); End;
Delphi-Quellcode:
Ein PKW
uses
MyInterfaces; TYPE PMasterdata = ^TMasterdata; TNavi = class(TObject,IMaster) PRIVATE datalist : TList; PROTECTED : : : PUBLISHED : : : PUBLIC function getItem(index:integer):TMasterData; procedure setItem(const index:integer;const data:TMasterdata); Property Items[index:integer]:TMasterData read getItem write setItem; procedure setDetail(element:IDetail); Property Detail:IDetail write setDetail; Procedure NewElement(data:TMasterdata); Procedure DeleteElement(data:TMasterdata); end;
Delphi-Quellcode:
Ein Hoverboard
uses
MyInterface; TYPE TPKW = Class(TObject,IDetail) PRIVATE ffarbe : Tcolor; fleistung: Integer; fmarke : TPKWMarke; fstatus: integer; fid : integer; PROTECTED PUBLISHED property Farbe:TColor read ffarbe write ffarbe; property Leistung:integer read fleistung write fleistung property Marke : TPKWMarke read fmarke write fmarke Property ID:integer read fid write fid; PUBLIC Procedure SetMaster(element:IMaster); Property Master:IMaster write setMaster; Procedure AddNew(); Procedure Edit(id:integer); procedure Delete(id:integer); End;
Delphi-Quellcode:
Nur mal zur Verdeutlichung grob hingezimmert. :)
uses
MyInterface; TYPE THoverboard = Class(TObject,IDetail) PRIVATE fid : integer; fstatus : integer; fname : string; fflughoehe : integer; fakkuleistung : double; PROTECTED PUBLISHED Property ID:integer read fid write fid; property Status: integer read fstatus write fstatus; : : PUBLIC Procedure SetMaster(element:IMaster); Property Master:IMaster write setMaster; Procedure AddNew(); Procedure Edit(id:integer); procedure Delete(id:integer); End; |
AW: Konzeptfrage: Interface oder Messages
Ok, ich würde das über Observer angehen.
Listboxen können sich z.B. bei einer PKW-Liste registrieren. Wird etwas in der Liste geändert, werden alle Beobachter informiert und werden sich daraufhin neu zeichnen. Die Einträge einer Liste wiederum können sich als Beobachter bei einem Datenobjekt eintragen. Eine Detailview kann sich bei einer Liste anmelden und wird informiert, wenn sich ihr aktueller Eintrag verändert. Die View kann sich dann das aktuelle Objekt von der Liste abrufen (es muss nicht die ID sein, weil ja ohnehin dort ein Objekt vorliegt) und seinen Inhalt neu zeichnen. Wird dort ein Wert des Datenobjektes geändert, muss das nicht die View an die Listbox melden weil ja die Listboxitems schon ihr Datenobjekt beobachten und sich bei Änderungsinformationen ohnehin neu zeichnen. Also müssen i.d.R. die Controls untereinander kaum kommunizieren (außer die Meldung einer Liste an angemeldete Views bei einem Recordwechsel, da die aktuell ausgewählte Recordzeile nichts im Datenmodell zu suchen hat). Ob Du Die Observerliste über Interfaces oder Objekte (vielleicht mit gemeinsamen Basisklassen) organisierst ist Geschmacksache. Ich würde jedenfalls die gegenseitige Abhängigkeit der Controls möglichst gering halten. NACHTRAG: Zitat:
Aber über die Beobachterliste kann man ja alle Interessenten anschauen und entscheiden, welche Informationen diese erhalten sollen. Interfaces muss man hierbei nicht verwenden. Es bringt ein paar Vorteile, aber auch mehr Aufwand. |
AW: Konzeptfrage: Interface oder Messages
Liste der Anhänge anzeigen (Anzahl: 1)
Öhmmm......ok.....ich hab mal gemalt. :)
Dabei sind die schwarzen Verbindungen der Datenfluss. Die grünen mein Ansatz. Die roten dein Vorschlag. (Ich hoffe ich hab dich da richtig Verstanden). Nochmal im Detail Zitat:
Zitat:
Zitat:
rausfliegen würde. Mehr würde da aber auch nicht drüber laufen. Da die Liste nicht alle Daten eines Datensatzes hat, kann die Detailview auch ihre daten nicht von der Liste bekommen. Wär auch nicht grad sinnig, den Hauptspeicher mit den ganzen Datensätzen zu zupflastern. :) Zitat:
Die Detailview übergibt die (eingegeben) Daten an ihr Datenobjekt (einzelner, kompletter DS), dieses Informiert seine Beobachter (u.a. die Datenliste) über die Veränderung. Die Datenliste wiederum informiert den Listview, das er sich neu zeichnet. hmmm.... |
AW: Konzeptfrage: Interface oder Messages
Ok..nach dem ich da nochmal in mich gegangen bin hab ich das jetzt glaub ich verstanden (ignorier einfach die roten und grünen Linien...passen nicht).
Aber letztlich würde das Observer-Pattern hier nur die "Richtung" ändern (statt linksrum, rechtsrum :)) Aber worum es mir eigentlich ging ist mehr die Implementierung. Eben ob Interfaces oder Messages (via PostMessage/SendMessage), oder wie auch immer. :) |
AW: Konzeptfrage: Interface oder Messages
Ich verwirre Dich wohl mehr als geplant. ;-)
Ich war zuletzt davon ausgegangen, dass Du dem Formular alle Daten in Form von Objekten bzw. Objektlisten bereitstellt. Wenn das Formular zur Anzeige der Daten nochmal auf die Datenbank zugreifen muss, sieht das natürlich noch etwas anders aus. Dann kannst Du keine Objekte zur Benutzung übergeben sondern tatsächlich die Datensatz-Ids. Grundsätzlich haust Du m.E. die Datenschicht und die Formularschicht zu sehr durcheinander. Versuche doch mal, das noch konsequenter zu trennen. Dafür gibt es verschiedene Möglichkeiten. Am einfachsten, alles was die Datenmanipulation betrifft in eine eigene Unit auslagern. Dann könntest Du theoretisch alle Änderungen ohne ein Formular durchführen. Z.B. in einer Methode oder über ein Script. Dann hast Du eine Datenschicht (und Businesslogik), die für sich funktioniert. Jetzt muss das Formular sich nur noch an diese Unit wenden und sagen, was es gerade braucht. Dann kannst Du eine PKW-Liste in Form von kompletten Objekten oder als DataSet übergeben. Auch kannst Du durch Aufruf bestimmter Methoden Änderungen in der Datenschicht veranlassen. Jetzt muss den Controls noch gesagt werden, was und wie sie sich zeichnen und verhalten sollen. Dabei solltest Du aber auf die Zuständigkeiten achten. In einer PKW-Klasse hat m.E. AddNew, Edit(IrgedeineID) und Delete(IrgendeineID) nichts verloren. Der PKW ist nicht dafür zuständig, irgendwelche Listen zu manipulieren. Er ist ein Objekt und fertig. Wenn der User in der View, die gerade einen PKW anzeigt, einen neuen PKW in die originalliste hinzufügen können soll, dann muss die View auch die Originalliste kennen. Besser sollte aber AddNew und Delete irgendwie über die Listbox selbst ermöglicht werden (ähnlich einem DBNavigator). Der PKW sollte üblicherweise auch nicht die Liste kennen, in der er enthalten ist - es sei denn, dies wäre aus dem Datenmodell heraus sinnvoll (Sohn muss seinen Vater kennen).
Delphi-Quellcode:
TPKW = Class(TObject,IDetail)
PRIVATE ffarbe : Tcolor; fleistung: Integer; fmarke : TPKWMarke; fstatus: integer; fid : integer; PROTECTED PUBLISHED property Farbe:TColor read ffarbe write ffarbe; property Leistung:integer read fleistung write fleistung property Marke : TPKWMarke read fmarke write fmarke Property ID:integer read fid write fid; PUBLIC Procedure SetMaster(element:IMaster); Property Master:IMaster write setMaster; Procedure AddNew(); // ??? Procedure Edit(id:integer); // ??? procedure Delete(id:integer); // ??? End; Ich denke, wenn Du Dich erst konkret um das Daten- und Geschäftsmodell kümmerst und erst als nächsten Schritt um die GUI wird es übersichtlicher. Aber mal sehen, vielleicht kann ja noch jemand anders besser helfen. |
AW: Konzeptfrage: Interface oder Messages
Also ich würde das mit Messages machen, aber nicht die Windows-Versionen, die haben zuviel Programmier-Overhead.
Schau dir mal ![]() ich weiss nur nicht ob du TurboDelphi hast, könnte sein das es da noch nicht drin ist. Die sind schlank, einfach zu handhaben, arbeiten mit Generics und anonymen Methoden und erfüllen ihren Zweck 100%. Die Messages finde ich mittlerweile viel handlicher als alles andere, weil man mit ihnen auch perfekt die Module enkoppeln kann. Selbst mit Interfaces hatte ich schon "Segmentation fault" gesehen, allerdings unter Android. Wenn du nur bei Windows bleibst ist aber wohl beides OK, aber trotzdem TMessage<TXyz> hat schon was ... Rollo |
AW: Konzeptfrage: Interface oder Messages
@Rollo
Nein, TD kennt das so nicht (schon gleich nicht mit Generics) :) Hab mir mal trotzdem den Wiki-Eintrag angeschaut und letztlich ists nicht viel anders als PostMessage/SendMessage (wenn auch um einiges bequemer :) ). Ein zentraler Manager (Messageloop) nimmt nachrichten von registierten sendern entgegen und leitet sie an die registrieren empfänger weiter :) |
AW: Konzeptfrage: Interface oder Messages
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Die Listview wendet sich an das Listen-Daten-Objekt um Daten für die Anzeige zu bekomen. Genauso wie sich die Detailview sich an ihr Datensatz-Daten-Objekt wendet um Daten zu bekommen bzw Daten zu manipulieren (vgl. Schaubild). 1. Kommunikations-Weg ohne Observer bei Änderung eines Datensatzes durch Detailview User änder Daten in Detailview -> Detailview schickt die Daten an Datensatz-Daten-Objekt(DDO) -> DDO ändert die Datenbank -> Detailview schickt nachricht an Listview -> Listview fragt Listen-Daten-Objekt (LDO) nach frischen Daten -> LDO aktuallisiert seine Daten von der DB ->Listview zeichnet sich neu. 2. Kommunikations-Weg mit Observer (so wie ich dich Verstanden hab): a)Registrierung LDO registriert sich bei DDO als Listener, die Listview registriert sich als Listener bei der LDO (Den Rückweg lass ich mal der einfachheithalber außer Acht) b) Der Weg Wie unter 1. ändert der User die Detailview -> diese sagt dem DDO, das es die Daten ändern soll -> DDO änder die Daten in der DB -> DDO schickt Nachrichten an seine Listener ->LDO bekommt nachricht und aktuallisiert seine Daten aus der DB->Benachrichtigt seine Listener, das es sich geändert hat->Listview zeichnet sich neu Der Unterschied zwischen 1 und 2 ist also, das nicht die UI untereinander kommuniziert (wie bei 1), sonder die Datenobjekte untereinander (was nach etwas Überlegung auch mehr Sinn ergibt). |
AW: Konzeptfrage: Interface oder Messages
Ja genau.
So wird das übersichtlicher. Die Listbox interessiert sich, wenn sich etwas an der Datenliste ändert. Also muss sie eine Info aus der Datenschicht bekommen: "Datenliste geändert". Die DetailView interessiert sich für ein Datenobjekt und muss dazu eine Änderungsmeldung erhalten. Aber die Listbox muss zusätzlich ihre DetailView kennen um sie zu beauftragen, jetzt ein anderes Datenobjekt anzuzeigen. Wenn jede Listbox genau eine DetailView hat, kann sie direkt die Instanz der View kennen. Ansonsten kann sie mehrere Views in einer Liste verwalten und nacheinander ansprechen oder sie kann einen Rundruf in die Welt senden und alle Views entscheiden selbst, ob sie darauf reagieren. Diese Nachricht einer Listbox an ihre DetailView(s) ist aber m.E. die einzige notwendige Kommunikation zwischen den Controls. Alles andere sollte über die Datenschicht kommuniziert werden. Dazu kann wiederum jedes Datenobjekt alle seine zuständigen Controls kennen und denen eine Änderungsnachricht schicken (Observer) oder die Datenschicht setzt ein Flag DataIsInvalidate und das Formular prüft zyklisch (in einem Timer oder in OnIdle), ob das gesetzt ist und veranlasst seine Controls, sich neu zu zeichnen. Beides hat Vor- und Nachteile. Jedenfalls sollte aus der DetailView heraus nach eine Datenänderung nicht noch eine Listbox oder ein anderes Control über die Änderung informiert werden müssen. Sonst wird vielleicht irgendwann einmal durch einen Job eine automatische Änderung der Daten durchgeführt und Du weißt gar nicht, welche Controls diese Daten anzeigen und welche Du jetzt eigentlich informieren musst weil die Änderung ja jetzt nicht in einer View veranlasst wurde. In Deiner Skizze hast Du jetzt quasi schon einen ORM dargestellt. Alle Zugriffe der Controls werden über Datenobjekte gemappt. Vorher hattest Du mal erwähnt, dass die Objekte nicht alle Datenbestandteile beinhalten und die GUI deswegen noch Daten aus der Datenbank holen müssen. In dem Fall wäre Deine Skizze so noch nicht korrekt. Also Du musst Dir überlegen, ob sämtliche Zugriffe auf die Daten über Objekte erfolgen sollen oder ob sich das Formular auch noch Daten aus der Datenbank holen muss. Davon ist dann auch nochmal abhängig, wie man das Projekt organisiert. Wenn Du nicht alles vollständig über Daten-Objekte handelst kann man sich auch überlegen, auf Objekte und Interfaces zu verzichten und die Datenzugriffe über Querys auf die DB zu organisieren. Wichtigstes Fazit aus meiner Sicht: Kommunikation zwischen Controls nur, soweit sie sich auf die GUI-Logik bezieht (abhängige Controls bei einem Datensatzwechsel informieren). |
AW: Konzeptfrage: Interface oder Messages
:-D:-D
Zitat:
Was ich meinte war eigentlich nur das in der LDO (und damit auch im Listview) nur die Daten vorgehalten werden, die zur Anzeige notwendig sind (also z.B. ID und Marke vom PKW), dafür aber mehrer Sätze, wärend im DDO (und damit in der Detailview) nur ein satz vorgehalten wird (der der zur Anzeige/Änderung notwendige), dafür aber mit allen feldern des DS (also id,marke,farbe,leistung usw...eines PKW) :) Im Moment spiel ich grad ein bischen mit dem Observer-Pattern rum und versucht mich in einem Testprojekt damit. Leider gelingt mir grad die Abstraktion nicht so ganz (in den Basis-Klassen kenn ich ja die konkreten Daten, die bei einer Notification übergeben werden noch garnicht). |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:03 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz