Er det noen gang en god idé å kode verdiene inn i applikasjonene våre? Eller er det alltid den rette tingen å kalle disse typene verdier dynamisk i tilfelle de trenger å endres?

Kommentarer

  • en konfigurasjonsparameter vil hjelpe deg
  • Du vet aldri når verdien til pi kan endres …
  • Mann, jeg antar at folk som @gabe er grunnen til dette er en » Regel «. Hvis du gjentar 3.14 på 20 steder i koden din og deretter finner ut at du faktisk trenger mer nøyaktighet, er du skrudd. Jeg skjønte ikke ‘ dette var ikke ‘ t åpenbart.
  • Det var litt uhøflig, @Bill. @Gabe spøkte tydeligvis, men bortsett fra det, handlet spørsmålet om hardcoding vs. config-parametere, ikke bruk av konstant vs. gjenta magiske tall flere steder.
  • Ja, hardcoding kan være en god ide noen ganger . Se Wikipedia-artikkelen om » Softcoding » antimønster.

Svar

Ja, men gjør det åpenbart .

Gjør:

Don «t:

Kommentarer

  • Hvilket er renere, diameter = 2 * radius eller diameter = RADIUS_TO_DIAMETER_FACTOR * radius? Det er faktisk hjørnesaker der et magisk tall kan være bedre løsning.
  • Jeg kan ‘ ikke er enig med dette svaret nok. Jeg pleier å tenke på programmering som å være forfatter. Du forteller historien din gjennom koden, og hvis folk ikke kan forstå logikken, gjør det koden din verdiløs etter min mening. At ‘ hvorfor godt gjennomtenkte navnekonvensjoner egentlig er for lesbarhet. Det er heller ingen god grunn til å bruke magiske tall. Ved å bruke magiske tall fjerner du » hvorfor » fra ligningen og gjør det vanskeligere å understreke tand. For eksempel: » diameter = 2 * radius » Hva er de to for? Denne » diameter = RADIUS_TO_DIAMETER_FACTOR * radius » gir mye mer mening.
  • diameter = 2 * radius er rett fra videregående matematikk. Årsaken til ikke å navngi » 2 » er at det for å ha en verdi av noe annet vil kreve en endring i lovene til fysikk eller matematikk, eller begge deler. (På den annen side er å navngi Pi eller Plancks konstant et godt trekk for enkel lesbarhet.
  • @Joonas: Pfft. Du mener sikkert diameter = radius << 1? Jeg antar at det også kan være diameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT.
  • hvordan ‘ om noen diameter = radius.toDiameter()

Svar

Det jeg synes er rart med denne Q & A så langt er at ingen faktisk har forsøkt å klart definere «hard-code» eller, enda viktigere, alternativene.

tl; dr : Ja, det er noen ganger en god idé å kode verdier, men det er ingen enkel regel med hensyn til når . Det avhenger helt av konteksten.

Spørsmålet begrenser det til verdier , som jeg tar for å bety magiske tall , men svaret på om de er «en god idé eller ikke, er i forhold til det de faktisk brukes til!

Flere eksempler på» hardkodede «verdier er:

  • Konfigurasjonsverdier

    Jeg kryper når jeg ser uttalelser som command.Timeout = 600. Hvorfor 600? Hvem bestemte det? Var det tidsfrist tidligere, og noen hevet tidsavbruddet som et hack i stedet for å fikse det underliggende ytelsesproblemet? Eller er det egentlig noen kjent og dokumentert forventning om behandlingstid?

    Disse burde ikke være magiske tall eller konstanter, de skal eksternaliseres i en konfigurasjonsfil eller database et sted med en meningsfylt navn, fordi deres optimale verdi bestemmes i stor grad eller utelukkende av miljøet som applikasjonen kjører i.

  • Matematiske formler

    Formler pleier å være ganske statiske, slik at naturen til de konstante verdiene inni ikke er veldig viktig. Volumet av en pyramide er (1/3) b * h. Bryr vi oss hvor 1 eller 3 kom fra? Ikke egentlig. En tidligere kommentator påpekte med rette at diameter = radius * 2 sannsynligvis er bedre enn diameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR – men det er en falsk dikotomi.

    Det du bør gjøre for denne typen scenarier er å lage en funksjon . Jeg trenger ikke å vite hvordan du kom opp med formelen, men jeg trenger fortsatt å vite hva den er til . Hvis jeg i stedet for noe tull skrevet ovenfor volume = GetVolumeOfPyramid(base, height) så blir alt plutselig mye tydeligere, og det er helt greit å ha magiske tall inne funksjonen (return base * height / 3) fordi det er åpenbart at de bare er en del av formelen.

    Nøkkelen her er selvfølgelig å ha korte og enkle funksjoner. Dette fungerer ikke for funksjoner med 10 argumenter og 30 linjer med beregninger. Bruk funksjonssammensetning eller konstanter i så fall.

  • Domene- / forretningsregler

    Denne er alltid det grå området fordi det avhenger av nøyaktig verdien. Mest av tiden er det disse spesielle magiske tallene som er kandidater til å bli til konstanter, fordi det gjør programmet lettere å forstå uten å komplisere programlogikken. Tenk på testen if Age < 19 vs. if Age < LegalDrinkingAge; sannsynligvis kan finne ut hva som skjer uten konstanten, men det er lettere med beskrivende tittel.

    Disse kan også bli kandidater for funksjonsabstrahering, for eksempel function isLegalDrinkingAge(age) { return age >= 19 }. Det eneste er at forretningslogikken din ofte er mye mer innviklet enn det, og det kan ikke være fornuftig å begynne å skrive ut dusinvis av funksjoner med 20-30 parametere hver. Hvis det ikke er noen klar abstraksjon basert på objekter og / eller funksjoner, er det OK å ty til konstanter.

    Advarselen er at hvis du jobber for skatteetaten, blir det virkelig virkelig belastende og ærlig meningsløst å skrive AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR). Du kommer ikke til å gjøre det t, du går til AttachForm("B-46") fordi hver enkelt utvikler som noen gang har jobbet eller noen gang vil jobbe der, vil vite at «B-46» er skjemakoden for en enkelt skattyter arkivering bla bla bla – skjemakodene er en del av selve domenet, de endres aldri, så de er egentlig ikke magiske tall.

    Så du må bruke konstanter sparsomt i forretningslogikken; i utgangspunktet må du forstå om det «magiske nummeret» egentlig er et magisk tall eller om det «er et kjent aspekt av domenet. Hvis det er et domene, trenger du ikke kode det med mindre det er veldig god sjanse for at det vil endre seg.

  • Feilkoder og statusflagg

    Dette er aldri i orden å hardkode, slik enhver dårlig bastard som noen gang har blitt truffet med Previous action failed due to error code 46 kan fortelle deg. Hvis språket ditt støtter det, bør du bruke en oppregningstype. Ellers vil du vanligvis ha en hel fil / modul full av konstanter som angir gyldige verdier for en bestemt feiltype.

    Ikke la meg se return 42 i en feilbehandler, capiche? Ingen unnskyldninger.

