ArtikelSoftware Engineering

Je code vertelt hoe het werkt, niet waarom

De redenen achter de keuzes in je code staan nergens opgeschreven. Dat kost jou, je team en je AI-agent later veel tijd. Met één kort bestand voorkom je dat.

Open een project dat je een half jaar geleden hebt gebouwd en probeer je eigen keuzes maar eens uit te leggen. Waarom zit er een extra controle in die ene functie? Waarom heb je deze library gekozen en niet die andere? Waarom staat de database-logica in een aparte module? Grote kans dat je het niet meer weet, terwijl je het zelf hebt geschreven.

Over dat probleem gaat dit artikel. Want code laat perfect zien hoe een systeem werkt, maar nergens staat waarom het systeem zo is gebouwd. Dit kan je oplossen in één kort bestand waarin je de redenen achter je keuzes opschrijft. Dat kost je een uur om te maken, maar het scheelt jou, eventueel je team en je AI-agent later veel uitzoekwerk.

Techitem_Je code vertelt hoe het werkt, niet waarom_1920x1080

Waarom niemand die redenen opschrijft

Tijdens het bouwen voelt opschrijven overbodig. Je hebt het complete plaatje in je hoofd: wat het systeem moet doen, hoe de onderdelen samenhangen en waarom je het zo hebt aangepakt. De taken staan in een tool en de rest zit in de chatgeschiedenis met je AI-agent. Maar een half jaar later is dat plaatje weg. Taken en prompts vertellen niet waarom je iets hebt gedaan. Wat overblijft is de code.

Drie ‘lezers’ hebben die redenen (het waarom) wel nodig en kunnen ze nu nergens vinden. De eerste ben jij, over een paar maanden. De tweede is (als je in een organisatie werkt) je team: en mensen komen en gaan terwijl het systeem blijft. Op een dag durft niemand meer iets te veranderen omdat niemand weet welke keuzes belangrijk waren. De derde is je AI-agent. Die leest je hele codebase in seconden, maar de redenen achter je keuzes vindt hij nergens. Dus vult hij ze zelf in en niet altijd zoals jij het bedoelde.

Misschien laat je je agent al een README of een notitiebestand bijhouden. Dat is slim, maar kijk eens wat erin staat. Waarschijnlijk beschrijft het wat de code doet, welke modules er zijn en hoe je het project start. Dat is uitleg over hoe het werkt. Die uitleg kun je ook in de code zelf lezen. Wat er zelden in staat is welk probleem je oplost, welke beperkingen vastliggen, wanneer het systeem goed genoeg is en welke keuzes je bewust hebt gemaakt. Dat kan een agent niet uit je code halen, want het staat er simpelweg niet in. En dus dat moet jij opschrijven.

De vijf vragen die je beantwoordt

Die vijf vragen komen uit arc42, een open template voor architectuurdocumentatie dat Michaël Hompus, IT-architect bij Info Support, al zeven jaar gebruikt. Het volledige template heeft twaalf hoofdstukken. Je begint met vijf vragen, elk in een paar zinnen beantwoord, in een Markdown-tekstbestand naast je code, bijvoorbeeld ARCHITECTURE.md.

1. Wat bouw je, voor wie en waarom? Welk probleem lost het systeem op en voor wie? Schrijf ook op wat het systeem uitdrukkelijk niet doet. Dat scheelt eindeloze discussies over features die er niet in horen.

2. Welke beperkingen liggen al vast? De programmeertaal die het team kent, het platform waarop het moet draaien, de regels van de organisatie. Alles waar je niet omheen kunt, en wat dat betekent voor wat je bouwt.

3. Uit welke onderdelen bestaat het? De drie tot vijf grote onderdelen, hoe ze met elkaar en met de buitenwereld communiceren en één scenario van begin tot eind: wat gebeurt er stap voor stap als een gebruiker het belangrijkste doet wat het systeem kan?

4. Wanneer is het goed genoeg? Twee of drie meetbare eisen. Niet “het moet snel zijn”, maar “een wijziging is binnen twee seconden op elk scherm zichtbaar”. Zulke eisen sturen elke keuze die je daarna maakt.

