AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Aufbau eigene Klasse mit Property und TStrings

Aufbau eigene Klasse mit Property und TStrings

Ein Thema von Jens Hartmann · begonnen am 30. Dez 2010 · letzter Beitrag vom 4. Jan 2011
Antwort Antwort
Seite 2 von 2     12
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#11

AW: Aufbau eigene Klasse mit Property und TStrings

  Alt 31. Dez 2010, 00:31
@Jens

Ich habe nach dem von Dir beschriebenen Schema bereits Steuerungen/Messungen umgesetzt, das funktioniert. Eine Basisklasse mit allgemeinen Eigenschaften und Ereignisbehandlungsroutinen, Fehlerroutinen (z.T. als virtual und oder abstract) und darauf die spezifischen Klassen für das Parsen/Interpretieren/Schreiben.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#12

AW: Aufbau eigene Klasse mit Property und TStrings

  Alt 31. Dez 2010, 02:12
Die Frage ist doch: WER erzeugt die Objekte für die seriellen Schnittstellen?
Nach deinem Konzept nach hältst du 4 ComPort-Objekte auf dem Datenmodul bereit.
Ich würde diese ComPort-Objekte aber dynamisch nach Bedarf über eine Factory-Klasse erzeugen.
Diese Factory-Klasse benötigt für ihre Arbeit den Dateinamen einer Ini-Datei.
Die Ini-Datei sieht z.B. so aus:
Code:
[Config]
DeviceCount=2
[Device1]
Device=MB100
Port=COM1
Baudrate=9600
Parity=N
[Device2]
Device=MB256
Port=COM3
Baudrate=19200
Parity=N
Hier der Grobentwurf der Factory-Klasse:
Delphi-Quellcode:
TDeviceFactory=class

public
  class function CreateMB100:TAlarmAnlage;
  class function CreateMB256:TAlarmAnlage;
  ...
  
  function GetDeviceCount:integer; // Anzahl der Geräte in der Ini-Datei

  function CreateDevice(deviceNr:integer):TAlarmAnlage;
  property IniFilename:string;
end;

function TDeviceFactory.CreateDevice(deviceNr:integer):TAlarmAnlage;
var
  devicename : string;
  inifile : TIniFile;
  section : string;
  comport : TComPort;
begin
  section := Format('Device%d', [devicenr]);
  inifile := TIniFile.Create(IniFilename);
  devicename := inifile.ReadString(section, 'Device');

  // hier ggf. prüfen, ob es die Section überhaupt gibt
  
  // Hardwarekomponente erzeugen
  if devicename='MB100then
    Result := CreateMB100
  else if devicename='MB256then
   Result := CreateMB256
  else if ...
  else
    raise Exception.CreateFmt('unbekanntes Device <%s>', [devicename]);
  
  // jetzt wird noch das Kommunikations-Objekt benötigt
  comport := TComPort.Create(Application {siehe Text unten});
  comport.Port := inifile.ReadString(section, 'Port');
  comport.BaudRate := inifile.ReadInteger(section, 'Baudrate');
  comport.Parity := inifile.ReadString(section, 'Parity');
  // hier ggf. weitere Properties (Handshake, Datenbits) berücksichtigen
  
  // Geräte-Objekt und Kommunikations-Objekt verheiraten
  Result.Comport := comport;
  comport.OnReceive := Result.ReceiveHandler; // Eventhandler zuweisen
  
  // serielle Schnittstelle öffnen
  comport.Connected := True;
  inifile.Free;
end;
In der obigen Funktion fehlen noch einige Feinheiten sowie eine wasserdichte Fehlerbehandlung.
Aber das Prinzip sollte klar sein.
Die Hardwarekomponente (bzw. Geräteklasse) kümmert sich nicht um Baudrate usw.
Die Factory erzeugt anhand den Informationen in der Ini-Datei die Hardwarekomponente sowie die Komponente für die serielle Schnittstelle und baut diese zu einem funktionierenden Verbund zusammen.

Es bleibt noch die Frage offen: WER ist der Owner der ComPort-Komponente?
Im Code oben habe ich Application angegeben; das ist noch etwas unschön.
Falls die Hardwarekomponente tatsächlich eine echte Komponente ist, würde man schreiben:
Delphi-Quellcode:
// jetzt wird noch das Kommunikations-Objekt benötigt
comport := TComPort.Create(Result {=die neu erzeugte Hardwarekomponente});
comport.Port := inifile.ReadString(section, 'Port');
Lass das mal etwas absacken; das Konzept der Factory-Klasse mag zunächst etwas fremd aussehen, hat aber entscheidende Vorteile.
  Mit Zitat antworten Zitat
