Sind Boolesche Werte als Methodenargumente nicht akzeptabel? [geschlossen]

123

Ein Kollege von mir erklärt, dass Boolesche Werte als Methodenargumente nicht akzeptabel sind . Sie werden durch Aufzählungen ersetzt. Zuerst sah ich keinen Nutzen, aber er gab mir ein Beispiel.

Was ist leichter zu verstehen?

file.writeData( data, true );

Oder

enum WriteMode {
  Append,
  Overwrite
};

file.writeData( data, Append );

Jetzt hab ich es verstanden! ;-)
Dies ist definitiv ein Beispiel, bei dem eine Aufzählung als zweiter Parameter den Code viel lesbarer macht.

Wie ist Ihre Meinung zu diesem Thema?

Thomas Koschel
quelle
7
Dies war eine sehr interessante Lektüre, ich werde diese Methode öfter implementieren.
Sara Chipps
hm, ich habe das schon mal gemacht, aber nie gemerkt, wie gut das Designmuster ist. Also geht die Aufzählung in die Datei?
Shawn
Aufzählungen sind aus semantischer Sicht sicherlich sinnvoller. In einem anderen Punkt wäre es interessant zu sehen, was sich einige Programmierer ausgedacht haben, um mit Fuzzy-Logik umzugehen.
James P.
2
Fragen Sie einfach den Zitronentyp in Adventure Time, ob dies nicht akzeptabel ist
ajax333221

Antworten:

131

Boolesche Werte stehen für "Ja / Nein". Wenn Sie ein "Ja / Nein" darstellen möchten, verwenden Sie einen Booleschen Wert. Dieser sollte selbsterklärend sein.

Wenn es sich jedoch um eine Wahl zwischen zwei Optionen handelt, von denen keine eindeutig Ja oder Nein ist, kann eine Aufzählung manchmal besser lesbar sein.

Skaffman
quelle
3
Außerdem muss der Methodenname klar sein, was das Argument yes oder no bewirkt, dh void turnLightOn (bool) setzt true, oder yes schaltet das Licht ein.
Simon
10
Obwohl ich in diesem Fall je nach Situation vielleicht lieber turnLightOn () und turnLightOff () hätte.
Skaffman
14
"turnLightOn (false)" bedeutet "Licht nicht einschalten"? Verwirrung.
Jay Bazuzi
17
Wie wäre es setLightOn(bool).
Finbarr
10
Später Kommentar, aber @Jay Bazuzi: Wenn Ihre Methode turnLightOn heißt und Sie false übergeben, können Sie die Methode auch überhaupt nicht aufrufen. Wenn Sie false übergeben, wird das Licht nicht eingeschaltet. Wenn das Licht bereits eingeschaltet ist, bedeutet dies nicht, dass es ausgeschaltet wird, sondern dass es nicht eingeschaltet wird. Wenn Sie eine Methode 'turnLight' haben, ist eine Aufzählung mit 'On' und 'Off' sinnvoll. TurnLight ( Ein), Licht ausschalten (Aus). Ich stimme Skaffman zu, ich würde lieber zwei verschiedene explizite Methoden verwenden, turnLightOn () und turnLightOff (). (Übrigens: Dieses Zeug wird in Onkel Bobs Buch "Clean Code" erklärt)
Phill
50

Aufzählungen ermöglichen auch zukünftige Änderungen, bei denen Sie jetzt eine dritte Auswahl (oder mehr) wünschen.

Simon
quelle
3
Oder GetMessage () von Win32: TRUE, FALSE oder -1.
bk1e
32

Verwenden Sie diejenige, die Ihr Problem am besten modelliert. In dem Beispiel, das Sie geben, ist die Aufzählung die bessere Wahl. Es würde jedoch andere Zeiten geben, in denen ein Boolescher Wert besser ist. Was für Sie sinnvoller ist:

lock.setIsLocked(True);

oder

enum LockState { Locked, Unlocked };
lock.setLockState(Locked);

In diesem Fall könnte ich die boolesche Option wählen, da ich denke, dass sie ziemlich klar und eindeutig ist, und ich bin mir ziemlich sicher, dass meine Sperre nicht mehr als zwei Zustände haben wird. Dennoch ist die zweite Wahl meiner Meinung nach gültig, aber unnötig kompliziert.

