Delphi-PRAXiS
Seite 4 von 4   « Erste     234   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Interface richtig umgesetzt? (https://www.delphipraxis.net/183251-interface-richtig-umgesetzt.html)

alda 26. Dez 2014 15:37

AW: Interface richtig umgesetzt?
 
Zitat:

Zitat von DJ-SPM (Beitrag 1284718)
Allerdings habe ich auch verstanden, dass sich die Methode "SendMessage" um alles kümmern soll. Trotzdem habe ich noch obiges Problem. Würde ich nur eine Klasse erstellen, würde ich zwar die Vorteile des Interfaces verlieren, aber da hätte ich diese Probleme nicht. Habe ich noch ein altes Klassendenken? :lol:

Ja, ich würde sagen das ist eine Mischung aus "altem Klassendenken" und vor allem alten Methodiken.

Ich denke Sir Rufo bringt es hier auf den Punkt:
Zitat:

Zitat von Sir Rufo (Beitrag 1284721)
Und schon gehören die zusammen. Das ist wie Lego. Man hat kleine Steine und steckt sich da größere, spezialisierte Dinge zusammen.

Das schwierigste hierbei ist die einzelnen Aufgaben und vor allem die verschiedenen Rollen (Post-Mitarbeiter, Kunde etc. ) korrekt zu identifizieren und zu implementieren (was hier ja sehr gut anhand des Post-Beispiels erläutert wurde). Was hierbei auch hilft ist einfach jede Implementierung zu testen - kannst Du eine Implementierung mal nicht richtig testen, ist Deine Klasse zu groß und Du solltest Dir was andres überlegen um den entsprechenden Code testbar zu machen. Wo man "früher" Funktionalität durch unzählige Vererbungshierarchien verfügbar (und untestbar) gemacht hat, liegt heute der Schwerpunkt auf der Aggregation von Funktionalitäten (den flexiblen Lego-Bausteinen).

TheMiller 26. Dez 2014 16:46

AW: Interface richtig umgesetzt?
 
Danke für die Antworten. Ich habe das alles jetzt mal umgesetzt und die Parameter in den Konstruktor gepackt. Das kann so nicht richtig sein.

Nochmal ganz konkret: Ja, ich rufe nur noch SendMessage() auf und die ganze Magie passiert in der implementierenden Klasse, weil mich das nicht interessiert was da vor sich geht. Okay. Doch wenn die Queue nicht existiertm, muss sie erst angelegt werden. Dann muss ich doch sagen können, wie sie angelegt werden soll.

Parameterübergabe entweder im Konstruktor oder garnicht. Richtig? Im Interface bei Send/Receive kann ich sie auch nicht übergeben, da die Send-Parameter bei MSMQ andere sind, also bei anderen Queues oder via TCP. Also müssten sie alle im Konstruktor übergeben werden - auch die, die vllt. gerade garnicht benötigt werden.

Oder muss ich mich dann auf Standard-Werte festlegen. Wenn eine Queue also nicht existiert, wird sie halt immer mit den von mir in der implementierenden Klasse festgelegten Standardwerten festgelegt. Also zB immer nicht transaktionell und nie weltlesbar.

Nun aber zur Umsetzung: Dies wären die möglichen Parameter:

MSMQ Create: Pathname, IsTransactional, IsWorldReadable
MSMQ Open: Formatname, Access (MQ_READ_ACCESS etc..), ShareMode
MSMQ Send: Subj, Body, DestinationQueue, Transaction
MSMQ Receive: Transaction, WantDestinationQueue, WantBody, ReceiveTimeout, WantConnectorType

Delphi-Quellcode:
  IMy_MQReceiver = interface
  ['{EECD3A9D-D9BC-4644-9D69-DADE10E65ED2}']
    function ReceiveMessage(): String;
  end;

  IMy_MQSender = interface
  ['{5C3F02B1-2E73-4500-9CD3-02EAFEDB332C}']
    function SendMessage(subject, msg: string): Boolean;
  end;

  TMQBroker = (mqMS, mqActiveMQ);

  TMy_MSMQ = class(TInterfacedObject, IMy_MQSender, IMy_MQReceiver)
  private

  public
    constructor Create(createPathName: String; createTransactional, createWorldReadable: Boolean; openAccess, openShareMode: LongInt; openFormatName: String; readTransaction: LongInt; readWantBody: Boolean; readTimeout; sendDestQueue: IMSMQQueue3; sendTransaction: LongInt);
    destructor Destroy();
    function ReceiveMessage(): String;
    function SendMessage(Subject, msg: String): Boolean;
  end;

// Und so könnte dann das Erstellen des Objektes aussehen:
procedure TForm1.Button4Click(Sender: TObject);
var
  mq: TMy_MSMQ;
begin
  mq:=TMy_MSMQ.Create('meineNeueQueue', false, false, MQ_READ_ACCESS, MQ_DENY_SHARE, '.\Private\meineNeueQueue', 0, true, INFITE, nil, 0);
end;
Ich habe verstanden, dass sich das implementierende Objekt um alles kümmern soll. Aber ich muss doch irgendwie Einfluss darauf haben, wie es die Queue im Notfall erstellen soll.

Habe mich gerade länger damit beschäftigen können und verschiedene Methoden ausprobiert. Bin jetzt gerade etwas verwirrt ;)

Sir Rufo 26. Dez 2014 17:26

AW: Interface richtig umgesetzt?
 
Bis auf die Tatsache, dass du eine Schreib-Lese-Queue erzeugen möchtest ist das doch alles richtig. Ich wüsste keinen Fall, wo ich in ein und derselben Queue lesen und schreiben möchte. Queues sind One-To-One Verbindungen. Eine Nachricht in einer Queue wird von einem Empfänger empfangen. Will ich an mehrere Empfänger die gleiche Nachricht senden, dann muss die Nachricht auch in mehrere Queues.

Warum sollte es falsch sein, der implementierenden Klasse alles benötigte an die Hand zu geben um zu funktionieren?

Mal abgesehen, dass es für dich ungewohnt ist anscheinend nicht alles in der Hand zu haben, wo siehst du in deiner Anwendung das konkrete Problem?

Zeig doch mal etwas halbwegs konkretes, wo du beim Benutzen des Interfaces den Wunsch verspüren würdest, z.B. den Namen der Queue zu ändern, oder die Queue auf Transaktion umzustellen.

BTW

Das passt aber nicht
Delphi-Quellcode:
  IMy_MQReceiver = interface
  ['{EECD3A9D-D9BC-4644-9D69-DADE10E65ED2}']
    function ReceiveMessage(): String;
  end;

  IMy_MQSender = interface
  ['{5C3F02B1-2E73-4500-9CD3-02EAFEDB332C}']
    function SendMessage(subject, msg: string): Boolean;
  end;
Bei SendMessage hast du Subject und Message aber bei ReceiveMessage gibt es nur einen String zurück. Was kommt denn da? Subject, Message oder beides zusammengewürfelt?

TheMiller 26. Dez 2014 22:16

AW: Interface richtig umgesetzt?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1284744)
ist das doch alles richtig.

Ahhhhh. Das ist also der springende Punkt. Doch alle Parameter in den constructor. Das kannte ich so wirklich nicht. Kenne es eigentlich immer nur so, dass man so wenige Parameter wie möglich hat und dann auch nur die, die man wirklich braucht. Hier habe ich ja jetzt alle die dabei, die ich vielleicht mal irgendwie gebrauchen könnte. Auch die Anzahl war mir nicht geheuer. Aber da das nun bestätigt ist, kann ich damit gut leben!

Zitat:

Zitat von Sir Rufo (Beitrag 1284744)
Ich wüsste keinen Fall, wo ich in ein und derselben Queue lesen und schreiben möchte. Queues sind One-To-One Verbindungen. Eine Nachricht in einer Queue wird von einem Empfänger empfangen. Will ich an mehrere Empfänger die gleiche Nachricht senden, dann muss die Nachricht auch in mehrere Queues.

Ja, das hat sich jetzt durch die Tests und Verdeutlichungen ergeben. Das weiß ich, hatte ich eigentlich auch nicht vor.

Zitat:

Zitat von Sir Rufo (Beitrag 1284744)
Bei SendMessage hast du Subject und Message aber bei ReceiveMessage gibt es nur einen String zurück. Was kommt denn da? Subject, Message oder beides zusammengewürfelt?

Ja, auch das hat sich durch Tests und so weiter ergeben. Ist natürlich auch nicht korrekt so.

Aber danke für diese Hinweise - hätte ja wirklich ein echter Fehler sein können. Die Interfaces etc werden dann später auch nicht mehr "TMY..." lauten ;)

---

Aber wenn wir schon dabei sind: Kannst du mir nochmal folgendes erklären

Zitat:

Zitat von Sir Rufo (Beitrag 1284723)
Delphi-Quellcode:
TPostStelle = class( TInterfacedObject, ISendQueue, IReceiveQueue )
private
  FSendQueues : // Liste mit den möglichen Queues und dem Regelwerk, wann welche genutzt wird
  FReceiveQueues : // Liste aller möglichen Empfangs-Queues
public
  // Erzeugen mit allen benötigten Informationen
  constructor Create( SendQueueRuleSet: ...; ReceiveQueues : ... );
  procedure Send(...); // ISendQueue
  function GetMessage(...):...; // IReceiveQueue
end;

Es geht um die "Liste mit den möglichen Queues und dem Regelwerk, wann welche genutzt wird". Kannst du mir mal ganz konkret erklären, wie sowas aussehen könnte? Also sowohl die Liste, als auch das Regelwerk? Und dann noch sagen, von welchem Datentyp das sein müsste und wie die Umsetzung ist. Das habe ich leider garnicht verstanden. Das wäre jetzt nur der Vollständigkeit halber!

Vielen Dank an alle!

Sir Rufo 26. Dez 2014 22:31

AW: Interface richtig umgesetzt?
 
Zum einen muss man ja auch nicht nur einen Konstruktor haben und zum anderen kann man auch eine Factory nehmen.

Für eine minimalistische Queue brauchst du z.B. nur 2 Parameter, dann erstell dir einen Konstruktor mit diesen 2 Parametern und für die superduper Gedöns-Queue benötigst du 42 Parameter, jo, dann eben noch so einen, und evtl. noch ein paar weitere.

Eine Factory hilft immer dann, wenn man sehr viele Instanzen benötigt mit sehr vielen gleichen und wenigen variablen Parametern. Dann erzeuge ich die Factory mit den gleichbleibenden Parametern und hole mir die Instanzen über die Angabe der noch fehlenden, aber eben variablen Parameter. Schon bleibt das hübsch übersichtlich.
Delphi-Quellcode:
TMSMQQueueFactory = class
  constructor Create( Server, { ganz viele Parameter } );
  function CreateSendQueue( const QueueName : string ) : ISendQueue;
  function CreateReceiveQueue( const QueueName : string ) : IReceiveQueue;
end;
Sieht ja schon einfacher aus :)

Das Beispiel mit dem Postamt wird bei dir jetzt nicht so richtig passen, es ging mehr um die Möglichkeiten. Ein Regelwerk könnte ja darin bestehen, dass z.B. Chat-Nachrichten in eine andere Queue kommen, als andere Nachrichten. Dann muss dein Postamt z.B. den Nachrichtentypen erkennen und sucht sich die passende Queue für die Chat-Nachrichten heraus und versendet darüber.

Ursa 5. Jan 2015 06:48

AW: Interface richtig umgesetzt?
 
Du diese Klasse nun doch an die Implementierung koppelst.




samsung galaxy A5 schutzhülle


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:57 Uhr.
Seite 4 von 4   « Erste     234   

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