![]() |
Verschachtelte Records
Um Programmoptionen strukturiert irgendwo ablegen zu können statt in globalen Variablen dachte ich an Records in Art
Delphi-Quellcode:
Lesend und schreibend etwa so erreichbar
type
TProgrammEinstellungen = record public type Allgemein = record class var Bla... end; type Dateien = record class var Bla... end; end;
Delphi-Quellcode:
So wäre das ein bisschen geordnet und man hat die Variablen thematisch noch einmal gruppiert.
TProgrammEinstellungen.Allgemein.Bla :=
TProgrammEinstellungen.Dateien.Bla := Macht man das so oder doch ganz anders? |
AW: Verschachtelte Records
Ich habe mir dafür eine „richtige“ Klasse TSettings erstellt. Dann einfach
Delphi-Quellcode:
Lässt sich einfach erweitern und alles ist schön gekapselt. Da ich diese übers Netzwerk als Stream versende habe ich ihr noch die entsprechenden LoadFromStream und SaveToStream Methoden spendiert..
Settings := TSettings.Create;
Settings.LoadFromFile(...); [...] Warum Records und keine Klasse? |
AW: Verschachtelte Records
Weil mir die Autovervollständigung sonst in der Liste zu viele Dinge anzeigt, die ich selber nirgendwo deklariert habe.
|
AW: Verschachtelte Records
Was soll class var bei einem Record sein?
Anyway. Records werden nicht ineinander veraschachtelt deklariert sondern untereinander. Also erst Anwendung, Dateien und dann Programmeinstellungen. |
AW: Verschachtelte Records
Ich denke die ganze Diskussion könnte und sollte in mehrere Aspekte aufgeteilt werden:
1. Record statt einzelne Variablen 2. class var statt global 3. Klasse statt record Zu 1.: Statt einzelnen globalen Variablen finde ich es schon besser diese in einen Records zusammenzufassen. Zu 2.: eine class var ist quasi wie eine globale Variable. Sie ist immer da und wird nicht wie eine Objekt jeweils instanziiert. Da würde ich doch eine globale Variable vom typ des records besser finden. Es ist ehrlicher und nicht so versteckt. Vorteil ist auch noch, dass man die Variable auch noch kürzer benennen kann und den Typ schön lang. Bei mir heißt einer dieser Variablen schlicht "G". Zu 3.: ich wüsste jetzt nicht was eine Klasse da bringen sollte. Größere Logik sollte die eh nicht enthalten, kleinere Methoden kann man auch in records machen. Nachteil ist, dass man die Klasse dann instanzieren muss. |
AW: Verschachtelte Records
Hat es einen speziellen Grund, weshalb man Records nicht verschachteln darf?
Die Verschachtelung wollte ich machen, da ich dann sowas aufrufen kann TProgrammEinstellungen.Allgemein.Bla. Ohne Verschachtelung könnte ich auch das hier aufrufen Allgemein.Bla und ich wäre nicht gezwungen, TProgrammEinstellungen vor alles zu schreiben. |
AW: Verschachtelte Records
Die einzelnen Anwendungsfälle (bzw. deren Kern) sollten niemals direkt auf irgendwelche Sachen außerhalb zugreifen.
Erst recht nicht auf globale Variablen oder ähnliches. Sonst ist der Anwendungfall nicht mehr unabhängig testbar. Anwendungskern <-> Repository <-> globale Variable Das Repository könnte eine Klasse sein, die eine Kopie der für den Anwendungsfall wichigen globalen Einstellungen erhält. Alternativ wäre auch ein Interface denbar, das eine Klasse verbirgt, die Zugriffe auf globale Variablen weiter leitet. Im Testfall könnte der Testfall selbst dieses Interface bereitstellen. So kann man für globale Einstellungen einfach TSettings verwenden, aber auch die für den jeweiligen Anwendungsfall wichtigen Einstellungen über das Repository per Property direkt ansprechen. |
AW: Verschachtelte Records
Versteh mich nicht falsch, aber könntest du das auch für jemanden erklären der nicht in dieser Materie drinsteckt?
|
AW: Verschachtelte Records
Um die Ursprungsfrage zu beantworten und Redeemers Antwort etwas auszuführen, man kann Records problemlos verschachteln, nur findet die Deklaration der Typen getrennt von der verschachtelten Struktur statt.
Also so:
Delphi-Quellcode:
type
TAllgemein = record var Bla... end; TDateien = record var Bla... end; TProgrammEinstellungen = record Allgemein: TAllgemein; Dateien: TDateien; end; var ProgrammEinstellungen: TProgrammEinstellungen; |
AW: Verschachtelte Records
Die stark vereinfachte Skizze einer Beispiel-Anwendung:
Berechne die Summe von zwei Zahlen. Das gerundete Ergebnis wird ausgegeben. Wie das Ergebnis gerundet wird, legt eine globale Einstellung fest. Die Globalen Einstellungen werden vom Anwendungsfall nicht verändert.
Delphi-Quellcode:
TAnwendungsfallSummeConfig könnte im einfachsten Fall auch ein Record oder verschachtelter Record sein.
TAnwendungsfallSummeConfig = class()
puplic property Rundungstyp: Integer; end; TAnwendungsfallSumme = class() constructor Create(AConfig: TAnwendungsfallSummeConfig); destructor Destroy; override; {...} protected property Config: TAnwendungsfallSummeConfig; puplic property Wert1: Float; property Wert2: Float; property Ergebnis: Float; end; implementation constructor TAnwendungsfallSumme.Create(AConfig: TAnwendungsfallSummeConfig); begin inherited; FConfig := AConfig; end; destructor TAnwendungsfallSumme.Destroy; begin FConfig.Free; inherited; end; Wichtig ist aber die Trennung "Global" vom konkreten Anwendungsfall. Anwendungsfall im Programm erzeugen
Delphi-Quellcode:
Im Testprojekt gibt es die Unit 'Global' nicht. Auch das Formular wird dort nicht gebraucht.
var
config: TAnwendungsfallSummeConfig; begin config := TAnwendungsfallSummeConfig.Create; config.Rundungstyp := Global.Settings['Allgemein.Rundungstyp']; AnwendungsfallSumme := TAnwendungsfallSumme.Create(config); // wie man den Anwendungsfall mit dem Formular verknüpft, ist schon das nächste Thema ... MVC usw. end; Dort soll unter anderem die Berechnung für jeden Rundungstyp getestet werden. Wie man eine Testanwendung und Testfälle erzeugt ist bekannt? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:36 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 by Thomas Breitkreuz