Este vreodată o idee bună să introducem valori hardcode în aplicațiile noastre? Sau este întotdeauna corect să apelați aceste tipuri de valori dinamic în cazul în care trebuie să se schimbe?
Comentarii
Răspundeți
Da, dar faceți-l evident .
Faceți:
- utilizați constante
- utilizați o descriptivă numele variabilei
Don „t:
- au orice numere magice plutind în jurul codului
Comentarii
- Care este mai curat,
diameter = 2 * radius
saudiameter = RADIUS_TO_DIAMETER_FACTOR * radius
? Există într-adevăr cazuri de colț în care un număr magic poate fi o soluție mai bună. - Nu pot ‘ să fiu de acord cu acest răspuns suficient. Tind să mă gândesc la programare ca la un romancier. Îți spui povestea prin cod și dacă oamenii nu pot înțelege logica, codul tău nu are valoare în opinia mea. Că ‘ de ce convențiile de denumire bine gândite sunt în esență pentru lizibilitate. De asemenea, nu există motive întemeiate pentru a utiliza numerele magice. Prin utilizarea numerelor magice eliminați ” de ce ” din ecuație și face mai dificil de sub tand. De exemplu: ” diametru = 2 * rază ” Pentru ce sunt cele două? Această ” diametru = RADIUS_TO_DIAMETER_FACTOR * raza ” are mult mai mult sens.
- diametrul = 2 * raza este direct de la matematica liceului. Motivul pentru care nu a fost denumit ” 2 ” este că pentru a avea o valoare de orice altceva ar necesita o modificare a legilor din fizică sau matematică sau ambele. (Pe de altă parte, numirea Pi sau constantă Plancks este o mișcare bună pentru o lizibilitate simplă).
- @Joonas: Pfft. Cu siguranță vrei să spui
diameter = radius << 1
? Presupun că ar putea fi șidiameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT
. - cum ‘ se confruntă cu unele
diameter = radius.toDiameter()
Răspuns
Ce mi se pare ciudat la acest Q & A până acum este că nimeni nu a încercat de fapt să definească în mod clar „hard-code” sau, mai important, alternativele.
tl; dr : Da, uneori este o idee bună pentru a codifica valorile, dar nu există o regulă simplă cu privire la când ; depinde complet de context.
Întrebarea o restrânge la valori , ceea ce consider că înseamnă numere magice , dar răspunsul la dacă sunt sau nu o idee bună este relativ la la ce sunt utilizate de fapt!
Câteva exemple de „cod „valorile sunt:
-
Valorile de configurare
Mă înfior de câte ori văd afirmații ca
command.Timeout = 600
. De ce 600? Cine a decis asta? A expirat înainte și cineva a ridicat timpul de expirare ca un hack în loc să rezolve problema de performanță care stă la baza? Sau este de fapt o așteptare cunoscută și documentată pentru timpul de procesare?Acestea nu ar trebui să fie numere magice sau constante, ele ar trebui externalizate într-un fișier de configurare sau bază de date undeva cu un nume semnificativ, deoarece valoarea lor optimă este determinată în mare parte sau în întregime de mediul în care rulează aplicația.
-
Formule matematice
Formulele tind de obicei să fie destul de statice, astfel încât natura valorilor constante din interior să nu fie cu adevărat deosebit de importantă. Volumul unei piramide este (1/3) b * h. Ne pasă de unde au venit 1 sau 3? Nu chiar. Un comentator anterior a subliniat pe bună dreptate că
diameter = radius * 2
este probabil mai bun decâtdiameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR
– dar aceasta este o dihotomie falsă.Ce ar trebui să faceți pentru acest tip de scenariu este crearea unei funcții . Nu trebuie să știu cum ați venit cu formula, dar trebuie să știu la ce servește . Dacă, în locul oricărui prostie scris mai sus, scriu
volume = GetVolumeOfPyramid(base, height)
, deodată totul devine mult mai clar și este perfect în regulă să ai numere magice în interior funcția (return base * height / 3
) deoarece este evident că sunt doar o parte a formulei.Cheia aici este, desigur, să aibă funcții scurte și simple . Acest lucru nu funcționează pentru funcții cu 10 argumente și 30 de linii de calcule. Utilizați compoziția funcției sau constante în acest caz.
-
Reguli de domeniu / afaceri
Aceasta este întotdeauna zona gri, deoarece depinde exact de valoarea. De cele mai multe ori de multe ori, sunt aceste numere magice speciale care pot fi transformate în constante, deoarece acest lucru face programul mai ușor de înțeles fără a complica logica programului. Luați în considerare testul
if Age < 19
vs.if Age < LegalDrinkingAge
; probabil puteți afla ce se întâmplă fără constantă, dar este mai ușor cu descriptivul title.Acestea pot de asemenea să devină candidați la abstracția funcției, de exemplu
function isLegalDrinkingAge(age) { return age >= 19 }
. Singurul lucru este că adesea logica dvs. de afaceri este mult mai complicat de atât și s-ar putea să nu aibă sens să începeți să scrieți zeci de funcții cu câte 20-30 de parametri fiecare. Dacă nu există o abstractizare clară bazată pe obiecte și / sau funcții, atunci recurgerea la constante este OK.Avertismentul este că, dacă lucrați pentru departamentul fiscal, devine cu adevărat, cu adevărat împovărător și sincer inutil să scrieți
AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR)
. Nu vei face asta t, mergi laAttachForm("B-46")
deoarece fiecare dezvoltator care a lucrat vreodată sau va lucra vreodată acolo va ști că „B-46” este codul formularului pentru un singur contribuabil filing bla bla bla – codurile formularului fac parte din domeniul în sine, ele nu se schimbă niciodată, așa că „nu sunt numere magice.Deci, trebuie să utilizați constante cu ușurință în logica de afaceri; practic trebuie să înțelegeți dacă acel „număr magic” este de fapt un număr magic sau dacă „este un aspect binecunoscut al domeniului. Dacă este domeniul, atunci nu îl codificați cu excepția cazului în care există„ un șanse foarte mari să se schimbe.
-
Coduri de eroare și steaguri de stare
Acestea nu sunt niciodată în regulă, așa cum vă poate spune orice nenorocit sărac care a fost lovit cu
Previous action failed due to error code 46
. Dacă limba dvs. o acceptă, ar trebui să utilizați un tip de enumerare. În caz contrar, veți avea de obicei un întreg fișier / modul plin de constante care specifică valorile valide pentru un anumit tip de eroare.Nu mă lăsați să văd vreodată
return 42
într-un gestionar de erori, capiche? Fără scuze.
Probabil că am lăsat deoparte mai multe scenarii, dar cred că acestea le acoperă pe cele mai multe dintre ele.
Deci, da, este o practică uneori acceptabilă la chestii cu coduri dure. Nu vă lăsați; ar trebui să fie o decizie conștientă, mai degrabă decât un vechi cod sloppy.
Comentarii
- Vă mulțumim pentru defalcarea bună! – majoritatea oamenilor nu ‘ nu se gândesc la toate opțiunile pe care le-aș adăuga ” Configurare mediu ” – Cred că acestea ar trebui evitate (nu sunt codificate), deoarece majoritatea datelor ar trebui introduse într-un fișier de configurare sau o bază de date. Aceasta urmează principiul ” păstrând datele și logica separate „, care este un pilon al MVC sau MVVM. șir TestServerVar = ” foo ” șir ProdServerVal = ” bara „;
Răspuns
Există diverse motive pentru atribuirea unui identificator unui număr.
- Dacă numărul s-ar putea schimba, ar trebui să aibă un identificator. Este mult mai ușor să găsești NUMBER_OF_PLANETS decât să cauți fiecare instanță de 9 și să te gândești dacă ar trebui să fie schimbat la 8. (Rețineți că vizibil pentru utilizator șirurile ar putea fi nevoite să se schimbe dacă software-ul trebuie folosit vreodată într-o altă limbă, iar acest lucru este „greu de prezis în avans.)
- Dacă numărul este greu de tastat în vreun fel. Pentru constantele precum pi, este mai bine să dați o definiție de precizie maximă decât să o retetați în mai multe locuri, posibil inexact.
- Dacă numărul apare în locuri diferite. Nu ar trebui să vă uitați la două utilizări ale 45 în funcțiile alăturate și să vă întrebați dacă înseamnă același lucru.
- Dacă semnificația nu este „recunoscută instantaneu. Este sigur să presupunem că toată lumea știe ce este 3.14159265 … Nu este sigur să presupunem că toată lumea va recunoaște constanta gravitațională sau chiar pi / 2. („Toată lumea” de aici depinde de natura software-ului. Se poate aștepta ca programatorii de sistem să cunoască reprezentarea octală a biților de permisiune Unix sau altele asemenea. În software-ul de arhitectură navală / marină, verificarea numărului Froude al corpului propus și viteza la vezi dacă „1.1 sau mai mare ar putea fi perfect auto-explicativ pentru oricine ar trebui să lucreze la el.)
- Dacă contextul nu este recunoscut . Toată lumea știe că există 60 de minute într-o oră, dar înmulțirea sau împărțirea la 60 poate fi neclară dacă nu există indicații imediate că cantitatea este o valoare a timpului sau o valoare a ratei .
Acest lucru ne oferă criterii pentru literele de codare dură. Acestea ar trebui să fie imuabile, nu greu de tastat, care apar doar într-un singur loc sau context și cu semnificație recunoscută. Nu are rost în definirea 0 ca ARRAY_BEGINNING, de exemplu, sau 1 ca ARRAY_INCREMENT.
Răspuns
Ca o completare la alte răspunsuri. Folosiți constante pentru șiruri atunci când este posibil. Desigur, nu vrei să ai
const string server_var="server_var";
dar ar trebui să ai
const string MySelectQuery="select * from mytable;";
(presupunând că aveți de fapt o interogare în care doriți să obțineți toate rezultatele dintr-un tabel specific, întotdeauna)
În afară de aceasta, utilizați constante pentru orice alt număr decât 0 (de obicei). Dacă aveți nevoie o mască bit de permisiune de 255, nu „utilizați
const int 8th_bit=255; //or some other obscure naming scheme that equates to 255.
utilizați în schimb
const int AllowGlobalRead=255;
Desigur, împreună cu constantele, știți când să utilizați enumeratoarele. Cazul de mai sus s-ar potrivi bine într-unul.
Comentarii
- typedef enum {state_0 = 0, state_1 = 1, state_2 = 2, .. .} … Nu ‘ nu râde, eu ‘ am văzut-o făcută. Loveste acea persoană în jurul capului cu un pește umed!
- @ rapid, bineînțeles că ‘ ai vrea ceva mai mult ca
typedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }
- THIS_NAMING_CONVENTION_IS_RECOMMENDED_FOR_CONSTANTS
- Pentru șiruri, nu ‘ nu doriți decât constante. Doriți să puneți orice șiruri vizibile de utilizator într-un fel de fișier de resurse (detaliile vor depinde de platforma dvs.), astfel încât să puteți schimba cu ușurință într-o altă limbă.
- De asemenea, este posibil să doriți să rămâneți legat de logica afacerii șiruri (cum ar fi interogările SQL) într-un fișier de resurse cu un fel de criptare sau ofuscare. Acest lucru va împiedica utilizatorii ” curioși ” de utilizatori să-și modifice logica (sau schema bazei de date).
Răspuns
Depinde de ceea ce considerați ca hardcoding. Dacă încercați să evitați toate lucrurile codificate, veți ajunge pe teritoriul softcoding și creați un sistem pe care numai creatorul îl poate gestiona (și acesta este hardcode final)
O mulțime de lucruri sunt codificate în orice cadru rezonabil și funcționează. Adică nu există niciun motiv tehnic pentru care nu ar trebui să pot schimba punctul de intrare al unei aplicații C # (static void Main ), dar codul hard care nu creează probleme pentru niciun utilizator (cu excepția SO întrebare ocazională )
Regula generală pe care o folosesc este că orice lucru care poate și se poate schimba, fără a afecta starea întregului sistem, ar trebui să fie confugurabil.
Deci, IMHO, este o prostie să nu faci lucruri cu coduri dure care nu se schimbă niciodată (pi, constanta gravitațională, o constantă într-o formulă matematică – gândiți-vă la volumul unei sfere).
De asemenea, este o prostie să nu codificați lucrurile sau procesele care vor avea un impact asupra sistemului dvs. care va necesita programare în orice caz, i .e. Este risipitor să permită utilizatorului să adauge câmpuri dinamice la un formular, dacă vreun câmp adăugat ar necesita ca dezvoltatorul de întreținere să intre și să scrie un script care să facă acest lucru să funcționeze. De asemenea, este prost (și l-am văzut de câteva ori în mediul de afaceri) să creez un instrument de configurare, deci nimic nu este codat, dar numai dezvoltatorii din departamentul IT îl pot folosi și este ușor mai ușor să-l folosiți decât să-l faceți în Visual Studio.
Deci, linia de jos, dacă un lucru ar trebui codat în mod dur este o funcție a două variabile:
- se va modifica valoarea
- cum va afecta sistemul o modificare a valorii
Răspuns
Este vreodată o idee bună să introduceți valori hardcode în aplicațiile noastre?
I hardcode values numai dacă valorile sunt specificate în Specificație (la o versiune finală a specificației), de ex. Răspunsul HTTP OK va fi întotdeauna 200
(cu excepția cazului în care se modifică în RFC), așa că veți vedea (în unele dintre codurile mele) constante precum:
public static final int HTTP_OK = 200;
În caz contrar, stochez constante în fișierul de proprietăți.
Motivul pentru care am specificat specificațiile este că schimbarea constantelor în specificații necesită gestionarea modificărilor, în care, părțile interesate vor revizui schimbarea și vor aproba / dezaproba. Nu se întâmplă niciodată peste noapte și durează luni / ani pentru aprobare. Nu uitați că mulți dezvoltatori folosesc specificații (de exemplu, HTTP), deci schimbarea acesteia înseamnă ruperea a milioane de sisteme.
Răspuns
- dacă valoarea se poate schimba și chiar s-ar putea schimba, atunci codificați-o de câte ori este posibil, atâta timp cât efortul implicat nu depășește rentabilitatea așteptată
- unele valori nu pot fi soft-coded; urmați instrucțiunile lui Jonathan în acele (rare) cazuri
Răspuns
Am observat că, de fiecare dată când puteți extrage date din codul dvs., îmbunătățește ce mai rămâne. Începeți să observați noi refactorizări și să îmbunătățiți secțiuni întregi ale codului dvs.
Este doar o idee bună să lucrați la extragerea constantelor, nu o considerați o regulă stupidă, gândiți-vă la asta ca la o oportunitate de codificare mai bine.
Cel mai mare avantaj ar fi modul în care ați putea găsi constante similare fiind singura diferență în grupurile de cod – abstractizarea lor în matrice m-a ajutat să reduc unele fișiere cu 90% din dimensiunea lor și să remedi destul câteva copii & lipesc erori între timp.
Încă nu am văzut un singur avantaj că nu extrag date.
Răspuns
Am codificat recent o funcție MySQL pentru a calcula corect distanța dintre două perechi lat / lung. Nu puteți face doar pitagor; liniile de longitudine se apropie între ele pe măsură ce latitudinea crește către poli, așa că sunt implicați niște trigoni păroși. Ideea este că am fost destul de sfâșiat dacă am să codez cu greu valoarea reprezentând raza pământului în mile.
Am ajuns să o fac, chiar dacă realitatea este că liniile lat / lng sunt mult mai apropiate între ele, să zicem, pe lună. Iar funcția mea ar subestima drastic distanțele dintre punctele de pe Jupiter. Mi-am dat seama că șansele ca site-ul web pe care îl construiesc să aibă o locație extraterestră să fie destul de redus.
Comentarii
- Da, probabil, dar ce despre google.com/moon
Răspuns
Ei bine, depinde dacă limba dvs. este compilată. Dacă nu este compilată, nu este mare lucru, doar editați codul sursă, chiar dacă va fi ușor delicat pentru un non-programator.
Dacă programați cu un limbaj compilat, aceasta nu este în mod clar o idee bună, deoarece dacă variabilele se schimbă, trebuie să vă recompilați, ceea ce reprezintă o mare pierdere de timp dacă doriți să ajustați această variabilă.
Nu este nevoie să faceți un glisor sau o interfață pentru a-i schimba dinamic variabila, dar cel mai puțin pe care l-ați putea face este un fișier text.
De exemplu, cu proiectul meu ogru, folosesc întotdeauna clasa ConfigFile pentru a încărca o variabilă pe care am scris-o într-un fișier de configurare.
Răspuns
Două ocazii în care constantele sunt (cel puțin în opinia mea) OK:
-
Constante care nu au legătură cu nimic altceva; puteți schimba aceste constante ori de câte ori doriți, fără a fi nevoie să schimbați altceva. Exemplu: lățimea implicită a unei coloane de grilă.
-
Constante absolut imuabile, precise, evidente, cum ar fi „numărul de zile pe săptămână”.
days = weeks * 7
Înlocuirea7
cu o constantăDAYS_PER_WEEK
oferă cu greu o valoare.
Răspuns
Sunt complet de acord cu Jonathan, dar, deoarece toate regulile sunt excepții …
„Număr magic în spec: Număr magic în cod”
Practic afirmă că orice numere magice care rămân în specificații după încercări rezonabile de a obține un context descriptiv pentru acestea ar trebui reflectate ca atare în cod. Dacă numerele magice rămân în cod, trebuie depuse toate eforturile pentru a le izola și a le face clar legate de punctul lor de origine.
Am efectuat câteva contracte de interfață în care este necesar să completez mesajele cu valori mapate. din baza de date. În majoritatea cazurilor, maparea este destul de simplă și s-ar încadra în liniile generale de orientare ale lui Jonathan, dar am întâlnit cazuri în care structura mesajului țintă era pur și simplu îngrozitoare.Peste 80% din valorile care trebuiau transmise în structură erau constante impuse de specificația sistemului îndepărtat. acest lucru, împreună cu faptul că structura mesajului a fost gigantică, a făcut ca o mulțime de astfel de constante să fie populate. În majoritatea cazurilor, nu au furnizat un sens sau un motiv, au spus doar „pune M aici” sau „pune 4.10.53.10100.889450.4452 aici”. Nici nu am încercat să pun un comentariu lângă toate acestea, ar fi făcut codul rezultat ilizibil. Cu toate acestea, m-am asigurat că secțiunile de cod în care apar aceste valori magice sunt izolate în mod corespunzător și că containerele lor (clase, pachete) sunt denumite în mod corespunzător pentru a indica direct specificațiile care le aplică. it … este aproape totul despre a face evident …
Răspunde
Dacă „codificați în mod durabil valoarea constantei gravitaționale a pământului, nimănui nu îi va păsa. Dacă codificați adresa IP a serverului proxy, veți avea probleme.
Comentarii
- S-ar putea să aveți nevoie de mai multă precizie pentru pământ ‘ s constanta gravitațională, deci o codificare dură de mai multe ori poate duce la probleme.
- Peter Noone? From Herman ‘ s Hermits ?
- Accelerația gravitațională pe Pământ este de aproape 9,81 m / s ^ 2 pentru majoritatea latitudinilor și altitudinilor (desigur, dacă ‘ căutați petrol subteran sau care trage ICBM-uri peste Polul Nord, știind că variația gravitației este foarte importantă pentru mult mai multe zecimale), accelerația gravitațională pe alte planete fiind un număr diferit, dar din câte știu, constanta gravitațională este constantă în jurul universului. Există o mulțime de fizică care ar trebui să se schimbe dacă g ar fi variabilă.
Răspuns
De cele mai multe ori nu, dar cred că este demn de remarcat faptul că vă wi Voi avea cele mai multe probleme atunci când începeți să copiați valoarea codificată. Dacă nu îl duplicați (de exemplu, utilizați-l o singură dată în implementarea unei clase), atunci nu utilizați o constantă ar putea fi bine.
pi
…