Jeg har sannsynligvis utelatt flere scenarier, men jeg tror det dekker de fleste av dem.

Så ja, det er noen ganger akseptabel praksis til hard code ting. Bare vær ikke lat med det; det bør være en bevisst beslutning i stedet for vanlig gammel slurvet kode.

Kommentarer

  • Takk for god sammenbrudd! – folk flest ikke ‘ ikke tenker gjennom alle alternativene jeg vil legge til » Miljøkonfigurasjon » – Jeg tror disse bør unngås (ikke hardkodet), siden de fleste data skal legges i en konfigurasjonsfil eller database. Dette følger prinsippet om » å holde data og logikk atskilt » som er en bærebjelke i MVC eller MVVM. streng TestServerVar = » foo «; streng ProdServerVal = » bar «;

Svar

Det er forskjellige grunner til å tilordne en identifikator til et nummer.

  • Hvis tallet kan endres, det skal ha en identifikator. Det er mye lettere å finne NUMBER_OF_PLANETS enn å søke etter hver forekomst på 9 og vurdere om den skal endres til 8. (Merk at bruker-synlig strenger må kanskje endres hvis programvaren noen gang må brukes på et annet språk, og det «er vanskelig å forutsi på forhånd.)
  • Hvis tallet er vanskelig å skrive på noen måte. For konstanter som pi, er det bedre å gi en definisjon med maksimal presisjon enn å skrive den inn flere steder, muligens unøyaktig.
  • Hvis tallet forekommer forskjellige steder. Du trenger ikke å se på to bruksområder av 45 i tilstøtende funksjoner og lure på om de betyr det samme.
  • Hvis betydningen ikke gjenkjennes umiddelbart. Det er trygt å anta at alle vet hva 3.14159265 … er. Det er ikke trygt å anta at alle vil gjenkjenne gravitasjonskonstanten, eller til og med pi / 2. («Alle» her avhenger av programvarens beskaffenhet. Systemprogrammerere kan forventes å kjenne den oktale representasjonen av Unix-tillatelsesbiter eller lignende. I marine- / marinearkitekturprogramvare sjekker du Froude-nummeret til et foreslått skrog og hastighet til se om det er 1.1 eller nyere kan være helt selvforklarende for alle som skal jobbe med det.)
  • Hvis konteksten ikke er gjenkjennelig . Alle vet at det er 60 minutter på en time, men å multiplisere eller dele med 60 kan være uklart hvis det ikke er noen umiddelbare indikasjoner på at mengden er en tidsverdi eller en hastighetsverdi .

