Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Property via AsString;AsInteger;AsBoolean;.. laden (https://www.delphipraxis.net/169970-property-via-asstring%3Basinteger%3Basboolean%3B-laden.html)

Iwo Asnet 23. Aug 2012 12:14

AW: Property via AsString;AsInteger;AsBoolean;.. laden
 
Wir arbeiten hier seit Jahren mit dem Vorschlag von Thom (Variants).

Unsere Lösung ist so banal, das wir auf Typensicherheit, OOP, CleanCode usw. an der Stelle verzichten. Die Unit ist 186 Zeilen lang und implementiert einen bösen Singleton namens 'Setup'. Fertig.

Wir verwenden die Eigenschaften 'AsInteger', 'AsString', 'AsBoolean', um komfortabler auf Daten zugreifen zu können (nötig ist das nicht):

Delphi-Quellcode:
ValueAsVariant := Setup['MySetting'];
ValueAsInteger := Setup.AsInteger['MyIntegerSetting'];
ValueAsBoolean := Setup.AsBoolean['MyBooleanSetting'];
...
Wir hatten bisher nie die Muße, über den Sinn zu diskutieren. Die Unit wurde in 30 min zusammengebaut und funktioniert.

Nein, und unsere Anwendungen haben keine 1000 Einstellungen. Höchstens 20.

Wer mit Metadaten arbeitet (und hier haben wir welche), sollte sich mit den Variants vertraut machen.

-=ZGD=- 23. Aug 2012 12:18

AW: Property via AsString;AsInteger;AsBoolean;.. laden
 
Zitat:

Zitat von Iwo Asnet (Beitrag 1179504)
Wir arbeiten hier seit Jahren mit dem Vorschlag von Thom (Variants).

Unsere Lösung ist so banal, das wir auf Typensicherheit, OOP, CleanCode usw. an der Stelle verzichten. Die Unit ist 186 Zeilen lang und implementiert einen bösen Singleton namens 'Setup'. Fertig.

Wir verwenden die Eigenschaften 'AsInteger', 'AsString', 'AsBoolean', um komfortabler auf Daten zugreifen zu können (nötig ist das nicht):

Delphi-Quellcode:
ValueAsVariant := Setup['MySetting'];
ValueAsInteger := Setup.AsInteger['MyIntegerSetting'];
ValueAsBoolean := Setup.AsBoolean['MyBooleanSetting'];
...
Wir hatten bisher nie die Muße, über den Sinn zu diskutieren. Die Unit wurde in 30 min zusammengebaut und funktioniert.

Nein, und unsere Anwendungen haben keine 1000 Einstellungen. Höchstens 20.

Wer mit Metadaten arbeitet (und hier haben wir welche), sollte sich mit den Variants vertraut machen.

Meine Worte :-)
Bei mir werden es auch nicht mehr als 50 Werte werden.

Ich finde diese Lösung eben einfach und alltagstauglich. Man muss nicht alles auf die Spitze treiben.

@Shark: Ich habe doch einen Setter im Record..wo finde ich meinen Fehler?

s.h.a.r.k 23. Aug 2012 12:48

AW: Property via AsString;AsInteger;AsBoolean;.. laden
 
Zitat:

Zitat von -=ZGD=- (Beitrag 1179506)
@Shark: Ich habe doch einen Setter im Record..wo finde ich meinen Fehler?

Jo, habe übersehen, dass es sich um eine reine write-Property bei Value handelt. Sowas gibts bei mir nie, daher ging von einem read aus :stupid:

Zitat:

Zitat von -=ZGD=- (Beitrag 1179506)
So, die Doku muss der Entwickler sowieso bei sich haben, damit er weiß, welche Konfigurationfelder er eigentlich hat, da ist´s egal, dass er noch schaut und liest: Typ.INTEGER.

Guter Code benötigt (fast) keine Doku. Ich persönlich finde es praktischer, wenn mir IntelliSense sagt, welche Optionen ich denn zur Auswahl habe, anstatt in der Doku nachschauen zu müssen. Dann kann ich alles an Ort und Stelle auswählen nud sehe auch beim Compilieren, ob es knallt, wenn Änderungen an der Configuration-Klasse vorgenommen werden.

Folgendes Beispiel:
Delphi-Quellcode:
Port := Config.GetValue('port').AsInteger;
Port := Config.GetValue('Port').AsInteger;
// Was von den beiden ist richtig? Klar, man könnte in der GetValue()
// Methode noch auf Lower- oder UpperCase umwandeln, aber es kann
// hier leicht knallen.

// Wenn ich aber nun folgendes habe, erscheint in meinem Code eine
// Auflistung aller optionen, die die Klasse Config anbietet. Grob
// mal mit IntelliSense skizziert :)
Port := Config.+----------------+
               | MySQL         |
               | Printer       |
               | UserSpecific  |
               +----------------+

