Verwendet "out" schlechte Praxis

8

Ich habe gerade einen out bool-Parameter zu einer Methode hinzugefügt, die ich geschrieben habe, um eine Warnung in meine Benutzeroberfläche zu bekommen. Ich habe ein out verwendet, anstatt die Methode selbst dazu zu bringen, false / true zurückzugeben, da dies bedeuten würde, dass DoSomething fehlgeschlagen / erfolgreich war. Mein Gedanke war, dass der warnUser anzeigen würde, was die Warnung eigentlich war, ohne sich die Implementierung der Methode ansehen zu müssen.

Originalcode

%Vor%

Neuer Code

%Vor%

Ich verwende Moq, um diesen Code zu testen, aber es unterstützt keine out / ref-Parameter, da sie nicht von Lambda-Ausdrücken

unterstützt werden

Testcode

%Vor%

Also, verwendet out Parameter schlechte Praxis und wenn ja, was mache ich stattdessen?

    
Antony Scott 23.11.2010, 10:42
quelle

7 Antworten

9

Die Verwendung eines out-Parameters in einer void-Methode ist im Allgemeinen eine schlechte Idee. Sie sagen, Sie haben es verwendet, "anstatt die Methode selbst dazu zu bringen, falsch / wahr zurückzugeben, da dies bedeuten würde, dass die DoSomething gescheitert ist / gelungen ist" - ich glaube nicht, dass diese Implikation vorhanden ist. In .NET-Fällen wird der Fehler normalerweise durch eine Ausnahme und nicht durch true / false angezeigt.

out -Parameter sind im Allgemeinen hässlicher zu verwenden als Rückgabewerte - insbesondere muss eine Variable vom richtigen Typ verwendet werden, damit Sie nicht einfach schreiben können:

%Vor%

Eine Alternative, die Sie in Erwägung ziehen könnten, ist eine Aufzählung, die die erforderliche Warnstufe angibt. Zum Beispiel:

%Vor%

Dann könnte die Methode WarningLevel anstelle von bool zurückgeben. Das würde deutlicher machen, was Sie meinten - obwohl Sie die Dinge vielleicht etwas umbenennen möchten. (Es ist schwierig, Ratschläge mit metasyntaktischen Namen wie "DoSomething" zu geben, obwohl ich völlig verstehe, warum Sie das hier benutzt haben.)

Eine andere Alternative ist natürlich, dass Sie möchten, dass mehr Informationen vorhanden sind - wie der Grund für die Warnung. Das könnte mit einem Enum gemacht werden, oder Sie möchten vielleicht etwas reicheres Ergebnis geben.

    
Jon Skeet 23.11.2010, 10:49
quelle
7

out ist sehr ein nützliches Konstrukt, insbesondere in Mustern wie bool TryGetFoo(..., out value) , wo Sie das "if" und das "was" wissen möchten separat (und Nullable ist nicht unbedingt eine Option).

Wie auch immer - in diesem Fall, warum nicht einfach:

%Vor%

und verwenden Sie den Rückgabewert, um dies zu signalisieren?

    
Marc Gravell 23.11.2010 10:50
quelle
3

Ein paar zusätzliche Gedanken:

  • Was FxCop sagt: CA1021: Vermeiden Sie Parameter

  • Für private / interne Methoden (Implementierungsdetails) out / ref Parameter sind weniger ein Problem

  • C # 7 Tupel sind oft eine bessere Alternative zu out parameters

  • Außerdem C # 7 verbessert die Handhabung des out -Parameters auf der Aufrufseite, indem "out-Variablen" eingeführt werden und out -Parameter

  • verworfen werden
ulrichb 23.11.2010 10:49
quelle
1

Das ist eine wirklich schwierige Frage, die Sie beantworten müssen, ohne mehr über den Kontext zu wissen.

Wenn DoSomething eine Methode in der UI-Ebene ist, die etwas mit der Benutzeroberfläche zu tun hat, dann ist es vielleicht in Ordnung. Wenn DoSomething jedoch eine Business-Schicht-Methode ist, dann ist dies wahrscheinlich kein guter Ansatz, da die Business-Schicht verstehen muss, was eine geeignete Antwort sein könnte, und sie muss möglicherweise sogar auf Lokalisierungsprobleme achten.

Aus rein subjektiver Sicht habe ich mich von den äußeren Parametern ferngehalten. Ich denke, sie stören den Fluss des Codes und machen es etwas weniger klar.

    
Damian Powell 23.11.2010 10:51
quelle
1

Angesichts einer großen Legacy-Code-Methode (sagen wir über 15 Zeilen, Legacy-Code-Methoden mit mehr als 200 Zeilen sind recht üblich), könnte man das Refactoring "Extract Method" verwenden, um Code aufzuräumen und Code spröder und wartungsfreundlicher zu machen.

Ein solches Refactoring führt sehr wahrscheinlich zu einer oder mehreren neuen Methoden ohne out-Parameter für das Setzen von Variablenwerten lokal für die vorherige Methode.

Persönlich verwende ich diesen Umstand als starken Hinweis darauf, dass in der früheren Methode eine oder mehrere diskrete Klassen versteckt waren, so dass ich "Klasse extrahieren" verwenden kann, wobei in der neuen Klasse diese out-Parameter Eigenschaften sichtbar machen die aufrufende (vorherige) Methode.

Ich halte es für eine schlechte Praxis, die extrahierten Methoden mit out-Parametern in der früheren Methode zu belassen und den kohärenten folgenden Schritt von "Klasse extrahieren" zu überspringen, weil diese lokalen Variablen in Ihrer früheren Funktion bleiben, aber semantisch bleiben gehören nicht mehr dazu.

Also, in einem solchen Szenario, sind meiner Meinung nach Parameter, die einen Code riechen, der SRP bricht.

    
Michael Würthner 23.02.2016 10:37
quelle
0

Ich denke, dass der beste Weg dies zu tun ist, erwartete Exceptions zu verwenden. Sie können eine Reihe von benutzerdefinierten Ausnahmen erstellen, die Ihre Warnungen definieren und sie in der aufrufenden Methode abfangen.

%Vor%

Die Idee wäre, dass die Ausnahme am Ende der DoSomething-Implementierung ausgelöst wird, damit der Fluss nicht in der Mitte aufhört

    
Daniel Perez 23.11.2010 10:49
quelle
0

Ich denke, die beste Lösung für Ihren Fall ist die Verwendung eines Delegierten anstelle von bool. Verwenden Sie etwas wie folgt:

%Vor%

Sie können eine leere Lambda übergeben, wenn Sie dem Benutzer keine Warnungen anzeigen möchten.

    
Juozas Kontvainis 23.11.2010 10:58
quelle

Tags und Links