Sind Flaggenvariablen böse? Sind die folgenden Variablen zutiefst unmoralisch und ist es böse, sie zu verwenden?
"Boolesche oder ganzzahlige Variablen, denen Sie an bestimmten Stellen einen Wert zuweisen, dann unten überprüfen Sie, ob Sie etwas tun oder nicht, beispielsweise indem Sie
newItem = true
einige Zeilen darunter verwenden.if (newItem ) then
"
Ich erinnere mich an ein paar Projekte, bei denen ich die Verwendung von Flags völlig vernachlässigt und bessere Architektur / Code erhalten habe. In anderen Projekten, in denen ich arbeite, ist dies jedoch eine gängige Praxis, und wenn Code wächst und Flags hinzugefügt werden, wächst IMHO-Code-Spaghetti ebenfalls.
Würden Sie sagen, dass es Fälle gibt, in denen die Verwendung von Flags eine gute oder sogar notwendige Praxis ist? Oder würden Sie zustimmen, dass die Verwendung von Flags im Code ... rote Fahnen sind und vermieden / überarbeitet werden sollten; Ich komme nur damit zurecht, Funktionen / Methoden auszuführen, die stattdessen in Echtzeit nach Zuständen suchen.
quelle
newItem = true
dann ein paar Zeilen weiter untenif (newItem ) then
Antworten:
Das Problem, das ich beim Verwalten von Code gesehen habe, der Flags verwendet, ist, dass die Anzahl der Status schnell zunimmt und es fast immer unbehandelte Status gibt. Ein Beispiel aus eigener Erfahrung: Ich habe an einem Code mit diesen drei Flags gearbeitet
Diese drei schufen acht Staaten (tatsächlich gab es auch zwei andere Flaggen). Der Code deckte nicht alle möglichen Wertekombinationen ab, und die Benutzer sahen Fehler:
Es stellte sich heraus, dass es Situationen gab, in denen die Annahme in der obigen if-Anweisung falsch war.
Flags setzen sich im Laufe der Zeit zusammen und verbergen den aktuellen Status einer Klasse. Deshalb sollten sie vermieden werden.
quelle
Hier ist ein Beispiel, wenn Flags nützlich sind.
Ich habe einen Code, der Passwörter generiert (unter Verwendung eines kryptografisch sicheren Pseudozufallszahlengenerators). Der Aufrufer der Methode entscheidet, ob das Passwort Großbuchstaben, Kleinbuchstaben, Ziffern, Grundsymbole, erweiterte Symbole, griechische Symbole, kyrillische Symbole und Unicode enthalten soll oder nicht.
Mit Flags ist das Aufrufen dieser Methode einfach:
und es kann sogar vereinfacht werden:
Was wäre die Methodensignatur ohne Flags?
so genannt:
Wie in den Kommentaren erwähnt, besteht ein anderer Ansatz darin, eine Sammlung zu verwenden:
Dies ist im Vergleich zum Satz von
true
und viel besser lesbarfalse
, weist jedoch immer noch zwei Nachteile auf:Der Hauptnachteil ist, dass Sie, um kombinierte Werte zuzulassen, so
CharacterSet.LettersAndDigits
etwas wie das inGenerate()
Methode schreiben würden :möglicherweise so umgeschrieben:
Vergleichen Sie dies mit dem, was Sie haben, indem Sie Flags verwenden:
Der zweite, sehr kleine Nachteil ist, dass nicht klar ist, wie sich die Methode verhalten würde, wenn sie wie folgt aufgerufen würde:
quelle
newItem = true
dann ein paar Zeilen weiter untenif (newItem ) then
Ein großer Funktionsblock ist der Geruch, nicht die Fahnen. Wenn Sie das Flag in Zeile 5 setzen, dann überprüfen Sie nur das Flag in Zeile 354, dann ist das schlecht. Wenn Sie das Flag in Zeile 8 setzen und in Zeile 10 nach dem Flag suchen, ist das in Ordnung. Außerdem sind ein oder zwei Flags pro Codeblock in Ordnung, 300 Flags in einer Funktion sind schlecht.
quelle
Normalerweise können Flags vollständig durch eine Variante des Strategiemusters ersetzt werden, wobei für jeden möglichen Wert des Flags eine Strategieimplementierung vorhanden ist. Dies erleichtert das Hinzufügen eines neuen Verhaltens erheblich.
In leistungskritischen Situationen können die Kosten der Indirektion auftauchen und eine Dekonstruktion in eindeutige Flags erforderlich machen. Trotzdem fällt es mir schwer, mich an einen einzigen Fall zu erinnern, in dem ich das tatsächlich tun musste.
quelle
Nein, Flaggen sind nicht schlecht oder ein Übel, das um jeden Preis umgestaltet werden muss.
Betrachten Sie Javas Aufruf Pattern.compile (String regex, int flags) . Dies ist eine traditionelle Bitmaske und es funktioniert. Werfen Sie einen Blick auf die Konstanten in Java und wo immer Sie 2 n sehen , wissen Sie, dass dort Flaggen sind.
In einer ideal umgestalteten Welt würde man stattdessen ein EnumSet verwenden, bei dem die Konstanten stattdessen Werte in einer Aufzählung sind und wie in der Dokumentation heißt:
In einer perfekten Welt wird dieser Aufruf von Pattern.compile
Pattern.compile(String regex, EnumSet<PatternFlagEnum> flags)
.Alles, was gesagt wurde, es ist immer noch Flaggen. Es ist viel einfacher, damit zu arbeiten,
Pattern.compile("foo", Pattern.CASE_INSENSTIVE | Pattern.MULTILINE)
als wenn manPattern.compile("foo", new PatternFlags().caseInsenstive().multiline())
versucht, das zu tun, was Flaggen wirklich sind und wozu sie gut sind.Flags werden häufig beim Arbeiten mit Dingen auf Systemebene gesehen. Wenn man mit etwas auf Betriebssystemebene arbeitet, hat man wahrscheinlich irgendwo ein Flag - sei es der Rückgabewert eines Prozesses oder die Berechtigungen einer Datei oder die Flags zum Öffnen eines Sockets. Der Versuch, diese Instanzen bei einer Hexenjagd gegen einen wahrgenommenen Codegeruch umzugestalten, führt wahrscheinlich zu einem schlechteren Code, als wenn man die Flagge akzeptiert und verstanden hätte.
Das Problem tritt auf, wenn Leute Flaggen missbrauchen, indem sie sie zusammenwerfen und ein frankenflag-Set aller Arten von nicht verwandten Flaggen erstellen oder versuchen, sie dort zu verwenden, wo sie überhaupt keine Flaggen sind.
quelle
Ich gehe davon aus, dass es sich um Flags in Methodensignaturen handelt.
Die Verwendung einer einzelnen Flagge ist schon schlimm genug.
Es wird Ihren Kollegen nichts bedeuten, wenn sie es sehen. Sie müssen sich den Quellcode der Methode ansehen, um festzustellen, was sie tut. Sie werden wahrscheinlich einige Monate später in der gleichen Position sein, wenn Sie vergessen, worum es bei Ihrer Methode ging.
Das Übergeben eines Flags an die Methode bedeutet normalerweise, dass Ihre Methode für mehrere Dinge verantwortlich ist. Innerhalb der Methode führen Sie wahrscheinlich eine einfache Überprüfung der folgenden Zeilen durch:
Das ist eine schlechte Trennung der Bedenken und man kann normalerweise einen Weg finden, dies zu umgehen.
Normalerweise habe ich zwei verschiedene Methoden:
Dies ist bei Methodennamen sinnvoller, die für das zu lösende Problem gelten.
Das Übergeben mehrerer Flags ist doppelt so schlimm. Wenn Sie wirklich mehrere Flags übergeben müssen, sollten Sie in Betracht ziehen, diese in einer Klasse zu kapseln. Selbst dann werden Sie immer noch vor dem gleichen Problem stehen, da Ihre Methode wahrscheinlich mehrere Dinge tut.
quelle
Flags und die meisten temporären Variablen sind ein starker Geruch. Höchstwahrscheinlich könnten sie überarbeitet und durch Abfragemethoden ersetzt werden.
Überarbeitet:
Flags und temporäre Variablen beim Ausdrücken des Status sollten in Abfragemethoden umgestaltet werden. Die Zustandswerte (Boolesche Werte, Ints und andere Primitive) sollten im Rahmen der Implementierungsdetails fast immer ausgeblendet werden.
Flags, die für die Steuerung, das Routing und den allgemeinen Programmfluss verwendet werden, weisen möglicherweise auch auf die Möglichkeit hin, Abschnitte der Steuerungsstrukturen in separate Strategien oder Fabriken umzugliedern, oder was auch immer situativ angemessen sein mag, die weiterhin die Abfragemethoden verwenden.
quelle
Wenn wir über Flags sprechen, sollten wir wissen, dass sie im Laufe der Programmausführung geändert werden und dass sie das Verhalten von Programmen auf der Grundlage ihrer Zustände beeinflussen. Solange wir die Kontrolle über diese beiden Dinge haben, werden sie großartig funktionieren.
Fahnen können gut funktionieren, wenn
Wenn es sehr viele Flags gibt, sollte gute Designarbeit vorausgehen, da Flags eine Schlüsselrolle im Programmverhalten spielen. Sie können sich für Zustandsdiagramme zur Modellierung entscheiden. Solche Diagramme dienen auch als Dokumentation und visuelle Anleitung, wenn Sie mit ihnen arbeiten.
Solange diese Dinge an Ort und Stelle sind, denke ich, wird es nicht zu dem Durcheinander führen.
quelle
Ich ging von der Frage aus, dass die QA Flag-Variablen (globale Variablen) und keine Bits eines Funktionsparameters bedeutet.
Es gibt Situationen, in denen Sie nicht viele andere Möglichkeiten haben. Ohne Betriebssystem müssen Sie beispielsweise Interrupts auswerten. Wenn ein Interrupt sehr häufig auftritt und Sie keine Zeit für eine ausführliche Auswertung im ISR haben, ist es nicht nur zulässig, sondern manchmal sogar die beste Vorgehensweise, nur einige globale Flags im ISR zu setzen (Sie sollten so wenig Zeit wie möglich verwenden in der ISR), und diese Flags in Ihrer Hauptschleife auszuwerten.
quelle
Ich denke nicht, dass irgendetwas jemals ein absolutes Übel in der Programmierung ist.
Es gibt eine andere Situation, in der Fahnen in Ordnung sein könnten, die hier noch nicht erwähnt wurden ...
Betrachten Sie die Verwendung von Verschlüssen in diesem Javascript-Snippet:
Die innere Funktion, die an "Array.forEach" übergeben wird, kann nicht einfach "true" zurückgeben.
Daher müssen Sie den Staat mit einer Flagge draußen lassen.
quelle