// Klar, muss die Configuration-Klasse entsprechend angepasst werden,
// sodass die Auswahl kommt. Aber so kann der Programmierer sich sehr
// leicht "durchhangeln", bis er das hat, was er sucht:
Port := Config.MySQL.Port;
Davon losgelöst kann man eben auch bzgl. den Variants argumentieren, was ich schon habe. Wer aber die Variants-Lösung bevorzugt, dem sei gesagt, dass ich nichts dagegen habe. Ich beschreibe hier nur den Weg, den ich bevorzugen würde -- aus besagten Gründen :wink:

Zitat:

Das alles sein Für und Wider hat, dagegen ist nichts einzuwenden. Letztlich entscheidet das Gutdünken des Entwicklers darüber, wie er es lösen möchte.
Was anderes habe ich nie behauptet :) Viele Wege führen ans Ziel...

bepe 23. Aug 2012 12:50

AW: Property via AsString;AsInteger;AsBoolean;.. laden
 
Zitat:

Zitat von -=ZGD=- (Beitrag 1179480)
Delphi-Quellcode:
type
  RConfig2 = record
  private
    fKey: String;
    fValue: Variant;
    function GetAsString: String;
    function GetAsInteger: Integer;
  public
    property Key: String read fKey write fKey;
    property Value: Variant write fValue;
    property AsString: String read GetAsString;
    property AsInteger: Integer read GetAsInteger;
  end;

Ich würde im Record die Setter Methoden einfügen, nicht in der Config Klasse. Dann kannst du einfach
Delphi-Quellcode:
...AsInteger := 4711
tippen, anstatt ein Record übergeben zu müssen.

Zitat:

Zitat von -=ZGD=- (Beitrag 1179480)
Delphi-Quellcode:
type
  TConfig = class(TObject)
  private
    ...
    fList: TConfigList;
    fList2: TConfigList2;

    ...
    function GetVariantValue(aID: String): RConfig2;
    procedure SetVariantValue(aID: string; aValue: Variant);

    ...
  public
    constructor create;

    ...
    property Item[aKey: String]: RConfig2 read GetVariantValue write SetVariantValue;
    ...
  end;

Hier ist der Getter ausreichend. Aber wenn schon ein Setter da ist, dann definitiv mit RConfig2 arbeiten nicht mit Variant. Auch wenn ich nichts gegen Variant habe (doch eigentlich schon :-D), es macht hier einfach keinen Sinn.

s.h.a.r.k 23. Aug 2012 13:00

AW: Property via AsString;AsInteger;AsBoolean;.. laden
 
Wenn du den Implicit-Operator überladen würdest, solltest du deine Setter-Methode so belassen können, wie du es hast. Mal schnell aus dem Kopf heraus aufgeschrieben:
Delphi-Quellcode:
TBlub = class
private
  FRec : TMyRecord;
  procedure SetRec(Value: TMyRecord);
public
  property Rec : TMyRecord read FRec write SetRec;
end;

procedure TBlub.SetRec(Value: TMyRecord);
begin
  FRec := Value;
end;


TMyRecord = class
private
  FValue : Integer;
public
  operator Implicit(Value: Integer): TMyRecord;
  property Value : Integer read FVaule;
end;

TMyRecord.Implicit(Value: Integer): TMyRecord;
begin
  Result.FValue := Value;
end;

Iwo Asnet 23. Aug 2012 13:03

AW: Property via AsString;AsInteger;AsBoolean;.. laden
 
Zitat:

Zitat von s.h.a.r.k (Beitrag 1179511)
Guter Code benötigt (fast) keine Doku.

Korrekt, aber das ist mit dem hier vorliegenden Problem (Zugriff über Metainformation, hier: Eigenschaftsnamen) nicht zu lösen.

Wir können das ganz einfach durch einen applikationsspezifischen Wrapper hinbekommen:

Delphi-Quellcode:
Type
  TSpecificConfig = Class
  Public
    Property MyInteger : Integer Read GetMyInteger  Write SetMyInteger;
  End;

...
Function TSpecificConfig.GetMyInteger : Integer;
Begin
  Result := VarToInt (Item['MyInteger']);
End;
Dies lässt sich noch vereinfachen, indem die Konfigurationsnamen in einem konstanten Array vorgehalten werden und es pro Datentyp einen IndexGetter und -setter gibt, also z.B. so:

Delphi-Quellcode:
Type
  TSpecificConfig = Class
    Const Values : Array [0..xx] of String = ('MyInt', 'MyString'...);
  Public
    Property MyInt : Integer index 0 Read GetInteger Write SetInteger;
    Property MyString : String index 1 Read GetString Write SetString;
  End;

...
Function TSpecificConfig.GeInteger (Index : Integer) : Integer;
Begin
  Result := VarToInt (Item[Values[Index]]);
End;
Der Zugriff erfolgt dann über eine Instanz der 'TSpecific'-Klasse.

Wie gesagt: Wer's toll findet, kann sich die Mühe machen.

Mir reicht:
Delphi-Quellcode:
Setup['MyInt'] := 4711;

-=ZGD=- 23. Aug 2012 14:56

AW: Property via AsString;AsInteger;AsBoolean;.. laden
 
Zitat:

Zitat von bepe (Beitrag 1179512)
Zitat:

Zitat von -=ZGD=- (Beitrag 1179480)
Delphi-Quellcode:
type
  RConfig2 = record
  private
    fKey: String;
    fValue: Variant;
    function GetAsString: String;
    function GetAsInteger: Integer;
  public
    property Key: String read fKey write fKey;
    property Value: Variant write fValue;
    property AsString: String read GetAsString;
    property AsInteger: Integer read GetAsInteger;
  end;

Ich würde im Record die Setter Methoden einfügen, nicht in der Config Klasse. Dann kannst du einfach
Delphi-Quellcode:
...AsInteger := 4711
tippen, anstatt ein Record übergeben zu müssen.

Zitat:

Zitat von -=ZGD=- (Beitrag 1179480)
Delphi-Quellcode:
type
  TConfig = class(TObject)
  private
    ...
    fList: TConfigList;
    fList2: TConfigList2;

    ...
    function GetVariantValue(aID: String): RConfig2;
    procedure SetVariantValue(aID: string; aValue: Variant);

    ...
  public
    constructor create;

    ...
    property Item[aKey: String]: RConfig2 read GetVariantValue write SetVariantValue;
    ...
  end;

Hier ist der Getter ausreichend. Aber wenn schon ein Setter da ist, dann definitiv mit RConfig2 arbeiten nicht mit Variant. Auch wenn ich nichts gegen Variant habe (doch eigentlich schon :-D), es macht hier einfach keinen Sinn.

Ich würde mich jetzt für die Variante mit Setter im Record entscheiden.
Die ist drin und sollte auch funktionieren...sollte.

Ich debugge.

Was passiert bei der jetzigen Konstellation:

Delphi-Quellcode:
type
  RConfig2 = record
  private
    fKey: String;
    fValue: Variant;
    function GetAsString: String;
    function GetAsInteger: Integer;
    procedure SetAValue(aValue: Variant);
  public
    property Key: String read fKey write fKey;
    property Value: Variant read fValue write fValue;
    property AsString: String read GetAsString;
    property AsInteger: Integer read GetAsInteger;
  end;
und
Delphi-Quellcode:
property Item[aKey: String]: RConfig2 read GetVariantValue;
Ich strebe an, über
Code:
.Value:= ?
die Wertzuweisung zu machen.

Jedoch läuft er beim Aufruf von
Delphi-Quellcode:
myConfig.Item['dbconfig'].Value:= 2312
immer in
Delphi-Quellcode:
GetVariantValue
was mir auch logisch erscheint.
Nur wie bringe ich diesen Zugriff so hin, dass es nach meinem Wunsch funktioniert?

s.h.a.r.k 23. Aug 2012 15:01

AW: Property via AsString;AsInteger;AsBoolean;.. laden
 
Du willst doch, dass es einfach funktioniert. Warum nimmst du dann nicht einfach das was ich geschrieben habe? Das was ich geschrieben habe, funktioniert nicht mal, da dann die Variable Key nicht mit übernommen wird. Shit...

-=ZGD=- 23. Aug 2012 15:11

AW: Property via AsString;AsInteger;AsBoolean;.. laden
 
Zitat:

Zitat von s.h.a.r.k (Beitrag 1179534)
Du willst doch, dass es einfach funktioniert. Warum nimmst du dann nicht einfach das was ich geschrieben habe?

Dann muss ich wieder so viel umbauen... :shock:

Und ich muss so ehrlich sein und sagen, dass mir die Einarbeitungszeit in Implicit für diese Miniklasse als zu hoch erscheint.

Es sieht so aus, als ist meine Vorstellung in dieser Art auf meiner Codebasis doch nicht so ohne Weiteres umzusetzen...

Ich bekomme einfach diese
Code:
Inkompatible Typen
Warnung nicht weg.

Vor allem frage ich mich, wie es funktionieren soll, wenn der Setter rein im Record deklariert ist..

s.h.a.r.k 23. Aug 2012 15:25

AW: Property via AsString;AsInteger;AsBoolean;.. laden
 
Zitat:

Zitat von -=ZGD=- (Beitrag 1179537)
Dann muss ich wieder so viel umbauen... :shock:

Viel wäre es ja nicht gewesen, sondern nur ein paar Zeilen. Nur leider hatte die Idee das gleiche Problem, wie du es im Moment hast.

Quick and Dirty könntest es so umbauen, dass du den folgenden Aufruf hast:
Delphi-Quellcode:
myConfig.Item['dbconfig'] := myConfig.Item['dbconfig'].SetValue(2312);
Schön ist aber was anders...

Würde dann eher vorschlagen, dass du der TConfig eine SetItemValue(Name: string; Value: Variant) Methode spendierst.

Oder eine ganz andere Alternative wäre es einen Zeiger auf den Record zurückzugeben, also bei GetVariantValue eien PRConfig2. Aber ob das so toll wäre...


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:42 Uhr.
Seite 3 von 4     123 4      

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