Benutzerbild von Jens Hartmann
Jens Hartmann

Registriert seit: 11. Jan 2009
Ort: Wilnsdorf
1.439 Beiträge
 
Delphi XE2 Professional
 
#13

AW: Aufbau eigene Klasse mit Property und TStrings

  Alt 31. Dez 2010, 10:04
Zitat von Bummi:
Ich habe nach dem von Dir beschriebenen Schema bereits Steuerungen/Messungen umgesetzt, das funktioniert. Eine Basisklasse mit allgemeinen Eigenschaften und Ereignisbehandlungsroutinen, Fehlerroutinen (z.T. als virtual und oder abstract) und darauf die spezifischen Klassen für das Parsen/Interpretieren/Schreiben.
So dachte ich halt und so wollte ich es eigendlich umsetzten...

Zitat von sx2008:
Die Frage ist doch: WER erzeugt die Objekte für die seriellen Schnittstellen?
Nach deinem Konzept nach hältst du 4 ComPort-Objekte auf dem Datenmodul bereit.
Ich würde diese ComPort-Objekte aber dynamisch nach Bedarf über eine Factory-Klasse erzeugen.
Diese Factory-Klasse benötigt für ihre Arbeit den Dateinamen einer Ini-Datei.
Die Komponente stammt aus dem CPortLib Package. Dies hat in meinem Fall den Vorteil, das Sie über eine zusätzlich Komponente ComDataPacket verfügt. Darüber realisiere ich, das ich immer nur einen Datensatz empfange. Und somit das Parsen schon auf die Abarbeitung von einem Datensatz beschränken kann. Sicherlich könnt ich diese Komponente auch dynamisch erzeugen, fragt sich nur, ob das bei vier bzw. acht Komponenten wirklich notwendig ist.

Zitat von sx2008:
In der obigen Funktion fehlen noch einige Feinheiten sowie eine wasserdichte Fehlerbehandlung.
Aber das Prinzip sollte klar sein.
Das Prinzip ist klar, und verstehe ich auch. Der Gedankengang scheint mir für meine Zwecke halt nur zu hoch angesetzt. Wenn ich nochmal auf meine Idee gehe, dann würde ich doch eines zumindestens Übersichtlich lösen. Alles was zur Zentrale A gehört, befindet sich auch in dessen Klasse. Über eine Ini-Datei oder ähnliches brauche ich nur noch festzulegen, welchen Zentrale welchen PORT nutzen tut. Eine Anbindung anderer Art als seriell wird nicht notwendig sein, daher dachte ich das alles schön sauber in eine Klasse zu vereinen.

Zitat von sx2008:
Delphi-Quellcode:
Delphi-Quellcode:
// jetzt wird noch das Kommunikations-Objekt benötigt
comport := TComPort.Create(Result {=die neu erzeugte Hardwarekomponente});
comport.Port := inifile.ReadString(section, 'Port');
Lass das mal etwas absacken; das Konzept der Factory-Klasse mag zunächst etwas fremd aussehen, hat aber entscheidende Vorteile.
Andererseits, kann ich die Idee von dir auch nachvollziehen und ich überlege, ob ich es so mal testen soll. Allerdings fehlen mir da noch so ein Paar zusammenhänge. Ich muss wie du es schon geschrieben hast, das ganze erstmal sacken lassen und mal die Google-Welt strapazieren.

Danke aber schon mal für die vielen Inputs.

Gruß Jens
Jens Hartmann
Das Leben selber ist zu kurz, also nutze jeden Tag wie er kommt.
  Mit Zitat antworten Zitat
r2c2

Registriert seit: 9. Mai 2005
Ort: Nordbaden
925 Beiträge
 
#14

AW: Aufbau eigene Klasse mit Property und TStrings

  Alt 31. Dez 2010, 15:35
Bin gestern mit dem Blog-Artikel über Magic Values doch nicht mehr fertig geworden. Jetzt aber endlich: http://www.christian-rehn.de/2010/12/31/magic-values/

Zitat:
Ich nehme ein Datenmodule, füge diesem 4 ComPort Komponenten zu, welche über den Dienst oder über die Anwendung
konfiguriert und genutzt werden können.
Wie viele Programme hast du jetzt? Ich dachte zwei: Einen Dienst und eine GUI. Und die GUI muss ja vom Com-Zeug eigentlich nix wissen. Oder hab ich da was falsch verstanden?

Zitat:
Soll heißen, da jede Hardware andere
Einstellungen nutzt(Baudrate, Parität, Parser), verankere ich die Einstellungen doch am besten in der
entsprechenden Klasse.
Nein, das sind Parameter, die man aus ner Konfigurationsdatei lesen sollte. "Put Abstractions in Code, details in metadata". Der Einfachheit halber kann man dieses Prinzip auch mal ignorieren (KISS). Das is mal wieder so ne Trade-off-Geschichte...

