Închis . Această întrebare trebuie să fie mai oncentrată
. În prezent, nu acceptă răspunsuri.
Comentarii
Răspuns
Problema pe care am văzut-o la menținerea codului care folosește steagurile este că numărul de state crește rapid și există aproape întotdeauna state care nu sunt gestionate. Un exemplu din propria mea experiență: lucram la un cod care avea aceste trei steaguri
bool capturing, processing, sending;
Aceste trei au creat opt state (de fapt, au existat alte două steaguri) de asemenea). Nu toate combinațiile de valori posibile au fost acoperite de cod, iar utilizatorii au văzut erori:
if(capturing && sending){ // we must be processing as well ... }
S-a dovedit că au existat situații în care presupunerea din instrucțiunea if mai sus a fost fals.
Steagurile tind să se compună în timp și ascund starea reală a unei clase. De aceea trebuie evitate.
Comentarii
Răspuns
Aici” este un exemplu când semnalizatoarele sunt utile.
Am o bucată de cod care generează parole (folosind un generator de numere pseudorandom aleatorii securizate criptografic). Apelantul metodei alege dacă sau nu parola trebuie să conțină litere mari, litere mici, cifre, simboluri de bază, simboluri extinse, simboluri grecești, chirilice și unicode.
Cu steaguri, apelarea acestei metode este ușoară:
var password = this.PasswordGenerator.Generate( CharacterSet.Digits | CharacterSet.LowercaseLetters | CharacterSet.UppercaseLetters);
și poate fi chiar simplificat la:
var password = this.PasswordGenerator.Generate(CharacterSet.LettersAndDigits);
Fără steaguri, care ar fi semnătura metodei?
public byte[] Generate( bool uppercaseLetters, bool lowercaseLetters, bool digits, bool basicSymbols, bool extendedSymbols, bool greekLetters, bool cyrillicLetters, bool unicode);
numit astfel:
// 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);
După cum sa menționat în comentarii, o altă abordare ar fi utilizarea unei colecții:
var password = this.PasswordGenerator.Generate( new [] { CharacterSet.Digits, CharacterSet.LowercaseLetters, CharacterSet.UppercaseLetters, });
Acest lucru este mult mai lizibil în comparație cu setul de true
și false
, dar are încă două dezavantaje:
Principalul dezavantaj este acela de a permite valori combinate, cum ar fi CharacterSet.LettersAndDigits
ați scrie ceva de genul acesta în metoda Generate()
:
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. }
posibil rescris astfel:
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. }
Comparați acest lucru cu ceea ce aveți utilizând steaguri:
if (set & CharacterSet.LowercaseLetters == CharacterSet.LowercaseLetters) { // The password should contain lowercase letters. }
s econd, dezavantajul foarte minor este că nu este clar cum s-ar comporta metoda dacă se numește așa:
var password = this.PasswordGenerator.Generate( new [] { CharacterSet.Digits, CharacterSet.LettersAndDigits, // So digits are requested two times. });
Comentarii
Răspuns
Un imens bloc funcțional este mirosul , nu steagurile. Dacă setați steagul pe linia 5, verificați doar steagul de pe linia 354, atunci „e rău. Dacă setați steagul pe linia 8 și verificați steagul de pe linia 10, este bine. De asemenea, unul sau două semnalizatoare pe bloc de cod este în regulă, 300 de semnalizări într-o funcție sunt rele.
Răspuns
De obicei, semnalizatoare poate fi complet înlocuit de o anumită aromă a modelului de strategie, cu o implementare a strategiei pentru fiecare valoare posibilă a steagului. Acest lucru face ca adăugarea unui comportament nou să fie mult mai ușor.
În situații critice de performanță, costul indirecției s-ar putea să apară și să facă deconstrucția în steaguri clare necesare. Acestea fiind spuse, „am probleme să-mi amintesc un singur caz în care de fapt a trebuit să fac asta.
Răspuns
Nu, steagurile nu sunt rele sau un rău care trebuie refăcut cu orice preț.
Luați în considerare Java „s Pattern.compile (String regex, int flags) apel. Aceasta este o mască de biți tradițională și funcționează. Aruncați o privire la constantele din java și oriunde vedeți o grămadă de 2 n știți că există steaguri acolo.
Într-o lume ideală refactorizată, ar fi folosit în schimb un EnumSet unde constantele sunt în schimb valori într-un enum și după cum se arată în documentație:
Performanța spațială și temporală a acestei clase ar trebui să fie suficient de bună pentru a permite utilizarea acesteia ca o alternativă de înaltă calitate, sigură la tip, la „semnalizatoarele de biți” tradiționale bazate pe int. / p>
Într-o lume perfectă, acel apel Pattern.compile devine Pattern.compile(String regex, EnumSet<PatternFlagEnum> flags)
.
Toate care a spus, steagurile sale încă.Este mult mai ușor să lucrați cu Pattern.compile("foo", Pattern.CASE_INSENSTIVE | Pattern.MULTILINE)
decât ar fi să aveți Pattern.compile("foo", new PatternFlags().caseInsenstive().multiline())
sau un alt stil de a încerca să faceți ceea ce sunt cu adevărat steagurile și bun pentru.
Steagurile sunt adesea văzute atunci când lucrați cu lucruri la nivel de sistem. Atunci când interfațați cu ceva la nivelul sistemului de operare, este probabil ca cineva să aibă un steag undeva – fie că este valoarea returnată a unui proces, fie permisiunile unui fișier, fie steagurile pentru deschiderea unui socket. Încercarea de a refactura aceste cazuri în unele vânătoare de vrăjitoare împotriva unui miros de cod perceput va ajunge probabil la un cod mai rău decât dacă unul a acceptat și a înțeles steagul.
Problema apare atunci când oamenii folosesc în mod abuziv steagurile care le aruncă împreună și crearea unui set frankenflag de tot felul de steaguri fără legătură sau încercarea de a le folosi acolo unde nu sunt „steaguri deloc.
Răspuns
Presupun că vorbim despre steaguri în cadrul semnăturilor metodei.
Folosirea unui singur steag este suficient de rea.
Nu va însemna nimic pentru colegii tăi de prima dată când îl văd. Va trebui să se uite la codul sursă al metodei pentru a stabili ce face. Probabil că veți fi în aceeași poziție la câteva luni în jos, când veți uita despre ce a fost metodă.
Trecerea unui steag către metodă înseamnă, în mod normal, că metoda dvs. este responsabilă pentru mai multe lucruri. În cadrul metodei, probabil că faceți o verificare simplă a liniilor:
if (flag) DoFlagSet(); else DoFlagNotSet();
Asta „este o separare slabă a preocupărilor și în mod normal puteți găsi o cale de a o rezolva.
În mod normal, am două metode separate:
public void DoFlagSet() { } public void DoFlagNotSet() { }
Acest lucru va avea mai mult sens cu numele metodelor care sunt aplicabile problemei pe care o rezolvați.
Trecerea mai multor semnalizări este de două ori mai rea. Dacă într-adevăr trebuie să treceți mai multe semnalizatoare, vă recomandăm să le încapsulați într-o clasă. Chiar și atunci, vă veți confrunta în continuare cu aceeași problemă, deoarece metoda dvs. face probabil mai multe lucruri.
Răspuns
Steaguri și cele mai multe variabile temp sunt un miros puternic. Cel mai probabil, acestea ar putea fi refactorizate și înlocuite cu metode de interogare.
Revizuite:
Steagurile și variabilele temp atunci când exprimă starea, ar trebui refactorizate la metodele de interogare. Valorile stării (booleeni, ints și alte elemente primitive) ar trebui aproape-întotdeauna ascunse ca parte a detaliilor implementării.
Semnalizatoarele care sunt utilizate pentru control, rutare și fluxul general al programului pot indica, de asemenea, oportunitate de refactorizare a secțiunilor structurilor de control în strategii sau fabrici separate, sau orice altceva ar putea fi adecvat din punct de vedere situațional, care continuă să folosească metodele de interogare.
Răspuns
Când vorbim despre steaguri, ar trebui să știm că acestea vor fi modificate în timpul execuției programului și că vor efectua comportamentul programului pe baza stărilor lor. Atâta timp cât avem un control îngrijit asupra acestor două lucruri, acestea vor funcționa excelent.
Steagurile pot funcționa excelent dacă
- le-ați definit într-un domeniu adecvat. Prin înțeles adecvat, domeniul de aplicare nu ar trebui să conțină niciun cod care să nu-i / nu ar trebui să-i modifice. Sau cel puțin codul este sigur (de exemplu, este posibil să nu fie apelat direct din exterior)
- Dacă este nevoie să se ocupe de steaguri din exterior și dacă există multe steaguri, putem codifica gestionarul de steaguri ca unică modalitate pentru a modifica în siguranță steagurile. Acest gestionar de steaguri poate încapsula el însuși steaguri și metode pentru a le modifica. Poate fi apoi realizat singleton și poate fi apoi împărțit între clasele care au nevoie de acces la steaguri.
- Și, în cele din urmă, pentru mentenabilitate, dacă există prea multe stegulețe:
- Nu este nevoie să spun că ar trebui urmați o denumire sensibilă
- Ar trebui să fie documentată cu valorile valide (pot fi cu enumerări)
- Ar trebui să fie documentate cu CODUL CARE VOR MODIFICA fiecare dintre ele și, de asemenea, cu CĂ CONDIȚIE va rezulta în atribuirea unei anumite valori steagului.
- CODUL ÎL VA CONSUMA și CE COMPORTAMENT va rezulta pentru o anumită valoare
Dacă există o mulțime de steaguri, ar trebui să lucreze o proiectare bună, deoarece steagurile vor începe să joace un rol cheie în comportamentul programului. Puteți alege diagramele de stat pentru modelare. Astfel de diagrame funcționează și ca documentare și îndrumare vizuală în timp ce se ocupă de ele.
Atâta timp cât aceste lucruri sunt la locul lor, cred că nu va duce la mizerie.
Răspuns
Am presupus din întrebare că QA însemna variabile steag (globale) și nu biți ai unui parametru funcțional.
Există situații unde nu aveți multe alte posibilități. De exemplu, fără un sistem de operare trebuie să evaluați întreruperile.Dacă o întrerupere apare foarte frecvent și nu aveți timp să faceți o evaluare îndelungată în ISR, nu este permis doar, dar uneori chiar și cele mai bune practici să setați doar câteva steaguri globale în ISR (ar trebui să petreceți cât mai puțin timp posibil în ISR) și pentru a evalua acele stegulețe din bucla dvs. principală.
Răspunde
Nu cred că orice este un rău absolut în programare, vreodată.
Există o altă situație în care steagurile ar putea fi în ordine, care încă nu au fost menționate aici …
Luați în considerare utilizarea închiderilor în acest fragment Javascript:
exports.isPostDraft = function ( post, draftTag ) { var isDraft = false; if (post.tags) post.tags.forEach(function(tag){ if (tag === draftTag) isDraft = true; }); return isDraft; }
Funcția interioară, fiind trecută la „Array.forEach”, nu poate pur și simplu „return true”.
Prin urmare, trebuie să păstrați statul afară cu un steag.