Jeremy Bourque
quelle
2
In deinem Beispiel hätte ich lieber zwei Methoden. lock.lock () lock.release () und lock.IsSet, aber alles hängt davon ab, was für den konsumierenden Code am sinnvollsten ist.
Robert Paulson
3
Das ist ein fairer Kommentar, aber ich denke, er zeigt auch den größeren Punkt, dass es viele Möglichkeiten gibt, ein bestimmtes Problem zu modellieren. Sie sollten das beste Modell für Ihre Umstände verwenden und die besten Tools verwenden, die die Programmierumgebung für Ihr Modell bereitstellt.
Jeremy Bourque
Ich stimme vollkommen zu :), ich habe gerade das spezielle Pseudocode-Angebot kommentiert, das noch eine weitere Einstellung bietet. Ich stimme Ihrer Antwort zu.
Robert Paulson
14

Für mich ist weder die Verwendung von Booleschen Werten noch die Aufzählung ein guter Ansatz. Robert C. Martin fängt dies sehr deutlich in seinem Clean Code-Tipp Nr. 12 ein: Eliminieren Sie boolesche Argumente :

Boolesche Argumente erklären lautstark, dass die Funktion mehr als eine Sache tut. Sie sind verwirrend und sollten beseitigt werden.

Wenn eine Methode mehr als eine Sache tut, sollten Sie lieber zwei verschiedene Methoden schreiben, zum Beispiel in Ihrem Fall: file.append(data)und file.overwrite(data).

Die Verwendung einer Aufzählung macht die Dinge nicht klarer. Es ändert nichts, es ist immer noch ein Flaggenargument.

Pascal Thivent
quelle
7
Bedeutet das nicht, dass eine Funktion, die eine ASCII-Zeichenfolge der Länge N akzeptiert, 128 ^ N Dinge tut?
Detly
@delty Ist das ein ernsthafter Kommentar? Wenn ja, codieren Sie häufig ein Wenn für alle möglichen Werte eines Strings? Gibt es einen möglichen Vergleich mit dem Fall eines booleschen Arguments?
Pascal Thivent
Ich glaube, sie sind akzeptabel, wenn Sie einen booleschen Wert in einem Objekt festlegen. Ein perfektes Beispiel wäre setVisible(boolean visible) { mVisible = visible; }. Was wäre eine Alternative, die Sie vorschlagen würden?
Brad
2
@Brad show () {mVisible = true} hide () {mVisible = false}
Oswaldo Acauan
@Oswaldo, obwohl immer noch korrekt, halte ich es nicht für absolut sinnvoll, zwei verschiedene Methoden zu haben, um verschiedenen Werten einen Booleschen Wert zuzuweisen. Sie haben kein setIntToOne (), setIntToTwo () setIntToThree (), oder? Es ist etwas mehrdeutiger, wenn Sie nur zwei mögliche Werte haben können, aber aus Gründen der Sauberkeit in diesem Fall einen Booleschen Wert verwenden.
Brad
13

Ich denke, Sie haben dies fast selbst beantwortet. Ich denke, das Endziel ist es, den Code lesbarer zu machen, und in diesem Fall hat die Aufzählung dies getan. IMO ist es immer am besten, das Endziel zu betrachten, anstatt pauschale Regeln, vielleicht mehr darüber nachzudenken Als Richtlinie, dh Aufzählungen sind im Code oft besser lesbar als generische Bools, Ints usw., aber es wird immer Ausnahmen von der Regel geben.

Tim Jarvis
quelle
13

Erinnern Sie sich an die Frage, die Adlai Stevenson während der Kubakrise an Botschafter Zorin bei der UN stellte ?

"Sie befinden sich gerade im Gerichtssaal der Weltmeinung und können mit Ja oder Nein antworten . Sie haben bestritten, dass [die Raketen] existieren, und ich möchte wissen, ob ich Sie richtig verstanden habe ... Ich bin bereit zu warten für meine Antwort, bis die Hölle zufriert, wenn das deine Entscheidung ist. "

Wenn das Flag, das Sie in Ihrer Methode haben, so beschaffen ist, dass Sie es auf eine binäre Entscheidung festlegen können und diese Entscheidung niemals zu einer Drei- oder N-Wege-Entscheidung wird, wählen Sie Boolesch. Anzeigen: Ihre Flagge heißt isXXX .

Machen Sie es nicht boolesch, wenn es sich um einen Modusschalter handelt . Es gibt immer noch einen Modus als Sie beim Schreiben der Methode gedacht haben.

