Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   MVC -- Kommunikation unter Controllern?! (https://www.delphipraxis.net/163773-mvc-kommunikation-unter-controllern.html)

s.h.a.r.k 15. Okt 2011 01:03

MVC -- Kommunikation unter Controllern?!
 
Hallo zusammen,

habe mich in letzter Zeit immer mehr dazu durchgerungen das MVC-Pattern für meine Applikationen zu nutzen. Nun habe ich aber folgendes Problem, da ich das ganze System eher von PHP-Frameworks her kenne: wie starte ich Aktionen eines Controllers, die nicht vom User angestoßen werden? Gibt es hier eine Art "Überstruktur" oder "Übercontroller"? Oder gibts es ein Konstrukt, welches gar kein Controller im MVC-Sinne ist?

Hintergrund ist folgender: ich hab einen Application-Controller geschrieben, der als "Bootloader" dient. Dieser startet alle möglichen Dinge (DB-Verbindung herstellen, Konfiguration laden, Startparameter verarbeiten, Splash-Screen darstellen, MainForm darstellen etc.) und muss somit ja auch andere Controller und deren Aktionen zugreifen. Ist sowas in diesem Pattern gewollt? Oder wie löst man sowas sonst?

Vorstellbar ist hier auch das Problem, dass eine Aktion immer wieder aufgerufen werden, oder allgemein gesprochen der Zugriff auf eine Aktion nicht vom User hervorgerufen werden soll, sondern von einem Programm/Code.

Bin über jeden Tipp dankbar :)

Sir Rufo 15. Okt 2011 01:37

AW: MVC -- Kommunikation unter Controllern?!
 
Ich lege mir für solche "Übercontroller" Klassen (nach Bereichen - z.B. Verbindung zur DB) an, wo diese gespeichert werden.
Die Klasse selber leite ich von TComponent ab und gebe der Instanz als Owner Application mit.

Aber für eine Aktion egal welcher Art muss es doch ein Event geben ... und sei es nur ein Timer der feuert ...

s.h.a.r.k 15. Okt 2011 01:57

AW: MVC -- Kommunikation unter Controllern?!
 
Das mit dem immer auftretenden Aufruf war auch nur ein Beispiel. Es geht dabei eher darum, dass Aktionen von Controllern nicht vom User selbst (Click auf Button z.B.) aufgerufen werden, sondern von z.B. einem Programmcode -- in meinem konkreten Beispiel wäre das der Startcode meiner Anwendung. Je mehr ich so darüber nachdenke, desto mehr glaube ich, dass ich so eine Überkomponente bauen sollte, die nicht mit dem MVC-Pattern direkt etwas zu tun hat. Diese ist dann -- in meinem speziellen Fall -- eben eine Art "Container", in dem dann alles abläuft, in dem dann auch die Controller "liegen", die eben ihre Aktionen anbieten.

Sir Rufo 15. Okt 2011 02:06

AW: MVC -- Kommunikation unter Controllern?!
 
Meinst du jetzt irgendwelche Instanzen oder einfach nur Units?

webcss 15. Okt 2011 09:40

AW: MVC -- Kommunikation unter Controllern?!
 
Zitat:

Zitat von s.h.a.r.k (Beitrag 1130590)
Je mehr ich so darüber nachdenke, desto mehr glaube ich, dass ich so eine Überkomponente bauen sollte, die nicht mit dem MVC-Pattern direkt etwas zu tun hat. Diese ist dann -- in meinem speziellen Fall -- eben eine Art "Container", in dem dann alles abläuft, in dem dann auch die Controller "liegen", die eben ihre Aktionen anbieten.

Im Prinzip hast Du diese Überkomponente schon: TApplication. Du kannst einen ApplicationController bauen, als wrapper für global Application, und hookst (<-was ein Wort) dort z.B. den OnMessage event von TApplication. Der Application Controller enthält eine Liste mit allen ChildControllern und leitet die Messages weiter, bis einer Handled true setzt (Chain of Responsability). Die VCL macht das eigentlich nicht anders, nur, das eben die Logik auf einer Form liegt, und nicht ausgelagert ist.

s.h.a.r.k 15. Okt 2011 10:14

AW: MVC -- Kommunikation unter Controllern?!
 
Zitat:

Zitat von Sir Rufo (Beitrag 1130591)
Meinst du jetzt irgendwelche Instanzen oder einfach nur Units?

Ein Controller ist bisher nur eine Klasse. Wie viele Instanzen ich davon habe kann ich dir pauschal leider nicht sagen, da ich das noch nicht komplett durchdacht habe. Ich wollte schon fast jeden Controller zu einem Singleton umbauen, aber bin mir da noch nicht so wirklich sicher, ob das sinnvoll ist.

Zitat:

Zitat von webcss (Beitrag 1130608)
Im Prinzip hast Du diese Überkomponente schon: TApplication. Du kannst einen ApplicationController bauen, als wrapper für global Application, und hookst (<-was ein Wort) dort z.B. den OnMessage event von TApplication. Der Application Controller enthält eine Liste mit allen ChildControllern und leitet die Messages weiter, bis einer Handled true setzt (Chain of Responsability). Die VCL macht das eigentlich nicht anders, nur, das eben die Logik auf einer Form liegt, und nicht ausgelagert ist.

Jup, ich habe bisher einen Wrapper für dieses TApplication-Objekt, wobei ich hier auf die Nachrichtenverwaltung nicht näher eingehe. Bisher unterstützt mich dieses Objekt nur beim "Hochfahren" und "Herunterfahren" der Anwendung. Insgesamt soll später mal eine Framework herauskommen, welches ich vor allem bei größeren Applikationen nutzen will.

Das mit den Messages muss ich mir mal anschauen, denn die Idee ist an sich nicht schlecht. Nur schaffe ich somit wieder Abhängigkeiten zwischen den einzelnen Controllern und deren Aktionen -- aber ich habe sowas ja eigentlich immer irgendwie, weswegen ich dann aber ein sinnvolles System aufbauen müsste, in so fern ich über Botschaften laufen will.

Mithrandir 15. Okt 2011 15:22

AW: MVC -- Kommunikation unter Controllern?!
 
Was du suchst, nennt sich Mediator-Pattern. Ich arbeite damit recht häufig privat, allerdings in Csharp: Jeder Controller hat eine Basisklasse, die wiederum einen statischen Mediator besitzt. So ist gewährleistet, dass jeder Controller dieselbe Instanz nutzt.

Kommuniziert wird klassisch, über String-Messages. Könnte man vielleicht auch mal ändern, muss man aber nicht. Jeder Controller muss sich dabei mit den Messages beim Mediator registrieren, für die er Nachrichten empfangen möchte.

Falls du ein bisschen C# kannst, kannst du dir ja mal dieses Beispiel ansehen und versuchen, dort etwas für dich abzuleiten. Mit Delphi kann ich leider nicht dienen. :cry:

webcss 15. Okt 2011 22:52

AW: MVC -- Kommunikation unter Controllern?!
 
Du solltest Dir auch mal TObject.Dispatch anschauen...
hier ist auch noch ein link dazu: The-quest-for-the-perfect-publish-subscribe-mechanism-in-Delphi
Ich arbeite an einem MVP framework und stehe vor demselben Problem :wink:

hoika 16. Okt 2011 08:44

AW: MVC -- Kommunikation unter Controllern?!
 
Hallo,

wer sagt, dass ein Controller nur Nutzer-Eingaben verwaltet.
Warum baust du dir keinen "System"-Controller, den du mit Anweisungen fütterst.
Dieser Controller führt die Anweisungen aus, so als wenn ein User selber geklickt hätte.


Heiko

s.h.a.r.k 17. Okt 2011 15:06

AW: MVC -- Kommunikation unter Controllern?!
 
Danke schon mal für die Gedanken und Hinweise! Vor allem bzgl. der Kommunikation der Controller untereinander bin ich nun sehr viel schlauer und werde dahingehend wohl einiges umbauen :thumb:

Seltsam finde ich auf die Dauer nur, dass mir sowas nicht viel früher über den Weg gelaufen ist und ich hier einfach zu wenig über genau sowas finde. Dachte schon ich habe sehr komische Probleme, die keinem anderen über den Weg laufen... :stupid:

webcss 17. Okt 2011 15:23

AW: MVC -- Kommunikation unter Controllern?!
 
An Deinen Erkenntnissen würde ich gerne teilhaben :wink:

Ich z.B. möchte die Kommunikation via Messages lösen, habe allerdings das Problem das ich alle möglichen Messages empfange, nur meine eigenen nicht... :gruebel:

Hast Du konkret eine Ahnung, wie ich die verschicken kann, damit ich sie auch empfange?
Meine Controller sind von TComponent abgeleitet, haben ein Handle und ein Wnd_Proc, aber sind für meine messages taub.

Gruß,
Clemens

Sir Rufo 17. Okt 2011 17:01

AW: MVC -- Kommunikation unter Controllern?!
 
Zitat:

Zitat von webcss (Beitrag 1130863)
An Deinen Erkenntnissen würde ich gerne teilhaben :wink:

Ich z.B. möchte die Kommunikation via Messages lösen, habe allerdings das Problem das ich alle möglichen Messages empfange, nur meine eigenen nicht... :gruebel:

Hast Du konkret eine Ahnung, wie ich die verschicken kann, damit ich sie auch empfange?
Meine Controller sind von TComponent abgeleitet, haben ein Handle und ein Wnd_Proc, aber sind für meine messages taub.

Gruß,
Clemens

Von Component ableiten ist ja schon gut, aber wozu haben die ein Handle?
Ich habe mal die Idee von dem FinalBuilder umgesetzt.

