Stengt . Dette spørsmålet må være mer fokusert . Det aksepteres for øyeblikket ikke svar.

Kommentarer

  • Det ser ut til at MainMa og meg har en annen definisjon av " flagg. " Jeg tenkte på prosessoren #ifdefs. Hvilken spurte du om?
  • Dette er et veldig bra spørsmål. Jeg ' har lurt på dette selv mye, og har faktisk funnet meg selv å si " oh well lets just use a flag " litt for mye.
  • Boolere er flagg. (Det samme er heltall, det er også …)
  • @KarlBielefeldt Jeg tror OP viser til boolske eller heltallvariabler som du tildeler en verdi på bestemte steder, så sjekker du ned for å gjøre noe eller under ikke, som for eksempel å bruke newItem = true så noen linjer under if (newItem ) then
  • Vurder også introdusere forklaring av variabel refactoring i denne sammenhengen. Så lenge metoden forblir kort og har et lavt antall stier gjennom den, anser jeg dette som en gyldig bruk.

Svar

Problemet jeg har sett når jeg vedlikeholder kode som bruker flagg, er at antall stater vokser raskt, og det er nesten alltid ubehandlede stater. Ett eksempel fra min egen erfaring: Jeg jobbet med en kode som hadde disse tre flaggene

bool capturing, processing, sending; 

Disse tre opprettet åtte stater (faktisk var det to andre flagg også). Ikke alle mulige verdikombinasjoner ble dekket av koden, og brukerne så feil:

if(capturing && sending){ // we must be processing as well ... } 

Det viste seg at det var situasjoner der antagelsen i if-setningen ovenfor var falsk.

Flagg har en tendens til å bli sammensatt over tid, og de skjuler den faktiske tilstanden til en klasse. Derfor bør de unngås.

Kommentarer

  • +1, " bør unngås ". Jeg vil legge til noe om ' men flagg er nødvendig i noen situasjoner ' (noen vil kanskje si ' et nødvendig onde ')
  • @TrevorBoydSmith Etter min erfaring er de ikke, du trenger bare litt mer enn den gjennomsnittlige hjernekraften du ville brukt til et flagg
  • I eksamenen din burde det ha vært et eneste enum som representerer stat, ikke 3 booleans.
  • Du kan komme til et lignende problem som jeg ' står overfor akkurat nå. I tillegg til å dekke alle mulige tilstander, kan to applikasjoner dele det samme flagget (for eksempel å laste opp kundedata). I dette tilfellet vil bare én opplasteren bruke flagget, sette det av og lykke til med å finne problemet i fremtiden.

Svar

Her er et eksempel når flagg er nyttige.

Jeg har et stykke kode som genererer passord (ved hjelp av en kryptografisk sikker pseudorandom nummergenerator). Innringeren av metoden velger om eller ikke passordet skal inneholde store bokstaver, små bokstaver, sifre, grunnleggende symboler, utvidede symboler, greske symboler, kyrilliske og unicode.

Med flagg er det enkelt å kalle denne metoden:

var password = this.PasswordGenerator.Generate( CharacterSet.Digits | CharacterSet.LowercaseLetters | CharacterSet.UppercaseLetters);

og det kan til og med forenkles til:

 var password = this.PasswordGenerator.Generate(CharacterSet.LettersAndDigits);  

Uten flagg, hva ville metodesignaturen være?

 public byte[] Generate( bool uppercaseLetters, bool lowercaseLetters, bool digits, bool basicSymbols, bool extendedSymbols, bool greekLetters, bool cyrillicLetters, bool unicode);  

kalt slik:

 // 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);  

Som nevnt i kommentarene, vil en annen tilnærming være å bruke en samling:

 var password = this.PasswordGenerator.Generate( new [] { CharacterSet.Digits, CharacterSet.LowercaseLetters, CharacterSet.UppercaseLetters, });  

Dette er mye mer leselig sammenlignet med settet med true og false, men har fremdeles to ulemper:

Den største ulempen er at for å tillate kombinerte verdier, som CharacterSet.LettersAndDigits du skriver noe sånt i Generate() metode:

 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. }  

muligens omskrevet slik:

 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. }  

Sammenlign dette med det du har ved å bruke flagg:

 if (set & CharacterSet.LowercaseLetters == CharacterSet.LowercaseLetters) { // The password should contain lowercase letters. }  

The s Økologisk, veldig liten ulempe er at det ikke er klart hvordan metoden vil oppføre seg hvis den kalles slik:

 var password = this.PasswordGenerator.Generate( new [] { CharacterSet.Digits, CharacterSet.LettersAndDigits, // So digits are requested two times. });  

Kommentarer

  • Jeg tror OP viser til boolske eller heltallvariabler som du tildeler en verdi på bestemte steder, så sjekker du ned under å gjøre noe eller ikke, som for eksempel å bruke newItem = true så noen linjer under if (newItem ) then
  • @MainMa Tilsynelatende der ' sa 3.: Versjonen med 8 boolske argumenter er det jeg tenkte på når jeg leste " flagg " …
  • Beklager, men IMHO dette er det perfekte tilfellet for metodekjetting ( en.wikipedia.org/wiki/Method_chaining), I tillegg kan du bruke en parametermat (må være en assosiativ matrise eller et kart), der en hvilken som helst oppføring i parametermatrisen du utelater, bruker standardverdiavvik for den parameteren. Til slutt kan samtalen via metodekjetting eller parameterarrayer være like kortfattet og uttrykksfull som bitflagg. Ikke alle språk har bitoperatorer (jeg liker faktisk binære flagg, men vil bruke metodene jeg nettopp nevnte i stedet). / li>
  • Det er ', ikke sant? Jeg ' d lager et grensesnitt ala: String myNewPassword = makePassword (randomComposeSupplier (new RandomLowerCaseSupplier (), new RandomUpperCaseSupplier (), new RandomNumberSupplier)); med streng makePassword (leverandør < Tegn > charSupplier); og leverandør < Tegn > randomComposeSupplier (leverandør < Tegn > … leverandører); Nå kan du gjenbruke leverandørene dine til andre oppgaver, komponere dem på den måten du vil, og forenkle genererePassword-metoden din slik at den bruker minimal tilstand.
  • @Dibbeke Snakk om en substantivriket

Svar

En enorm funksjonsblokk er lukten , ikke flaggene. Hvis du setter flagget på linje 5, så bare sjekk etter flagget på linje 354, så er det dårlig. Hvis du setter flagget på linje 8 og ser etter flagget på linje 10, er det greit. Et eller to flagg per kodeblokk er også bra, 300 flagg i en funksjon er dårlig.

Svar

Vanligvis flagg kan erstattes fullstendig av en eller annen smak av strategimønsteret, med en strategiimplementering for alle mulige verdier av flagget. Dette gjør det lettere å legge til ny oppførsel.

I ytelseskritiske situasjoner kan kostnadene ved indireksjonen kanskje overflate og gjøre dekonstruksjon til klare flagg nødvendig. Når det er sagt, har jeg problemer med å huske et enkelt tilfelle der jeg faktisk måtte gjøre det.

Svar

Nei, flagg er ikke dårlig eller et ondskap som for enhver pris må omformuleres.

Vurder Java «s Pattern.compile (String regex, int flags) samtale. Dette er en tradisjonell bitmaske, og den fungerer. Se på konstanter i java, og uansett hvor du ser en haug med 2 n , vet du at det er flagg der.

I en ideell refaktorisert verden vil man i stedet bruke en EnumSet der konstantene i stedet er verdier i enum og som dokumentasjonen lyder:

Ytelsen til plass og tid i denne klassen bør være god nok til å tillate bruk som et høykvalitets, typesafe alternativ til tradisjonelle int-baserte «bitflagg.» / p>

I en perfekt verden blir det Pattern.compile-anropet Pattern.compile(String regex, EnumSet<PatternFlagEnum> flags).

Alt når det er sagt, det er fortsatt flagg.Det er mye lettere å jobbe med Pattern.compile("foo", Pattern.CASE_INSENSTIVE | Pattern.MULTILINE) enn det ville være å ha Pattern.compile("foo", new PatternFlags().caseInsenstive().multiline()) eller en annen stil for å prøve å gjøre hva flagg egentlig er og bra for.

Flagg blir ofte sett når du arbeider med ting på systemnivå. Når du grensesnitt med noe på operativsystemnivå, vil en sannsynligvis ha et flagg et sted – det være seg returverdien til en prosess, eller tillatelsene til en fil eller flaggene for å åpne en stikkontakt. Å prøve å omlegge disse tilfellene i en eller annen heksejakt mot en oppfattet kodelukt, vil sannsynligvis ende opp med dårligere kode enn hvis man brukte akseptert og forstått flagget. lage et frankenflag-sett med alle slags ikke-relaterte flagg eller prøve å bruke dem der de ikke er flagg i det hele tatt.

Svar

Jeg antar at vi snakker om flagg i metodesignaturer.

Å bruke et enkelt flagg er dårlig nok.

Det betyr ingenting for kollegene dine den gangen de ser det. De må se på kildekoden til metoden for å finne ut hva den gjør. Du vil sannsynligvis være i samme posisjon noen måneder senere, når du glemmer hva metoden handlet om.

Å sende et flagg til metoden betyr normalt at metoden din er ansvarlig for flere ting. Inne i metoden gjør du sannsynligvis en enkel sjekk på linjene til:

if (flag) DoFlagSet(); else DoFlagNotSet(); 

Det er en dårlig separasjon av bekymringer, og du kan normalt finne en vei rundt det.

Jeg har normalt to separate metoder:

public void DoFlagSet() { } public void DoFlagNotSet() { } 

Dette vil være mer fornuftig med metodenavn som gjelder for problemet du løser.

Å sende flere flagg er dobbelt så ille. Hvis du virkelig trenger å sende flere flagg, bør du vurdere å kapsle dem i en klasse. Selv da vil du fremdeles møte det samme problemet, da metoden din sannsynligvis gjør flere ting.

Svar

Flagg og de fleste tempvariablene har en sterk lukt. Mest sannsynlig kan de refaktoriseres og erstattes med spørringsmetoder.

Revidert:

Flagg og tempvariabler når de uttrykker tilstand, bør omformuleres til spørringsmetoder. Tilstandsverdiene (booleans, ints og andre primativer) burde nesten – alltid – være skjult som en del av implementeringsdetaljene.

Flagg som brukes til kontroll, ruting og generell programflyt kan også indikere mulighet til å omforme deler av kontrollstrukturene til separate strategier eller fabrikker, eller hva som helst som er situasjonsmessig hensiktsmessig, som fortsetter å bruke spørringsmetodene.

Svar

Når vi snakker om flagg, bør vi vite at de kommer til å bli endret over tid for programutførelse, og at de kommer til å påvirke oppførselen til programmet basert på deres tilstander. Så lenge vi har god kontroll over disse to tingene, vil de fungere bra.

Flagg kan fungere bra hvis

  • Du har definert dem i et passende omfang. Med hensiktsmessig mener jeg omfanget ikke skal inneholde noen kode som ikke trenger / ikke bør endre dem. Eller i det minste er koden sikker (for eksempel kalles den kanskje ikke utenfra)
  • Hvis det er behov for å håndtere flagg utenfra, og hvis det er mange flagg, kan vi kode flagghåndterer som den eneste måten for å modifisere flagg trygt. Denne flaggbehandleren kan selv kapsle inn flagg og metoder for å endre dem. Den kan deretter lages singleton og kan deretter deles mellom klasser som trenger tilgang til flagg.
  • Og til slutt for vedlikehold, hvis det er for mange flagg:
    • Ingen grunn til å si at de burde følg fornuftig navngivning
    • Bør dokumenteres med hva som er gyldige verdier (kan være med oppregninger)
    • Bør dokumenteres med HVILK KODE MODIFISERER hver av dem, og også med HVILKET BETINGELSE vil resultere i tildeling av en bestemt verdi til flagget.
    • HVILKEN KODE FORBRUKER dem og HVAD OPPFØRING vil resultere for en bestemt verdi

Hvis det er mange flagg, bør godt designarbeid gå foran siden flagg begynner å spille en nøkkelrolle i programoppførselen. Du kan gå for tilstandsdiagrammer for modellering. Slike diagrammer fungerer også som dokumentasjon og visuell veiledning mens du arbeider med dem.

Så lenge disse tingene er på plass, tror jeg det ikke vil føre til rot.

Svar

Jeg antok fra spørsmålet at QA betydde flaggvariabler (globale), og ikke biter av en funksjonsparameter.

Det er situasjoner der du ikke har mange andre muligheter. For eksempel, uten et operativsystem, må du evaluere avbrudd.Hvis et avbrudd kommer veldig ofte, og du ikke har tid til å gjøre en lang evaluering i ISR, er det ikke bare tillatt, men noen ganger til og med best praksis, å bare sette noen globale flagg i ISR (du bør bruke så lite tid som mulig i ISR), og for å evaluere disse flaggene i hovedsløyfen.

Svar

Jeg tror ikke hva som helst er et absolutt ondskap i programmering, alltid.

Det er en annen situasjon der flagg kan være i orden, som ble ikke nevnt her ennå …

Vurder bruken av nedleggelser i dette Javascript-utdraget:

exports.isPostDraft = function ( post, draftTag ) { var isDraft = false; if (post.tags) post.tags.forEach(function(tag){ if (tag === draftTag) isDraft = true; }); return isDraft; } 

Den indre funksjonen, som blir bestått til «Array.forEach», kan ikke bare «returnere sant».

Derfor må du holde staten utenfor med et flagg.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *