Stel je voor: het is 2030, je opdrachtgever belt en wil de analyse van vijf jaar geleden herhalen.
▶Inhoudsopgave
- Waarom dit zo belangrijk is voor onderzoekers
- Wat zijn software-afhankelijkheden eigenlijk?
- Gebruik een package manager en vastlegbestand
- Ga verder dan alleen pakketnamen: leg je hele omgeving vast
- Gebruik versiebeheer voor alles, niet alleen voor code
- Bewaar je omgeving op een toegankelijke plek
- Documenteer ook de niet-digitale context
- Test je reproduceerbaarheid voordat je publiceert
- De kosten van niets doen
- Begin vandaag, niet morgen
- Veelgestelde vragen
Je opent de code, drukt op "run" en… niets werkt. De packages zijn verouderd, de API's bestaan niet meer, en Python 2 is eindelijk helemaal dood. Klinkt als een nachtmerrie?
Het is er een. Maar het is ook volledig te voorkomen. In dit artikel leg je uit hoe je nu al je software-afhankelijkheden vastlegt, zodat jouw onderzoek over vijf, tien of zelfs vijftien jaar nog gewoon draait.
Waarom dit zo belangrijk is voor onderzoekers
Open Science draait om reproduceerbaarheid. Dat betekent niet alleen dat je data goed moet zijn, maar ook dat je hele analyse-omgeving reproduceerbaar moet zijn.
En daar zit het probleem: software verandert voortdurend. Een package die vandaag perfect werkt, kan over een jaar een brengende wijziging hebben doorgevoerd. Of erger: de ontwikkelaar stopt ermee en het hele project verdwijnt van internet.
Als onderzoeker hoef je geen informaticus te zijn om dit op te lossen. Maar je moet wel een paar slimme stappen zetten. En het mooie is: het kost je nu een uur tijd, en bespaart je later weken van frustratie.
Wat zijn software-afhankelijkheden eigenlijk?
Een software-afhankelijkheid is alles wat jouw code nodig heeft om te draaien, behalve je eigen scripts.
Denk aan programmeertalen (Python, R, Julia), bibliotheken (pandas, ggplot2, NumPy), besturingssysteem-tools, en zelfs de versie van je compiler. Hoe complexer je analyse, hoe meer afhankelijkheden je hebt. En elke afhankelijkheid is een potentieel breekpunt. Het verschil tussen een analyse die over tien jaar nog werkt en een die niet werkt, zit hem in hoe je deze afhankelijkheden vastlegt.
Gebruik een package manager en vastlegbestand
De eerste en belangrijkste regel: nooit handmatig software installeren zonder het vast te leggen.
Gebruik altijd een package manager die een exact vastlegbestand genereert. Voor Python werkt je met pip en een requirements.txt bestand, of beter nog, met conda en een environment.yml. Met conda kun je niet alleen Python-pakketten vastleggen, maar ook systeembibliotheken en zelfs de Python-versie zelf. Een opdracht als conda env export > environment.yml slaat je complete omgeving op. Voor R gebruik je het pakket renv.
Dit werkt vergelijkbaar: renv::init() start een projectbibliotheek en renv::snapshot() legt alle versies vast in een renv.lock bestand. Dit bestand bevat zelfs de exacte bron van elk pakket, inclusief de repository-URL. Voor Julia is er Project.toml en Manifest.toml.
De Manifest bevat de exacte versies van alle afhankelijkheden, tot op de patch-niveau.
Dit is een van de meest nauwkeurige systemen die er bestaan. Het cruciale punt: leg niet alleen de pakketnamen vast, maar ook de exacte versies. pandas==2.1.3 is wat je wilt, niet pandas>=2.0.
Ga verder dan alleen pakketnamen: leg je hele omgeving vast
Een vastlegbestand met pakketversies is een goede start, maar het is niet genoeg.
Je besturingssysteem, je programmeertaal-versie, en zelfs hardware-afhankelijke libraries kunnen van invloed zijn op je resultaten. Daarom is de gouden standaard om je complete rekenomgeving vast te leggen. Er zijn drie manieren om dit te doen, van licht tot zwaar:
1. Een Dockerfile: je omgeving als code
Met Docker beschrijf je in een Dockerfile precies welk besturingssysteem je gebruikt, welke software je installeert, en in welke volgorde. Iedereen die dit Dockerfile uitvoert, krijgt exact dezelfde omgeving.
Tools als Docker Desktop maken het relatief eenvoudig om images te bouwen en te delen.
2. Een volledige machine-image met Vagrant
Voor onderzoekers is dit waardevol omdat je het Dockerfile samen met je code kunt bewaren in je repository. Over tien jaar kun je het image nog bouwen, ook als de originele pakketbronnen zijn verdwenen, zolang het Dockerfile zelf maar toegankelijk is. Als je nog meer controle wilt, kun je met Vagrant een complete virtuele machine definiëren. Dit is zwaarder dan Docker, maar geeft je een exacte kopie van een volledig werkende desktop-omgeving.
3. Een conda-lock bestand voor maximale precisie
Dit is vooral handig als je onderzoek afhankelijk is van GUI-applicaties of specifieke systeemconfiguraties. Als je bij conda het commando conda-lock gebruikt, genereert je een lock-bestand met exacte URL's en checksums voor elk pakket.
Dit betekent dat je niet alleen weet welke versie je had, maar ook precies waar het vandaan kwam en of het intact is. Dit is de meest robuuste aanpak binnen het Python-ecosysteem.
Gebruik versiebeheer voor alles, niet alleen voor code
Git is al gangbaar voor code, maar je moet het ook gebruiken voor je afhankelijkheidsbestanden. Leg je requirements.txt, environment.yml, Dockerfile, en renv.lock vast in dezelfde repository als je analysecode. Maak daarbij gebruik van tags.
Wanneer je een analyse afrondt of een paper indient, tag je de repository met een versienummer.
Zo kun je altijd terug naar de exacte staat van zowel je code als je omgeving op dat moment. GitHub, GitLab en Bitbucket ondersteunen dit allemaal.
En platforms zoals Zenodo kunnen automatisch een DOI genereren voor elke release van je GitHub-repository. Dat maakt je werk niet alleen reproduceerbaar, maar ook citeerbaar.
Bewaar je omgeving op een toegankelijke plek
Het vastleggen is de helft. De andere helft is bewaren.
En hier struikelen veel onderzoekers. Je afhankelijkheidsbestanden moeten op minstens twee plekken staan: je versiebeheerrepository en een langetijnbewaarplaats. Zenodo, Figshare, of de DANS Data Station (specifiek voor Nederlandse onderzoekers) zijn uitstekende opties.
Deze platforms garanderen bewaring voor tien jaar of langer, en geven je data een persistente identifier.
Let op: als je Docker-images gebruikt, moet je die ook ergens bewaren. Docker Hub is handig, maar geen langetijnbewaarplaats. Overweeg om je images te pushen naar een registry die gekoppeld is aan je instituut, of om de image-lagen als tarball te exporteren en die te archiveren.
Documenteer ook de niet-digitale context
Dit klinkt misschien verrassend in een artikel over software, maar het is essentieel. Leg bij je repository ook vast: Een simpel README.md bestand met deze informatie, of een Jupyter notebook die over vijf jaar nog werkt, maakt het verschil tussen "iemand kan dit over vijf jaar nog begrijpen" en "dit is een mysterie".
- Welk besturingssysteem je gebruikte (inclusief versie)
- Welke hardware relevant was (bijvoorbeeld GPU-type voor machine learning)
- Welke externe data-bronnen je gebruikte en op welke datum je ze raadpleegde
- Welke API's je aanriep en welke versie van die API actief was
Test je reproduceerbaarheid voordat je publiceert
Dit is de stap die iedereen overslaat, en het is de waardevolste. Voordat je een paper indient of je data deelt, doe je het volgende:
- Maak een lege map aan op een andere computer (of in een virtuele machine)
- Clone je repository
- Volg je eigen instructies om de omgeving op te bouwen
- Run je analyse
- Controleer of de output identiek is
Als dit werkt, heb je bewezen dat je reproduceerbaar. Als het niet werkt, weet je nog aankondiging het te fixen.
Collega's of studenten kunnen ook helpen als "reproduceerbaarheidstester" — laat iemand anders het proberen zonder jouw uitleg.
De kosten van niets doen
Wat gebeurt er als je dit niet doet? De statistieken zijn niet bemoedigend.
Uit onderzoek blijkt dat een groot deel van wetenschappelijke artikelen met code niet reproduceerbaar is, vaak vanwege ontbrekende of verouderde afhankelijkheden.
Dat is niet alleen een probleem voor anderen die je werk willen voortzetten — het is ook een probleem voor jezelf. Onderzoekers die hun eigen werk na een paar jaar niet meer kunnen herhalen, verspillen tijd en middelen. En in het kader van Open Science en de FAIR-principes (Findable, Accessible, Interoperable, Reusable) is het vastleggen van je software-omgeving geen luxe, maar een verantwoordelijkheid.
Begin vandaag, niet morgen
Je hoeft niet alles in één keer perfect te doen. Begin met het meest basale: genereer een vastlegbestand voor je huidige project en leg het bij je code.
Dat kost vijf minuten. Vervolgens kun je stap voor stap Docker toevoegen, lock-bestanden gebruiken, en je bewaring regelen.
De tijd die je nu investeert, betaalt zich terug in gemoedsrust. Want als die bel in 2030 komt, open je gewoon je repository, bouw je je omgeving, en draait je analyse. Zonder zweet. Zonder tranen. Zonder paniek.
Veelgestelde vragen
Waarom is het belangrijk om software-afhankelijkheden vast te leggen voor onderzoek?
Het is cruciaal om software-afhankelijkheden vast te leggen om de reproduceerbaarheid van je onderzoek te waarborgen. Wanneer je onderzoek over vijf, tien of vijftien jaar wordt herzien, is het essentieel dat de software die je hebt gebruikt nog steeds functioneert, zonder dat je zelf de moeite moet doen om alles opnieuw te installeren. Een software-afhankelijkheid omvat alle elementen die je code nodig heeft om te draaien, zoals programmeertalen, bibliotheken en besturingssysteem-tools.
Wat is een software-afhankelijkheid precies, en waarom is het een breekpunt?
Elke afhankelijkheid vormt een potentieel breekpunt, omdat deze kan veranderen, worden verwijderd of ondersteund worden door de ontwikkelaar.
Hoe kan ik software-afhankelijkheden vastleggen voor mijn onderzoek?
Het is dus belangrijk om deze afhankelijkheden te documenteren. Gebruik een package manager, zoals Conda voor Python of Renv voor R, om je projectomgeving vast te leggen.
Wat zijn de voordelen van het gebruik van een requirements.txt of environment.yml bestand?
Deze tools genereren een bestand (bijvoorbeeld een requirements.txt of environment.yml) dat alle benodigde softwareversies en afhankelijkheden bevat, zodat je je omgeving later gemakkelijk kunt reproduceren. Het gebruik van een requirements.txt of environment.yml bestand zorgt ervoor dat je precies dezelfde softwareversies kunt installeren als je ze in het verleden hebt gebruikt. Dit minimaliseert de kans op incompatibiliteiten en zorgt ervoor dat je onderzoek reproduceerbaar blijft, zelfs na jaren.
Welke tools zijn er beschikbaar om software-afhankelijkheden vast te leggen in verschillende programmeertalen?
Voor Python kun je gebruik maken van `pip` en `requirements.txt`, of beter nog `conda` en `environment.yml`.
Voor R is `renv` een goede optie, die een `renv.lock` bestand genereert met alle benodigde versies. Voor Julia zijn `Project.toml` en `Manifest.toml` de juiste tools.