Dette gir oss kriterier for hardkodende bokstaver. De bør være uforanderlige, ikke vanskelige å skrive, forekommer bare på ett sted eller i en sammenheng og med gjenkjennelig betydning. Det er ikke noe poeng i å definere 0 som ARRAY_BEGINNING, for eksempel, eller 1 som ARRAY_INCREMENT.

Svar

Som et tillegg til andre svar. Bruk konstanter for strenger når det er mulig. Selvfølgelig vil du ikke ha

const string server_var="server_var"; 

men du bør ha

const string MySelectQuery="select * from mytable;"; 

(forutsatt at du faktisk har et spørsmål der du alltid vil få alle resultatene fra en bestemt tabell)

Annet enn det, bruk konstanter for et annet tall enn 0 (vanligvis). en tillatelses bitmask på 255, bruk ikke

const int 8th_bit=255; //or some other obscure naming scheme that equates to 255. 

bruk i stedet

const int AllowGlobalRead=255; 

Selvfølgelig, sammen med konstanter, vet når du skal bruke teller. Ovennevnte tilfelle vil sannsynligvis passe godt i ett.

Kommentarer

  • typedef enum {state_0 = 0, state_1 = 1, state_2 = 2, .. .} … Ikke ‘ t le, jeg ‘ har sett det gjort. Slå vedkommende rundt hodet med en våt fisk!
  • @ raskt vel selvfølgelig vil du ‘ d noe mer som typedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }
  • THIS_NAMING_CONVENTION_IS_RECOMMENDED_FOR_CONSTANTS
  • For strenger, vil du ikke ‘ t bare vil ha konstanter. Du vil sette alle brukersynlige strenger i en slags ressursfil (detaljene vil avhenge av plattformen din), slik at du enkelt kan bytte til et annet språk.
  • Det kan også være lurt å holde forretningslogikkrelatert strenger (som SQL-spørsmål) i en ressursfil med en slags kryptering eller forvirring. Dette vil forhindre » nysgjerrige » brukere fra å reversere logikken din (eller databaseskjemaet).

Svar

Det kommer an på hva du anser som hardkoding. Hvis du prøver å unngå alle hardkodede ting, havner du i softcoding område, og lager et system som bare skaperen kan administrere (og det er ultimate hardcode)

Mange ting er hardkodet i ethvert rimelig rammeverk, og de fungerer, dvs. det er ingen teknisk grunn til at jeg ikke kan endre inngangspunktet til et C # -program (statisk ugyldig Main ), men hardkoding som ikke skaper noen problemer for noen brukere (unntatt en og annen SÅ spørsmål )