In diesem Fall würde ich aber auch die Factory nehmen. Egal ob jetzt von mir aus in der Factory hardgecoded oder aus ner Konfigurationsdatei gelesen. Aber deine Klasse muss von Baudrate & Co. eigentlich erstmal nix wissen. Das ist Sache von TComPort. ==> Separation of Concerns.

Zitat:
So habe ich doch den Vorteil, einen neue Hardware, eine neue Klasse.
Das hast du bei DependencyInjection genauso.

Zitat:
Desweiteren wird ja der Parser der entsprechenden Hardware in der Klasse implementiert. Somit habe ich alles
was zur Hardware MB100 gehört in der Klasse MB100, usw.
Das hört sich für mich an, als wären deine Klassen zu groß. Als täten sie zu viel. Eine Klasse sollte genau eine Aufgabe haben. Nicht mehr und nicht weniger. ==> Single Responsibility Princliple.

Ich weiß nicht, was deine Klasse alles tun soll, aber, wenn sie mehr tut als das Protokoll verarbeiten (also vermutlich das, was du Parsen nennst), dann solltest du das in mehrere Klassen aufteilen.

Zitat:
Alles was zur Zentrale A gehört, befindet sich auch in dessen Klasse.
Eben das genau nicht. Das ist nicht objektorientiert. Nicht alles in eine Klasse. Sonst kriegst du Gottklassen, die letztendlich nur noch unübersichtlich sind. D.h. du solltest feiner Aufteilen. Es ist schon richtig, dass du das, was zusammengehört auch zusammen haben sollst, aber das muss nicht notwenidigerweise eine einzige Klasse sin. Das kann auch eine Gruppe von Klassen sein, sofern jede Klasse für sich genommen eine abgegrenzte Aufgabe hat und du dich nicht in Redundanzen verrennst. Lies mal http://www.christian-rehn.de/2009/08...hinen-und-ood/ bzw. http://www.objectmentor.com/resource...offeeMaker.pdf

mfg

Christian
Kaum macht man's richtig, schon klappts!
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#15

AW: Aufbau eigene Klasse mit Property und TStrings

  Alt 31. Dez 2010, 16:10
Man kann und ich würde es in diesem Fall so tun, das ganze auch als hochspezialisierte/erweiterte Comportklassen sehen.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von Jens Hartmann
Jens Hartmann

Registriert seit: 11. Jan 2009
Ort: Wilnsdorf
1.439 Beiträge
 
Delphi XE2 Professional
 
#16

AW: Aufbau eigene Klasse mit Property und TStrings

  Alt 3. Jan 2011, 19:25
Zitat von r2c2:
Bin gestern mit dem Blog-Artikel über Magic Values doch nicht mehr fertig geworden. Jetzt aber endlich: http://www.christian-rehn.de/2010/12/31/magic-values/
Danke für den Hinweis, werde ich mir aufjedenfall mal ansehen.

Zitat von r2c2:
Wie viele Programme hast du jetzt? Ich dachte zwei: Einen Dienst und eine GUI. Und die GUI muss ja vom Com-Zeug eigentlich nix wissen. Oder hab ich da was falsch verstanden?
Ja, ich habe vor zwei Programme zu schreiben. Allerdings sollen beide die selbe Aufgabe erfüllen. Soll heißen, startet man die Anwendung, hab ich eine Oberfläche auf der ich die Aktivitäten auf den Com-Schnittstellen und den Datenverkehr der Datenbank beobachten kann. Siehe Screenshot 1.Desweiteren möchte ich einen Dienst, der die selbe Aufgabe erfüllt, allerdings die Funktion eines Dienstes hat. z.B. "Keine Windows Anmeldung erforderlich". Somit muss aber die GUI auch einen Bezug zu den COM-Ports haben. Zum Außerwerden der Datenbank, so vermute ich war dein Gedanke, gibt es eine weitere Anwendung die WEB-basierent läuft.

Zitat von r2c2:
Nein, das sind Parameter, die man aus ner Konfigurationsdatei lesen sollte. "Put Abstractions in Code, details in metadata". Der Einfachheit halber kann man dieses Prinzip auch mal ignorieren (KISS). Das is mal wieder so ne Trade-off-Geschichte...

