Ich lese McConells Code Complete und er diskutiert die Verwendung von Booleschen Variablen, um Ihren Code zu dokumentieren. Zum Beispiel anstelle von:
if((elementIndex < 0) || (MAX_ELEMENTS < elementIndex) ||
(elementIndex == lastElementIndex)){
...
}
Er schlägt vor:
finished = ((elementIndex < 0) || (MAX_ELEMENTS < elementIndex));
repeatedEntry = (elementIndex == lastElementIndex);
if(finished || repeatedEntry){
...
}
Dies erscheint mir logisch, bewährte und sehr selbstdokumentierend. Ich zögere jedoch, diese Technik regelmäßig anzuwenden, da ich fast nie darauf gestoßen bin. und vielleicht wäre es nur deshalb verwirrend, weil es selten ist. Meine Erfahrung ist jedoch noch nicht sehr umfangreich, daher bin ich daran interessiert, die Meinung der Programmierer zu dieser Technik zu hören, und ich wäre gespannt, ob jemand diese Technik regelmäßig verwendet oder sie beim Lesen von Code oft gesehen hat. Ist dies eine lohnende Konvention / Stil / Technik? Werden andere Programmierer es verstehen und schätzen oder es für seltsam halten?
quelle
Antworten:
Das Aufteilen eines zu verschachtelten und komplizierten Ausdrucks in einfachere Unterausdrücke, die lokalen Variablen zugewiesen und dann wieder zusammengesetzt werden, ist eine weit verbreitete und beliebte Technik - ganz unabhängig davon, ob die Unterausdrücke und / oder der Gesamtausdruck boolesch sind oder von fast jeder andere Typ. Bei ausgewählten Namen kann eine geschmackvolle Zerlegung dieser Art die Lesbarkeit verbessern, und ein guter Compiler sollte keine Probleme haben, Code zu generieren, der dem ursprünglichen, komplizierten Ausdruck entspricht.
Einige Sprachen, die nicht das Konzept der "Zuweisung" an sich haben, wie Haskell, führen sogar spezielle Konstrukte ein, mit denen Sie die Technik "einem Unterausdruck einen Namen geben" (die
where
Klausel in Haskell) verwenden können - scheinen einige zu sprechen Popularität für die betreffende Technik! -)quelle
Ich habe es verwendet, obwohl ich normalerweise boolesche Logik in eine wiederverwendbare Methode einbinde (wenn sie von mehreren Speicherorten aufgerufen wird).
Es verbessert die Lesbarkeit und wenn sich die Logik ändert, muss es nur an einer Stelle geändert werden.
Andere werden es verstehen und es nicht seltsam finden (außer denen, die immer nur tausend Zeilenfunktionen schreiben).
quelle
Ich versuche es wo immer möglich. Sicher, Sie verwenden eine "zusätzliche Codezeile", aber gleichzeitig beschreiben Sie, warum Sie zwei Werte vergleichen.
In Ihrem Beispiel schaue ich mir den Code an und frage mich: "Okay, warum ist die Person, die den Wert sieht, kleiner als 0?" Im zweiten Teil sagen Sie mir deutlich, dass einige Prozesse in diesem Fall abgeschlossen sind. Keine Vermutung im zweiten, was Ihre Absicht war.
Das große Problem für mich ist, wenn ich eine Methode wie die folgende sehe:
DoSomeMethod(true);
Warum wird sie automatisch auf true gesetzt? Es ist viel besser lesbarquelle
[Object createOrderWithSource:YES backOrder:NO custom:YES type:kCreditCard];
Das bereitgestellte Beispiel:
Kann auch umgeschrieben werden, um Methoden zu verwenden, die die Lesbarkeit verbessern und die boolesche Logik beibehalten (wie Konrad betonte):
Es hat natürlich einen Preis, der zwei zusätzliche Methoden darstellt. Wenn Sie dies häufig tun, wird Ihr Code möglicherweise besser lesbar, Ihre Klassen jedoch weniger transparent. Andererseits können Sie die zusätzlichen Methoden auch in Hilfsklassen verschieben.
quelle
Ich kann nur sehen, dass dies schief geht, wenn das boolesche Fragment keinen sinnvollen Namen hat und trotzdem ein Name ausgewählt wird.
Ich weise darauf hin, weil es üblich ist, Regeln wie "Kommentieren Sie Ihren gesamten Code" zu erstellen, "benannte Boolesche Werte für alle if-Kriterien mit mehr als 3 Teilen zu verwenden", um nur Kommentare zu erhalten, die semantisch leer der folgenden Art sind
quelle
Auf diese Weise
Sie entfernen die Logik aus Ihrem Gehirn und fügen sie in den Code ein. Jetzt weiß das Programm , was Sie gemeint haben.
Wann immer Sie etwas benennen , geben Sie es physisch dar. Es existiert.
Sie können es manipulieren und wiederverwenden.
Sie können sogar den gesamten Block als Prädikat definieren:
und mache mehr Sachen (später) in dieser Funktion.
quelle
Wenn der Ausdruck komplex ist, verschiebe ich ihn entweder in eine andere Funktion, die ein
bool
eg zurückgibt ,isAnEveningInThePubAGoodIdea(dayOfWeek, sizeOfWorkLoad, amountOfSpareCash)
oder überarbeite den Code, damit ein solch komplexer Ausdruck nicht erforderlich ist.quelle
Ich denke, es ist besser, Funktionen / Methoden anstelle von temporären Variablen zu erstellen. Auf diese Weise wird die Lesbarkeit erhöht, auch weil die Methoden kürzer werden. Martin Fowlers Buch Refactoring enthält gute Ratschläge zur Verbesserung der Codequalität. Refactorings, die sich auf Ihr spezielles Beispiel beziehen, heißen "Temp durch Abfrage ersetzen" und "Extraktionsmethode".
quelle
Persönlich denke ich, dass dies eine großartige Praxis ist. Die Auswirkungen auf die Ausführung des Codes sind minimal, aber die Klarheit, die er bei ordnungsgemäßer Verwendung bieten kann, ist von unschätzbarem Wert, wenn es darum geht, den Code später zu warten.
quelle
Denken Sie daran, dass Sie auf diese Weise mehr als nötig berechnen. Da Sie Bedingungen aus dem Code herausnehmen, berechnen Sie immer beide (kein Kurzschluss).
Damit:
Nach der Transformation wird:
In den meisten Fällen kein Problem, aber in einigen Fällen kann dies eine schlechtere Leistung oder andere Probleme bedeuten, z. B. wenn Sie im zweiten Ausdruck davon ausgehen, dass der erste fehlgeschlagen ist.
quelle
Wenn die Methode eine Benachrichtigung über den Erfolg erfordert: (Beispiele in c #) Ich verwende gerne die
anfangen. Der Code ist ein Fehler, bis ich ihn ändere in:
dann am Ende:
quelle
Ich denke, es hängt davon ab, welchen Stil Sie / Ihr Team bevorzugen. Refactoring "Variable einführen" könnte nützlich sein, aber manchmal nicht :)
Und ich sollte Kevin in seinem vorherigen Beitrag nicht zustimmen. Sein Beispiel, nehme ich an, kann verwendet werden, wenn die eingeführte Variable geändert werden kann, aber das Einführen nur für einen statischen Booleschen Wert ist nutzlos, da wir in einer Methodendeklaration einen Parameternamen haben. Warum also im Code duplizieren?
zum Beispiel:
quelle
Nach meiner Erfahrung bin ich oft zu alten Skripten zurückgekehrt und habe mich gefragt, was zum Teufel ich damals gedacht habe. Zum Beispiel:
das ist nicht so intuitiv wie:
quelle
Ich erstelle selten separate Variablen. Was ich mache, wenn die Tests kompliziert werden, ist, die IFs zu verschachteln und Kommentare hinzuzufügen. Mögen
Der zugegebene Fehler bei dieser Technik ist, dass der nächste Programmierer, der mitkommt, die Logik ändern kann, sich aber nicht die Mühe macht, die Kommentare zu aktualisieren. Ich denke, das ist ein allgemeines Problem, aber ich habe oft einen Kommentar gesehen, in dem "Kunden-ID validieren" steht, und in der nächsten Zeile wird die Teilenummer oder eine solche untersucht, und ich muss mich fragen, wo der Kunde ist ID kommt herein.
quelle