“Spikat” och “hardkoda” är slangtermer som innebär att värden fixeras direkt i programkoden, istället för att flytta ut dem till inställningar eller konfiguration. Hardkod är ett av de mest kända anti-mönstren inom utveckling, eftersom det minskar kodens flexibilitet och återanvändbarhet. Enligt Refactoring Guru försvårar hardkod testning, underhåll och anpassning av applikationen till olika miljöer. Medveten användning av konstanter istället för hardkod är ett tecken på mogen arkitektur.
Huvudpunkter
Hardkoda (spikat) – bädda in ett specifikt värde i programkoden så att för att ändra det krävs redigering av källkoden och omkompilering av applikationen. Metaforen “spikat” speglar exakt essensen: värdet är fast fixerat och kan endast lossas från koden med ansträngning.
Exempel på hardkod – en server-URL som skrivits som en sträng direkt i funktionens kropp. Om servern flyttas till en annan adress måste utvecklaren hitta strängen i koden, ändra den, bygga om applikationen och lansera en ny version. I en applikation med korrekt arkitektur skulle en sådan URL ha flyttats till en konfigurationsfil, miljövariabel eller konfigurationstjänst.
Termen “spikat” har en mer emotionell klang: den betonar att värdet är fast inbäddat utan möjlighet till snabbt byte. I den svenskspråkiga miljön används båda uttrycken som fullständiga synonymer med negativ klang. Ibland kallas hardkod ironiskt “en konstant som flyttats till en separat konstant från en konstant”.
Hardkod är ett anti-mönster eftersom det bryter mot principerna om underhållbarhet, testbarhet och utbyggbarhet. I kod där värden är “spikade” kräver varje förändring av miljö, design eller logik manuell sökning och ersättning i källorna. Detta ökar risken för fel och saktar ner utvecklingen.
Låt oss titta på de konkreta konsekvenserna av hardkod med exemplet på en typisk mobilapplikation. Om avståndet för alla knappar anges med en siffra i koden, inte via en resurs – kommer en designförändring att kräva att alla förekomster hittas och ersättas. Om endpoint-URL:en är hårt kodad – är växling mellan miljöer (dev, stage, prod) omöjlig utan omkompilering.
| Konsekvens | Beskrivning | Kritiskhetsnivå |
|---|---|---|
| Underhållssvårighet | Förändring kräver sökning i hela koden | Hög |
| Kopieringsfel | Alla förekomster hittas och ersätts inte | Hög |
| Omöjlighet att testa | Testdata kan inte ersättas | Medel |
| Lokaliseringsproblem | Texter i koden översätts inte | Medel |
| Svårare kodgranskning | Granskaren måste komma ihåg alla sammanhang | Låg |
En funktion som använder magiska tal och hårt kodade strängar är en klassiker inom hardkod. Efter en månad kommer författaren inte ihåg vad 18, 0.07 och 2.5 betyder. Efter ett år – ingen i teamet vågar ändra dessa siffror av rädsla för att bryta logiken. Att flytta värden till namngivna konstanter gör koden självdokumenterande.
// Dåligt: magiska tal och strängar
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
}
En hardkodad databas-URL tillåter inte att tester körs på en lokal in-memory-databas. Utvecklaren måste starta en fullständig server eller ändra koden före testning. Att flytta konfiguration ur koden löser problemet: tester använder testparametrar, produktion använder verkliga parametrar och koden ändras inte.
Hardkod är ett anti-mönster, men det finns legitima undantag när ett hårt kodat värde inte bara är tillåtet utan också att föredra. Gränsen går längs variabilitetsaxeln: om värdet aldrig eller nästan aldrig förändras under applikationens livscykel kan det hardkodas. Om det åtminstone potentiellt kan ändras – flytta till konfiguration.
Matematiska och fysikaliska konstanter – Pi, gravitationsaccelerationen, antalet millisekunder i en sekund – är säkra för hardkod. De definieras av naturen eller standarder och kommer inte att ändras. Storlekar på konstanta arrayer som definierats av specifikationen kan också fixeras hårt, men med en kommentar om talets ursprung.
Antalet millisekunder i en sekund är en stabil konstant som definieras av tidsstandarden. Det är meningslöst att flytta den till en konfig, eftersom den aldrig kommer att ändras. Men även sådana konstanter är bättre att deklarera med ett begripligt namn, så att koden inte innehåller “magiska tal”: skriv MILLISECONDS_IN_SECOND istället för 1000.
// Berättigad hardkod: stabila konstanter
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."
}
Det finns flera beprövade metoder för att undvika hardkod, var och en lämplig för sin typ av värde. Valet av alternativ beror på hur ofta värdet ändras och vem som ändrar det: utvecklaren, devops eller slutanvändaren.
För server-URL:er, API-nycklar och feature-flaggor, använd konfigurationsfiler i formaten JSON, YAML eller TOML. På Android är det build.gradle med buildConfigField eller res/values/config.xml. På iOS – Info.plist eller xcconfig. Konfigar byggs tillsammans med applikationen men kan vara olika för olika byggscheman.
För hemligheter (tokens, lösenord) och miljöparametrar, använd miljövariabler. De hamnar inte i repositoryt och kan skilja sig på dev-, stage- och prod-servrar. I mobil utveckling emuleras miljövariabler ofta genom Xcode-byggscheman eller build-flavorer i Gradle.
Strängar, färger, storlekar, bilder bör flyttas till resursfiler: strings.xml på Android, Localizable.strings på iOS, ARB-filer i Flutter. Detta förenklar lokalisering, anpassning till olika skärmar och mörkt läge. Att ändra en sträng i resurser kräver inte omskrivning av kod.
<!-- Android: res/values/strings.xml -->
<resources>
<string name="app_name">MyApp</string>
<string name="api_base_url">https://api.example.com</string>
</resources>
För tjänster och leverantörer, använd Dependency Injection via Dagger, Hilt eller Koin på Android, Swinject på iOS. DI-ramverk möjliggör utbyte av implementeringar i farten – för tester, för olika miljöer, för olika användare. Detta är den högsta abstraktionsnivån, där “spikningen” av värdet ersätts av extern injektion.
Refaktorering av hardkod är processen att flytta hårt kodade värden till konfiguration eller resurser. Det är en av de säkraste refaktoreringsoperationerna, om den utförs metodiskt. Sekvensen som beskrivs nedan är lämplig för alla språk och plattformar.
Sökning kan göras via IDE (Search in Project) eller med ett skript. Sök efter strängar, URL:er, numeriska literal, storlekar, timeout. Särskild uppmärksamhet på upprepande värden: om samma tal förekommer på fem ställen är det en kandidat för att flyttas till en konstant. Använd grep eller inbyggd sökning i IDEA / Xcode.
För varje funnet värde, skapa en konstant med ett meningsfullt namn. Gruppera konstanter efter modul eller klass. Namnet ska förklara vad värdet betyder, inte hur det används: API_TIMEOUT, inte TIMEOUT_30. Efter ersättning ska inget tal i koden lämnas utan förklaring.
// Före: magiskt tal 0.4
let cardHeight = screenHeight * 0.4
// Efter: namngiven konstant
private let cardHeightRatio: CGFloat = 0.4
let cardHeight = screenHeight * cardHeightRatio
Om värdet kan ändras mellan byggen eller miljöer – flytta det till en konfigurationsfil eller applikationsresurser. För strängar, använd lokaliseringsfiler. För URL:er – build config eller xcconfig. För storlekar – resursfiler (dimens.xml på Android). Kontrollera att applikationen kompilerar och fungerar korrekt efter flytten.
Efter refaktorering, skriv ett test som kontrollerar att konfigurationen laddas korrekt och värdena motsvarar förväntningarna. Om någon i framtiden ändrar konfigen, kommer testet att påvisa avvikelsen. Ett konfigurationstest är ett snabbt och tillförlitligt sätt att förhindra regression.
Efter flytt till konfig, kontrollera att alla ställen där det gamla värdet användes hänvisar till en enda källa. Ta bort kommenterad kod och gamla konstanter som inte längre används. Avsluta refaktoreringen med en commit som beskriver vilka värden och vart de har flyttats.
Vanliga frågor
Hardkoda – att skriva ett värde hårt i källkoden istället för att flytta det till konfiguration eller resurser. Detta gör koden mindre flexibel och svårare att underhålla.
Hardkod försvårar ändring av applikationens beteende, hindrar testning, skapar dubbelarbete och ökar risken för kopieringsfel. Ändring av ett hardkodat värde kräver ombyggnad och ny lansering av applikationen.
Tillåtet för matematiska konstanter, stabila värden som inte förändras under applikationens livscykel och för temporära prototyper. I produktion är det bättre att även konstanter flyttas till namngivna variabler.
Hitta alla magiska tal genom sökning, ersätt dem med namngivna konstanter eller flytta till en konfigurationsfil. Skriv ett test som kontrollerar laddning av konfigurationen. Ta bort dubbletter och gör en commit med beskrivning av ändringarna.
Konstant – ett namngivet värde i koden, tillgängligt för ändring på en plats. Hardkod – onamngivna värden utspridda i koden. God praxis: använd alltid namngivna konstanter med meningsfulla namn.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också