Sind optionale Parameter hilfreich oder ein Hindernis für die Anwendungswartung? [geschlossen]

14

Sind optionale Parameter, wie sie in C # verwendet werden, hilfreich oder behindern sie die Anwendungswartung und sollten vermieden werden, da sie das Verständnis des Codes erschweren können?

rjzii
quelle
3
Haftungsausschluss: Jedes in den falschen Händen befindliche Sprachmerkmal kann missbraucht werden. Wenn eine Sprache dies auf intelligente Weise implementiert und diese Sprachfunktion nicht zu sehr mit einer vorhandenen Sprachfunktion in langweiliger Weise überlappt, sind sie in Ordnung, in der Tat sehr nützlich. Python hat einige nette Parameter zum Packen / Entpacken und andere Parameter "Tricks" (Tricks im guten, nicht im Perl-Sinne).
Job
Versuchen Sie, eine App in C # zu schreiben, die eine Schnittstelle zu Excel ohne Verwendung optionaler Parameter herstellt. Das sollte Ihre Frage zweifelsfrei beantworten.
Dunk

Antworten:

22

Optionale Parameter waren meiner Erfahrung nach eine gute Sache. Ich habe sie nie verwirrend gefunden (zumindest nicht verwirrender als die eigentliche Funktion), da ich immer die Standardwerte abrufen kann und weiß, wie sie heißen.

Eine Verwendung für sie ist, wenn ich einer Funktion, die bereits allgemein verwendet wird, oder zumindest in der öffentlichen Schnittstelle, einen weiteren Parameter hinzufügen muss. Ohne sie müsste ich die ursprüngliche Funktion wiederholen, um eine Funktion aufzurufen, die ein anderes Argument enthält, und das kann sehr alt werden, wenn ich mehr als einmal Argumente hinzufüge.

David Thornley
quelle
1
+1 Und es ist wertvoll bei überladenen Methoden, die ein Argument hinzufügen, wie new Circle(size, color, filled, ellipseProportions)wo sizeund colorerforderlich sind, und der Rest ist Standard.
Michael K
15

Wenn Sie häufig viele / optionale Parameter benötigen, tun Ihre Funktionen im Allgemeinen zu viel und sollten getrennt werden. Sie brechen wahrscheinlich SRP (Single Responsibility Principle).

Suchen Sie nach Parametern, die gruppiert werden können, z. B. (x und y werden zu einem Punkt).

Sind diese optionalen Parameter-Flags voreingestellt? Wenn Sie Flags verwenden, sollte die Funktion aufgeteilt werden.

Das heißt nicht, dass Sie niemals optionale Parameter haben sollten, aber im Allgemeinen deuten mehr als ein oder zwei Parameter auf einen Codegeruch hin.

Es könnte auch ein Hinweis sein, dass die Funktion tatsächlich eine Klasse sein sollte, wobei die optionalen Parameter in Eigenschaften geändert wurden und der erforderliche Parameterteil des Konstruktors.

CaffGeek
quelle
1
+1 für Vorsicht. Jedes noch so gute Feature kann missbraucht werden.
Michael K
3
Dies ist ein guter Rat für die Erstellung von überarbeitetem Ravioli-Code, bei dem Benutzer Ihrer API mindestens 6 Klassen und 15 Funktionen verwenden müssen, um selbst das Einfachste zu ermöglichen.
Dsimcha
1
@dsimcha, wie bekommst du das von dem, was ich geschrieben habe? Beeindruckend. Bitte erkläre? Das wäre genauso schlecht wie eine "Superfunktion", die Sie erhalten, wenn Sie viele optionale Parameter haben. Lesen Sie mehr über SOLID-Designprinzipien und schreiben Sie testbaren Code. Vorzugsweise mit TDD. Dann kommen Sie zurück und versuchen Sie mir zu erklären, dass das Reduzieren von Parametern in Funktionen eine schlechte Sache ist.
CaffGeek
1
Testbarer Code ist nett, aber auch eine saubere, benutzbare API, die nicht übermäßig feinkörnig oder ausführlich ist und Klassen nicht in Situationen schiebt, in denen eine Funktion die richtige Abstraktion ist. Ich glaube an das Prinzip der einheitlichen Verantwortung mit Verantwortlichkeiten, die auf einer hohen Abstraktionsebene definiert sind. Wenn Verantwortlichkeiten auf einer zu niedrigen Ebene definiert sind, werden einzelne Einheiten zu stark vereinfacht, so dass ihre Interaktionen zu komplex sind.
dsimcha
1
@dsimcha, du verpasst den Punkt. Einzelne Einheiten sollten einzelne Einheiten bleiben und nicht zu einer einzigen Funktion zusammengefasst werden. Das bedeutet auch nicht, dass es sich um öffentlich zugängliche Funktionen handelt. Ihre API ist das Tor zum Code und sollte sauber und prägnant sein. Eine Funktion mit mehreren optionalen Parametern ist weder übersichtlich noch prägnant. Das Überladen einer einzelnen Funktion mit logischen Parametern ist jedoch viel klarer. Beispielsweise gibt es in vielen APIs Funktionen, bei denen zwei Parameter optional sind, der eine oder andere jedoch erforderlich ist. Was ist daran klar, wenn beide als optional markiert sind?
CaffGeek
4

Optionale Parameter sind in Ordnung

In der Regel lautet die Rechtfertigung entweder: a) Sie wissen, dass Sie viele mögliche Argumente für Ihre Methode haben, aber aus Angst, Ihre API zu überladen, nicht möchten, oder b) Sie kennen nicht alle möglichen Argumente außer Ihnen Sie möchten Ihren Benutzer nicht zwingen, ein Array bereitzustellen. In jedem Fall retten optionale Parameter auf elegante Art und Weise.

Hier sind einige Beispiele:

1. Sie möchten eine Überlastung vermeiden und möchten kein Array angeben

Schauen Sie sich printf () von C, Perl, Java usw. an. Es ist ein großartiges Beispiel für die Leistungsfähigkeit optionaler Parameter.

Beispielsweise:

printf("I want %d %s %s",1,"chocolate","biccies");

printf("I want %d banana",1);

Keine Überladung, keine Arrays, einfach und intuitiv (sobald Sie die Standard-String-Format-Codes verstanden haben). Einige IDEs teilen Ihnen sogar mit, ob Ihre Formatzeichenfolge nicht Ihren optionalen Parametern entspricht.

2. Sie möchten die Verwendung von Standardeinstellungen zulassen und diese für den Benutzer der Methode verborgen halten

sendEmail ("[email protected]");

Die sendEmail-Methode erkennt, dass verschiedene wichtige Werte fehlen, und füllt sie mit definierten Standardwerten (Betreff, Text, CC, BCC usw.). Die API bleibt sauber und dennoch flexibel.

Ein Hinweis auf zu viele Parameter

Wie andere bereits festgestellt haben, deutet eine zu große Anzahl von obligatorischen Parametern für eine Methode darauf hin, dass möglicherweise ein Fehler in Ihrem Entwurf vorliegt. Dies gilt insbesondere dann, wenn sie denselben Typ haben, da sie vom Entwickler versehentlich gewechselt werden können, was zur Laufzeit zu merkwürdigen Ergebnissen führt:

String myMethod(String x, String y, String z, String a, int b, String c, int d) {}

ist ein idealer Kandidat für das Refactoring von Introduce Parameter Object

String myMethod(ParameterObject po) {}

class ParameterObject {
  // Left as public for clarity
  public String x;
  public String y;
  ... etc

}

Dies kann wiederum zu einem besseren Design führen, das auf einem Factory-Muster mit einer bereitgestellten Spezifikation als Parameterobjekt basiert.

Gary Rowe
quelle
1
String-Formatierungsfunktionen wie printf sind die Ausnahme von der Regel. Man könnte argumentieren, dass sie zwar eine unbegrenzte Liste optionaler Parameter verwenden, das Argument jedoch eher ein Array als optionale Parameter ist, unabhängig davon, wie es implementiert ist.
CaffGeek
@Chad Ich habe meine Antwort angepasst, um zwischen optionalen Parametern und dem Übergang in einen Codegeruch besser unterscheiden zu können (wie Sie in Ihrer Antwort erwähnt haben).
Gary Rowe
@ Gary Rowe, zu viele optionale Parameter sind in den meisten Fällen auch schlecht.
CaffGeek
@Chad Ich stimme zu, aber die meisten Sprachen bieten keine Möglichkeit, eine Begrenzung für die Anzahl der optionalen Argumente festzulegen, sodass es sich um einen Alles-oder-Nichts-Ansatz handelt. Sie sind gezwungen, es Ihrer Methode zu überlassen, diese zu erzwingen. Wenn Ihre Methode 500 Variablen behandelt, muss sie definitiv überarbeitet werden.
Gary Rowe
@ Gary Rowe, was meinst du mit "Die meisten Sprachen bieten keine Möglichkeit, die Anzahl der optionalen Argumente zu begrenzen"? In den meisten Sprachen kennzeichnen Sie sie als solche oder geben sie beim Aufrufen der Funktion nicht an, aber im Funktionsheader sind noch die Parameter definiert. Zugegeben, in einigen Sprachen können Sie so viele Parameter hinzufügen, wie Sie möchten, nachdem Sie die definierten ausgefüllt haben, aber ich denke nicht, dass dies die Art von optionalen Parametern ist, über die wir hier sprechen. (Abgesehen von der Ausnahme des Zeichenfolgenformats)
CaffGeek 30.11.10
2