5. Wat heb je besloten en waarom? Elke keuze die je niet in een middag kunt terugdraaien, leg je vast in vijf regels: de situatie, de keuze, de alternatieven die je niet hebt genomen en waarom niet. Zo'n notitie heet een Architecture Decision Record (ADR). Zelfs “het was een willekeurige keuze” is de moeite waard om op te schrijven, want dan weet je later dat de andere optie net zo goed was.

Zo kort kan zo'n bestand zijn. Hieronder staat een voorbeeld voor ‘Pitstop’, een voorbeeldsysteem voor autogarages:

ARCHITECTURE.md

Pitstop

Wat en waarom. Garages plannen afspraken in het ene systeem en voeren het werk uit in het andere. Bij uitloop of een ontbrekend onderdeel kloppen die twee niet meer met elkaar en krijgt de klant verkeerde informatie. Pitstop is de ene plek waar de actuele status van elke werkorder staat.

Wat het niet doet. Pitstop plant geen afspraken, beheert geen voorraad en stuurt geen facturen.

Wat vastligt. Pitstop draait op een server in de garage zelf en moet blijven werken zonder internet. Dat betekent: lokale opslag, een wachtrij voor wijzigingen en synchronisatie zodra de verbinding terug is.

Onderdelen. Een backend, een scherm voor de planning, een scherm voor de werkplaats, een database en per planningsleverancier een adapter.

Wanneer het goed genoeg is. Een statuswijziging is binnen twee seconden op elk scherm zichtbaar. Bij een netwerkstoring van een kwartier werkt de werkplaats gewoon door.

Beslissingen. Eén applicatie met strikt gescheiden modules, geen microservices. Het domein verandert nog te veel en één applicatie is makkelijker aan te passen.

Meer is het niet. Het is een tekstbestand, zonder diagramtool of apart systeem. Groeit het project, dan groeit het bestand mee. arc42 heeft ook hoofdstukken voor hoe het systeem wordt uitgerold, voor wat alle onderdelen samen delen (zoals logging en toegangsbeheer), voor de risico's die je kent en voor een woordenlijst met termen uit het domein. Die vul je pas als je ze nodig hebt.

Zo houd je het bestand actueel

Het bestand staat in de repository, naast de code, dus het gaat mee in elke pull request. Wie een feature bouwt, past in dezelfde wijziging het bestand aan en de reviewer beoordeelt beide tegelijk. Twee afspraken houden het actueel: verandert de code, dan controleer je of het bestand mee moet veranderen; neem je een besluit, dan schrijf je een ADR. Het uitschrijven mag je aan je agent overlaten. De reden achter een keuze moet van jou komen, want die kan een agent niet verzinnen.

Wat je AI-agent ermee doet

Zet in het instructiebestand van je agent (bijvoorbeeld AGENTS.md) dat hij dit bestand leest voordat hij code voorstelt. Dat een agent zich daar ook echt aan houdt, testte Michaël in een van zijn eigen open-sourceprojecten, geschreven in C#. Hij voegde aan de documentatie een regel toe waarvan hij wist dat die onmogelijk is: elke nieuwe methode moet een emoji in zijn naam hebben. Daarna vroeg hij Codex, een AI-agent die code schrijft, om twee nieuwe methodes te maken. De agent kwam terug met een vraag in plaats van met code. Volgens de documentatie moest er een emoji in de naam, maar C# staat dat niet toe en een andere regel in het project eist dat alle code compileert. De agent wilde weten welke regel voorrang had.

Wat de agent hier met een onmogelijke regel deed, doet hij ook met de echte regels in jouw bestand: dat het systeem zonder internet moet blijven werken, dat facturatie er niet in hoort, dat een nieuwe leverancier een nieuwe adapter betekent. Een agent die deze redenen kent, bouwt code die bij het project past. Dat geldt net zo goed voor de collega die volgend jaar jouw code overneemt.

Begin bij je volgende project

Schrijf het bestand voordat je de eerste regel code schrijft of de eerste prompt typt. Het dwingt je om te bedenken wat je eigenlijk bouwt en wat niet. Dat alleen al bespaart werk. Over een half jaar open je het project, lees je het bestand en weet je binnen een minuut weer waarom alles is zoals het is.