Tommelfingerregelen jeg bruker er at alt som kan og vil endre seg, uten å påvirke tilstanden til hele systemet, skal kunne konfigureres.

Så, IMHO, det er dumt å ikke hardkode ting som aldri endrer seg (pi, gravitasjonskonstant, en konstant i en matematisk formel – tenk volumet av en sfære).

Det er også dumt å ikke hardkode ting eller prosesser som vil ha innvirkning på systemet ditt som krever programmering i alle fall, i .e. det er bortkastet å tillate brukeren å legge til dynamiske felt i et skjema, hvis et felt som er lagt til vil kreve at vedlikeholdsutvikleren går inn og skriver noe skript som får den til å fungere. Det er også dumt (og jeg har sett det noen ganger i bedriftsmiljøer) for å lage et konfigurasjonsverktøy, så ingenting er hardkodet, men det er bare utviklerne i IT-avdelingen som kan bruke det, og det er bare litt lettere å bruke det enn å gjøre det i Visual Studio.

Så, bunnlinjen, om en ting skal være hardkodet er en funksjon av to variabler:

  • vil verdien endres
  • hvordan vil en endring i verdien påvirke systemet

Svar

Er det noen gang en god idé å kode verdiene inn i applikasjonene våre?

I hardkodeverdier bare hvis verdiene er spesifisert i spesifikasjonen (på en endelig utgivelse av spesifikasjonen), f.eks. HTTP OK-svaret vil alltid være 200 (med mindre det endres i RFC), så du vil se (i noen av kodene mine) konstanter som:

public static final int HTTP_OK = 200; 

Ellers lagrer jeg konstanter i egenskapsfilen.

Årsaken til at jeg spesifiserte spesifikasjoner, er at endring av konstanter i spesifikasjoner krever endringsledelse, der interessenter vil gjennomgå endringen og godkjenne / avvise. Det skjer aldri over natten og tar måneder / år for godkjenning. Ikke glem at mange utviklere bruker spesifikasjoner (f.eks. HTTP), så å endre det betyr å bryte millioner av systemer.

Svar

  • hvis verdien kan endres, og faktisk kan endres, så kod det når det er mulig så lenge innsatsen ikke overstiger forventet avkastning
  • noen verdier kan ikke være soft-coded; følg Jonathans retningslinjer i de (sjeldne) tilfellene

Svar

Jeg har lagt merke til at når som helst du kan trekke ut data fra koden din, forbedrer det det som er igjen. Du begynner å legge merke til nye refaktorer og forbedre hele deler av koden din.

Det er bare en god idé å jobbe mot å hente ut konstanter, ikke betrakte det som en dum regel, tenk på det som en mulighet til å kode bedre.

Den største fordelen er hvordan du kan finne lignende konstanter som den eneste forskjellen i grupper av koder – å abstrahere dem i matriser har hjulpet meg med å redusere noen filer med 90% av størrelsen og fikse ganske noen få kopier & lim inn feil i mellomtiden.

Jeg har ennå ikke sett en eneste fordel ved ikke å trekke ut data.

Svar

Jeg kodet nylig en MySQL-funksjon for å beregne avstanden mellom to lat / lange par. Du kan ikke bare gjøre pythagorus; lengdegradslinjer kommer nærmere hverandre når breddegraden øker mot polene, så det er litt hårete trig involvert. Poenget er at jeg var ganske revet med om jeg skulle hardkode verdien som representerer jordens radius i miles.

Det endte med at jeg gjorde det, selv om faktum er at lat / linjelinjer er mye nærmere hverandre, for eksempel månen. Og min funksjon ville drastisk underrapportere avstander mellom punkter på Jupiter. Jeg skjønte at oddsen for nettstedet jeg bygger med en utenomjordisk plassering blir ganske slank.

Kommentarer

Svar

Vel, det kommer an på om språket ditt er kompilert. Hvis det ikke er kompilert, er det ikke så farlig, du redigerer bare kildekoden, selv om den vil være litt delikat for en ikke-programmerer.