Das Dilemma mit einem weiteren Modus hat z. B. Unix heimgesucht, wo die möglichen Berechtigungsmodi, die eine Datei oder ein Verzeichnis heute haben kann, zu seltsamen Doppelbedeutungen von Modi führen, abhängig von Dateityp, Besitz usw.

Thorsten79
quelle
13

Es gibt zwei Gründe, warum ich darauf gestoßen bin, dass dies eine schlechte Sache ist:

  1. Weil manche Leute Methoden schreiben wie:

    ProcessBatch(true, false, false, true, false, false, true);
    

    Dies ist offensichtlich schlecht, da es zu einfach ist, Parameter zu verwechseln, und Sie keine Ahnung haben, wenn Sie sich ansehen, was Sie angeben. Nur ein Bool ist aber nicht schlecht.

  2. Da die Steuerung des Programmflusses durch einen einfachen Ja / Nein-Zweig bedeuten kann, dass Sie zwei völlig unterschiedliche Funktionen haben, die auf unangenehme Weise in einer zusammengefasst sind. Zum Beispiel:

    public void Write(bool toOptical);
    

    Wirklich, das sollten zwei Methoden sein

    public void WriteOptical();
    public void WriteMagnetic();
    

    weil der Code in diesen völlig anders sein könnte; Möglicherweise müssen sie alle möglichen Fehlerbehandlungen und -validierungen durchführen oder sogar die ausgehenden Daten unterschiedlich formatieren. Sie können das nicht einfach mit Write()oder sogar sagen Write(Enum.Optical)(obwohl Sie natürlich auch eine dieser Methoden haben könnten, rufen Sie einfach die internen Methoden WriteOptical / Mag auf, wenn Sie möchten).

Ich denke es kommt nur darauf an. Ich würde nicht zu viel daraus machen, außer # 1.

Sam Schutte
quelle
Sehr gute Punkte! Zwei boolesche Parameter in einer Methode sehen in der Tat schrecklich aus (es sei denn, Sie haben das Glück, Parameter benannt zu haben).
Yarik
Diese Antwort könnte jedoch von einer Neuformatierung profitieren! ;-)
Yarik
7

Aufzählungen sind besser, aber ich würde boolesche Parameter nicht als "inakzeptabel" bezeichnen. Manchmal ist es einfach einfacher, einen kleinen Booleschen Wert hineinzuwerfen und weiterzumachen (denken Sie an private Methoden usw.)

Borek Bernard
quelle
Machen Sie die Methode einfach sehr beschreibend, damit klar ist, was wahr oder ja bedeutet.
Simon
6

Boolesche Werte können in Sprachen mit benannten Parametern wie Python und Objective-C in Ordnung sein, da der Name erklären kann, was der Parameter bewirkt:

file.writeData(data, overwrite=true)

oder:

[file writeData:data overwrite:YES]
Chris Lundie
quelle
1
IMHO ist writeData () ein schlechtes Beispiel für die Verwendung eines booleschen Parameters, unabhängig davon, ob benannte Parameter unterstützt werden oder nicht. Unabhängig davon, wie Sie den Parameter benennen, ist die Bedeutung des falschen Werts nicht offensichtlich!
Yarik
4

Ich würde nicht zustimmen, dass es eine gute Regel ist . Natürlich sorgt Enum in einigen Fällen für einen besseren expliziten oder ausführlichen Code, aber in der Regel scheint er weit über das Erreichen hinauszugehen.

Lassen Sie mich zunächst Ihr Beispiel nehmen: Die Verantwortung (und Fähigkeit) des Programmierers, guten Code zu schreiben, wird durch einen booleschen Parameter nicht wirklich gefährdet. In Ihrem Beispiel hätte der Programmierer genauso ausführlichen Code schreiben können, indem er Folgendes schrieb:

dim append as boolean = true
file.writeData( data, append );

oder ich bevorzuge allgemeiner

dim shouldAppend as boolean = true
file.writeData( data, shouldAppend );

Zweitens: Das von Ihnen angegebene Enum-Beispiel ist nur "besser", weil Sie eine CONST bestehen. Höchstwahrscheinlich sind in den meisten Anwendungen zumindest einige, wenn nicht die meisten Zeitparameter, die an Funktionen übergeben werden, VARIABLEN. In diesem Fall ist mein zweites Beispiel (Variablen mit guten Namen angeben) viel besser und Enum hätte Ihnen wenig Vorteile gebracht.

