„Vastpinnen“ en „hardcoden“ zijn jargontermen die betekenen dat waarden direct in de programmacode worden vastgezet, in plaats van ze in instellingen of configuratie onder te brengen. Hardcode is een van de bekendste anti-patronen in ontwikkeling, omdat het de flexibiliteit en herbruikbaarheid van code vermindert. Volgens Refactoring Guru bemoeilijkt hardcode het testen, onderhouden en aanpassen van de applicatie aan verschillende omgevingen. Bewust gebruik van constanten in plaats van hardcode is een teken van volwassen architectuur.
Belangrijkste
Hardcoden (vastpinnen) – een specifieke waarde in de programmacode inbouwen zodanig dat voor wijziging ervan de broncode moet worden bewerkt en de applicatie opnieuw moet worden gecompileerd. De metafoor „vastpinnen“ geeft de essentie precies weer: de waarde is stevig vastgezet en kan alleen met moeite van de code worden losgemaakt.
Voorbeeld van hardcode – een server-URL die als string direct in de body van een functie is geschreven. Als de server naar een ander adres verhuist, moet de ontwikkelaar de string in de code vinden, wijzigen, de applicatie opnieuw bouwen en een release uitrollen. In een applicatie met correcte architectuur zou zo'n URL zijn ondergebracht in een configuratiebestand, omgevingsvariabele of configuratiedienst.
De term „vastpinnen“ heeft een meer emotionele lading: het benadrukt dat de waarde stevig is ingevoegd zonder mogelijkheid tot snelle vervanging. In de Nederlandstalige omgeving worden beide uitdrukkingen gebruikt als volledige synoniemen met een negatieve connotatie. Soms wordt hardcode ironisch „een constante die naar een aparte constante uit een constante is verplaatst“ genoemd.
Hardcode is een anti-patroon omdat het de principes van onderhoudbaarheid, testbaarheid en uitbreidbaarheid van code schendt. In code waar waarden „vastgepind“ zijn, vereist elke wijziging van omgeving, ontwerp of logica handmatig zoeken en vervangen in de bronbestanden. Dit verhoogt het risico op fouten en vertraagt de ontwikkeling.
Laten we de concrete gevolgen van hardcode bekijken aan de hand van een typische mobiele applicatie. Als de afstand van alle knoppen is ingesteld met een getal in de code in plaats van via een bron – dan vereist een ontwerpwijziging het vinden en vervangen van alle voorkomens. Als de endpoint-URL hard is gecodeerd – is schakelen tussen omgevingen (dev, stage, prod) onmogelijk zonder hercompilatie.
| Gevolg | Beschrijving | Kritikaliteitsniveau |
|---|---|---|
| Moeilijk onderhoud | Wijziging vereist zoeken in de hele code | Hoog |
| Kopieerfouten | Niet alle voorkomens worden gevonden en vervangen | Hoog |
| Onmogelijkheid tot testen | Testgegevens kunnen niet worden ingevoegd | Gemiddeld |
| Lokalisatieproblemen | Teksten in code worden niet vertaald | Gemiddeld |
| Complexere code-review | Reviewer moet alle contexten onthouden | Laag |
Een functie die magische getallen en hard gecodeerde strings gebruikt, is een klassiek voorbeeld van hardcode. Na een maand herinnert de auteur zich niet meer wat 18, 0.07 en 2.5 betekenen. Na een jaar – durft niemand in het team deze getallen te wijzigen uit angst de logica te breken. Het verplaatsen van waarden naar benoemde constanten maakt de code zelfdocumenterend.
// Slecht: magische getallen en strings
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
}
Een hardgecodeerde database-URL staat niet toe dat tests op een lokale in-memory database worden uitgevoerd. De ontwikkelaar moet een volledige server opzetten of de code aanpassen voor het testen. Het verplaatsen van configuratie uit de code lost het probleem op: tests gebruiken testparameters, productie gebruikt productieparameters en de code verandert niet.
Hardcode is een anti-patroon, maar er bestaan legitieme uitzonderingen waarbij een hard gecodeerde waarde niet alleen is toegestaan, maar zelfs de voorkeur verdient. De grens loopt langs de as van veranderlijkheid: als een waarde nooit of bijna nooit verandert in de levenscyclus van de applicatie, kan deze worden gehardcode. Als deze op zijn minst potentieel kan veranderen – verplaats deze dan naar de configuratie.
Wiskundige en natuurkundige constanten – Pi, zwaartekrachtversnelling, aantal milliseconden in een seconde – zijn veilig voor hardcode. Ze worden gedefinieerd door de natuur of standaarden en zullen niet veranderen. Groottes van constante arrays die door specificatie zijn gedefinieerd, kunnen ook hard worden vastgezet, maar met een opmerking over de oorsprong van het getal.
Het aantal milliseconden in een seconde is een stabiele constante gedefinieerd door de tijdstandaard. Het heeft geen zin om deze naar een config te verplaatsen, omdat deze nooit zal veranderen. Zelfs dergelijke constanten kunnen echter beter met een begrijpelijke naam worden gedeclareerd, zodat de code geen „magische getallen“ bevat: schrijf in plaats van 1000 MILLISECONDS_IN_SECOND.
// Gerechtvaardigde hardcode: stabiele constanten
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."
}
Er zijn verschillende beproefde methoden om hardcode te vermijden, elk geschikt voor een specifiek type waarde. De keuze van het alternatief hangt af van hoe vaak de waarde verandert en wie deze wijzigt: de ontwikkelaar, de devops of de eindgebruiker.
Voor server-URL's, API-sleutels en feature flags gebruik je configuratiebestanden in JSON-, YAML- of TOML-formaat. Op Android is dit build.gradle met buildConfigField of res/values/config.xml. Op iOS – Info.plist of xcconfig. Configs worden samen met de applicatie gebouwd, maar kunnen verschillen voor verschillende buildschema's.
Voor geheimen (tokens, wachtwoorden) en omgevingsparameters gebruik je omgevingsvariabelen. Ze komen niet in de repository terecht en kunnen verschillen op dev-, stage- en prod-servers. In mobiele ontwikkeling worden omgevingsvariabelen vaak geëmuleerd via Xcode-buildschema's of build flavors in Gradle.
Strings, kleuren, afmetingen, afbeeldingen moeten worden ondergebracht in bronbestanden: strings.xml op Android, Localizable.strings op iOS, ARB-bestanden in Flutter. Dit vereenvoudigt lokalisatie, aanpassing aan verschillende schermen en donkere modus. Het wijzigen van een string in bronnen vereist geen herschrijving van code.
<!-- Android: res/values/strings.xml -->
<resources>
<string name="app_name">MyApp</string>
<string name="api_base_url">https://api.example.com</string>
</resources>
Voor services en providers gebruik je Dependency Injection via Dagger, Hilt of Koin op Android, Swinject op iOS. DI-frameworks maken het mogelijk implementaties ter plekke te vervangen – voor tests, voor verschillende omgevingen, voor verschillende gebruikers. Dit is het hoogste abstractieniveau, waarbij het „vastpinnen“ van de waarde wordt vervangen door injectie van buitenaf.
Refactoring van hardcode is het proces van het verplaatsen van hard gecodeerde waarden naar configuratie of bronnen. Dit is een van de veiligste refactoring-operaties, mits deze methodisch wordt uitgevoerd. De hieronder beschreven volgorde is geschikt voor elke taal en platform.
Zoeken kan via IDE (Search in Project) of met een script. Zoek naar strings, URL's, numerieke literals, afmetingen, time-outs. Bijzondere aandacht voor herhalende waarden: als hetzelfde getal op vijf plaatsen voorkomt, is dit een kandidaat voor verplaatsing naar een constante. Gebruik grep of de ingebouwde zoekfunctie van IDEA / Xcode.
Maak voor elke gevonden waarde een constante met een betekenisvolle naam. Groepeer constanten per module of klasse. De naam moet uitleggen wat de waarde betekent, niet hoe deze wordt gebruikt: API_TIMEOUT, niet TIMEOUT_30. Na vervanging mag geen enkel getal in de code zonder uitleg blijven.
// Voor: magisch getal 0.4
let cardHeight = screenHeight * 0.4
// Na: benoemde constante
private let cardHeightRatio: CGFloat = 0.4
let cardHeight = screenHeight * cardHeightRatio
Als de waarde kan veranderen tussen builds of omgevingen – verplaats deze dan naar een configuratiebestand of applicatiebronnen. Gebruik voor strings lokalisatiebestanden. Voor URL's – build config of xcconfig. Voor afmetingen – bronbestanden (dimens.xml op Android). Controleer dat de applicatie correct compileert en werkt na het verplaatsen.
Schrijf na de refactoring een test die controleert dat de configuratie correct wordt geladen en de waarden overeenkomen met de verwachtingen. Als iemand in de toekomst de config wijzigt, wijst de test op de afwijking. Een configuratietest is een snelle en betrouwbare manier om regressie te voorkomen.
Controleer na het verplaatsen naar de config of alle plaatsen waar de oude waarde werd gebruikt naar een enkele bron verwijzen. Verwijder uitgecommentarieerde code en oude constanten die niet meer worden gebruikt. Rond de refactoring af met een commit met een bericht dat beschrijft welke waarden waarheen zijn verplaatst.
Veelgestelde vragen
Hardcoden – een waarde hard in de broncode schrijven in plaats van deze naar configuratie of bronnen te verplaatsen. Dit maakt de code minder flexibel en moeilijker te onderhouden.
Hardcode bemoeilijkt het wijzigen van het applicatiegedrag, belemmert testen, creëert duplicatie en verhoogt het risico op kopieerfouten. Het wijzigen van een hardgecodeerde waarde vereist herbouw en heruitgave van de applicatie.
Toegestaan voor wiskundige constanten, stabiele waarden die niet veranderen in de levenscyclus van de applicatie en voor tijdelijke prototypen. In productie is het beter om zelfs constanten naar benoemde variabelen te verplaatsen.
Vind alle magische getallen door te zoeken, vervang ze door benoemde constanten of verplaats ze naar een configuratiebestand. Schrijf een test die het laden van de configuratie controleert. Verwijder duplicaten en commit met een beschrijving van de wijzigingen.
Constante – een benoemde waarde in de code, toegankelijk voor wijziging op één plaats. Hardcode – onbenoemde waarden verspreid over de code. Goede praktijk: gebruik altijd benoemde constanten met betekenisvolle namen.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook