„Přibít hřebíky“ a „hardcode“ jsou slangové výrazy znamenající pevné ukotvení hodnot přímo v kódu programu, místo jejich přesunutí do nastavení nebo konfigurace. Hardcode je jedním z nejznámějších anti-vzorů ve vývoji, protože snižuje flexibilitu a znovupoužitelnost kódu. Podle Refactoring Guru hardcode komplikuje testování, údržbu a přizpůsobení aplikace různým prostředím. Vědomé používání konstant místo hardcode je známkou zralé architektury.
Hlavní
Hardcode (přibít hřebíky) – vložit konkrétní hodnotu do kódu programu tak, že pro její změnu je třeba upravit zdrojový kód a znovu zkompilovat aplikaci. Metafora „přibít hřebíky“ přesně odráží podstatu: hodnota je pevně fixovaná a lze ji od kódu oddělit pouze s námahou.
Příklad hardcode – URL serveru zapsané jako řetězec přímo v těle funkce. Pokud se server přesune na jinou adresu, vývojář musí najít řetězec v kódu, změnit jej, znovu sestavit aplikaci a vydat novou verzi. V aplikaci se správnou architekturou by takové URL bylo přesunuto do konfiguračního souboru, proměnné prostředí nebo konfigurační služby.
Termín „přibít hřebíky“ má emocionálnější nádech: zdůrazňuje, že hodnota je vložena pevně a bez možnosti rychlé výměny. V českém prostředí se oba výrazy používají jako úplná synonyma s negativní konotací. Někdy se hardcode ironicky nazývá „konstanta přesunutá do samostatné konstanty z konstanty“.
Hardcode je anti-vzor, protože porušuje principy udržovatelnosti, testovatelnosti a rozšiřitelnosti kódu. V kódu, kde jsou hodnoty „přibité hřebíky“, každá změna prostředí, designu nebo logiky vyžaduje ruční vyhledávání a nahrazování ve zdrojích. To zvyšuje riziko chyb a zpomaluje vývoj.
Podívejme se na konkrétní důsledky hardcode na příkladu typické mobilní aplikace. Pokud je mezera všech tlačítek dána číslem v kódu, nikoli prostřednictvím zdroje – změna designu bude vyžadovat nalezení všech výskytů a jejich nahrazení. Pokud je URL endpointu pevně zapsáno – přepínání mezi prostředími (dev, stage, prod) není možné bez překompilování.
| Důsledek | Popis | Úroveň kritičnosti |
|---|---|---|
| Obtížnost údržby | Změna vyžaduje prohledání celého kódu | Vysoká |
| Chyby při kopírování | Ne všechny výskyty jsou nalezeny a nahrazeny | Vysoká |
| Nemožnost testování | Nelze dosadit testovací data | Střední |
| Problémy s lokalizací | Texty v kódu se nepřekládají | Střední |
| Ztížení code-review | Kontrolující si musí pamatovat všechny kontexty | Nízká |
Funkce, která používá magická čísla a pevně zapsané řetězce, je klasikou hardcode. Po měsíci si autor nebude pamatovat, co znamená 18, 0.07 a 2.5. Po roce – nikdo v týmu se neodváží tato čísla měnit, ze strachu, že zlomí logiku. Přesunutí hodnot do pojmenovaných konstant činí kód samodokumentující.
// Špatně: magická čísla a řetězce
fun calculatePrice(base: Double): Double {
val tax = base * 0.07
val tip = base * 0.15
val discount = if (base > 100) 10 else 0
return base + tax + tip - discount
}
Hardcode URL databáze neumožní spouštět testy na lokální in-memory databázi. Vývojář bude muset spustit plnohodnotný server nebo upravit kód před testováním. Přesunutí konfigurace z kódu řeší problém: testy používají testovací parametry, produkce produkční parametry a kód se přitom nemění.
Hardcode je anti-vzor, ale existují legitimní výjimky, kdy pevně zapsaná hodnota není jen povolena, ale je preferována. Hranice prochází podél osy proměnlivosti: pokud se hodnota nikdy nebo téměř nikdy nemění během životního cyklu aplikace, lze ji hardcode. Pokud se alespoň potenciálně může změnit – přesuňte do konfigurace.
Matematické a fyzikální konstanty – číslo Pí, gravitační zrychlení, počet milisekund v sekundě – jsou pro hardcode bezpečné. Jsou definovány přírodou nebo standardy a nezmění se. Velikosti konstantních polí definované specifikací lze také pevně fixovat, ale s komentářem o původu čísla.
Počet milisekund v sekundě je stabilní konstanta definovaná časovým standardem. Nemá smysl ji přesouvat do konfigu, protože se nikdy nezmění. Nicméně i takové konstanty je lepší deklarovat s pochopitelným názvem, aby kód neobsahoval „magická čísla“: místo 1000 napište MILLISECONDS_IN_SECOND.
// Oprávněný hardcode: stabilní konstanty
private const val MILLIS_IN_SECOND = 1000
private const val LOGIN_TIMEOUT_SECONDS = 30
fun formatDuration(ms: Long): String {
val seconds = ms / MILLIS_IN_SECOND
return "${seconds} sec."
}
Existuje několik osvědčených způsobů, jak se vyhnout hardcode, z nichž každý je vhodný pro svůj typ hodnot. Výběr alternativy závisí na tom, jak často se hodnota mění a kdo ji mění: vývojář, devops nebo koncový uživatel.
Pro URL serverů, API klíče a feature flagy používejte konfigurační soubory ve formátech JSON, YAML nebo TOML. Na Androidu je to build.gradle s buildConfigField nebo res/values/config.xml. Na iOS – Info.plist nebo xcconfig. Konfigy se sestavují spolu s aplikací, ale mohou být různé pro různá schémata sestavení.
Pro tajemství (tokeny, hesla) a parametry prostředí používejte proměnné prostředí. Ty se nedostanou do repozitáře a mohou se lišit na dev, stage a prod serverech. V mobilním vývoji se proměnné prostředí často emulují pomocí Xcode schémat sestavení nebo build flavorů v Gradlu.
Řetězce, barvy, velikosti, obrázky by měly být přesunuty do souborů zdrojů: strings.xml na Androidu, Localizable.strings na iOS, ARB soubory ve Flutteru. To zjednodušuje lokalizaci, přizpůsobení různým obrazovkám a tmavému režimu. Změna řetězce ve zdrojích nevyžaduje přepisování kódu.
<!-- Android: res/values/strings.xml -->
<resources>
<string name="app_name">MyApp</string>
<string name="api_base_url">https://api.example.com</string>
</resources>
Pro služby a poskytovatele používejte Dependency Injection přes Dagger, Hilt nebo Koin na Androidu, Swinject na iOS. DI frameworky umožňují výměnu implementací za běhu – pro testy, pro různá prostředí, pro různé uživatele. To je nejvyšší úroveň abstrakce, kde je „přibití“ hodnoty nahrazeno vkládáním zvenčí.
Refaktorování hardcode je proces přesouvání pevně zapsaných hodnot do konfigurace nebo zdrojů. Je to jedna z nejbezpečnějších refaktorovacích operací, pokud se provádí metodicky. Níže popsaná sekvence je vhodná pro jakýkoli jazyk a platformu.
Vyhledávání lze provést pomocí IDE (Search in Project) nebo skriptem. Hledejte řetězce, URL, číselné literály, velikosti, časové limity. Zvláštní pozornost věnujte opakujícím se hodnotám: pokud se stejné číslo objevuje na pěti místech, je to kandidát na přesun do konstanty. Použijte grep nebo vestavěné vyhledávání IDEA / Xcode.
Pro každou nalezenou hodnotu vytvořte konstantu s výstižným názvem. Seskupte konstanty podle modulů nebo tříd. Název by měl vysvětlovat, co hodnota znamená, ne jak se používá: API_TIMEOUT, ne TIMEOUT_30. Po nahrazení by žádné číslo v kódu nemělo zůstat bez vysvětlení.
// Před: magické číslo 0.4
let cardHeight = screenHeight * 0.4
// Po: pojmenovaná konstanta
private let cardHeightRatio: CGFloat = 0.4
let cardHeight = screenHeight * cardHeightRatio
Pokud se hodnota může měnit mezi sestaveními nebo prostředími – přesuňte ji do konfiguračního souboru nebo zdrojů aplikace. Pro řetězce používejte lokalizační soubory. Pro URL – build config nebo xcconfig. Pro velikosti – soubory zdrojů (dimens.xml na Androidu). Zkontrolujte, že se aplikace po přesunutí správně sestavuje a funguje.
Po refaktorování napište test, který kontroluje, že se konfigurace načítá správně a hodnoty odpovídají očekávaným. Pokud v budoucnu někdo změní konfig, test upozorní na nesoulad. Test konfigurace je rychlý a spolehlivý způsob, jak zabránit regresi.
Po přesunutí do konfigu zkontrolujte, že všechna místa, kde se používala stará hodnota, odkazují na jednotný zdroj. Odstraňte zakomentovaný kód a staré konstanty, které se již nepoužívají. Dokončete refaktorování commitem se zprávou popisující, jaké hodnoty a kam byly přesunuty.
Často kladené otázky
Hardcode – pevně zapsat hodnotu do zdrojového kódu místo přesunutí do konfigurace nebo zdrojů. To činí kód méně flexibilním a obtížněji udržovatelným.
Hardcode ztěžuje změnu chování aplikace, brání testování, vytváří duplicitu a zvyšuje riziko chyb při kopírování. Změna hardcode hodnoty vyžaduje překompilování a nové vydání aplikace.
Povolen pro matematické konstanty, stabilní hodnoty, které se nemění během životního cyklu aplikace, a pro dočasné prototypy. V produkci je lepší i konstanty přesouvat do pojmenovaných proměnných.
Najděte všechna magická čísla pomocí vyhledávání, nahraďte je pojmenovanými konstantami nebo je přesuňte do konfiguračního souboru. Napište test kontrolující načítání konfigurace. Odstraňte duplikáty a udělejte commit s popisem změn.
Konstanta – pojmenovaná hodnota v kódu, přístupná pro změnu na jednom místě. Hardcode – nepojmenované hodnoty rozptýlené po kódu. Dobrá praxe: vždy používejte pojmenované konstanty s výstižnými názvy.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také