csmba
quelle
1
Obwohl ich damit einverstanden bin, dass boolesche Parameter in vielen Fällen akzeptabel sind, ist in diesem Beispiel writeData () der boolesche Parameter wie shouldAppend sehr unangemessen. Der Grund ist einfach: Es ist nicht sofort klar, was Falsch bedeutet.
Yarik
4

Aufzählungen haben definitiv einen Vorteil, aber Sie sollten nicht einfach alle Ihre Booleschen Werte durch Aufzählungen ersetzen. Es gibt viele Orte, an denen wahr / falsch tatsächlich der beste Weg ist, um darzustellen, was vor sich geht.

Die Verwendung als Methodenargumente ist jedoch etwas verdächtig, einfach weil Sie nicht sehen können, ohne sich mit den Dingen zu befassen, die sie tun sollen, da Sie sehen können, was wahr / falsch ist tatsächlich bedeutet

Eigenschaften (insbesondere bei C # 3-Objektinitialisierern) oder Schlüsselwortargumente (a la ruby ​​oder python) sind ein viel besserer Weg, um dahin zu gelangen, wo Sie sonst ein boolesches Argument verwenden würden.

C # Beispiel:

var worker = new BackgroundWorker { WorkerReportsProgress = true };

Ruby Beispiel

validates_presence_of :name, :allow_nil => true

Python-Beispiel

connect_to_database( persistent=true )

Das einzige, was ich mir vorstellen kann, wo ein boolesches Methodenargument das Richtige ist, ist in Java, wo Sie weder Eigenschaften noch Schlüsselwortargumente haben. Dies ist einer der Gründe, warum ich Java hasse :-(

Orion Edwards
quelle
4

Während es wahr ist, dass Enums in vielen Fällen lesbarer und erweiterbarer sind als Boolesche Werte, ist eine absolute Regel, dass "Boolesche Werte nicht akzeptabel sind", dumm. Es ist unflexibel und kontraproduktiv - es lässt keinen Raum für menschliches Urteilsvermögen. Sie sind in den meisten Sprachen ein grundlegender integrierter Typ, weil sie nützlich sind. Erwägen Sie, sie auf andere integrierte Typen anzuwenden: Zum Beispiel wäre es einfach verrückt zu sagen, dass Sie niemals ein int als Parameter verwenden.

Diese Regel ist nur eine Frage des Stils, nicht des Potenzials für Fehler oder die Laufzeitleistung. Eine bessere Regel wäre "aus Gründen der Lesbarkeit Enums gegenüber Booleschen Werten bevorzugen".

Schauen Sie sich das .Net-Framework an. Boolesche Werte werden bei einigen Methoden als Parameter verwendet. Die .Net-API ist nicht perfekt, aber ich denke nicht, dass die Verwendung von Booleschen Werten als Parameter ein großes Problem darstellt. Der Tooltip gibt Ihnen immer den Namen des Parameters an, und Sie können diese Art von Anleitung auch erstellen. Geben Sie Ihre XML-Kommentare zu den Methodenparametern ein. Diese werden im Tooltip angezeigt.

Ich sollte auch hinzufügen, dass es einen Fall gibt, in dem Sie Boolesche Werte eindeutig in eine Aufzählung umgestalten sollten - wenn Sie zwei oder mehr Boolesche Werte in Ihrer Klasse oder in Ihren Methodenparametern haben und nicht alle Zustände gültig sind (z. B. ist es nicht gültig, sie zu haben) beide setzen wahr).

Zum Beispiel, wenn Ihre Klasse Eigenschaften wie hat

public bool IsFoo
public bool IsBar

Und es ist ein Fehler, beide gleichzeitig wahr zu haben. Was Sie tatsächlich haben, sind drei gültige Zustände, besser ausgedrückt als:

enum FooBarType { IsFoo, IsBar, IsNeither };
Anthony
quelle
4

Einige Regeln, die Ihr Kollege möglicherweise besser einhält, sind:

  • Sei nicht dogmatisch mit deinem Design.
  • Wählen Sie aus, was für die Benutzer Ihres Codes am besten geeignet ist.
  • Versuchen Sie nicht, sternförmige Stifte in jedes Loch zu schlagen, nur weil Ihnen die Form diesen Monat gefällt!
Alex Worden
quelle
3

Ein Boolescher Wert wäre nur akzeptabel, wenn Sie nicht beabsichtigen, die Funktionalität des Frameworks zu erweitern. Die Aufzählung wird bevorzugt, da Sie die Aufzählung erweitern und frühere Implementierungen des Funktionsaufrufs nicht unterbrechen können.

Der andere Vorteil der Aufzählung ist, dass sie leichter zu lesen ist.

David Basarab
quelle
2

Wenn die Methode eine Frage stellt wie:

KeepWritingData (DataAvailable());

wo

bool DataAvailable()
{
    return true; //data is ALWAYS available!
}

void KeepWritingData (bool keepGoing)
{
   if (keepGoing)
   {
       ...
   }
}

Argumente der booleschen Methode scheinen absolut sinnvoll zu sein.

Jesse C. Slicer
quelle
Eines Tages müssen Sie "Schreiben Sie weiter, wenn Sie freien Speicherplatz haben" hinzufügen, und dann werden Sie trotzdem von Bool zu Enum wechseln.
Ilya Ryzhenkov
Und dann haben Sie bahnbrechende Veränderungen oder eine veraltete Überlastung oder können so etwas wie KeppWritingDataEx sein :)
Ilya Ryzhenkov
1
@Ilya oder vielleicht wirst du nicht! Das Erstellen einer möglichen Situation, in der derzeit keine vorhanden ist, negiert die Lösung nicht.
Jesse C. Slicer
1
Jesse hat recht. Eine solche Veränderung zu planen ist dumm. Mach was Sinn macht. In diesem Fall ist der Boolesche Wert sowohl intuitiv als auch klar. c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html
Derek Park
@Derek, in diesem Fall wird Boolean nicht einmal benötigt, da DataAvailable immer true zurückgibt :)
Ilya Ryzhenkov
2

Das hängt von der Methode ab. Wenn die Methode etwas tut, das ganz offensichtlich wahr / falsch ist, dann ist es in Ordnung, z. B. unten [obwohl ich nicht sage, dass dies das beste Design für diese Methode ist, ist es nur ein Beispiel dafür, wo die Verwendung offensichtlich ist].

CommentService.SetApprovalStatus(commentId, false);

In den meisten Fällen, wie in dem von Ihnen erwähnten Beispiel, ist es jedoch besser, eine Aufzählung zu verwenden. Es gibt viele Beispiele in .NET Framework selbst, in denen diese Konvention nicht befolgt wird. Dies liegt jedoch daran, dass diese Entwurfsrichtlinie erst spät im Zyklus eingeführt wurde.

Greg Beech
quelle
2

Es macht die Dinge ein bisschen expliziter, erweitert aber die Komplexität Ihrer Schnittstellen massiv - bei einer bloßen booleschen Wahl wie Anhängen / Überschreiben scheint es übertrieben. Wenn Sie eine weitere Option hinzufügen müssen (an die ich in diesem Fall nicht denken kann), können Sie jederzeit einen Refactor durchführen (abhängig von der Sprache).

Jennifer
quelle
1
Was ist mit dem Voranstellen als dritte mögliche Option? ;-))
Yarik
2

Aufzählungen können den Code sicherlich lesbarer machen. Es gibt noch ein paar Dinge zu beachten (zumindest in .net)

Da der zugrunde liegende Speicher einer Aufzählung ein int ist, ist der Standardwert Null. Stellen Sie daher sicher, dass 0 ein sinnvoller Standardwert ist. (Zum Beispiel haben Strukturen beim Erstellen alle Felder beim Erstellen auf Null gesetzt, daher gibt es keine Möglichkeit, einen anderen Standard als 0 anzugeben. Wenn Sie keinen 0-Wert haben, können Sie die Aufzählung nicht einmal testen, ohne sie in int umzuwandeln schlechter Stil.)

Wenn Ihre Aufzählungen für Ihren Code privat sind (niemals öffentlich zugänglich gemacht), können Sie hier aufhören zu lesen.

Wenn Ihre Aufzählungen veröffentlicht sind in irgendeiner Weise zu externem Code und / oder außerhalb des Programms gespeichert, können Sie diese explizit Nummerierung. Der Compiler nummeriert sie automatisch von 0, aber wenn Sie Ihre Aufzählungen neu anordnen, ohne ihnen Werte zu geben, können Fehler auftreten.

Ich kann legal schreiben

WriteMode illegalButWorks = (WriteMode)1000000;
file.Write( data, illegalButWorks );

Um dem entgegenzuwirken, muss jeder Code, der eine Aufzählung verwendet, deren Sie sich nicht sicher sind (z. B. öffentliche API), überprüfen, ob die Aufzählung gültig ist. Sie tun dies über

if (!Enum.IsDefined(typeof(WriteMode), userValue))
    throw new ArgumentException("userValue");

Die einzige Einschränkung Enum.IsDefinedist, dass es Reflexion verwendet und langsamer ist. Es gibt auch ein Versionsproblem. Wenn Sie den Aufzählungswert häufig überprüfen müssen, ist Folgendes besser:

public static bool CheckWriteModeEnumValue(WriteMode writeMode)
{
  switch( writeMode )
  {
    case WriteMode.Append:
    case WriteMode.OverWrite:
      break;
    default:
      Debug.Assert(false, "The WriteMode '" + writeMode + "' is not valid.");
      return false;
  }
  return true;
}

Das Versionsproblem besteht darin, dass alter Code möglicherweise nur mit den 2 Aufzählungen umgehen kann. Wenn Sie einen dritten Wert hinzufügen, ist Enum.IsDefined wahr, aber der alte Code kann nicht unbedingt damit umgehen. Hoppla.

Es gibt noch mehr Spaß, den Sie mit [Flags]Aufzählungen machen können, und der Validierungscode dafür ist etwas anders.

Ich werde auch beachten, dass Sie aus Gründen der Portabilität den Aufruf ToString()der Enumeration verwenden und Enum.Parse()beim Einlesen verwenden sollten. Beide ToString()und Enum.Parse()können damit umgehen[Flags] ENUM ist auch, also gibt es keinen Grund , sie nicht zu verwenden. Wohlgemerkt, es ist eine weitere Gefahr, denn jetzt können Sie nicht einmal den Namen der Aufzählung ändern, ohne möglicherweise den Code zu brechen.

Manchmal müssen Sie also alles oben Genannte abwägen, wenn Sie sich fragen. Kann ich mit nur einem Narren davonkommen?

Robert Paulson
quelle
1

IMHO scheint es, als wäre eine Aufzählung die offensichtliche Wahl für jede Situation, in der mehr als zwei Optionen möglich sind. Aber es gibt definitiv Situationen, in denen ein Boolescher Wert alles ist, was Sie brauchen. In diesem Fall würde ich sagen, dass die Verwendung einer Aufzählung, in der ein Bool funktionieren würde, ein Beispiel für die Verwendung von 7 Wörtern wäre, wenn 4 ausreichen.

Jurassic_C
quelle
0

Boolesche Werte sind sinnvoll, wenn Sie einen offensichtlichen Schalter haben, der nur eines von zwei Dingen sein kann (dh den Zustand einer Glühbirne, ein oder aus). Abgesehen davon ist es gut, es so zu schreiben, dass es offensichtlich ist, was Sie übergeben - z. B. Festplattenschreibvorgänge - ungepuffert, zeilengepuffert oder synchron - als solches übergeben werden sollten. Auch wenn Sie jetzt keine synchronen Schreibvorgänge zulassen möchten (und sich daher auf zwei Optionen beschränken), sollten Sie überlegen, sie ausführlicher zu gestalten, um zu wissen, was sie auf den ersten Blick tun.

Sie können jedoch auch False und True (Boolesche Werte 0 und 1) verwenden. Wenn Sie später weitere Werte benötigen, erweitern Sie die Funktion, um benutzerdefinierte Werte (z. B. 2 und 3) und Ihre alten 0/1-Werte zu unterstützen wird gut portieren, so dass Ihr Code nicht brechen sollte.

Dan Udey
quelle
0

Manchmal ist es einfach einfacher, ein anderes Verhalten mit Überlastungen zu modellieren. Um von Ihrem Beispiel fortzufahren, wäre:

file.appendData( data );  
file.overwriteData( data );

Dieser Ansatz verschlechtert sich, wenn Sie mehrere Parameter haben, die jeweils einen festen Satz von Optionen zulassen. Beispielsweise kann eine Methode, die eine Datei öffnet, mehrere Permutationen des Dateimodus (Öffnen / Erstellen), des Dateizugriffs (Lesen / Schreiben) und des Freigabemodus (Keine / Lesen / Schreiben) aufweisen. Die Gesamtzahl der Konfigurationen entspricht den kartesischen Produkten der einzelnen Optionen. In solchen Fällen sind Mehrfachüberlastungen natürlich nicht angebracht.

Aufzählungen können in einigen Fällen die Lesbarkeit von Code verbessern, obwohl es schwierig sein kann, den genauen Aufzählungswert in einigen Sprachen (z. B. C #) zu überprüfen.

Oft wird ein boolescher Parameter als neue Überladung an die Liste der Parameter angehängt. Ein Beispiel in .NET ist:

Enum.Parse(str);  
Enum.Parse(str, true); // ignore case

Die letztere Überlastung wurde in einer späteren Version des .NET-Frameworks als die erste verfügbar.

Wenn Sie wissen, dass es immer nur zwei Möglichkeiten gibt, ist ein Boolescher Wert möglicherweise in Ordnung. Aufzählungen sind so erweiterbar, dass alter Code nicht beschädigt wird, obwohl alte Bibliotheken möglicherweise keine neuen Aufzählungswerte unterstützen, sodass die Versionierung nicht vollständig ignoriert werden kann.


BEARBEITEN

In neueren Versionen von C # können benannte Argumente verwendet werden, die IMO das Aufrufen von Code auf die gleiche Weise wie Aufzählungen klarer machen können. Verwenden Sie das gleiche Beispiel wie oben:

Enum.Parse(str, ignoreCase: true);
Drew Noakes
quelle
0

Wo ich zustimme, dass Aufzählungen ein guter Weg sind, bei Methoden, bei denen Sie zwei Optionen haben (und nur zwei Optionen, können Sie ohne Aufzählung lesbar sein).

z.B

public void writeData(Stream data, boolean is_overwrite)

Ich liebe die Aufzählungen, aber Boolesche Werte sind auch nützlich.

Haris Krajina
quelle
0

Dies ist ein später Eintrag in einem alten Beitrag, und er befindet sich so weit unten auf der Seite, dass niemand ihn jemals lesen wird, aber da niemand ihn bereits gesagt hat ...

Ein Inline-Kommentar trägt wesentlich zur Lösung des unerwarteten boolProblems bei. Das ursprüngliche Beispiel ist besonders abscheulich: Stellen Sie sich vor, Sie versuchen, die Variable in der Funktionsdeklaration zu benennen! Es wäre so etwas wie

void writeData( DataObject data, bool use_append_mode );

Nehmen wir zum Beispiel an, das ist die Erklärung. Dann habe ich für ein ansonsten ungeklärtes boolesches Argument den Variablennamen in einen Inline-Kommentar eingefügt. Vergleichen Sie

file.writeData( data, true );

mit

file.writeData( data, true /* use_append_mode */);
Robert Martin
quelle
-1

Es hängt wirklich von der genauen Art des Arguments ab. Wenn es kein Ja / Nein oder Wahr / Falsch ist, wird es durch eine Aufzählung besser lesbar. Bei einer Aufzählung müssen Sie jedoch das Argument überprüfen oder ein akzeptables Standardverhalten aufweisen, da undefinierte Werte des zugrunde liegenden Typs übergeben werden können.

CheeZe5
quelle
-1

Die Verwendung von Aufzählungen anstelle von Booleschen Werten in Ihrem Beispiel trägt dazu bei, dass der Methodenaufruf besser lesbar ist. Dies ist jedoch ein Ersatz für mein Lieblingswunschelement in C #, benannte Argumente in Methodenaufrufen. Diese Syntax:

var v = CallMethod(pData = data, pFileMode = WriteMode, pIsDirty = true);

wäre perfekt lesbar, und Sie könnten dann tun, was ein Programmierer tun sollte, dh den am besten geeigneten Typ für jeden Parameter in der Methode auswählen, unabhängig davon, wie er in der IDE aussieht.

C # 3.0 erlaubt benannte Argumente in Konstruktoren. Ich weiß nicht, warum sie das nicht auch mit Methoden machen können.

MusiGenesis
quelle
Eine interessante Idee. Aber könnten Sie Parameter neu anordnen? Parameter weglassen? Wie würde der Compiler wissen, an welche Überladung Sie gebunden haben, wenn dies optional wäre? Müssen Sie auch alle Parameter in der Liste benennen?
Drew Noakes
-1

Boolesche Werte true/ falsenur. Es ist also nicht klar, was es darstellt. Enumkann aussagekräftige Namen haben, zB OVERWRITE, APPENDusw. So Aufzählungen sind besser.

fastcodejava
quelle