Er det nogensinde en god idé at indstille værdier i vores applikationer? Eller er det altid den rigtige ting at kalde disse typer værdier dynamisk, hvis de skulle ændre sig?
Kommentarer
Svar
Ja, men gør det indlysende .
Gør:
- brug konstanter
- brug en beskrivende variabelnavn
Don “t:
- har magiske tal flyder rundt om koden
Kommentarer
- Hvilket er renere,
diameter = 2 * radius
ellerdiameter = RADIUS_TO_DIAMETER_FACTOR * radius
? Der er faktisk hjørnesager, hvor et magisk nummer kan være en bedre løsning. - Jeg kan ‘ ikke er enig med dette svar nok. Jeg har tendens til at tænke på programmering som at være romanforfatter. Du fortæller din historie gennem koden, og hvis folk ikke kan forstå logikken, gør det din kode værdiløs efter min mening. At ‘ hvorfor grundigt gennemtænkte navngivningskonventioner i det væsentlige er for læsbarhed. Der er heller ingen god grund til at bruge magiske tal. Ved at bruge magiske tal fjerner du ” hvorfor ” fra ligningen og gøre det sværere at understrege tand. For eksempel: ” diameter = 2 * radius ” Hvad er de to til? Denne ” diameter = RADIUS_TO_DIAMETER_FACTOR * radius ” giver meget mere mening.
- diameter = 2 * radius er lige fra gymnasium matematik. Årsagen til ikke at navngive ” 2 ” er, at det for at have en værdi af noget andet ville kræve en ændring af lovgivningen i fysik eller matematik eller begge dele. (På den anden side er navngivning af Pi eller Plancks konstant et godt skridt for enkel læsbarhed).
- @Joonas: Pfft. Du mener bestemt
diameter = radius << 1
? Jeg formoder, at det også kunne værediameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT
. - hvordan ‘ om nogle
diameter = radius.toDiameter()
Svar
Hvad jeg finder underligt ved denne Q & A indtil videre er, at ingen faktisk har forsøgt at klart definere “hard-code” eller, vigtigere, alternativerne.
tl; dr : Ja, det er til tider en god idé at kode værdier, men der er ingen enkel regel med hensyn til når ; det afhænger helt af kontekst.
Spørgsmålet indsnævrer det til værdier som jeg mener betyder magiske tal , men svaret på, om de “er en god idé eller ej, er i forhold til hvad de faktisk bruges til!
Flere eksempler på” hårdkodet “værdier er:
-
Konfigurationsværdier
Jeg kryber sammen, når jeg ser udsagn som
command.Timeout = 600
. Hvorfor 600? Hvem besluttede det? Var det timingen før, og nogen hævede timeout som et hack i stedet for at løse det underliggende præstationsproblem? Eller er det faktisk en kendt og dokumenteret forventning om behandlingstid?Disse burde ikke være magiske tal eller konstanter, de skal eksternaliseres i en konfigurationsfil eller database et eller andet sted med en meningsfuldt navn, fordi deres optimale værdi i vid udstrækning eller helt bestemmes af det miljø, som applikationen kører i.
-
Matematiske formler
Formler har normalt en tendens til at være ret statiske, således at karakteren af de konstante værdier indeni ikke er særlig vigtig. Volumenet af en pyramide er (1/3) b * h. Er vi ligeglad med hvor 1 eller 3 kom fra? Ikke rigtig. En tidligere kommentator påpegede med rette, at
diameter = radius * 2
sandsynligvis er bedre enddiameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR
– men det er en falsk dikotomi.Hvad du skal gøre for denne type scenarie er at oprette en funktion . Jeg behøver ikke at vide, hvordan du kom op med formlen, men jeg har stadig brug for at vide hvad det er til . Hvis jeg i stedet for noget af det vrøvl, der er skrevet ovenfor, skriver
volume = GetVolumeOfPyramid(base, height)
så bliver alt pludselig meget klarere, og det er helt okay at have magiske tal inde funktionen (return base * height / 3
), fordi det er tydeligt, at de bare er en del af formlen.Nøglen her er selvfølgelig at have korte og enkle funktioner. Dette fungerer ikke for funktioner med 10 argumenter og 30 linjer med beregninger. Brug funktionssammensætning eller konstanter i dette tilfælde.
-
Domæne / forretningsregler
Denne er altid det grå område, fordi det afhænger af, hvad værdien er. Mest af tiden er det disse særlige magiske tal, der er kandidater til at blive konstanter, fordi det gør programmet lettere at forstå uden at komplicere programlogikken. Overvej testen
if Age < 19
vs.if Age < LegalDrinkingAge
; du sandsynligvis kan finde ud af, hvad der foregår uden konstanten, men det er lettere med det beskrivende titel.Disse kan også blive kandidater til funktionsabstraktion, for eksempel
function isLegalDrinkingAge(age) { return age >= 19 }
. Det eneste er, at din forretningslogik ofte er meget mere indviklet end det, og det giver måske ikke mening at begynde at skrive snesevis af funktioner med hver 20-30 parametre. Hvis der ikke er en klar abstraktion baseret på objekter og / eller funktioner, er det OK at ty til konstanter.Advarslen er, hvis du arbejder for skatteafdelingen, bliver det virkelig virkelig besværligt og ærligt meningsløst at skrive
AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR)
. Du vil ikke gøre det t, du går tilAttachForm("B-46")
fordi hver enkelt udvikler, der nogensinde har arbejdet eller nogensinde vil arbejde der, vil vide, at “B-46” er formkoden for en enkelt skatteyder arkivering bla bla bla – formkoderne er en del af selve domænet, de ændres aldrig, så de er ikke rigtig magiske tal.Så du skal bruge konstanter sparsomt i forretningslogik; dybest set skal du forstå, om det “magiske nummer” faktisk er et magisk tal, eller om det “er et velkendt aspekt af domænet. Hvis det er domæne, skal du ikke soft-code det, medmindre der er” sa virkelig god chance for, at det vil ændre sig.
-
Fejlkoder og statusflag
Disse er aldrig okay for hard-code, som enhver dårlig bastard, der nogensinde er blevet ramt af
Previous action failed due to error code 46
kan fortælle dig. Hvis dit sprog understøtter det, skal du bruge en optællingstype. Ellers vil du normalt have en hel fil / modul fuld af konstanter, der angiver de gyldige værdier for en bestemt fejltype.Lad mig aldrig se
return 42
i en fejlhåndterer, capiche? Ingen undskyldninger.
Jeg har sandsynligvis udeladt flere scenarier, men jeg tror, det dækker de fleste af dem.
Så ja, det er undertiden acceptabel praksis til hårde kode ting. Bare vær ikke doven med det; det burde være en bevidst beslutning snarere end almindelig gammel slurvet kode.
Kommentarer
- Tak for den gode sammenbrud! – de fleste mennesker tænker ikke ‘ ikke igennem alle de muligheder, jeg vil tilføje ” Miljøkonfiguration ” – Jeg synes, at disse bør undgås (ikke hårdkodede), da de fleste data skal placeres i en konfigurationsfil eller database. Dette følger princippet om ” at holde data og logik adskilt “, der er en grundpille i MVC eller MVVM. streng TestServerVar = ” foo “; streng ProdServerVal = ” bar “;
Svar
Der er forskellige grunde til at tildele et nummer til et nummer.
- Hvis nummeret muligvis ændres, det skal have en identifikator. Det er meget lettere at finde NUMBER_OF_PLANETS end at søge efter hver forekomst af 9 og overveje, om det skal ændres til 8. (Bemærk, at bruger-synlig strenge bliver muligvis nødt til at ændre sig, hvis softwaren nogensinde skal bruges på et andet sprog, og at det er en svær ting at forudsige på forhånd.
- Hvis tallet er svært at skrive på nogen måde. For konstanter som pi er det bedre at give en maksimal præcisionsdefinition end at indtaste det flere steder, muligvis unøjagtigt.
- Hvis nummeret findes forskellige steder. Du skal ikke se på to anvendelser af 45 i tilstødende funktioner og spekulerer på, om de betyder det samme.
- Hvis betydningen ikke umiddelbart kan genkendes. Det er sikkert at antage, at alle ved, hvad 3.14159265 … er. Det er ikke sikkert at antage, at alle vil genkende tyngdekonstanten, eller endda pi / 2. (“Alle” her afhænger af softwarens natur. Systemprogrammerere kan forventes at kende den oktale repræsentation af Unix-tilladelsesbits eller lignende. I sø- / marine-arkitektursoftware kontrolleres Froude-nummeret på et foreslået skrog og hastighed til se om det “1.1 eller nyere kan være helt selvforklarende for alle, der skal arbejde på det.)
- Hvis konteksten ikke kan genkendes . Alle ved, at der er 60 minutter på en time, men at gange eller dividere med 60 kan være uklart, hvis der ikke er nogen umiddelbare indikationer på, at mængden er en tidsværdi eller en hastighedsværdi .
Dette giver os kriterier for bogstaver med hårdt kodning. De skal være uforanderlige, ikke svære at skrive, forekommer kun ét sted eller i en sammenhæng og med genkendelig betydning. Der er ingen mening ved at definere 0 som f.eks. ARRAY_BEGINNING eller 1 som ARRAY_INCREMENT.
Svar
Som en tilføjelse til andre svar. Brug konstanter til strenge, når det er muligt. Selvfølgelig vil du ikke have
const string server_var="server_var";
men du skal have
const string MySelectQuery="select * from mytable;";
(forudsat at du faktisk har en forespørgsel, hvor du altid vil have alle resultaterne fra en bestemt tabel)
Bortset fra det skal du bruge konstanter til et andet antal end 0 (normalt). en tilladelses bitmask på 255, brug ikke
const int 8th_bit=255; //or some other obscure naming scheme that equates to 255.
brug i stedet
const int AllowGlobalRead=255;
Selvfølgelig ved sammen med konstanter, hvornår de skal bruge tællere. Ovenstående sag passer sandsynligvis godt i en.
Kommentarer
- typedef enum {state_0 = 0, state_1 = 1, state_2 = 2, .. .} … Don ‘ t griner, jeg ‘ har set det gjort. Smæk den person rundt om hovedet med en våd fisk!
- @ hurtigt, selvfølgelig vil du ‘ gerne have noget mere som
typedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }
- THIS_NAMING_CONVENTION_IS_RECOMMENDED_FOR_CONSTANTS
- For strenge behøver du ikke ‘ ikke bare ønsker konstanter. Du vil anbringe alle brugersynlige strenge i en slags ressourcefil (detaljer afhænger af din platform), så du nemt kan skifte til et andet sprog.
- Du vil muligvis også holde fast i forretningslogikrelateret strenge (som SQL-forespørgsler) i en ressourcefil med en eller anden form for kryptering eller forvirring. Det forhindrer ” nysgerrige ” brugere i at reverse-engineering din logik (eller databaseskema).
Svar
Det afhænger af, hvad du anser for hardcoding. Hvis du prøver at undgå alt hårdkodede ting, ender du i softcoding område og opretter et system, som kun skaberen kan administrere (og det er ultimativ hardcode)
Masser af ting er hårdkodet i enhver rimelig ramme, og de fungerer, dvs. der er ingen teknisk grund til, at jeg ikke kunne ændre indgangsstedet for en C # -applikation (statisk ugyldigt Main ), men hardcoding, der ikke skaber nogen problemer for nogen bruger (undtagen lejlighedsvis SO-spørgsmål )
Den tommelfingerregel, jeg bruger, er at alt, hvad der kan og vil ændre, uden at påvirke hele systemets tilstand, skal kunne konfigureres.
Så IMHO, det er fjollet ikke at hardcode ting, der aldrig ændrer sig (pi, tyngdekonstant, en konstant i en matematisk formel – tænk volumen af en kugle).
Det er også fjollet ikke at hardcode ting eller processer, der har indflydelse på dit system, der kræver programmering under alle omstændigheder, i .e. det er spildt at lade brugeren føje dynamiske felter til en formular, hvis et tilføjet felt kræver, at vedligeholdelsesudvikleren går ind og skriver et script, der får den ting til at fungere. Det er også dumt (og jeg har set det et par gange i virksomhedsmiljøer) at skabe noget konfigurationsværktøj, så intet er hårdkodet, men kun udviklerne i it-afdelingen kan bruge det, og det er kun lettere at bruge det end at gøre det i Visual Studio.
Så alt i alt, om en ting skal være hardkodet, er en funktion af to variabler:
- ændres værdien
- hvordan vil en ændring i værdien påvirke systemet
Svar
Er det nogensinde en god idé at hardcode værdier i vores applikationer?
I hardcode-værdier kun hvis værdierne er specificeret i specifikationen (ved en endelig frigivelse af specifikationen), f.eks. HTTP OK-svaret vil altid være 200
(medmindre det ændres i RFC), så du vil se (i nogle af mine koder) konstanter som:
public static final int HTTP_OK = 200;
Ellers gemmer jeg konstanter i egenskabsfilen.
Årsagen til, at jeg specificerede specifikationer, er at ændring af konstanter i specifikationer kræver ændringsstyring, hvor interessenter vil gennemgå ændringen og godkende / afvise. Det sker aldrig natten over og tager måneder / år for en godkendelse. Glem ikke, at mange udviklere bruger specifikationer (f.eks. HTTP), så ændring betyder at bryde millioner af systemer.
Svar
- hvis værdien kan ændre sig og muligvis ændre sig, så soft-code det når det er muligt, så længe den involverede indsats ikke overstiger det forventede afkast
- nogle værdier kan ikke være blødkodet; følg Jonathans retningslinjer i disse (sjældne) tilfælde
Svar
Jeg har bemærket at når som helst du kan udtrække data fra din kode, forbedrer det, hvad der er tilbage. Du begynder at lægge mærke til nye refaktorer og forbedre hele sektioner af din kode.
Det er bare en god idé at arbejde hen imod at udvinde konstanter, betragt det ikke som en dum regel, tænk på det som en mulighed for at kode bedre.
Den største fordel er den måde, du kan finde lignende konstanter på som den eneste forskel i kodegrupper – at abstrahere dem i arrays har hjulpet mig med at reducere nogle filer med 90% af deres størrelse og rette helt et par kopier & Indsæt fejl i mellemtiden.
Jeg har endnu ikke set en enkelt fordel ved ikke at udtrække data.
Svar
Jeg har for nylig kodet en MySQL-funktion til korrekt beregning af afstanden mellem to lat / lange par. Du kan bare ikke lave pythagorus; længdegrader kommer tættere på hinanden, når breddegraden stiger mod polerne, så der er en slags behåret trig involveret. Pointen er, jeg var ret revet over, om jeg skulle hårdkode værdien, der repræsenterer jordens radius i miles.
Jeg endte med at gøre det, selvom faktum er, at lat / lng linjer er meget tættere på f.eks. månen. Og min funktion ville drastisk underrapportere afstande mellem punkter på Jupiter. Jeg regnede med, at oddsen for det websted, jeg bygger en udenjordisk placering, der kommer ind, er ret slank.
Kommentarer
- Ja sandsynligvis, men hvad om google.com/moon
Svar
Nå, det afhænger af, om dit sprog er kompileret. Hvis det ikke er kompileret, er det ikke en stor ting, du redigerer bare kildekoden, selvom den er lidt delikat for en ikke-programmør.
Hvis du programmerer med et kompileret sprog, er dette tydeligvis ikke en god ide, for hvis variablerne ændres, skal du kompilere igen, hvilket er et stort spild af tid, hvis du vil justere denne variabel.
Du behøver ikke oprette en skyder eller grænseflade for dynamisk at ændre hans variabel, men det mindste du kunne gøre er en tekstfil.
For eksempel med mit ogre-projekt bruger jeg altid ConfigFile-klassen for at indlæse en variabel, jeg har skrevet til en konfigurationsfil.
Svar
To lejligheder, hvor konstanter er (i det mindste efter min mening) OK:
-
Konstanter, der ikke vedrører noget andet; du kan ændre disse konstanter, når du vil uden at skulle ændre noget andet. Eksempel: Standardbredden på en gitterkolonne.
-
Helt uforanderlige, præcise, åbenlyse konstanter, som “antal dage om ugen”.
days = weeks * 7
Udskiftning af7
med en konstantDAYS_PER_WEEK
giver næppe nogen værdi.
Svar
Jeg er helt enig med Jonathan, men som alle regler er der undtagelser …
“Magisk nummer i spec: Magisk nummer i koden”
Angiver grundlæggende, at eventuelle magiske tal, der forbliver i specifikationen efter rimelige forsøg på at få beskrivende sammenhæng for dem, skal afspejles som sådan i koden. Hvis der forbliver magiske numre i koden, bør alle bestræbelser gøres for at isolere dem og gøre dem tydeligt knyttet til deres oprindelsessted.
Jeg har udført et par grænsefladekontrakter, hvor det er nødvendigt at udfylde meddelelser med kortlagte værdier. fra databasen. I de fleste tilfælde er kortlægningen ret ligetil og passer ind i Jonathans generelle retningslinjer, men jeg har stødt på tilfælde, hvor målbeskedstrukturen bare var forfærdelig.Mere end 80% af de værdier, der skulle overføres i strukturen, blev konstanter håndhævet af specifikationen for det fjerne system. dette kombineret med det faktum, at meddelelsesstrukturen var gigantisk, gjorde, at MASSE af sådanne konstanter måtte befolkes. I de fleste tilfælde gav de ingen mening eller grund, men sagde bare “sæt M her” eller “sæt 4.10.53.10100.889450.4452 her”. Jeg forsøgte heller ikke at placere en kommentar ud for dem alle, det ville have gjort den resulterende kode ulæselige. Jeg sørgede dog for, at kodeafsnittene, hvor disse magiske værdier vises, er korrekt isolerede, og at deres containere (klasser, pakker) navngives passende for at pege direkte på specifikationen, der håndhæver dem.
Når det er sagt, når du tænker på det … det handler stort set om at gøre det indlysende …
Svar
Hvis du “hardcoderer værdien af jordens tyngdekonstant, er der ingen, der kommer til at bekymre sig. Hvis du hardcoder IP-adressen på din proxyserver, er du i problemer.
Kommentarer
- Du har muligvis brug for mere præcision til jorden ‘ s tyngdekonstant, så hårdkodning det flere gange kan føre til problemer.
- Peter Noone? Fra Herman ‘ s Hermits ?
- Tyngdeacceleration på Jorden er stort set 9,81 m / s ^ 2 for de fleste breddegrader og højder (selvfølgelig hvis du ‘ søger efter olie under jorden eller skyde ICBMer over Nordpolen, idet det at vide, at variationen i tyngdekraften er meget vigtig for meget flere decimaler), hvor tyngdeacceleration på andre planeter er et andet antal, men så vidt jeg ved, er tyngdekonstanten konstant rundt om i universet. Der er en masse fysik, der skulle ændre sig, hvis g var variabel.
Svar
For det meste nej, men jeg synes, det er værd at bemærke, at du wi Jeg har de fleste problemer, når du begynder at duplikere den hårdkodede værdi. Hvis du ikke duplikerer det (f.eks. Bruger det kun en gang i implementeringen af en klasse), kan det ikke være i orden at bruge en konstant.
pi
måske ændres …