Eines der Probleme mit Standardparametern in C # (ich denke, DoSomething ist ungültig (int x = 1)) sind Konstanten. Das heißt, wenn Sie die Standardeinstellung ändern, müssen Sie alle Konsumenten dieses Methodenaufrufs neu kompilieren. Dies ist zwar einfach genug, aber es gibt Situationen, in denen dies gefährlich ist.

Po-Ta-Toe
quelle
1

Es hängt davon ab, was Ihr Code tut. Wenn es sinnvolle Standardeinstellungen gibt, sollten Sie optionale Parameter verwenden. Wenn es jedoch keine sinnvollen Standardeinstellungen gibt, wird der Code durch Hinzufügen optionaler Parameter komplizierter. In vielen Fällen sind optionale Parameter eine gute Möglichkeit, Nullprüfungen zu umgehen und die Verzweigungslogik zu umgehen. Javascript hat keine optionalen Parameter, aber es gibt eine Möglichkeit, sie mit || zu emulieren (logisch oder) und ich benutze es die ganze Zeit, wenn ich datenbankbezogene Dinge mache, denn wenn der Benutzer keinen Wert angibt, dann ersetze ich meine eigenen Werte mit Hilfe von || Das erspart mir die Mühe, eine ganze Reihe von if then-Anweisungen zu schreiben.

davidk01
quelle
1

Optionale Parameter sind eine großartige Möglichkeit, um einfache und komplizierte Dinge gleichzeitig zu ermöglichen. Wenn die meisten Benutzer, zumindest in schnellen und unsauberen Anwendungsfällen, eine eindeutige vernünftige Vorgabe wünschen, sollten sie nicht jedes Mal, wenn sie Ihre Funktion aufrufen, ein Boilerplate schreiben müssen, um es manuell anzugeben. Auf der anderen Seite, wenn die Leute einen guten Grund haben, es ändern zu wollen, dann muss es aufgedeckt werden.

Die Verwendung einer Klasse ist meiner Meinung nach eine schreckliche Lösung, da sie wortreich, ineffizient und im Widerspruch zum typischen mentalen Modell dessen steht, was eine Klasse tut. Eine Funktion ist die perfekte Abstraktion für ein Verb, dh etwas tun und zurückkehren. Eine Klasse ist die richtige Abstraktion für ein Substantiv, dh etwas, das einen Zustand hat und auf verschiedene Arten manipuliert werden kann. Wenn Ersteres das mentale Modell des API-Benutzers sein soll, dann machen Sie es nicht zu einer Klasse.

dsimcha
quelle
1

Das Problem mit optionalen Argumenten ist, dass die Leute dazu neigen, immer mehr (und mehr) Argumente für die Funktion zu verwenden, anstatt relevanten Code in eine neue Funktion zu extrahieren. Dies wird in PHP auf das Äußerste getrieben . Zum Beispiel:

bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
                      [, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
Martin Wickman
quelle
1

Optionale Parameter sind grundsätzlich eine andere Art, eine Funktion zu überladen. Das heißt also im Grunde: "Überlastet eine Funktion schlecht"?

Pieter B
quelle
1

Ich habe dieses Feature in Python anfangs geliebt und es verwendet, um bereits verwendete Methoden zu erweitern. Und es sah nett und einfach aus, aber es kehrte bald zurück; Denn als ich einen optionalen Parameter hinzufügte, änderte dies das Verhalten einer vorhandenen Methode, auf die sich der alte Client stützte, und auf eine Weise, die von vorhandenen Unit-Testfällen nicht erfasst wurde. Im Grunde bedeutet dies, das Open Closed-Prinzip zu brechen. Code ist zur Erweiterung offen, aber zur Änderung geschlossen. Daher halte ich es nicht für eine gute Idee, diese Funktion zum Ändern des vorhandenen Codes zu verwenden. aber okay, wenn von Anfang an verwendet

Alex Punnen
quelle
0

Ich denke, es wäre besser, eine Funktion mit anderen Signaturen (dh Parametern) zu überladen, als optionale Parameter zu verwenden.

HardCode
quelle
Warum? Ich denke, es ist sauberer, wenn Sie eine Reihe von überladenen Methoden in einer Methode mit Standardparametern kombinieren können, wenn alle Methoden die gleiche Grundfunktionalität haben
Amit Wadhwa
Das kannst du dir denken. Ich bin nicht der einzige, der glaubt, dass Microsoft alles richtig macht, aber wenn Sie genau sind, würde es bei Verwendung des .NET-Frameworks nie zu Überlastungen kommen, nur zu einer großen Funktionssignatur - wie in der alten VB6.
HardCode