Is het ooit een goed idee om waarden hard te coderen in onze applicaties? Of is het altijd goed om dit soort waarden dynamisch aan te roepen voor het geval ze moeten worden gewijzigd?
Opmerkingen
Antwoord
Ja, maar maak het duidelijk .
Wel:
- gebruik constanten
- gebruik een beschrijvende variabelenaam
Don “t:
- hebben magische getallen zwevend rond de code
Reacties
- Dat is schoner,
diameter = 2 * radius
ofdiameter = RADIUS_TO_DIAMETER_FACTOR * radius
? Er zijn inderdaad hoekgevallen waarin een magisch getal een betere oplossing kan zijn. - Ik kan ‘ niet akkoord gaan met dit antwoord genoeg. Ik heb de neiging om programmeren te beschouwen als een romanschrijver. Je vertelt je verhaal door middel van de code en als mensen de logica niet begrijpen, wordt je code naar mijn mening waardeloos. Dat ‘ Daarom zijn goed doordachte naamgevingsconventies in wezen bedoeld voor leesbaarheid. Er is ook geen goede reden om magische getallen te gebruiken. Door magische getallen te gebruiken, verwijdert u de ” waarom ” uit de vergelijking en maak het moeilijker om te onderschatten tand. Bijvoorbeeld: ” diameter = 2 * straal ” Waar zijn de twee voor? Deze ” diameter = RADIUS_TO_DIAMETER_FACTOR * straal ” is veel logischer.
- diameter = 2 * straal is rechtstreeks van wiskunde op de middelbare school. De reden om de ” 2 ” niet te noemen, is dat als het een waarde van iets anders heeft, een wijziging in de wetten van natuurkunde of wiskunde, of beide. (Aan de andere kant is het een goede zet om Pi of Plancks-constante te noemen voor eenvoudige leesbaarheid.)
- @Joonas: Pfft. Bedoel je zeker
diameter = radius << 1
? Ik veronderstel dat dat ookdiameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT
zou kunnen zijn. - hoe ‘ ongeveer
diameter = radius.toDiameter()
Answer
Wat ik vreemd vind aan deze Q & A tot nu toe is dat niemand daadwerkelijk heeft geprobeerd om “hard-code” of, nog belangrijker, de alternatieven duidelijk te definiëren.
tl; dr : Ja, het is soms een goed idee om waarden hard te coderen, maar er is geen simpele regel voor wanneer ; het hangt volledig af van de context.
De vraag beperkt de vraag tot waarden , waarmee ik magische getallen bedoel , maar het antwoord op de vraag of ze “een goed idee zijn of niet, is relatief ten opzichte van waarvoor ze” daadwerkelijk worden gebruikt!
Verschillende voorbeelden van “hard-coded “waarden zijn:
-
Configuratiewaarden
Ik krimp ineen als ik uitspraken zie zoals
command.Timeout = 600
. Waarom 600? Wie heeft dat besloten? Was het eerder een time-out en heeft iemand de time-out verhoogd als een hack in plaats van het onderliggende prestatieprobleem op te lossen? Of is het eigenlijk een bekende en gedocumenteerde verwachting voor verwerkingstijd?Dit mogen geen magische getallen of constanten zijn, ze moeten worden extern gemaakt in een configuratiebestand of database ergens met een betekenisvolle naam, omdat hun optimale waarde grotendeels of volledig wordt bepaald door de omgeving waarin de applicatie wordt uitgevoerd.
-
Wiskundige formules
Formules zijn meestal vrij statisch, zodat de aard van de constante waarden binnenin niet echt bijzonder belangrijk is. Het volume van een piramide is (1/3) b * h. Maakt het ons uit waar de 1 of 3 vandaan kwam? Niet echt. Een eerdere commentator wees er terecht op dat
diameter = radius * 2
waarschijnlijk beter is dandiameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR
– maar dat is een valse tweedeling.Wat u zou moeten doen voor dit type scenario, is het maken van een functie . Ik hoef niet te weten hoe je de formule hebt bedacht , maar ik moet nog steeds weten waarvoor het is . Als ik, in plaats van een van de onzin die hierboven is geschreven,
volume = GetVolumeOfPyramid(base, height)
schrijf, dan wordt alles ineens een stuk duidelijker en is het prima om magische getallen binnen de functie (return base * height / 3
) omdat het “duidelijk is dat ze” slechts een deel van de formule zijn.De sleutel hier is natuurlijk om korte en simpele functies. Dit werkt niet voor functies met 10 argumenten en 30 regels berekeningen. Gebruik in dat geval functiesamenstelling of constanten.
-
Domein- / bedrijfsregels
Dit is altijd het grijze gebied omdat het afhangt van wat de waarde precies is. Meestal zijn het deze specifieke magische getallen die kandidaten zijn om in constanten te veranderen, omdat dat het programma gemakkelijker te begrijpen maakt zonder de programmalogica te compliceren. Beschouw de test
if Age < 19
vs.if Age < LegalDrinkingAge
; je kan waarschijnlijk achterhalen wat er aan de hand is zonder de constante, maar het is gemakkelijker met de beschrijvende title.Deze kunnen ook kandidaten worden voor functie-abstractie, bijvoorbeeld
function isLegalDrinkingAge(age) { return age >= 19 }
. Het enige is dat uw bedrijfslogica vaak is veel ingewikkelder dan dat, en het is misschien niet logisch om te beginnen met het schrijven van tientallen functies met elk 20-30 parameters. Als er geen duidelijke abstractie is op basis van objecten en / of functies, dan is toevlucht nemen tot constanten OK.Het voorbehoud is dat als je voor de belastingdienst werkt, het echt echt lastig en eerlijk gezegd zinloos wordt om
AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR)
te schrijven. Dat ga je niet doen t, je “gaat naarAttachForm("B-46")
omdat elke ontwikkelaar die ooit heeft gewerkt of ooit zal werken daar zal weten dat” B-46 “de formuliercode is voor een enkele belastingbetaler blah blah blah indienen – de formuliercodes maken deel uit van het domein zelf, ze veranderen nooit, dus het zijn “niet echt magische getallen.Je moet dus spaarzaam met constanten omgaan in bedrijfslogica; in feite moet je begrijpen of dat “magische getal” eigenlijk een magisch getal is of dat het “een bekend aspect van het domein is. Als het een domein is, dan moet je het niet programmeren tenzij er een grote kans dat het verandert.
-
Foutcodes en statusvlaggen
Deze zijn nooit oké om hard te coderen, zoals elke arme klootzak die ooit is geraakt met de
Previous action failed due to error code 46
je kan vertellen. Als uw taal dit ondersteunt, zou u een opsommingstype moeten gebruiken. Anders heb je “gewoonlijk een heel bestand / module vol met constanten die de geldige waarden voor een bepaald fouttype specificeren.Laat me nooit
return 42
in een foutafhandelaar, capiche? Geen excuses.
Ik heb waarschijnlijk verschillende scenarios weggelaten, maar ik denk dat dit de meeste ervan dekt.
Dus ja, het is soms acceptabel om te oefenen om dingen hard te coderen. Wees er gewoon niet lui over; het zou een bewuste beslissing moeten zijn in plaats van gewoon oude slordige code.
Opmerkingen
- Bedankt voor de goede uitsplitsing! – de meeste mensen ‘ denken niet na over alle opties die ik zou toevoegen ” Omgevingsconfiguratie ” – Ik denk dat deze moeten worden vermeden (niet hard-coded), aangezien de meeste gegevens in een configuratiebestand of database moeten worden geplaatst. Dit volgt het principe van ” het gescheiden houden van gegevens en logica ” dat een steunpilaar is van MVC of MVVM. string TestServerVar = ” foo “; string ProdServerVal = ” bar “;
Antwoord
Er zijn verschillende redenen om een ID aan een nummer toe te wijzen.
- Als het nummer zou kunnen veranderen, het zou een ID moeten hebben. Het is veel gemakkelijker om NUMBER_OF_PLANETS te vinden dan naar elk exemplaar van 9 te zoeken en te overwegen of het moet worden gewijzigd in 8. (Merk op dat strings moeten mogelijk veranderen als de software ooit in een andere taal moet worden gebruikt, en dat is “moeilijk van tevoren te voorspellen.)
- If het nummer is op geen enkele manier te typen. Voor constanten zoals pi is het beter om één definitie met maximale precisie te geven dan om het op verschillende plaatsen opnieuw te typen, mogelijk onnauwkeurig.
- Als het nummer op verschillende plaatsen voorkomt. Het is niet nodig om naar twee manieren van gebruik van 45 in aangrenzende functies te kijken en je af te vragen of ze hetzelfde betekenen.
- Als de betekenis niet “direct herkenbaar is. Het is veilig om aan te nemen dat iedereen weet wat 3.14159265 … is. Het is niet veilig om aan te nemen dat iedereen zal de gravitatieconstante herkennen, of zelfs pi / 2. (“Iedereen” hangt hier wel af van de aard van de software. Van systeemprogrammeurs kan worden verwacht dat ze de octale representatie van Unix-toestemmingsbits of iets dergelijks kennen. In software voor scheeps- / maritieme architectuur controleert u het Froude-nummer van een voorgestelde romp en kijk of het “1.1 of hoger is, zou volkomen vanzelfsprekend kunnen zijn voor iedereen die eraan zou moeten werken.)
- Als de context niet herkenbaar is . Iedereen weet dat er 60 minuten in een uur zitten, maar vermenigvuldigen of delen door 60 kan onduidelijk zijn als er geen directe aanwijzingen zijn dat de hoeveelheid een tijdswaarde of een koerswaarde is .
Dit geeft ons criteria voor het vastleggen van letterlijke woorden. Ze moeten onveranderlijk zijn, niet moeilijk te typen, slechts op één plaats of in een bepaalde context voorkomen, en met een herkenbare betekenis. Het heeft geen zin bij het definiëren van 0 als bijvoorbeeld ARRAY_BEGINNING, of 1 als ARRAY_INCREMENT.
Antwoord
Als aanvulling op andere antwoorden. Gebruik waar mogelijk constanten voor strings. Je wilt natuurlijk niet
const string server_var="server_var";
hebben, maar je zou moeten hebben
const string MySelectQuery="select * from mytable;";
(ervan uitgaande dat u daadwerkelijk een zoekopdracht heeft waarbij u altijd alle resultaten van een specifieke tabel wilt krijgen)
Gebruik anders constanten voor een ander getal dan 0 (meestal). Als u een bitmasker met toestemming van 255, gebruik niet
const int 8th_bit=255; //or some other obscure naming scheme that equates to 255.
gebruik in plaats daarvan
const int AllowGlobalRead=255;
Weet natuurlijk, samen met constanten, wanneer u enumerators moet gebruiken. Het bovenstaande geval zou er waarschijnlijk goed in passen.
Reacties
- typedef enum {state_0 = 0, state_1 = 1, state_2 = 2, .. .} … Niet ‘ lachen, ik ‘ heb het zien gebeuren. Sla die persoon om het hoofd met een natte vis!
- @snel natuurlijk, je ‘ zou iets meer willen zoals
typedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }
- THIS_NAMING_CONVENTION_IS_RECOMMENDED_FOR_CONSTANTS
- Voor strings hoeft u ‘ niet alleen constanten te gebruiken. U wilt voor de gebruiker zichtbare strings in een soort bronbestand plaatsen (details zijn afhankelijk van uw platform) zodat u gemakkelijk naar een andere taal kunt overschakelen.
- Misschien wilt u ook bedrijfslogica-gerelateerde strings (zoals SQL-querys) in een bronbestand met een soort versleuteling of versluiering. Dat voorkomt dat ” nieuwsgierige ” gebruikers uw logica (of databaseschema) reverse-engineeren.
Answer
Het hangt ervan af wat je als hardcoding beschouwt. Als je alle hardcoded dingen probeert te vermijden, kom je terecht in softcoding -gebied en maak je een systeem dat alleen de maker kan beheren (en dat is het ultieme hardcode)
Veel dingen zijn hard gecodeerd in elk redelijk raamwerk en ze werken. dwz er is geen technische reden waarom ik het toegangspunt van een C # -toepassing niet zou kunnen wijzigen (static void Main ), maar hardcoding die voor geen enkele gebruiker tot problemen leidt (behalve af en toe DUS vraag )
De vuistregel die ik gebruik is dat alles wat kan en zal veranderen, zonder de toestand van het hele systeem te beïnvloeden, confugureerbaar moet zijn.
Dus, IMHO, het “dwaas om dingen die nooit veranderen niet hard te coderen (pi, gravitatieconstante, een constante in een wiskundige formule – denk aan het volume van een bol).
Het is ook “dwaas om dingen of processen die een impact hebben op je systeem die in elk geval moeten worden geprogrammeerd, niet hard te coderen. .e. het is verspilling om de gebruiker in staat te stellen dynamische velden aan een formulier toe te voegen, als voor een toegevoegd veld de onderhoudsontwikkelaar moet ingaan en een script moet schrijven dat ervoor zorgt dat dat ding werkt. Het is ook stom (en ik heb het een paar keer gezien in bedrijfsomgevingen) om een configuratietool te maken, dus niets is hardcoded, maar alleen de ontwikkelaars op de IT-afdeling kunnen het gebruiken, en het is maar een klein beetje eenvoudiger om het te gebruiken dan om het te doen in Visual Studio.
Dus het komt erop neer dat of iets hardcoded moet worden een functie is van twee variabelen:
- verandert de waarde
- hoe zal een verandering in de waarde het systeem beïnvloeden
Antwoord
Is het ooit een goed idee om waarden hard te coderen in onze applicaties?
Ik hardcodeer waarden alleen als de waarden zijn gespecificeerd in de specificatie (op een laatste release van de specificatie), bijv. Het HTTP OK-antwoord zal altijd 200
zijn (tenzij het verandert in de RFC), dus je zult (in sommige van mijn codes) constanten zien zoals:
public static final int HTTP_OK = 200;
Anders sla ik constanten op in het eigenschappenbestand.
De reden waarom ik specificaties heb gespecificeerd, is dat het veranderen van constanten in specificaties wijzigingsbeheer vereist, waarin de belanghebbenden zullen de wijziging beoordelen en goedkeuren / afkeuren. Het gebeurt nooit van de ene op de andere dag en het duurt maanden / jaren voor een goedkeuring. Vergeet niet dat veel ontwikkelaars specificaties gebruiken (bijv. HTTP), dus het veranderen ervan betekent het breken van miljoenen systemen.
Antwoord
- als de waarde kan veranderen, en inderdaad zou kunnen veranderen, codeer deze dan waar mogelijk, zolang de inspanning niet groter is dan het verwachte rendement.
- sommige waarden kunnen niet worden soft-coded; volg de richtlijnen van Jonathan in die (zeldzame) gevallen
Antwoord
Ik heb gemerkt dat elke keer dat u gegevens uit uw code kunt halen, het verbetert wat er nog over is. Je begint nieuwe refactorings op te merken en hele secties van je code te verbeteren.
Het is gewoon een goed idee om te werken aan het extraheren van constanten, beschouw het niet als een domme regel, beschouw het als een kans om te coderen beter.
Het grootste voordeel zou zijn de manier waarop je zou kunnen vinden dat vergelijkbare constanten het enige verschil zijn in groepen code – door ze te abstraheren in arrays heb ik sommige bestanden met 90% van hun grootte kunnen verkleinen en behoorlijk opgelost een paar kopieën & plak bugs in de tussentijd.
Ik “heb nog geen enkel voordeel gezien om geen gegevens te extraheren.
Answer
Ik heb onlangs een MySQL-functie gecodeerd om de afstand tussen twee lat / long-paren correct te berekenen. Je kunt “niet alleen pythagorus doen; lengtegraadlijnen komen dichter bij elkaar naarmate de breedtegraad toeneemt naar de polen, dus er is een soort harige triggering bij betrokken. Punt is, ik was nogal gescheurd over het al dan niet hard coderen van de waarde die de straal van de aarde in mijlen vertegenwoordigt.
Ik heb het uiteindelijk gedaan, ook al zijn de lat / lng-lijnen veel dichter bij elkaar op bijvoorbeeld de maan. En mijn functie zou de afstanden tussen punten op Jupiter drastisch onderschrijven. Ik dacht dat de kans dat de website die ik aan het bouwen ben een buitenaardse locatie krijgt, vrij klein is.
Reacties
- Ja, waarschijnlijk, maar wat over google.com/moon
Antwoord
Het hangt ervan af of je taal is gecompileerd. Als het niet is gecompileerd, maakt het niet uit, je bewerkt gewoon de broncode, zelfs als het een beetje delicaat is voor een niet-programmeur.
Als je programmeert met een gecompileerde taal, is dit duidelijk geen goed idee, want als de variabelen veranderen, moet je opnieuw compileren, wat een grote tijdverspilling is als je deze variabele wilt aanpassen.
Je hoeft geen schuifregelaar of interface te maken om zijn variabele dynamisch te veranderen, maar het minste wat je zou kunnen doen is een tekstbestand.
Bijvoorbeeld met mijn ogre-project gebruik ik altijd de ConfigFile-klasse om een variabele te laden die ik naar een configuratiebestand heb geschreven.
Answer
Twee gevallen waarin constanten (in ieder geval naar mijn mening) OK zijn:
-
Constanten die met niets anders verband houden; u kunt die constanten wanneer u maar wilt wijzigen zonder iets anders te hoeven veranderen. Voorbeeld: de standaardbreedte van een rasterkolom.
-
Absoluut onveranderlijke, precieze, duidelijke constanten, zoals “aantal dagen per week”.
days = weeks * 7
Vervanging van7
door een constanteDAYS_PER_WEEK
levert nauwelijks enige waarde op.
Answer
Ik ben het volledig met Jonathan eens, maar zoals alle regels zijn er uitzonderingen …
“Magisch getal in de specificatie: Magisch getal in de code”
Stelt in feite dat alle magische getallen die in de specificatie achterblijven na redelijke pogingen om een beschrijvende context ervoor te krijgen, moeten als zodanig in de code worden weergegeven. Als er magische getallen in de code blijven, moet alles in het werk worden gesteld om ze te isoleren en ze duidelijk te koppelen aan hun punt van herkomst.
Ik heb een paar interfacing-contracten uitgevoerd waarbij het nodig is om berichten te vullen met in kaart gebrachte waarden uit de database. In de meeste gevallen is het in kaart brengen redelijk rechttoe rechtaan en zou het passen in de algemene richtlijnen van Jonathan, maar ik ben gevallen tegengekomen waarin de doelberichtstructuur gewoon verschrikkelijk was.Meer dan 80% van de waarden die in de structuur moesten worden doorgegeven, waren constanten die werden afgedwongen door de specificatie van het systeem op afstand. Dit in combinatie met het feit dat de berichtstructuur gigantisch was, zorgde ervoor dat er VEEL van dergelijke constanten moesten worden ingevuld. In de meeste gevallen gaven ze geen betekenis of reden, ze zeiden alleen “plaats M hier” of “plaats 4.10.53.10100.889450.4452 hier”. Ik heb ook niet geprobeerd om er een opmerking naast te plaatsen, dit zou de resulterende code onleesbaar hebben gemaakt. Ik heb er echter voor gezorgd dat de codesecties waarin deze magische waarden verschijnen correct geïsoleerd zijn en dat hun containers (klassen, pakketten) de juiste naam hebben om rechtstreeks naar de specificatie te verwijzen die ze afdwingt.
Dat gezegd hebbende, als je nadenkt over het … het gaat er eigenlijk om dat het voor de hand liggend …
Antwoord
Als je de waarde van de gravitatieconstante van de aarde hard codeert, zal het niemand iets kunnen schelen. Als je het IP-adres van je proxyserver hard codeert, krijg je problemen.
Opmerkingen
- Misschien heb je meer precisie nodig voor earth ‘ s gravitatieconstante, dus meerdere keren hardcoderen kan tot problemen leiden.
- Peter Noone? Van Herman ‘ s Hermits ?
- De zwaartekrachtversnelling op aarde is vrijwel 9,81 m / s ^ 2 voor de meeste breedtegraden en hoogten (natuurlijk, als je ‘ op zoek bent naar olie ondergronds, of ICBMs over de Noordpool schieten, wetende dat de variatie in zwaartekracht erg belangrijk is tot veel meer decimalen), waarbij de zwaartekrachtversnelling op andere planeten een ander getal is, maar voor zover ik weet, is de zwaartekrachtconstante constant rond het universum. Er is veel natuurkunde die zou moeten veranderen als g variabel was.
Antwoord
Meestal nee, maar ik denk dat het de moeite waard is om op te merken dat je wi Ik heb de meeste problemen wanneer u begint met het dupliceren van de hardgecodeerde waarde. Als je het niet dupliceert (gebruik het bijvoorbeeld maar één keer bij de implementatie van een klasse), dan is het misschien goed om geen constante te gebruiken.
pi
zou kunnen veranderen …