Opmerkingen
Antwoord
Het probleem dat ik heb gezien bij het onderhouden van code die gebruikmaakt van vlaggen, is dat het aantal toestanden snel toeneemt, en er zijn bijna altijd onverwerkte toestanden. Een voorbeeld uit mijn eigen ervaring: ik werkte aan een code met deze drie vlaggen
bool capturing, processing, sending;
Deze drie creëerden acht staten (eigenlijk waren er twee andere vlaggen ook). Niet alle mogelijke waardecombinaties werden gedekt door de code, en gebruikers zagen bugs:
if(capturing && sending){ // we must be processing as well ... }
Het bleek dat er situaties waren waarin de aanname in de if-instructie above was false.
Vlaggen worden in de loop van de tijd steeds groter en verbergen de feitelijke status van een klasse. Daarom moeten ze worden vermeden.
Reacties
- +1, " moeten worden vermeden ". Ik zou iets willen toevoegen over ' maar vlaggen zijn nodig in sommige situaties ' (sommigen zeggen misschien ' een noodzakelijk kwaad ')
- @TrevorBoydSmith In mijn ervaring zijn ze dat niet, je hebt gewoon iets meer nodig dan de gemiddelde hersenkracht die je zou gebruiken voor een vlag
- In je voorbeeld had het een enkele opsomming moeten zijn die staat voorstelt, niet 3 booleans.
- Je zou op een soortgelijk probleem kunnen stuiten als wat ik ' m naar u toe. Behalve dat ze alle mogelijke staten bestrijken, kunnen twee applicaties dezelfde vlag delen (bijv. Het uploaden van klantgegevens). In dit geval zal slechts één uploader de vlag gebruiken, deze uitschakelen en veel succes met het vinden van het probleem in de toekomst.
Antwoord
Hier is een voorbeeld wanneer vlaggen nuttig zijn.
Ik heb een stukje code dat wachtwoorden genereert (met behulp van een cryptografisch veilige pseudo-willekeurige nummergenerator). De aanroeper van de methode kiest of niet het wachtwoord mag hoofdletters, kleine letters, cijfers, basissymbolen, uitgebreide symbolen, Griekse symbolen, Cyrillische symbolen en unicode bevatten.
Met vlaggen is het aanroepen van deze methode eenvoudig:
var password = this.PasswordGenerator.Generate( CharacterSet.Digits | CharacterSet.LowercaseLetters | CharacterSet.UppercaseLetters);
en het kan zelfs worden vereenvoudigd tot:
var password = this.PasswordGenerator.Generate(CharacterSet.LettersAndDigits);
Wat zou de handtekening van de methode zijn zonder vlaggen?
public byte[] Generate( bool uppercaseLetters, bool lowercaseLetters, bool digits, bool basicSymbols, bool extendedSymbols, bool greekLetters, bool cyrillicLetters, bool unicode);
wordt als volgt genoemd:
// Very readable, isn"t it? // Tell me just by looking at this code what symbols do I want to be included? var password = this.PasswordGenerator.Generate( true, true, true, false, false, false, false, false);
Zoals opgemerkt in de commentaren, zou een andere benadering zijn om een collectie te gebruiken:
var password = this.PasswordGenerator.Generate( new [] { CharacterSet.Digits, CharacterSet.LowercaseLetters, CharacterSet.UppercaseLetters, });
Dit is veel beter leesbaar in vergelijking met de set van true
en false
, maar heeft nog steeds twee nadelen:
Het grootste nadeel is dat om gecombineerde waarden mogelijk te maken, zoals CharacterSet.LettersAndDigits
je zou zoiets schrijven in de Generate()
methode:
if (set.Contains(CharacterSet.LowercaseLetters) || set.Contains(CharacterSet.Letters) || set.Contains(CharacterSet.LettersAndDigits) || set.Contains(CharacterSet.Default) || set.Contains(CharacterSet.All)) { // The password should contain lowercase letters. }
mogelijk als volgt herschreven:
var lowercaseGroups = new [] { CharacterSet.LowercaseLetters, CharacterSet.Letters, CharacterSet.LettersAndDigits, CharacterSet.Default, CharacterSet.All, }; if (lowercaseGroups.Any(s => set.Contains(s))) { // The password should contain lowercase letters. }
Vergelijk dit met wat je hebt door vlaggen te gebruiken:
if (set & CharacterSet.LowercaseLetters == CharacterSet.LowercaseLetters) { // The password should contain lowercase letters. }
De s ten tweede, een zeer klein nadeel is dat het “niet duidelijk is hoe de methode zich zou gedragen als deze zo wordt aangeroepen:
var password = this.PasswordGenerator.Generate( new [] { CharacterSet.Digits, CharacterSet.LettersAndDigits, // So digits are requested two times. });
Reacties
- Ik geloof dat OP verwijst naar booleaanse of integer variabelen die je op bepaalde plaatsen een waarde toekent en vervolgens beneden je controleert dan in een andere om iets te doen of niet, zoals bijvoorbeeld
newItem = true
gebruiken en vervolgens enkele regels hieronderif (newItem ) then
- @MainMa Blijkbaar daar ' sa 3e: de versie met 8 booleaanse argumenten is waar ik aan dacht toen ik " vlaggen " …
- Sorry, maar IMHO dit is het perfecte geval voor methodeketting ( en.wikipedia.org/wiki/Method_chaining), Bovendien kunt u een parameterarray gebruiken (moet een associatieve array of map zijn), waarbij elke invoer in die parameterarray die u weglaat het standaardwaardegedrag gebruikt voor die parameter. Uiteindelijk kan de aanroep via methodeketting of parameterarrays net zo beknopt en expressief zijn als bitvlaggen, ook heeft niet elke taal bitoperatoren (ik hou eigenlijk van binaire vlaggen, maar zou in plaats daarvan de methoden gebruiken die ik zojuist noemde). / li>
- Het ' is niet erg OOP, toch? Ik ' d maak een interface ala: String myNewPassword = makePassword (randomComposeSupplier (nieuwe RandomLowerCaseSupplier (), nieuwe RandomUpperCaseSupplier (), nieuwe RandomNumberSupplier)); met String makePassword (Leverancier < Karakter > charSupplier); en leverancier < teken > randomComposeSupplier (leverancier < teken > … leveranciers); Nu kunt u uw leveranciers hergebruiken voor andere taken, ze op elke gewenste manier samenstellen en uw GenereerPassword-methode vereenvoudigen zodat deze de minimale status gebruikt.
- @Dibbeke Praten over een koninkrijk van zelfstandige naamwoorden …
Answer
Een enorm functieblok is de geur , niet de vlaggen. Als je de vlag op regel 5 zet, controleer dan alleen de vlag op regel 354, dan is dat slecht. Als je de vlag op regel 8 zet en de vlag op regel 10 controleert, is dat prima. Ook is een of twee vlaggen per codeblok prima, 300 vlaggen in een functie is slecht.
Antwoord
Meestal vlaggen kan volledig worden vervangen door een smaak van het strategiepatroon, met één strategie-implementatie voor elke mogelijke waarde van de vlag. Dit maakt het toevoegen van nieuw gedrag een stuk eenvoudiger.
In prestatiekritische situaties zouden de kosten van de indirecte kunnen naar boven komen en deconstructie in duidelijke vlaggen noodzakelijk maken. Dat gezegd hebbende, “heb ik moeite om me een enkel geval te herinneren waarin ik dat eigenlijk moest doen.
Antwoord
Nee, vlaggen zijn niet slecht of een kwaad dat koste wat het kost moet worden geherstructureerd.
Overweeg Java “s Pattern.compile (String regex, int flags) bellen. Dit is een traditioneel bitmasker en het werkt. Bekijk de constanten in java en waar je ook een stel van 2 n ziet, je weet dat er vlaggen aanwezig zijn.
In een ideale geherstructureerde wereld zou men in plaats daarvan een EnumSet gebruiken waar de constanten in plaats daarvan waarden in een enum zijn en zoals de documentatie luidt:
De ruimte- en tijdprestaties van deze klasse zouden goed genoeg moeten zijn om het gebruik ervan mogelijk te maken als een kwalitatief hoogstaand, typeveilig alternatief voor traditionele int-gebaseerde “bitvlaggen”.
In een perfecte wereld wordt die Pattern.compile-aanroep Pattern.compile(String regex, EnumSet<PatternFlagEnum> flags)
.
Alle dat gezegd hebbende, het zijn nog steeds vlaggen.Het is veel gemakkelijker om met Pattern.compile("foo", Pattern.CASE_INSENSTIVE | Pattern.MULTILINE)
te werken dan met Pattern.compile("foo", new PatternFlags().caseInsenstive().multiline())
of een andere manier om te proberen te doen wat vlaggen werkelijk zijn en goed voor.
Vlaggen worden vaak gezien bij het werken met dingen op systeemniveau. Wanneer je met iets op het niveau van het besturingssysteem communiceert, heb je waarschijnlijk ergens een vlag – of het nu de retourwaarde van een proces is, of de machtigingen van een bestand, of de vlaggen voor het openen van een socket. Als je probeert deze gevallen weg te werken in een heksenjacht tegen een waargenomen codegeur, zal de code waarschijnlijk slechter worden dan wanneer iemand de vlag accepteerde en begreep.
Het probleem doet zich voor wanneer mensen vlaggen misbruiken door ze samen te gooien en een frankenflag-set maken van allerlei niet-gerelateerde vlaggen of proberen ze te gebruiken waar ze helemaal geen vlaggen zijn.
Answer
Ik neem aan dat we het hebben over vlaggen binnen methodhandtekeningen.
Het gebruik van een enkele vlag is al erg genoeg.
Het zal uw collegas niets zeggen de eerste keer dat ze het zien. Ze zullen naar de broncode van de methode moeten kijken om erachter te komen wat deze doet. Je zult waarschijnlijk een paar maanden later in dezelfde positie zijn als je vergeet waar je methode over ging.
Het doorgeven van een vlag aan de methode betekent normaal gesproken dat uw methode verantwoordelijk is voor meerdere dingen. Binnen de methode voert u waarschijnlijk een eenvoudige controle uit op de volgende regels:
if (flag) DoFlagSet(); else DoFlagNotSet();
Dat “is een slechte scheiding van zorgen en je kunt er normaal gesproken een manier omheen vinden.
Ik heb normaal gesproken twee verschillende methoden:
public void DoFlagSet() { } public void DoFlagNotSet() { }
Dit wordt logischer met methodenamen die van toepassing zijn op het probleem dat u aan het oplossen bent.
Meerdere vlaggen passeren is twee keer zo erg. Als je echt meerdere vlaggen moet passeren, overweeg dan om ze in een klas in te kapselen. Zelfs dan zul je nog steeds met hetzelfde probleem worden geconfronteerd, aangezien je methode waarschijnlijk meerdere dingen doet.
Antwoord
Vlaggen en de meeste tijdelijke variabelen zijn een sterke geur. Hoogstwaarschijnlijk kunnen ze worden geherstructureerd en vervangen door query-methoden.
Herzien:
Vlaggen en tijdelijke variabelen bij het uitdrukken van state, moeten worden geherstructureerd naar query-methoden. De toestandswaarden (booleans, ints en andere primatieven) zouden bijna -altijd- verborgen moeten zijn als onderdeel van de implementatiedetails.
Vlaggen die worden gebruikt voor controle, routing en algemene programmastroom kunnen ook de mogelijkheid om secties van de controlestructuren om te zetten in afzonderlijke strategieën of fabrieken, of wat voor de situatie ook geschikt is, die gebruik blijven maken van de zoekmethoden.
Antwoord
Als we het hebben over vlaggen, moeten we weten dat ze tijdens de uitvoering van het programma zullen worden gewijzigd en dat ze het gedrag van het programma zullen beïnvloeden op basis van hun status. Zolang we de controle hebben over deze twee dingen, zullen ze geweldig werken.
Vlaggen kunnen geweldig werken als
- Je hebt ze gedefinieerd in een geschikt bereik. Met toepasselijk bedoel ik dat de scope geen code mag bevatten die ze niet hoeft / mag wijzigen. Of de code is tenminste veilig (hij mag bijvoorbeeld niet rechtstreeks van buitenaf worden aangeroepen)
- Als het nodig is om vlaggen van buitenaf te behandelen en als er veel vlaggen zijn, kunnen we de vlaghandler coderen als enige manier om vlaggen veilig te wijzigen. Deze vlagbehandelaar kan zelf vlaggen en methoden om ze te wijzigen inkapselen. Het kan dan singleton gemaakt worden en kan dan gedeeld worden met klassen die toegang tot vlaggen nodig hebben.
- En tot slot voor onderhoudbaarheid, als er te veel vlaggen zijn:
- Het is niet nodig om te zeggen dat ze dat zouden moeten doen volg verstandige naamgeving
- Moet worden gedocumenteerd met wat geldige waarden zijn (mogelijk met opsommingen)
- Moet worden gedocumenteerd met WELKE CODE ZAL elk van hen AANPASSEN, en ook met WELKE VOORWAARDE zal resulteren in toewijzing van een bepaalde waarde aan de vlag.
- WELKE CODE ZAL ze VERBRUIKEN en WELK GEDRAG zal resulteren voor een bepaalde waarde
Als er een heleboel vlaggen zijn, zou goed ontwerpwerk moeten voorafgaan, aangezien vlaggen dan een sleutelrol gaan spelen in het gedrag van het programma. Voor het modelleren kunt u terecht bij toestandsdiagrammen. Zulke diagrammen werken ook als documentatie en visuele begeleiding bij het omgaan met ze.
Zolang deze dingen aanwezig zijn, denk ik dat het niet tot de puinhoop zal leiden.
Antwoord
Ik ging ervan uit dat de QA vlag (globale) variabelen betekende, en niet bits van een functieparameter.
Er zijn situaties waar je niet veel andere mogelijkheden hebt. Zonder besturingssysteem moet je bijvoorbeeld interrupts evalueren.Als een onderbreking heel vaak komt en u geen tijd hebt om een lange evaluatie in de ISR uit te voeren, is het niet alleen toegestaan, maar soms zelfs best practice om slechts enkele globale vlaggen in de ISR in te stellen (u moet zo min mogelijk tijd besteden in de ISR), en om die vlaggen in je hoofdlus te evalueren.
Antwoord
Ik denk niet alles is een absoluut kwaad in programmeren, ooit.
Er is een andere situatie waarin vlaggen in orde kunnen zijn, die werden hier nog niet genoemd …
Overweeg het gebruik van sluitingen in dit Javascript-fragment:
exports.isPostDraft = function ( post, draftTag ) { var isDraft = false; if (post.tags) post.tags.forEach(function(tag){ if (tag === draftTag) isDraft = true; }); return isDraft; }
De innerlijke functie wordt doorgegeven naar de “Array.forEach”, kan niet simpelweg “true retourneren”.
Daarom moet u de staat buiten houden met een vlag.
newItem = true
gebruiken en dan enkele regels eronderif (newItem ) then