In diesem Fall würde ich aber auch die Factory nehmen. Egal ob jetzt von mir aus in der Factory hardgecoded oder aus ner Konfigurationsdatei gelesen. Aber deine Klasse muss von Baudrate & Co. eigentlich erstmal nix wissen. Das ist Sache von TComPort. ==> Separation of Concerns.
Hab ich verstanden, werde ich allerdings für mich als Zusammenhang in die Unit der entsprechenden Hardware packen. Da denke ich so wie "Bummi".

Zitat von Bummi:
Man kann und ich würde es in diesem Fall so tun, das ganze auch als hochspezialisierte/erweiterte Comportklassen sehen.
Zitat von r2c2:
Das hört sich für mich an, als wären deine Klassen zu groß. Als täten sie zu viel. Eine Klasse sollte genau eine Aufgabe haben. Nicht mehr und nicht weniger. ==> Single Responsibility Princliple.

Ich weiß nicht, was deine Klasse alles tun soll, aber, wenn sie mehr tut als das Protokoll verarbeiten (also vermutlich das, was du Parsen nennst), dann solltest du das in mehrere Klassen aufteilen.
Von der Sache her ja, allerdings macht diese Klasse/das Unit ja nur folgendes. Die Parameter bereitstellen welche notwendig sind um Daten anzufordern und zweitens diese Angeforderten Daten Parsen"Verarbeiten" bzw. in seine Einzelteile zerlegen und an das Datenmodul zurück zu geben. Die an das Datenmodul übergebenen Daten werden dann von dem Datenmodul in die Datenbank geschrieben. Somit wäre in der Klasse bzw. Unit ein kleines Packet max. 4 Methoden die aber für eine Aufgabe zuständig sind. Alle diese Methoden werden benötigt um Daten von A - B zu bekommen. Und daher denke ich, das die Klasse nicht zu viele Aufgaben hat. Vieleicht sollte ich einfach sagen, das ich damit meinen Code mehr Strukturieren will. Hätte ich dies nicht vor, würde diese Aufgabe auch im Datenmodul Platz finden.

Vieleicht konnte ich meine Ziel jetzt noch etwas besser erläutern. Was mir wichtig ist, ist halt, das wenn schon eine externe Unit, das diese auch sauber Programmiert ist. Ich fange gerade halt erst mit Klassen an und da will ich halt nicht direkt den größten Bock schießen.

Gruß Jens
Miniaturansicht angehängter Grafiken
screenshot-1.png  
Jens Hartmann
Das Leben selber ist zu kurz, also nutze jeden Tag wie er kommt.
  Mit Zitat antworten Zitat
Benutzerbild von bernau
bernau

Registriert seit: 1. Dez 2004
Ort: Köln
1.190 Beiträge
 
Delphi 10.3 Rio
 
#17

AW: Aufbau eigene Klasse mit Property und TStrings

  Alt 4. Jan 2011, 00:16

property ComPortProperties: TStrings read FComPortProperty; .

wenn du unbedingt write haben willst, dann implementier dieses als 'ne Assign-Methode,
Ist zwar eigendlich schon geklärt, daß man für die Lösung nicht unbedingt Tstrings benötigt, sondern ein Record verwenden kann. Aber ich möchte mal grundsätzlich auf das Thema TStrings als Property eingehen. Deinen Post, himitsu, habe ich mal als Aufhänger genommen. Könnte aber auch 2-3 anderes Posts Quoten, die ein Assign im Setter vorschlagen.

Im Zweifel weis man nicht, wie die Setter-Methode implementiert ist. Diese könnte eine Zuweisung einer Stringliste auf eine interne Variable sein (Interne Variable wurde dann z.B. nicht im Constructor instanziert), oder eben ein Assign auf eine bereits instanzierte Variable.

Daher gibt es bei mir die Konvention, daß eine interne bereits im Create instanzierte Stringliste nur über eine Function oder ein Readonly-Property zugreifbar ist.

property ComPortPropertys: TStrings read FComPortPropertys;
Delphi-Quellcode:
function ComPortPropertys: TStrings;
begin
 result:=FComPortPropertys;
end;
Eine Stringliste, die im Objekt nicht instanziert wurde, die bekommt eine Getter UND eine Setter-Methode. Mit dieser Vorgabe weis ich genau, ob das Objekt die Zerstörung der übergebenen Stringlist übernimmt. Soll die Zerstörung der zugewiesenen Stringliste nicht vom Objekt übernommen werden, dann muss vorher ein NIL zugewiesen werden, oder es gibt ein Property mit dem namen OwnsStringlist. Gilt im übrigen nicht nur für Stringlisten, sonder für alle Objekte, die in einem Objekt zugreifbar sind.


Alles andere birgt die Gefahr eines Speicherlecks oder einer Schutzverletzung.
Gerd
Kölner Delphi Usergroup: http://wiki.delphitreff.de
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 17:55 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf