Les variables de drapeau sont-elles mauvaises? Les types de variables suivants sont-ils profondément immoraux et est-il mauvais de les utiliser?
"Les variables booléennes ou entières que vous attribuez une valeur à certains endroits puis en dessous vous permettent ensuite de faire quelque chose ou non, comme, par exemple, en utilisant
newItem = true
ensuite quelques lignes en dessousif (newItem ) then
"
Je me souviens d’avoir fait deux projets où j’ai totalement négligé d’utiliser des drapeaux pour finir avec une meilleure architecture / code; Cependant, c'est une pratique courante dans d'autres projets pour lesquels je travaille et, lorsque le code croît et que des indicateurs sont ajoutés, le code-spaghetti IMHO se développe également.
Diriez-vous qu'il existe des cas où l'utilisation de drapeaux est une bonne pratique ou même nécessaire ?, ou seriez-vous d'accord pour dire que l'utilisation de drapeaux dans le code est ... un drapeau rouge et doit être évitée / refactorisée; moi, je me débrouille simplement avec des fonctions / méthodes qui vérifient les états en temps réel.
la source
newItem = true
quelques lignes ciif (newItem ) then
Réponses:
Le problème que j'ai constaté lors de la gestion de code utilisant des indicateurs est que le nombre d'états augmente rapidement et qu'il y a presque toujours des états non gérés. Un exemple de ma propre expérience: je travaillais sur un code qui avait ces trois drapeaux
Ces trois pays ont créé huit États (en fait, il y avait également deux autres drapeaux). Toutes les combinaisons de valeurs possibles n'étaient pas couvertes par le code et les utilisateurs voyaient des bogues:
Il s'est avéré qu'il y avait des situations où l'hypothèse dans la déclaration if ci-dessus était fausse.
Les drapeaux ont tendance à s'aggraver avec le temps et cachent l'état réel d'une classe. C'est pourquoi ils devraient être évités.
la source
Voici un exemple où les drapeaux sont utiles.
J'ai un morceau de code qui génère des mots de passe (en utilisant un générateur de nombres pseudo-aléatoires cryptographiquement sécurisé). L'appelant de la méthode choisit si le mot de passe doit contenir des lettres majuscules, des lettres minuscules, des chiffres, des symboles de base, des symboles étendus, des symboles grecs, des caractères cyrilliques et unicode.
Avec les drapeaux, appeler cette méthode est simple:
et il peut même être simplifié de:
Sans drapeaux, quelle serait la signature de la méthode?
appelé comme ça:
Comme indiqué dans les commentaires, une autre approche consisterait à utiliser une collection:
Ceci est beaucoup plus lisible par rapport à
true
etfalse
, mais a toujours deux inconvénients:L'inconvénient majeur est que pour permettre des valeurs combinées,
CharacterSet.LettersAndDigits
vous écrivez quelque chose comme ça dans laGenerate()
méthode:éventuellement réécrit comme ceci:
Comparez cela avec ce que vous avez en utilisant des drapeaux:
Le deuxième inconvénient très mineur est qu'il n'est pas clair comment la méthode se comporterait si elle était appelée ainsi:
la source
newItem = true
quelques lignes ciif (newItem ) then
L'odeur est un énorme bloc fonctionnel, pas les drapeaux. Si vous définissez le drapeau sur la ligne 5, vérifiez uniquement si le drapeau est sur la ligne 354, alors c'est mauvais. Si vous définissez le drapeau sur la ligne 8 et vérifiez le drapeau sur la ligne 10, c'est bien. En outre, un ou deux indicateurs par bloc de code suffisent, 300 indicateurs dans une fonction sont incorrects.
la source
Habituellement, les drapeaux peuvent être complètement remplacés par une variante du modèle de stratégie, avec une implémentation de stratégie pour chaque valeur possible du drapeau. Cela facilite l’ajout de nouveaux comportements.
Dans les situations critiques de performances, le coût de l'indirection peut faire surface et faire de la déconstruction un indicateur clair nécessaire. Cela étant dit, j'ai du mal à me souvenir d'un cas dans lequel je devais le faire.
la source
Non, les drapeaux ne sont ni mauvais ni un mal qui doit être refait à tout prix.
Considérons l' appel Java Pattern.compile (regex String, int flags) . Ceci est un masque de bits traditionnel et cela fonctionne. Coup d' œil sur les constantes en Java et où vous voyez un groupe de 2 n vous savez qu'il ya des drapeaux étant là.
Dans un monde refactorisé idéal, on utilisera plutôt un EnumSet où les constantes sont des valeurs dans un enum et comme le dit la documentation:
Dans un monde parfait, cet appel à Pattern.compile devient
Pattern.compile(String regex, EnumSet<PatternFlagEnum> flags)
.Cela dit, ça reste des drapeaux. Il est beaucoup plus facile de travailler avec ce
Pattern.compile("foo", Pattern.CASE_INSENSTIVE | Pattern.MULTILINE)
que ce ne serait le casPattern.compile("foo", new PatternFlags().caseInsenstive().multiline())
ou avec un autre style d’essai de faire ce que les drapeaux sont vraiment et pour lequel ils sont bons.Les drapeaux sont souvent visibles lorsque vous travaillez avec des objets de niveau système. Lors de l’interfaçage avec quelque chose au niveau du système d’exploitation, il est probable que l’on ait un indicateur quelque part, que ce soit la valeur de retour d’un processus, les autorisations d’un fichier ou les indicateurs d’ouverture d’un socket. Tenter de réorganiser ces événements lors d’une chasse aux sorcières contre une odeur de code perçue aboutira probablement à un code pire que si l’on utilisait accepté et comprenait le drapeau.
Le problème survient lorsque des personnes utilisent à mauvais escient des drapeaux en les jetant ensemble pour créer un ensemble de flancs francs de toutes sortes de drapeaux sans rapport ou en essayant de les utiliser là où ils ne sont pas du tout.
la source
Je suppose que nous parlons de drapeaux dans les signatures de méthodes.
Utiliser un seul drapeau est déjà assez grave.
Cela ne signifiera rien pour vos collègues la première fois qu’ils le verront. Ils devront examiner le code source de la méthode afin d’établir ce qu’elle fait. Vous serez probablement dans la même position quelques mois plus tard, lorsque vous oublierez le sens de votre méthode.
Passer un indicateur à la méthode signifie normalement que votre méthode est responsable de plusieurs choses. Dans la méthode, vous effectuez probablement une vérification simple sur les lignes suivantes:
C'est une mauvaise séparation des préoccupations et vous pouvez normalement trouver un moyen de la contourner.
J'ai normalement deux méthodes distinctes:
Cela aura plus de sens avec les noms de méthodes applicables au problème que vous résolvez.
Passer plusieurs drapeaux est deux fois plus mauvais. Si vous avez réellement besoin de passer plusieurs indicateurs, envisagez de les encapsuler dans une classe. Même dans ce cas, vous serez toujours confronté au même problème, car votre méthode est susceptible de faire plusieurs choses.
la source
Les drapeaux et la plupart des variables de température dégagent une forte odeur. Très probablement, ils pourraient être refactorisés et remplacés par des méthodes de requête.
Modifié:
Les drapeaux et les variables temp lors de l’expression de l’état doivent être refactorisés en méthodes de requête. Les valeurs d'état (booléens, entiers et autres primatives) devraient presque toujours être masquées dans les détails de la mise en œuvre.
Les drapeaux utilisés pour le contrôle, l'acheminement et le déroulement général du programme peuvent également indiquer la possibilité de reformuler des sections des structures de contrôle en stratégies ou usines distinctes, ou de faire ce qui est approprié en fonction de la situation, qui continuent à utiliser les méthodes de requête.
la source
Lorsque nous parlons de drapeaux, nous devrions savoir qu'ils vont être modifiés au cours de l'exécution du programme et qu'ils vont affecter le comportement du programme en fonction de leurs états. Tant que nous maîtriserons parfaitement ces deux choses, elles fonctionneront très bien.
Les drapeaux peuvent très bien si
S'il y a beaucoup de drapeaux, un bon travail de conception doit précéder car ils commencent à jouer un rôle clé dans le comportement du programme. Vous pouvez choisir des diagrammes d'état pour la modélisation. De tels diagrammes servent également de documentation et de guidage visuel lors de l'utilisation.
Tant que ces choses seront en place, je pense que cela ne mènera pas au désordre.
la source
A partir de la question, j'ai supposé que le QA était une variable de drapeau (globale), et non des bits d'un paramètre de fonction.
Il y a des situations où vous n'avez pas beaucoup d'autres possibilités. Par exemple, sans système d'exploitation, vous devez évaluer les interruptions. Si une interruption survient très fréquemment et que vous n'avez pas le temps de faire une longue évaluation dans l'ISR, il est non seulement permis, mais parfois même la meilleure pratique consiste à définir uniquement des drapeaux globaux dans l'ISR (vous devriez passer le moins de temps possible ISR) et d’évaluer ces indicateurs dans votre boucle principale.
la source
Je ne pense pas que rien soit un mal absolu dans la programmation, jamais.
Il y a une autre situation où des drapeaux pourraient être en ordre, qui n'étaient pas encore mentionnés ici ...
Considérez l'utilisation de fermetures dans cet extrait de code Javascript:
La fonction interne, étant passée à "Array.forEach", ne peut pas simplement "renvoyer true".
Par conséquent, vous devez conserver l'état extérieur avec un drapeau.
la source