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
Seite 3 von 4     123 4      
Benutzerbild von Sir Rufo
Sir Rufo

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

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
 
#22

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
Benutzerbild von Sir Rufo
Sir Rufo

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

AW: Interface richtig umgesetzt?

  Alt 25. Dez 2014, 20:32
Der grundlegende Denk-Fehler ist, dass du der Meinung bist, in der Anwendung alles Mögliche über das Interface geben zu müssen. Aber eben genau diese Implementations-spezifischen Informationen habe dort nichts verloren.

Nehmen wir mal den ganz simplen Fall, dass wir einfach nur einen Text versenden wollen. Dann sähe das interface so aus
Delphi-Quellcode:
IMy_MQ = interface
  procedure Send( const AText : string );
end;
So, jetzt wollen wir diesen Text wie in deinem Beispiel über MSMQ versenden:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  mq: IMy_MQ; //Interface
begin
  mq := TMy_MSMQ.Create( 'DIRECT=OS:.\Private$\Test', MQ_RECEIVE_ACCESS, MQ_DENY_NONE ); //Objekt vom Typ "TMy_MSMQ"
  mq.Send( 'Mal was senden' );
end;
In der Implementierung von TMy_MSMQ kann ich doch nun ganz gemütlich überprüfen, ob die Queue schon geöffnet wurde, wenn nicht, die Queue öffnen und einfach den Text versenden. Genauso eben auch Empfangen. Der Anwendung kann es wie gesagt völlig egal sein, was alles passieren muss, damit ein Text versendet werden kann. Das ist Aufgabe der Implementierung dieses entsprechend zu gewährleisten.

(Das das Beispiel jetzt nicht ganz passt, weil du hier eine Empfangs-Queue öffnen willst und ich etwas senden möchte weiß ich, es sollte aber den Ansatz hinreichend erklären).

Denk immer daran, wie das im wahren Leben funktioniert. Egal ob du mit UPS, DHL, Hermes, etc. ein Paket verschicken möchtest, bei allen ist folgendes gleich:
  • Paket mit Inhalt
  • Adresse
  • kostet Geld
Die Unterschiede sind die Paketaufkleber und die Abgabestellen. Dein Interface ist jetzt der Mitarbeiter in der hauseigenen Poststelle. Dem gibst du das Paket und der kümmert sich um den Versand. Ob dann heute mit UPS, morgen mit DHL, übermorgen mit Hermes oder in ferner Zukunft per berittenem Boten das Paket transportiert wird, für die Mitarbeiter im Haus ändert sich nichts, denn die geben das Paket wie eh und je beim Mitarbeiter der Poststelle ab.

Das ist dann ein Interface
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
 
#24

AW: Interface richtig umgesetzt?

  Alt 25. Dez 2014, 21:04
Super Erklärung!

Aber dann habe ich wohl technisch was falsch umgesetzt. Denn ich kann nicht auf die Methoden von TMy_MSMQ zugreifen. Ich würde nur die Methode "Send" sehen, welche vom Interface kommt. Denn "mq" ist vom Typ IMy_MQ. Ich hatte es ja schon probiert, der Klasse TMy_MSMQ neben den Methoden des Interfaces noch weitere Methoden und Felder hinzuzufügen. Aber die waren mir in OI immer verborgen. Ich kann nicht darauf zugreifen. Was müsste denn richtigerweise .Create von TMy_MSMQ zurückgeben?

Oder ist das der Grund, warum du die Parameter im Constructor übergibst?
  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
 
#25

AW: Interface richtig umgesetzt?

  Alt 25. Dez 2014, 22:31
Wieso denn jetzt auf einmal OI? Möchtest du eine Komponente bauen?

Ja, kann man auch machen, würde ich allerdings nicht, denn warum sollte ich auf eine Form sowas draufklatschen, das gehört für mich ein paar Ebenen tiefer in die Anwendung.

Anyway, bauen wir uns also so eine Sende-Komponente:
Delphi-Quellcode:
// Basis Komponente für alle Send Queues
TCustomSendQueue = class( TComponent )
protected
  procedure DoSend( const AText : string ); virtual; abstract;
public
  procedure Send( const AText : string ); // ruft OnSend und DoSend auf
published
  // Ein paar Events?
  property OnSend : TNotifyEvent;
end;

// Konkrete Komponenten für MSMQ
TMSMQConnection = class( TComponent )
published
  property Server : string;
  property ...
end;

// Konkrete Ableitung für MSMQ SendQueue
TMSMQSendQueue = class( TCustomSendQueue )
protected
  procedure DoSend( const AText : string ); override;
published
  property Connection : TMSMQConnection;
  property Queue : string;
  property ...
end;
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
 
#26

AW: Interface richtig umgesetzt?

  Alt 26. Dez 2014, 09:30
Guten Morgen.

Es tut mir schrecklich leid - ich habe mich vertran. Ich schiebe es mal auf meine Erkältung. Ja, ich schrieb OI, meinte aber lediglich die Codevervollständigung. Dort werden mir die weiteren Methoden nicht angezeigt. Eine Komponente macht da wirklich keinen Sinn.

Das Interface hat z.B. nur GetMessage, SendMessage. TMy_MSMQ hat darüber hinaus noch SetEncryption, IsActiveDirectory, etc.pp (alles fiktiv). Bei meinem Codebeispiel von oben sehe ich wie gesagt nur die Methoden des Interfaces Get/SendMessage. Ich weiß also nicht - außer mit einem TypeCast - wie ich auf die Methoden der KLasse zugreifen kann. Daher denke ich, noch irgenetwas falsch zu machen.

Dass ein Interface minimalistisch und allgemein gehalten werden soll, habe ich jetzt verstanden. Weiß daher jetzt auch, warum es nur Get/SendMessage zu haben braucht. Deine Erklärung mit Post etc. war echt gut. Es wird. Langsam, aber es wird

Danke (auch für die Geduld)
  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
 
#27

AW: Interface richtig umgesetzt?

  Alt 26. Dez 2014, 10:54
Aber warum willst du auf die Methoden der implementierenden Klasse zurückgreifen?

Wenn du eine Nachricht verschicken willst, dann benutze das Interface und verschicke die Nachricht. Es ist Aufgabe der implementierenden Klasse sich um den gesamten konkreten Versandablauf zu kümmern, denn nur die weiß, wie man z.B. mit MSMQ sprechen muss. Ich als Versender muss doch gar nicht wissen, was da intern alles passiert, es muss nur passieren.

Am sinnvollsten ist es dem Konstruktor der implementierenden Klasse alles mitzugeben, damit ich ein funktionierendes Interface bekomme.

Generell würde ich allerdings auch eine Trennung zwischen Sende- und Empfangs-Queue vornehmen (also 2 Interfaces). Die Möglichkeit besteht ja, dass ich x Sende-Queues und y Empfangs-Queues benötige. Und die Sende-Queue ist idR nicht die Empfangs-Queue (warum soll ich mir selber Nachrichten schicken).
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
 
#28

AW: Interface richtig umgesetzt?

  Alt 26. Dez 2014, 13:48
Okay, habe ich jetzt so alles gemacht, wie du es gesagt hast. Leuchtet alles ein, funktioniert auch soweit.

Nur irgendwie werde ich den Verdacht nicht los, dass ich mich - zumindest bei den MessageQueues - mit den Interfaces einschränke. Ich habe nun zwei Interfaces, eines für das Senden, eines für das Empfangen. Habe jetzt auch zwei implementierende Klassen (obwohl ich die zusammenführen könnte - mach ich noch).

Wenn eine Nachricht gesendet wird, prüft die implementierende Klasse, ob es die Queue schon gibt. Wenn nicht, wird sie erstellt, dann geöffnet und die Nachricht eingetragen. Soweit okay. Der Versender kümmert sich also um nichts - wie ich bei der Post.

Beim Erstellen einer Queue kann man aber so viele Optionen angeben, wie übermittle ich die? zB Journal, Transaktionen (IsTransactional), Zugriff (IsWorldReadable), Verschlüsselung, ACL, etc. Und das sind nur die Optionen für das Erstellen einer Queue. Ich kann ja nicht alle Parameter, die ich irgendwann mal gebrauchen könnte, in dem Constructor definieren. Verstehst du mein Problem?

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?

Ach unabhängig davon: Wenn die Queue bei MSMQ nicht existiert, muss man um sie zu erstellen, einen Pfad benutzen, um sie zu öffnen/lesen/löschen einen Formatnamen. Also gibt es da auch wieder unterschiede, auf die ich nicht zu reagieren weiß.

Geändert von TheMiller (26. Dez 2014 um 13:53 Uhr)
  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
 
#29

AW: Interface richtig umgesetzt?

  Alt 26. Dez 2014, 14:21
Anders herum gefragt:

Du hast da eine Poststelle wo alle ihre Post hinbringen, auf dass diese versendet wird.

Wer legt das konkrete Verhalten der Poststelle fest? Die Mitarbeiter, die ihre Post versendet haben wollen? Oder eventuell eher doch die Geschäftsleitung?

Und nochmal: Was interessiert es dich wie die Queue funktioniert (mit Transaktion oder ohne, mit Schleifchen oder Bändern, in rot oder grün) wenn du nur etwas versenden willst und du bekommst etwas geliefert, womit du versenden kannst.

Ich denke du springst zu sehr zwischen den Ebenen in deiner Anwendung hin und her.

Wenn die Anwendung z.B. ein Konstrukt aus Sende- und Empfangs-Queue benötigt, dann gib ihr das so
Delphi-Quellcode:
TFoo = class
  constructor Create( SendQueue: ISendQueue; ReceiveQueue: IReceiveQueue );
  // entweder Methoden
  procedure Send(...);
  function GetMessage(..):...;
  // oder als Eigenschaften
  property SendQueue : ISendQueue;
  property ReceiveQueue : IReceiveQueue;
end;
Und schon gehören die zusammen. Das ist wie Lego. Man hat kleine Steine und steckt sich da größere, spezialisierte Dinge zusammen.
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 Sir Rufo
Sir Rufo

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

AW: Interface richtig umgesetzt?

  Alt 26. Dez 2014, 14:29
Um nochmals die Poststelle aufzugreifen:

Die Poststelle kann ja durchaus mehrere Versandkanäle benutzen, die z.B. abhängig von Größe, Gewicht und Volumen genutzt werden. Die Mitarbeiter liefern trotzdem ihre Sachen an die Poststelle und die kümmert sich intern um die Bestimmung in welche Queu jetzt das geschoben wird.

Und der Empfang von ausserhalb geht auch durch die Poststelle und kommt aus unterschiedlichen Queues. Die Mitarbeiter bekommen davon nichts mit, denn die kennen nur ... die Poststelle.
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;
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
Antwort Antwort
Seite 3 von 4     123 4      


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 06:44 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