Da sieht das dann wie folgt aus:

Message-Typ definieren:
Delphi-Quellcode:
unit Msg.Foo;

const
  MSG_FOO = $1000; // kann beliebig gewählt werden (muss aber ein Cardinal sein

  MSG_FOO_AKTION1 = MSG_FOO + $1;

type
  TMsgFooAktion1 = packed record
    MsgID : Cardinal;
    Unused : array [1 .. 12] of Byte;
    Info : string;
    constructor Create( const AInfo : string );
  end;

implementation

{ TMsgFooAktion1 }

constructor TMsgFooAktion1.Create(const AInfo: string);
begin
  MsgID := MSG_FOO_AKTION1;
  Info := AInfo;
end;

end.
Jetzt mal den Controller
Delphi-Quellcode:
unit Ctrl.Foo;

uses
  Msg.Foo,
  MVC.ViewController;

type
  TCtrlFoo = class( TMVCCustomViewController )
  protected
    procedure DoMsgFooAktion1( var Message : TMsgFooAktion1 ); message MSG_FOO_AKTION1;
  end;

implementation

uses
  Dialogs;

procedure TCtrlFoo.DoMsgFooAktion1( var Message : TMsgFooAktion1 );
begin
  ShowMessage( Message.Info );
end;

end;
DIe Message wird nun wie folgt gesendet:
Delphi-Quellcode:
...
uses
  AppMsg,
  Msg.Foo;

...
var
  lMsg : TMsgFooAktion1;
begin
  lMsg.Create( 'Hello World!' );
  Publisher.SendMessage( lMsg );
end;
Die Unit
Delphi-Quellcode:
AppMsg
ermöglicht den Zugriff auf den Publisher (als Interface), an dem sich die Controller anmelden
Delphi-Quellcode:
Subscribe
oder abmelden
Delphi-Quellcode:
UnSubscribe
.
Dieses An- und Abmelden erfolgt schon automatisch durch die Controller-Basis-Klasse.

Sehr nett ist das vor allem im Hinblick darauf, dass man hierbei einfach diese Controller in die Luft erzeugen kann, und diese trotzdem
a) mit den Messages erreicht
und
b) am Ende der Anwendung automatisch aufgeräumt werden
Delphi-Quellcode:
TCtrlFoo.Create( nil );
und der Controller ist einsatzbereit :) (bis auf die Tatsache, dass dieser ViewController keine View bekommen hat ;) )

Ich schicke nachher mal die Units hier hoch.

webcss 17. Okt 2011 19:54

AW: MVC -- Kommunikation unter Controllern?!
 
Zitat:

Zitat von Sir Rufo (Beitrag 1130885)
Von Component ableiten ist ja schon gut, aber wozu haben die ein Handle?

Damit sie als Empfänger von Nachrichten erkannt werden bzw. adressiert werden können.
Zitat:

Zitat von Sir Rufo (Beitrag 1130885)
Ich habe mal die Idee von dem FinalBuilder umgesetzt.

Das hab ich auch schon gemacht und das funktioniert wunderbar, allerdings hat der Gedanke eines globalen Messengers sein "G'schmäckle". Ich wollte ihn zumindest als class var in die Controller Klasse einbauen, aber irgendwie hält der nicht die Subscriber, obwohl als klassisches object ohne RefCount eingebaut.

Außerdem wäre es schön, aus den Views heraus einfach messages auf dem bestehenden Weg zu schicken, eben ohne globalen Messenger (neben TApplication).

Sir Rufo 17. Okt 2011 20:29

AW: MVC -- Kommunikation unter Controllern?!
 
Nun es gibt einen globalen Messenger (per Default) der die Nachrichten für die Controls verschickt.
Jetzt baue ich einen weiteren parallel dazu, der die Nachrichten für/an die Controller verschickt.

Hmmm, wieso ist denn jetzt der eine Messenger ok und der andere mit einem Geschmäckle? :gruebel:

Der macht quasi nichts anderes ist aber für die Controller gedacht.

Da wir ja View Controller und Model trennen wollen und die Views einen Messenger haben, die Models keinen brauchen ist es meiner Ansicht nach für die Trennung nur konsequent einen Messenger für die Controller zu haben.

Und nur wenn der global ist, dann macht der auch Sinn, weil nur dann gewährleistet ist, dass ich alle Controller erreichen kann.

webcss 17. Okt 2011 20:37

AW: MVC -- Kommunikation unter Controllern?!
 
Zitat:

Zitat von Sir Rufo (Beitrag 1130936)
Und nur wenn der global ist, dann macht der auch Sinn, weil nur dann gewährleistet ist, dass ich alle Controller erreichen kann.

Du hast wohl recht, ich bevorzuge es halt lieber, bestehende Wege zu laufen und nicht neue parallel zu legen. :wink:

P.S. Die Models können das messagingsystem auch nutzen, um auf status/property änderungen aufmerksam zu machen...


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:59 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