Je někdy dobrý nápad naprogramovat hodnoty do našich aplikací napevno? Nebo je vždy správné volat tyto typy hodnot dynamicky pro případ, že by bylo potřeba je změnit?
Komentáře
Odpověď
Ano, ale udělejte to zřejmé .
Proveďte:
- použijte konstanty
- použijte popisný název proměnné
Nepoužívejte:
- žádná magická čísla plovoucí kolem kódu
Komentáře
- Což je čistší,
diameter = 2 * radius
nebodiameter = RADIUS_TO_DIAMETER_FACTOR * radius
? Existují opravdu rohové případy, kdy může být magické číslo lepším řešením. - Nemohu ‚ souhlasit tato odpověď je dost. Mám sklon myslet na programování jako na romanopisce. Vyprávíte svůj příběh prostřednictvím kódu a pokud lidé nebudou rozumět logice, bude váš kód podle mého názoru bezcenný. To ‚ Proč jsou dobře promyšlené konvence pojmenování v zásadě čitelné. Neexistuje také žádný dobrý důvod používat magická čísla. Použitím magických čísel odstraníte “ proč “ z rovnice a znesnadnit unders tand. Například: “ diameter = 2 * radius “ K čemu jsou dva? Tento “ diameter = RADIUS_TO_DIAMETER_FACTOR * radius “ dává mnohem větší smysl.
- diameter = 2 * radius is straight from matematika na střední škole. Důvodem pro nepojmenování “ 2 “ je to, že mít hodnotu čehokoli jiného by vyžadovalo změnu zákonů fyzika nebo matematika nebo obojí. (Na druhou stranu, pojmenování Pi nebo Planckova konstanta je dobrý krok pro snadnou čitelnost).
- @Joonas: Pfft. Určitě myslíte
diameter = radius << 1
? Předpokládám, že by to mohlo být takédiameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT
. - jak ‚ o něco
diameter = radius.toDiameter()
Odpověď
Co mi na tom Q připadá divné Q & Zatím se nikdo nepokusil jasně definovat „hard-code“ nebo, co je důležitější, alternativy.
tl; dr : Ano, je někdy dobré naprogramovat hodnoty napevno, ale neexistuje jednoduché pravidlo kdy ; záleží zcela na kontextu.
Otázka to zúží na hodnoty , což chápu jako magická čísla , ale odpověď na to, zda „jsou dobrý nápad, je relativní k tomu, k čemu skutečně slouží!
Několik příkladů„ pevně zakódovaných “ „hodnoty jsou:
-
konfigurační hodnoty
Krčím se, kdykoli vidím prohlášení jako
command.Timeout = 600
. Proč 600? Kdo o tom rozhodl? Bylo to dříve načasování a někdo zvýšil časový limit jako hack místo toho, aby opravil základní problém s výkonem? Nebo je to vlastně nějaké známé a zdokumentované očekávání doby zpracování?Neměla by to být magická čísla nebo konstanty, měla by být externalizována v konfiguračním souboru nebo databázi někde s smysluplný název, protože jejich optimální hodnota je určena převážně nebo úplně prostředím, ve kterém aplikace běží.
-
Matematické vzorce
Vzorce obvykle bývají docela statické, takže povaha konstantních hodnot uvnitř není opravdu zvlášť důležitá. Objem pyramidy je (1/3) b * h. Záleží nám na tom, odkud pochází 1 nebo 3? Spíš ne. Předchozí komentátor správně poukázal na to, že
diameter = radius * 2
je pravděpodobně lepší neždiameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR
– ale to je falešná dichotomie.Co byste měli pro tento typ scénáře dělat, je vytvoření funkce . Nepotřebuji vědět, jak jsi přišel s tímto vzorcem, ale stále potřebuji vědět k čemu to je . Pokud namísto kteréhokoli z výše uvedených nesmyslů napíšu
volume = GetVolumeOfPyramid(base, height)
, najednou se vše stane mnohem jasnějším a je naprosto v pořádku mít magická čísla uvnitř funkce (return base * height / 3
), protože je zřejmé, že jsou pouze součástí vzorce.Klíčem zde samozřejmě je krátké a jednoduché funkce. To nefunguje u funkcí s 10 argumenty a 30 řádky výpočtů. V takovém případě použijte složení funkce nebo konstanty.
-
Doménová / obchodní pravidla
Toto je vždy šedá oblast, protože záleží na tom, co přesně je hodnota. Většinou času jsou to právě tato magická čísla, která jsou kandidáty na přeměnu na konstanty, protože to usnadňuje pochopení programu bez komplikování logiky programu. Zvažte test
if Age < 19
vs.if Age < LegalDrinkingAge
; pravděpodobně můžete zjistit, co se děje bez konstanty, ale s popisem je to jednodušší title.Tito se mohou také stát kandidáty na abstrakci funkcí, například
function isLegalDrinkingAge(age) { return age >= 19 }
. Jediná věc je, že často je vaše obchodní logika mnohem komplikovanější než to a nemusí mít smysl začít psát desítky funkcí s 20 až 30 parametry. Pokud není jasná abstrakce založená na objektech a / nebo funkcích, uchýlení se ke konstantám je v pořádku.Upozornění je, že pokud pracujete pro daňové oddělení, stane se skutečně opravdu obtížným a upřímně zbytečným psát
AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR)
. Ty to nebudeš dělat t, chystáte seAttachForm("B-46")
protože každý vývojář, který tam kdy pracoval nebo tam bude pracovat, bude vědět, že „B-46“ je kód formuláře pro jednoho daňového poplatníka podání bla bla bla – kódy formulářů jsou součástí samotné domény, nikdy se nemění, takže nejde o skutečně magická čísla.Takže v obchodní logice musíte konstanty používat střídmě; v zásadě musíte pochopit, zda to „magické číslo“ je nebo není ve skutečnosti magickým číslem, nebo jestli je to známý aspekt domény. Pokud je to doména, pak ji „soft-code“ neprovedete, pokud zde není opravdu velká šance, že se to změní.
-
Chybové kódy a stavové příznaky
Toto jsou nikdy v pořádku s pevným kódem, jak vám může říci každý ubohý bastard, který byl někdy zasažen
Previous action failed due to error code 46
. Pokud to váš jazyk podporuje, měli byste používat typ výčtu. Jinak obvykle budete mít celý soubor / modul plný konstant specifikujících platné hodnoty pro konkrétní typ chyby.Nikdy mi nedovolte zobrazit
return 42
v obslužné rutině chyb, capiche? Žádné výmluvy.
Pravděpodobně jsem vynechal několik scénářů, ale myslím, že pokrývá většinu z nich.
Takže ano, někdy je to přijatelná praxe na pevný kód. Jen na to nebuďte líní; mělo by to být vědomé rozhodnutí, nikoli obyčejný starý nedbalý kód.
Komentáře
- Díky za dobrý rozpis! – většina lidí si ‚ nepřemýšlí nad všemi možnostmi, které bych přidal “ Konfigurace prostředí “ – myslím, že je třeba se jim vyhnout (nikoli napevno), protože většina dat by měla být vložena do konfiguračního souboru nebo databáze. Vyplývá to z principu “ udržování oddělených dat a logiky „, což je základ MVC nebo MVVM. řetězec TestServerVar = “ foo „; řetězec ProdServerVal = “ bar „;
odpověď
Přiřazení identifikátoru k číslu má různé důvody.
- Pokud se číslo může změnit, měl by mít identifikátor. Je mnohem snazší najít NUMBER_OF_PLANETS, než hledat každou instanci 9 a zvážit, zda by měla být změněna na 8. (Všimněte si, že viditelné pro uživatele Je možné, že se řetězce budou muset změnit, pokud bude software někdy použit v jiném jazyce, a to je těžké předem předvídat.)
- Pokud číslo se těžko jakýmkoli způsobem zadává. U konstant jako pi je lepší dát jednu definici s maximální přesností, než ji přepsat na několik míst, možná nepřesně.
- Pokud se číslo vyskytuje na různých místech. Neměli byste se muset dívat na dvě použití 45 v sousedních funkcích a zajímat se, zda znamenají totéž.
- Pokud význam není okamžitě rozpoznatelný. Je bezpečné předpokládat, že každý ví, co je 3.14159265 … Není bezpečné předpokládat, že každý pozná gravitační konstantu, nebo dokonce pi / 2. („Všichni zde závisejí na povaze softwaru. Lze očekávat, že programátoři systémů budou znát osmičkové zastoupení bitů povolení Unix apod. V softwaru pro námořní / námořní architekturu je třeba zkontrolovat Froudeovo číslo navrhovaného trupu a rychlost zjistěte, zda je to verze 1.1 nebo vyšší, může být zcela vysvětlující každému, kdo by na tom měl pracovat.)
- Pokud kontext není rozpoznatelný . Každý ví, že za hodinu je 60 minut, ale vynásobení nebo dělení 60 může být nejasné, pokud neexistují okamžité náznaky, že veličinou je časová hodnota nebo hodnota rychlosti .
Toto nám dává kritéria pro pevně zakódované literály. Měly by být neměnné, neměly by se těžko psát, vyskytovat se pouze na jednom místě nebo v kontextu a s rozpoznatelným významem. Nemá smysl při definování například 0 jako ARRAY_BEGINNING nebo 1 jako ARRAY_INCREMENT.
Odpověď
Jako doplněk k dalším odpovědím. Pokud je to možné, použijte pro řetězce konstanty. Samozřejmě, že nechcete mít
const string server_var="server_var";
, ale měli byste mít
const string MySelectQuery="select * from mytable;";
(za předpokladu, že ve skutečnosti máte dotaz, kde chcete získat všechny výsledky z konkrétní tabulky, vždy)
Kromě toho použijte konstanty pro jakékoli jiné číslo než 0 (obvykle). Pokud potřebujete bitová maska oprávnění 255, nepoužívejte
const int 8th_bit=255; //or some other obscure naming scheme that equates to 255.
místo toho používejte
const int AllowGlobalRead=255;
Samozřejmě spolu s konstantami víte, kdy použít enumerátory. Výše uvedený případ by pravděpodobně dobře zapadl do jednoho.
Komentáře
- typedef enum {state_0 = 0, state_1 = 1, state_2 = 2, .. .} … směj se ‚, viděl jsem to ‚ hotové. Udeřte toho člověka do hlavy mokrou rybou!
- @ rychle, samozřejmě, že ‚ chcete něco podobného
typedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }
- THIS_NAMING_CONVENTION_IS_RECOMMENDED_FOR_CONSTANTS
- U řetězců nechcete ‚ prostě chtít konstanty. Chcete vložit jakýkoli uživatelsky viditelný řetězec do nějakého souboru prostředků (podrobnosti budou záviset na vaší platformě), abyste mohli snadno přejít na jiný jazyk.
- Můžete také chtít uvést související s obchodní logikou řetězce (jako dotazy SQL) v souboru prostředků s nějakým druhem šifrování nebo zamlžování. To zabrání “ zvědavým “ uživatelům zpětně analyzovat vaši logiku (nebo databázové schéma).
Odpověď
Záleží na tom, co považujete za hardcoding. Pokud se pokusíte vyhnout se všem pevně zakódovaným věcem, dostanete se na softcoding území a vytvoříte systém, který bude moci spravovat pouze tvůrce (a to je ultimate hardcode)
Spousta věcí je napevno zakódována v jakémkoli rozumném rámci a fungují. tj. neexistuje žádný technický důvod, proč bych neměl být schopen změnit vstupní bod aplikace C # (static void Main ), ale hardcoding, který nevytváří žádné problémy pro žádného uživatele (kromě příležitostných SO question )
Pravidlo, které používám, je že vše, co se může a bude měnit, aniž by to ovlivnilo stav celého systému, by mělo být konfigurovatelné.
Takže IMHO je hloupé nekódovat věci, které se nikdy nemění (pi, gravitační konstanta, konstanta v matematickém vzorci – uvažujte o objemu koule).
Také je hloupé nekódovat věci nebo procesy, které budou mít dopad na váš systém a které budou v každém případě vyžadovat programování, tzn. Je to zbytečné umožnit uživateli přidávat dynamická pole do formuláře, pokud by nějaké přidané pole vyžadovalo, aby vývojář údržby vstoupil a napsal nějaký skript, díky kterému bude tato věc fungovat. Je také hloupé (a několikrát jsem to viděl v podnikových prostředích) vytvořit nějaký konfigurační nástroj, takže nic není napevno zakódováno, ale mohou ho používat pouze vývojáři v IT oddělení a je to jen o něco jednodušší použít to, než to udělat ve Visual Studiu.
Takže spodní řádek, zda má být věc pevně zakódována, je funkcí dvou proměnných:
- změní se hodnota
- jak změna hodnoty ovlivní systém
odpověď
Je někdy dobrý nápad naprogramovat hodnoty do našich aplikací napevno?
Hodnoty napevno zakóduji pouze , pokud jsou hodnoty jsou specifikovány ve specifikaci (při finálním vydání specifikace), např. Odpověď HTTP OK bude vždy 200
(pokud se nezmění v RFC), takže uvidíte (v některých mých kódech) konstanty jako:
public static final int HTTP_OK = 200;
Jinak ukládám konstanty do souboru vlastností.
Důvod, proč jsem specifikoval specifikaci, je ten, že změna konstant ve specifikacích vyžaduje správu změn, ve které zúčastněné strany změnu zkontrolují a schválí / zamítnou. Nikdy se to nestane přes noc a schválení trvá měsíce / roky. Nezapomeňte, že mnoho vývojářů používá specifikace (např. HTTP), takže jejich změna znamená rozbití milionů systémů.
Odpověď
- pokud se hodnota může změnit, a skutečně se může změnit, pak ji soft-kódujte, kdykoli je to možné, pokud vynaložené úsilí nepřekročí očekávanou návratnost
- některé hodnoty nelze měkké kódování; v těchto (vzácných) případech postupujte podle pokynů Jonathana
Odpověď
Všiml jsem si že kdykoli můžete z kódu extrahovat data, vylepšuje to, co zbylo. Začnete si všímat nových refaktorů a vylepšujete celé části svého kódu.
Je to dobrý nápad pracovat na extrakci konstant, nepovažujte to za nějaké hloupé pravidlo, nepřemýšlejte o tom jako o příležitosti kódovat lepší.
Největší výhodou by byl způsob, jakým byste mohli najít podobné konstanty jako jediný rozdíl ve skupinách kódu – jejich abstrahování do polí mi pomohlo snížit některé soubory o 90% jejich velikosti a docela je opravit několik kopií & mezitím vložte chyby.
Ještě nevidím jedinou výhodu v tom, že nebudu extrahovat data.
Odpověď
Nedávno jsem kódoval funkci MySQL, abych správně vypočítal vzdálenost mezi dvěma páry lat / long. Nelze udělat pythagorus; čáry zeměpisné délky se přibližují k sobě, jak se zeměpisná šířka zvětšuje směrem k pólům, takže je zapojena nějaká chlupatá spoušť. Jde o to, že jsem byl dost roztrhaný, zda napevno naprogramovat hodnotu představující poloměr Země v mílích.
Nakonec jsem to udělal, i když ve skutečnosti jsou čáry lat / lng mnohem blíže k sobě, řekněme na Měsíci. A moje funkce by drasticky podhodnocovala vzdálenosti mezi body na Jupiteru. Zjistil jsem, že šance, že webová stránka, která má mimozemské umístění, do které vstoupím, je docela malá.
Komentáře
- Ano, pravděpodobně, ale co o google.com/moon
odpovědi
Záleží na tom, zda je váš jazyk kompilován. Pokud není kompilován, nejde o velký problém, pouze upravíte zdrojový kód, i když pro neprogramátora bude mírně choulostivý.
Pokud programujete s kompilovaným jazykem, zjevně to není dobrý nápad, protože pokud se proměnné změní, musíte je překompilovat, což je velká ztráta času, pokud chcete tuto proměnnou upravit.
Pro dynamickou změnu jeho proměnné nepotřebujete nějaký posuvník nebo rozhraní, ale to nejmenší, co můžete udělat, je textový soubor.
Například u mého projektu Ogre vždy používám třída ConfigFile pro načtení proměnné, kterou jsem zapsal do konfiguračního souboru.
Odpověď
Dvě příležitosti, kdy jsou konstanty (alespoň podle mého názoru) v pořádku:
-
Konstanty, které se netýkají ničeho jiného; tyto konstanty můžete kdykoli změnit, aniž byste museli měnit cokoli jiného. Příklad: Výchozí šířka sloupce mřížky.
-
Absolutně neměnné, přesné a zjevné konstanty, například „počet dní v týdnu“.
days = weeks * 7
Nahrazení7
konstantouDAYS_PER_WEEK
sotva poskytuje žádnou hodnotu.
Odpověď
Souhlasím úplně s Jonathanem, ale jako všechna pravidla existují výjimky …
„Magické číslo ve specifikaci: Magické číslo v kódu“
V podstatě uvádí, že jakákoli magická čísla, která zůstanou ve specifikaci po rozumných pokusech získat pro ně popisný kontext, by se měla v kódu promítnout jako taková. Pokud v kódu zůstanou magická čísla, je třeba vyvinout veškeré úsilí k jejich izolaci a jasnému propojení s jejich počátkem.
Provedl jsem několik kontraktů o propojení, kde je nutné naplnit zprávy mapovanými hodnotami z databáze. Ve většině případů je mapování poměrně přímé a zapadalo by do obecných vodicích linií Jonathana, ale setkal jsem se s případy, kdy byla struktura cílové zprávy prostě hrozná.Více než 80% hodnot, které musely být předány ve struktuře, byly konstanty vynucené specifikací vzdáleného systému. toto spolu se skutečností, že struktura zprávy byla gargantuan, způsobilo, že MNOŽSTVÍ takových konstant muselo být naplněno. Ve většině případů neposkytli smysl ani důvod, pouze řekli „sem vložte M“ nebo „sem vložte 4.10.53.10100.889450.4452“. Nepokusil jsem se ani dát komentář vedle všech z nich, výsledný kód by byl nečitelný. Ujistil jsem se však, že sekce kódu, kde se tyto magické hodnoty objevují, jsou správně izolované a že jejich kontejnery (třídy, balíčky) jsou pojmenovány vhodným způsobem, aby ukazovaly přímo na jejich specifikaci.
to … jde hlavně o to, aby to bylo zřejmé …
odpověď
Pokud napíšete pevně hodnotu gravitační konstanty Země, nebude to nikoho zajímat. Pokud napevno napíšete IP adresu svého proxy serveru, máte problémy.
Komentáře
- Možná budete potřebovat větší přesnost pro earth ‚ s gravitační konstanta, takže její pevné zakódování by několikrát mohlo vést k problémům.
- Peter Nikdo? Od Hermana ‚ s Hermits ?
- Gravitační zrychlení na Zemi je pro většinu zeměpisných šířek a nadmořských výšek celkem 9,81 m / s ^ 2 (samozřejmě, pokud ‚ hledáte ropu v podzemí, nebo střelba ICBM nad severním pólem, znalost gravitačních odchylek je velmi důležitá na mnohem více desetinných míst), přičemž gravitační zrychlení na jiných planetách je jiné číslo, ale pokud vím, gravitační konstanta je konstantní kolem vesmíru. Existuje spousta fyziky, která by se musela změnit, pokud by g bylo proměnné.
Odpověď
Většinou ne, ale myslím, že stojí za zmínku, že wi Když začnete duplikovat pevně zakódovanou hodnotu, budete mít nejvíce problémů. Pokud jej neduplikujete (např. Nepoužíváte ji při implementaci třídy jen jednou), pak by nemuselo být použití konstanty v pořádku.
pi
může změnit …