AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Interface richtig umgesetzt?

Ein Thema von TheMiller · begonnen am 23. Dez 2014 · letzter Beitrag vom 5. Jan 2015
Antwort Antwort
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#1

AW: Interface richtig umgesetzt?

  Alt 23. Dez 2014, 18:28
Gut, wenn sich die Parameter so unterscheiden, dann hast Du zusätzlich zu der "allgemeinen" Schnittstelle auch noch speziellere Schnittstellen, mit entsprechenden Methoden.
Dann kannst Du das aber nicht sauber mit einem allgemeinen Typ abbilden (auch mit Klassen nicht). Du musst quasi schon VOR dem Verwenden wissen, ob es sich um eine MQ mit 2 oder mit 3 Parametern handelt.
Die Optionen die ich hier sehe sind also:
- Du versucht eine allgemeines "Open" zu definieren und die eine Klasse verwendet alle 3 Parameter, die anderen nur 2 (das ist aber nicht gerade die feine englische Art)
- zwei separate "Basis" Interfaces, einmal für das Open mit 3 Parametern, einmal mit 2 Parametern
- ein Basis-Interface mit zwei Spezialisierungen (abgeleitete Interfaces, jeweils mit der eigenen Open-Definition)

Allerdings kenne ich auch hier nicht Deinen kompletten Anwendungsfall. Des Weiteren stell ich mal die Frage: gibt es nicht bereits vorhandene Implementierungen im Netz ?

