![]() |
Über den Umgang mit vielen optionalen Parametern
Thread zur Steigerung der Codequalität Nr. 2....
Ich denke fast jeder kennt das Problem... ich habe hier z.B. eine Funktion mit 4 optionalen Parametern (von denen 3 auch noch typgleich sind - Zahlen frei erfunden ;) ). Mit dem klassischen Versuch:
Delphi-Quellcode:
und der Weiterleitung der parameterarmen Funktionsrufen an die parameterreichen kommt man da schnell nicht mehr weiter - zumindest nicht schön.
function foo(a): z;
function foo(a, b): z; function foo(a, b, c): z; Also habe ich mir überlegt... man erstellt sich einen Record mit einem Feld pro Parameter.
Delphi-Quellcode:
Verwenden könnte man das ganze dann so:
TParams = record
paramAValue: integer; paramBValue: integer; paramCValue: integer; function paramA(i: Integer): TParams; ... end; TParams.paramA(i: Integer): TParams; begin Result := Clone(self); Result.paramAValue := i; end;
Delphi-Quellcode:
Allerdings ist das auch noch blöd, wegen der zwingend nötigen params-Variable. Die will man ja möglichst auch noch loswerden.
var
params: TParams; begin result := foo(params.paramA(1).paramF(120)); Ideal wäre also sowas (WAS LEIDER NICHT ZU GEHEN SCHEINT)
Delphi-Quellcode:
Da könnte man dann auch schön beim Aufruf der Klassenmethoden die Felder mit default-werten belegen (denn das ist dann ja eindeutig die Stelle wo ein neues Objekt erzeugt wird). Verwenden könnte man es dann einfach so:
TParams = class
paramAValue: Integer; ... function paramA(i: Integer): TParams; ... class function paramA(i: Integer): TParams;
Delphi-Quellcode:
Nunja... das scheitert schon allein daran, dass man keine gleichnahmigen class/instance-Methods anlegen kann :( (Smalltalk kann das :tongue: )
result := foo(TParams.paramA(5));
Soo... was haltet ihr allgemein von der Idee? Habt ihr irgendwelche anderen / besseren / zielführenderen? |
Re: Umgang mit vielen optionalen Parametern
Dir ist schon klar, dass folgendes geht:
Delphi-Quellcode:
?
function foo(a: Integer; b: Integer = 0; c: Integer = 0): z;
foo(1); foo(1,2); foo(1,2,3); |
Re: Umgang mit vielen optionalen Parametern
Zitat:
|
Re: Über den Umgang mit vielen optionalen Parametern
Dann musst du in den sauren Apfel beißen und B doch angeben :-P
Ich setze häufig genutzte Parameter dann eben ganz weit links in die Liste. Die am seltensten genutzten optionalen Parameter kommen dann weiter nach rechts. Edit: Hab mir deinen Ansatz nicht genau angeschaut. Sieht aber nach Overkill aus. |
Re: Über den Umgang mit vielen optionalen Parametern
So mache ich es auch meistens, also wie Neutral General es sagte.
Dieses Konzept hier mit dem Record wird so ähnlich ja auch an vielen Stellen in Zusammenhang mit der WinAPI zum Beispiel angewendet - ist wohl etwas weniger Performant, das dann auch noch mit Klassen zu machen, aber... |
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
|
Re: Über den Umgang mit vielen optionalen Parametern
Wenn Du so viele optionale Parameter hast, dann macht die Funktion aber mehr als sie sollte. Wieso bricht du dir denn einen ab und versuchst auf Deibel komm raus, so viel Funktionalität in eine Funktion zu packen?
Ich würde mir mal Gedanken machen, ob das der richtige Weg ist. |
Re: Über den Umgang mit vielen optionalen Parametern
Offiziell würde man für sowas wohl eine Parameter-Klasse erstellen
oder gleich die Funktion in eine eigene Klasse verfrachten und dann die Parameter extra behandeln (also Funktion ohne direkte Parameter).
Delphi-Quellcode:
Ansonsten vergiß nicht, daß du eventuell die ungenutzen Parameter auch so initialisieren mußt, so daß sie als ungenutzt erkennbar sind oder daß sie wenigstens mit einen Standardwert belegt sind.
var params: TParams;
result := foo(params.clear.paramA(1).paramF(120)); // oder result := foo(TParams.Create.paramA(1).paramF(120)); In Clear oder Create würden dann erstmal alle Parameter initialisiert. (Bei Strings wäre das ja kein Problem, da sie automatisch von Delphi mit '' initialisiert werden, aber deine Beispielinteger hätten so, mit großer Wahrscheinlichkeit, undefinierte Zustände. |
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
Die Funktionen setzen im Endeffekt nur Requests an einen Webservice zusammen (so richtig viel kann ich nich dazu sagen... quasi-NDA) - machen also nicht sehr viel und eine Aufspaltung in weitere Funktionen wäre sinnlos. Der Service bietet halt nunmal diese Optionen an, die ich irgendwie in meinem Wrapper nach außen tragen muss. Und genau darum geht es ja gerade: Wie. Ein völlig gegenläufiges Konzept wäre es z.B., pro Funktion/Request-Typ eine Klasse anzulegen. Hat halt auch Vor- und Nachteile... Zitat:
|
Re: Über den Umgang mit vielen optionalen Parametern
Ok, dann ist das Konzept der Parameterstrukturen zu empfehlen, und zwar mit definierten Default/ Don't Care - Werten. Hier könnten z.B. Variants zum Einsatz kommen, mit "Null" als Defaultwert.
|
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
Delphi-Quellcode:
Viel schöner wäre natürlich, wenn sie mal ein wenig bei Prism plündern würden :) .
foo(Default(TParams).paramA(1).paramF(120))
Delphi-Quellcode:
Und für etwas ältere Versionen: Wie wäre es mit einem einfachen
Foo(new Params(A = 1, F = 120));
Delphi-Quellcode:
:?:
foo(TParams.GetDefault.paramA(1)...
Zitat:
Code:
foo(1, c: 2);
Zitat:
|
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
Zitat:
Delphi-Quellcode:
Aber ich bin mir nicht sicher ob das gemeint war :mrgreen:
var
params: TParams; begin params := TParams.Create; params.a := foo; params.b := bar; foo(params); // gleichbedeutend mit foo(TParams.getDefault.setA(foo).setB(bar)); end; |
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
Ich frage mich auch, wie eine Funktion aussehen soll, die einerseits eine Latte von Parametern akzeptiert, von denen alle optional sind, und andererseits so einfach gestrickt ist, das man sie nicht in mehrere Funktionen aufbrechen kann. Aber gut, vielleicht ist es auch nur eine Design- bzw. 'Best practice' Frage. |
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
[add]
Delphi-Quellcode:
Oder das Ganze als Interface.
type
TParams = record //class function Create: TParams; static; constructor Create; function Default: TParams; function paramA(i: Integer): TParams; function paramB(i: Integer): TParams; function ParamList: TParams; private paramAValue: Integer; paramBValue: Integer; end; constructor TParams.Create; begin Default; end; function TParams.Default: TParams; begin Finalize(Self); FillChar(@Self, SizeOf(Self), 0); Result := Self; end; function TParams.paramA(i: Integer): TParams; begin paramAValue := i; Result := Self; end; function TParams.paramB(i: Integer): TParams; begin paramBValue := i; Result := Self; end; function TParams.ParamList: TParams; begin Result := Self; end; Als Interface wäre es Speichersparender. Also Objekt ginge zwar auch, aber da darf man dann das Freigeben nicht vergessen, welches bei einigen Aufrufvarianten unmöglich/schwer zu realisieren ist.
Delphi-Quellcode:
foo(TParams.Create.paramA(1).paramB(9));
var Params: TParams; Params.Default; // oder Params := TParams.Create; Params.paramA(1); Params.paramB(9); foo(Params); with TParams.Create do begin paramA(1); paramB(9); foo(ParamList); end; with TParams.Create do begin paramA(1); //foo(ParamList.paramB(9)); foo(paramB(9)); end; |
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
Code:
und nu?
result := list.select(foo).orderBy(bar).thenBy(bar2).intersect(wuppdi);
Zitat:
Your try. Zitat:
|
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
Taucht ja in einigen deiner Posts auf. Das heißt alle Objekte (abgesehen von welchen in Interface-Typen), die du erstellst, musst du auch selbst wegräumen. |
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
![]() Das hat man nun davon. Hat man die bessere Welt erstmal kennengelernt, gefällts einem in der anderen nicht mehr :stupid: |
Re: Über den Umgang mit vielen optionalen Parametern
Interfaces und Records, sowie dyn. Arrays und String räumen sich selber auf, bzw. Delphi macht dieses für einen.
Pointer und Objekte muß man manuell aufräumen seit D2006: mit einem Record geht es einfach und mit Interfaces isses Ergebnis "schöner" |
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
Zitat:
Zitat:
Code:
ist mir dann doch etwas zu "tricky" (und vor allem zu blöd zum Implementieren). Dann lieber
new Bar()
.AddItem(1) .AddItem(2) .WithOptions() .SetCached(true) .EndOptions()
Code:
Zwischen new TParams() und TParams.GetDefault sehe ich allerdings keinen großartigen Unterschied :| . In Ruby könnten wir es "gimme!" nennen :mrgreen: .
new Bar {
Items = { 1, 2 }, Options = new Options(cached: true) } |
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
Aber wieso eigentlich immer "zurecht"? Statt der TParams.GetDefault-Methode könnte man notfalls auch noch eine CreateParams-Funktion erstellen
Delphi-Quellcode:
type
TParams = record class function Create: TParams; static; function Default: TParams; function paramA(i: Integer): TParams; function paramB(i: Integer): TParams; function ParamList: TParams; private paramAValue: Integer; paramBValue: Integer; end; function CreateParams: TParams; function CreateParams: TParams; begin Result.Default; end; class function TParams.Create: TParams; begin Result.Default; end; function TParams.Default: TParams; begin Finalize(Self); FillChar(@Self, SizeOf(Self), 0); Result := Self; end; function TParams.paramA(i: Integer): TParams; begin paramAValue := i; Result := Self; end; function TParams.paramB(i: Integer): TParams; begin paramBValue := i; Result := Self; end; function TParams.ParamList: TParams; begin Result := Self; end; |
Re: Über den Umgang mit vielen optionalen Parametern
Zitat:
Zitat:
Von Klassen ist ein Entwickler gewohnt: Wenn er ein Objekt in der Hand hat, ist davon auch der Konstruktor aufgerufen worden. Aber was sollte passieren, wenn du ein Record-Array erstellst? Die Record-Objekte sind ja schon "da", Klassen-Instanzen wären einfach nil; also müsste der Compiler durch das Array gehen und für alle Elemente den Default-Konstruktor aufrufen. Das hat der Programmierer aber wahrscheinlich doch wieder nicht erwartet, wir sind hier doch nicht bei C++ ;) . Zitat:
|
Re: Über den Umgang mit vielen optionalen Parametern
Dann wird es Zeit, daß hier endlich mal mir einem schönen POP oder ROP begonnen wird. :lol:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:57 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