Hvis du programmerer med et kompilert språk, er dette tydeligvis ikke en god ide, for hvis variablene endres, må du kompilere på nytt, noe som er mye bortkastet tid hvis du vil justere denne variabelen.

Du trenger ikke lage noen glidebryter eller grensesnitt for å endre variabelen dynamisk, men det minste du kan gjøre er en tekstfil.

For eksempel med mitt ogre-prosjekt bruker jeg alltid ConfigFile-klassen for å laste inn en variabel jeg har skrevet til en konfigurasjonsfil.

Svar

To anledninger der konstanter er (etter min mening i det minste) OK:

  1. Konstanter som ikke er relatert til noe annet; du kan endre disse konstantene når du vil uten å måtte endre noe annet. Eksempel: Standardbredden til en rutenettkolonne.

  2. Helt uforanderlige, presise, åpenbare konstanter, som «antall dager per uke». days = weeks * 7 Å erstatte 7 med en konstant DAYS_PER_WEEK gir nesten ingen verdi.

Svar

Jeg er helt enig med Jonathan, men som alle regler er det unntak …

«Magisk nummer i spesifikasjonen: Magisk nummer i koden»

Sier i utgangspunktet at eventuelle magiske tall som er igjen i spesifikasjonen etter rimelige forsøk på å få beskrivende sammenheng for dem, skal gjenspeiles som sådan i koden. Hvis magiske tall forblir i koden, bør alle anstrengelser gjøres for å isolere dem og gjøre dem tydelig knyttet til opprinnelsesstedet.

Jeg har utført noen grensesnittkontrakter der det er nødvendig å fylle ut meldinger med verdikartede verdier. fra databasen. I de fleste tilfeller er kartleggingen ganske rett frem og passer inn i Jonathans generelle retningslinjer, men jeg har opplevd tilfeller der målmeldingsstrukturen bare var forferdelig.Mer enn 80% av verdiene som måtte overføres i strukturen ble konstanter håndhevet av spesifikasjonen til det fjerne systemet. dette kombinert med det faktum at meldingsstrukturen var gigantisk, gjorde at mange slike konstanter måtte befolkes. I de fleste tilfeller ga de ingen mening eller grunn, bare sa «sett M her» eller «sett 4.10.53.10100.889450.4452 her». Jeg prøvde ikke å legge noen kommentar ved siden av dem alle, det ville ha gjort den resulterende koden uleselig. Jeg sørget imidlertid for at kodeseksjonene der disse magiske verdiene vises er skikkelig isolert og at beholderne (klasser, pakker) har fått passende navn for å peke direkte på spesifikasjonen som håndhever dem.

Når det er sagt, når du tenker på det … det handler stort sett om å gjøre det åpenbart

Svar

Hvis du hardkoder verdien av jordens gravitasjonskonstant, vil ingen bry seg. Hvis du hardkoder IP-adressen til proxy-serveren din, er du inne for problemer.

Kommentarer

  • Du trenger kanskje mer presisjon for jorden ‘ s gravitasjonskonstant, så hardkoding det flere ganger kan føre til problemer.
  • Peter Noone? Fra Herman ‘ s Hermits ?
  • Gravitasjonsakselerasjonen på jorden er ganske mye 9,81 m / s ^ 2 for de fleste breddegrader og høyder (selvfølgelig hvis du ‘ leter etter olje under jorden, eller å skyte ICBMer over Nordpolen, det er veldig viktig å vite om variasjonen i tyngdekraften for mange flere desimaler), med gravitasjonsakselerasjonen på andre planeter som er et annet tall, men så vidt jeg vet er gravitasjonskonstanten konstant rundt universet. Det er mye fysikk som måtte endres hvis g var variabel.

Svar

For det meste nei, men jeg tror det er verdt å merke seg at du Jeg har flest problemer når du begynner å duplisere den hardkodede verdien. Hvis du ikke dupliserer det (f.eks. Bruker det bare en gang i løpet av en klasse), kan det ikke være greit å ikke bruke en konstant.

Legg igjen en kommentar

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