Geändert von alda (23. Dez 2014 um 18:31 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von TheMiller
TheMiller

Registriert seit: 19. Mai 2003
Ort: Gründau
2.480 Beiträge
 
Delphi XE7 Architect
 
#2

AW: Interface richtig umgesetzt?

  Alt 23. Dez 2014, 18:47
Vielen Dank für die Antworten.

Ausgangspunkt war folgender: Ich wusste nicht, welche MessageQueue-Lösung ich final im Produkt verwenden möchte. Für den Anfang reicht MSMQ. Vielleicht kommt irgendwann mal ein MAC-Client o.ä. dazu. Dann hab ich mit MSMQ schlechte Karten und müsste auf ActiveMQ (oder einen anderen) umsteigen. Daher riet mir Sir Rufo, ein Interface zu implementieren und später beim Umstieg nur einen winzigen Teil im Programm ändern müsste.

Daher ein Interface mit z.B. "Open" (welches die MessageQueue öffnet). MSMQ verlangt zwei Parameter. ActiveMQ mit Sicherheit ganz andere. Und darauf weiß ich gerade nicht zu reagieren, außer einen Typecast zum TMy_MSMQ-Objekt oder einem Array im Interface namens "Params", die vor dem Open (oder anderen Methoden) entsprechend gefüllt und in der Methode ausgelesen und wieder gelert, quasi als Container.

Wenn wir die Interface-Geschichte mal außen vor lassen: Mit der MSMQ komme ich nun in den Grundzügen klar, kann erstellen, lesen, schreiben etc.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Interface richtig umgesetzt?

  Alt 23. Dez 2014, 19:11
Also wenn ich einen Brief versenden will, dann muss ich trotzdem nicht das Postamt öffnen, oder den Briefkasten aufschließen. Ich gehe einfach zu meinem Interface IBriefPost und sende den Brief ab mit IBriefPost.Sende( Brief); . Soll sich das Interface doch selber darum kümmern.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von TheMiller
TheMiller

Registriert seit: 19. Mai 2003
Ort: Gründau
2.480 Beiträge
 
Delphi XE7 Architect
 
#4

AW: Interface richtig umgesetzt?

  Alt 23. Dez 2014, 19:36
Ich verstehe, was du damit sagen willst. Bleiben wir dabei: Es gibt die Post, TransoFlex und UPS. Bei allen kann ich noch Post fragen. Dafür habe ich IMessages.GetMessage.

Nun kann ich bei der Post auswählen, ob nur das Vorliegen neuer Post erfragt werden soll und wer das machen darf (Open MQ_RECEIVE_ACCESS, MQ_DENY_NONE), erfragen und gleich mitnehmen <bei Post löschen> aber nur spezielle Leute das machen dürfen (Open MQ_PEEK_ACCESS, MQ_DENY_RECEIVE_SHARE) etc.

Bei TransoFlex kann ich genau das gleiche machen, nur nicht festlegen, wer diese Aktionen durchführen darf.

UPS will garnicht genau wissen, was ich vorhabe, sondern ich kann mich selbst dort bedienen.

Wie soll ich darauf mit IMessage.GetMessage reagieren?

Ich habe als Zwischenlösung (nur damit ich weiter testen kann) ein Array mit Parametern angelegt:

Delphi-Quellcode:
procedure TMy_MSMQ.SetParam(Value: string);
begin
  SetLength(fParams, Succ(Length(fParams)));
  fParams[High(fParams)]:=Value;
end;

...
procedure TMy_MSMQ.QueueOpen
begin
  fQueue:=fQueueInfo.Open(StrToInt(fParams[0]), StrToInt(fParams[1])); //MQ_SEND_ACCESS / MQ_RECEIVE_ACCESS etc.
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  mq: IMy_MQ;
begin
  mq:=TMy_MSMQ.Create;

  //Verbinden
  mq.SetParam(IntToStr(MQ_RECEIVE_ACCESS));
  mq.SetParam(IntToStr(MQ_DENY_NONE));
  if (mq.QueueOpen('DIRECT=OS:.\Private$\Test')) then
    ShowMessage('Queue opened');

end;
Funktioniert, ist aber nicht optimal...
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#5

AW: Interface richtig umgesetzt?

  Alt 25. Dez 2014, 13:11
Ich habe als Zwischenlösung (nur damit ich weiter testen kann) ein Array mit Parametern angelegt:

Delphi-Quellcode:
procedure TMy_MSMQ.SetParam(Value: string);
begin
  SetLength(fParams, Succ(Length(fParams)));
  fParams[High(fParams)]:=Value;
end;

...
procedure TMy_MSMQ.QueueOpen
begin
  fQueue:=fQueueInfo.Open(StrToInt(fParams[0]), StrToInt(fParams[1])); //MQ_SEND_ACCESS / MQ_RECEIVE_ACCESS etc.
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  mq: IMy_MQ;
begin
  mq:=TMy_MSMQ.Create;

  //Verbinden
  mq.SetParam(IntToStr(MQ_RECEIVE_ACCESS));
  mq.SetParam(IntToStr(MQ_DENY_NONE));
  if (mq.QueueOpen('DIRECT=OS:.\Private$\Test')) then
    ShowMessage('Queue opened');

end;
Funktioniert, ist aber nicht optimal...
Ja das ist wohl wahr, bin mir auch nicht sicher was hier der eleganteste Weg ist. Ich gehe jetzt einfach mal davon aus, dass es maximal 0-N Setup-Parameter für jede MessageQueue gibt, gemäß Deiner Beschreibung aus:
Nun kann ich bei der Post auswählen, ob nur das Vorliegen neuer Post erfragt werden soll und wer das machen darf (Open MQ_RECEIVE_ACCESS, MQ_DENY_NONE), erfragen und gleich mitnehmen <bei Post löschen> aber nur spezielle Leute das machen dürfen (Open MQ_PEEK_ACCESS, MQ_DENY_RECEIVE_SHARE) etc..
Erstmal zu Deinem Beispiel:
Das ist insofern unschön, da Du einen undefiniertem Wert übergibst den Du innerhalb der Open-Implementierung ja wieder auswerten musst- man sieht innerhalb der Open-Implementierung also gar nicht auf den ersten Blick was gemeint ist.

Alternative mit Parametern zu Deinem Beispiel:
Sofern Du dabei bleiben möchtest, ein MQ-Interface bereitzustellen mit einem allgemeingültigen Open-Aufruf, dann solltest Du die Parameter sogt wie möglich typisieren. Du hast ja überall definierte Zustände, das bedeutet alle "Rechte" kannst Du als Enums darstellen (wie Du diese letztendlich gestaltest überlass ich mal Dir), die man dann entsprechend auch einfach und leserlich auswerten kann. Wenn möglich könntest Du sogar ein großes Enum deklarieren und in der Open-Methode einfach ein Enum-Set verlangen, z.B:
Delphi-Quellcode:
TMQSetupType = (mqsReceiveAccess, mqsDenyNone, mqsPeekAccess, mqsDenyReceiveShare);
TMQSetupTypes = set of TMQSetupType;

IMyMQ= interface
...
    procedure Open(const ASetup: TMQSetupTypes);
end;

.....

procedure TMy_MSMQ.QueueOpen
begin
  fQueue:=fQueueInfo.Open([mqsSendAccess, mqsReceiveAccess]);
end;
Jede Implementierung entscheidet dann selbst, ob und wie die übergebenen Parameter verwertet werden. Der Vorteil ist, Du musst beim austauschen der MQ-Implementierung nicht den Open-Aufruf anpassen und siehst gleich am Namen des Enums um was für ein Recht es sich handelt und kannst entsprechend einfach darauf prüfen und es auswerten. Nachteil ist weiterhin , dass man hier keine Rückmeldung erhält, sofern gesetzte (Rechte)Parameter ignoriert werden.

Alternativen:
Du solltest Dir einfach mal die MQ-Implementierungen anderer Sprachen anschauen und herausfinden wie das dort gelöst wurde (der Anwendungsfall sollte ja exakt der gleiche sein) - vielleicht findet sich da ja eine elegante Lösung, oder jemand anderem im Forum fällt bis dahin was schickes ein.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Interface richtig umgesetzt?

  Alt 25. Dez 2014, 14:46
Es ist doch unsinnig die Open Methode im Interface zu deklarieren. Wozu soll die gut sein?

Ich will eine Nachricht senden. Ob dafür bei MSMQ erst die Queue erst mit welchen Parametern auch immer geöffnet werden muss oder bei TrallalaMQ erst ein Purzelbaum geschlagen werden muss, das interssiert bei der konkreten Implementierung aber nicht das Interface. Das ermöglicht mir das Senden einer Nachricht. Das Wie regelt die Implementierung.

Das Empfangen geht genauso: Was alles gemacht werden und erfolgen muss, darum kümmert sich die Implementierung. Das Interface hat z.B. 2 Methoden HasMessage und GetMessage.

Wenn man das Interface zu konkret aufbaut, dann arbeitet man am Interface-Gedanken vorbei und kann sich das auch gleich sparen.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von TheMiller
TheMiller

Registriert seit: 19. Mai 2003
Ort: Gründau
2.480 Beiträge
 
Delphi XE7 Architect
 
#7

AW: Interface richtig umgesetzt?

  Alt 25. Dez 2014, 19:44
Hi,

erstmal vorab: Ich wünsche euch allen eine frohe Weihnachtszeit!

Ich nutze gerade mal die Gelegenheit zwischen den Essen und Familienfeiern, auf die Nachricht hier zu antworten:

Das Problem habe ich verstanden. Nur da ich ja als Rückgabeparameter das Interface erhalte, sehe ich auch nur die Mehtoden, die es hat, nicht aber die der TMy_MSMQ-Klasse. Würde ich jetzt aber im ganzen Programm mit der TMY_MSMQ-Klasse arbeiten, so wäre ich wieder an dieses Objekt gebunden und der gewünschte Vorteil des Interfaces wäre nicht mehr gegeben. Ebenso, wenn ich das den Interface-Zeiger nach TMy_MSMQ caste. Ich muss da noch irgendwas falsch verstehen...

Ich wüsste also derzeit nicht, wo ich die Open-Methode deklarieren könnte, damit ich mit ihr arbeiten kann. Entweder darf ich mir kein Interface-Zeiger zurückgeben lassen, dann könnte ich eben mit der My_MSMQ.Open arbeiten, bin dann aber programmweit an sie gebunden. Oder ich nutze das Interface und habe eben diese Parameter-Probleme. So ist derzeit meine Sicht - ich weiß, da ist was falsch, aber ich komme nicht drauf was.

Oder gibt es für mein konkretes Vorhaben nicht diese Lösung, dass ich bei einem Provider-Wechsel nur eine Quelltextzeile austauschen muss?

Nochmal der Vollständigkeit halber - Dies ist mein letzter "Entwicklungs"-Stand:

Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  mq: IMy_MQ; //Interface
begin
  mq:=TMy_MSMQ.Create; //Objekt vom Typ "TMy_MSMQ"

  //Verbinden
  mq.SetParam(IntToStr(MQ_RECEIVE_ACCESS)); //Notlösung
  mq.SetParam(IntToStr(MQ_DENY_NONE)); //Hier auch ;)
  if (mq.QueueOpen('DIRECT=OS:.\Private$\Test')) then
    ShowMessage('Queue opened');
end;
Danke und weiterhin noch schöne Feiertage!
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:10 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