AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Klassendesign: Blockierender Constructor?
Thema durchsuchen
Ansicht
Themen-Optionen

Klassendesign: Blockierender Constructor?

Offene Frage von "Namenloser"
Ein Thema von Zacherl · begonnen am 3. Nov 2016 · letzter Beitrag vom 3. Nov 2016
Antwort Antwort
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#1

Klassendesign: Blockierender Constructor?

  Alt 3. Nov 2016, 11:43
Delphi-Version: 10 Seattle
Hallo zusammen,

ich re-designe grade eine Klasse, die eine Netzwerk-Protokoll-Schicht implementiert. Dabei wollte ich beim Klassendesign folgende Aspekte vereinen:
  • SÄMTLICHE Kommunikation soll über meine IO-Handler Klasse ablaufen (Send Methoden und Receive Events)
  • Die darunterliegende Socket Implementierung (nur blocking) soll austauschbar sein
Für eingehende Daten hatte der IO-Handler bisher eine Methode HandleData , an die der Benutzer manuell die Daten übergeben musste, die er mit seinem Socket empfangen hat.
Für ausgehende Daten hatte ich bisher zwei Ansätze:
  1. Socket Instanz wird im Constructor übergeben und der IO-Handler ruft dann selbstständig Send auf
  2. IO-Handler hat ein OnSend Event, was vom Benutzer implementiert werden muss
Nun möchte ich aber einerseits HandleData loswerden und anderseits, dass der IO-Handler selbstständig senden kann (also eher Ansatz 1). Sprich: Der IO-Handler soll "Besitzer" des Sockets sein.

Meine Idee war jetzt das Socket im Constructor zu übergeben und dann selbstständig zu pullen:
Delphi-Quellcode:
type
  ISocket = interface
    function Send(Data: Pointer; Size: UInt32): UInt32;
    function Receive(Data: Pointer; Size: UInt32): Integer;
  end;

  TIOHandler = class(TObject)
  private
    FSocket: ISocket;
  public
    constructor Create(Socket: ISocket);
  end;

constructor TIOHandler.Create(Socket: ISocket);
var
  Data: array[0..1024 * 16] of Byte;
  Size: Integer;
begin
  inherited Create;
  FSocket := ISocket;
  // ..
  // internen Send-Thread erzeugen
  // ..
  repeat
    Size := FSocket.Receive(@Data[0], SizeOf(Data)); // blocking
    if (Size > 0) then
    begin
      InternalHandleData(@Data[0], Size);
    end;
  until (Size < 0);
end;
Meiner Intuition nach empfinde ich es allerdings als schlechtes Design im Constructor zu blockieren und komplexe Operationen auszuführen. Was sagt ihr dazu? Alternative wäre das Pullen in eine Methode auszulagern, aber dann habe ich wieder eine Art HandleData Methode, die extra aufgerufen werden müsste (was ich gerne vermeiden will).

Viele Grüße
Zacherl
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.045 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#2

AW: Klassendesign: Blockierender Constructor?

  Alt 3. Nov 2016, 12:00
Da fiel mir sofort das hier ein: http://misko.hevery.com/code-reviewe...oes-real-work/
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Der schöne Günther
Online

Registriert seit: 6. Mär 2013
6.196 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Klassendesign: Blockierender Constructor?

  Alt 3. Nov 2016, 12:01
Meiner Intuition nach empfinde ich es allerdings als schlechtes Design im Constructor zu blockieren und komplexe Operationen auszuführen. Was sagt ihr dazu?
Absolut.

Vielleicht möchte ich, als Benutzer der Klasse noch gar nichts senden. Vielleicht möchte ich die Klasse nur testen und sitze grade irgendwo ohne Netz. Es gibt viele Gründe, Google, Microsoft und Konsorten raten in ihren Ratgebern explizit immer davon ab, "real work" im constructor zu erledigen.

Der hier z.B. fasst das ganz nett zusammen:
http://www.daedtech.com/beware-the-bloated-constructor/
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.339 Beiträge
 
Delphi 12 Athens
 
#4

AW: Klassendesign: Blockierender Constructor?

  Alt 3. Nov 2016, 12:05
Es gibt auch noch AfterConstruction, aber aus sicht des Programmierers wird das auch "im" TMyClass.Create aufgerufen.

Alternativ eine Start/Init-Methode, welche von Extern nach dem Create aufgeufen wird.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#5

AW: Klassendesign: Blockierender Constructor?

  Alt 3. Nov 2016, 12:31
Okay, dann sind wir uns bezüglich des Constructors ja schonmal einig Testen der Klasse ohne Internet ist kein Problem. Dafür kann man das Socket Interface ja als Dummy implementieren.

Dann mal die Frage nach der besten Alternative. Momentan steht zu Auswahl:
  • AfterConstruction
  • Init/Start Methode, um Polling zu starten
Oder würdet ihr an meiner Stelle das Polling doch eher dem Benutzer überlassen (also der alte HandleData Ansatz)?
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.629 Beiträge
 
Delphi 12 Athens
 
#6

AW: Klassendesign: Blockierender Constructor?

  Alt 3. Nov 2016, 12:42
Wie wäre es denn mit einem Event-gesteuerten Ansatz in der Art Socket.OnDataAvailable := MyHandleDataEvent ?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#7

AW: Klassendesign: Blockierender Constructor?

  Alt 3. Nov 2016, 13:03
Wie wäre es denn mit einem Event-gesteuerten Ansatz in der Art Socket.OnDataAvailable := MyHandleDataEvent ?
Das ginge ja in die selbe Richtung wie mein alter HandleData Ansatz. Da aber ja nicht jede Socket Komponente so ein Event besitzt (vor allem nicht mit der selben Parameter-Definition), sollte der Benutzer damals selbst auf ein OnDataAvailable Event reagieren und darin dann HandleData vom IO-Handler aufrufen. Bzw. im Fall von blocking Sockets hat der Benutzer entsprechend nach neuen Daten gepollt und bei Empfang dann HandleData aufgerufen.

Ist natürlich ohne Frage der Ansatz, der dem Benutzer die größte Freiheit lässt.

Was mich einfach stört ist, dass das Senden dann dem IO-Handler obliegt, das Empfangen aber in der Hand des Benutzers ist. Das Receive im Socket Interface wäre damit auf jeden Fall obsolet.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

Geändert von Zacherl ( 3. Nov 2016 um 13:06 Uhr)
  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 07:50 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