Blog · 3 juli 2026

Softwareontwerp in het tijdperk van agents: je inzet bepalen

Verslag van de Future of Software Engineering-retreat van Thoughtworks

Deze week nam Mathias Verraes van Aardling deel aan de Future of Software Engineering-retreat van Thoughtworks in Engelberg, Zwitserland. Het was een event op uitnodiging met zo'n 60 leiders uit de sector, gehost door Martin Fowler. Het event gebruikte een open-spaceformaat, waarbij alle sessies de vorm hadden van groepsdebatten, grotendeels gericht op agentic development. Dit zijn enkele van Mathias' observaties over de veranderende rol van softwareontwerp.

Samenvatting:

  • Codekwaliteit is waarschijnlijk nog steeds belangrijk, maar is automatiseerbaar.

  • Softwareontwerp op hoog niveau blijft menselijk terrein, met AI als assistent.

  • De focus verschuift weg van code naar domeinmodellen en specificaties.

  • Specificaties zouden code kunnen vervangen als de enige bron van waarheid.

  • Rigueur en engineeringpraktijken blijven cruciaal.

  • Dek je in tegen de risico's van AI door systemen te bouwen die kunnen terugkeren naar menselijke engineering.

De deelnemers aan de retreat

De deelnemers hadden zeer uiteenlopende achtergronden, en hun gebruik van agentic development was al even gevarieerd. Sommigen gebruikten het voor kleine projecten en proofs of concept, anderen voor delen van hun productieomgeving, en enkelen gebruikten het op bedrijfskritische systemen en in sterk gereguleerde omgevingen.

De stijlen van de deelnemers gingen van mensen die programmeren en kleine wijzigingen aan de LLM delegeren, over pair programming met een LLM, geautomatiseerde generatie met menselijke verificatie en geautomatiseerde generatie met geautomatiseerde verificatie, tot volledige dark-factorypijplijnen. (In de industrie is een dark factory een volledig geautomatiseerde fabriek waar mensen niet toegelaten zijn.) In die stijl beperkt menselijk toezicht zich bijna uitsluitend tot het verbeteren van de kwaliteit van de pijplijnen. Ongeacht de stijl waren velen het eens over de waarde van harness engineering als manier om resultaten te garanderen.

Codekwaliteit op laag niveau

Een terugkerende vraag was hoeveel we nog moeten geven om softwareontwerp op het niveau van de code. Dat gaat over zaken als naamgeving, codeduplicatie, dode code, vermengde verantwoordelijkheden, modulariteit, koppeling en cohesie. Ik kan de meningen van de deelnemers grofweg in twee tegengestelde argumenten indelen:

  1. Deze bekommernissen bestaan voor de leesbaarheid en begrijpelijkheid van de code door mensen, en beïnvloeden de kost van verandering. Agents verlagen de kost van verandering aanzienlijk en hebben zulke ontwerpprincipes niet nodig.

  2. Agents hebben baat bij goed gestructureerde en goed ontworpen code.

De mensen in het tweede kamp brachten enkele overtuigende argumenten aan.

  • LLM's zijn getraind op menselijke talen en hebben beperkingen die lijken op die van menselijke programmeurs. Helderheid is voor LLM's even belangrijk als voor ons.

  • Net als bij mensen doet codekwaliteit er weinig toe bij kortlopende projecten, maar heeft ze een enorme impact op de onderhoudbaarheid en veranderbaarheid van de code op lange termijn. Kamp 1 kijkt dus niet ver genoeg vooruit.

  • De contextvensters van LLM's zijn beperkt. Meer accidentele complexiteit in de code vergroot de context.

  • Complexiteit verhoogt de tokenkost.

  • Mensen moeten de code misschien debuggen wanneer de LLM dat niet kan. Die mensen zullen de code niet kennen, dus goed ontwerp wordt cruciaal.

  • En misschien wel de interessantste observatie: LLM's versterken slechte code. Ze bootsen de stijl en de patronen van de bestaande code na bij het genereren van nieuwe code.

Ik wil hier een speculatief zijargument maken: naarmate we de kwaliteit van gegenereerde code verbeteren, zou het aantal productieproblemen relatief moeten dalen. De hoeveelheid productiecode zal echter exponentieel toenemen, en de problemen zullen in absolute termen stijgen. De eenvoudig oplosbare problemen kunnen met agents opgelost worden. Wat overblijft voor de mensen zijn de complexste problemen met de meest dramatische gevolgen. (Zie Bainbridge's Ironies of Automation)

Dus ik zet mijn geld op de kwaliteit van het codeontwerp:

  • Als kamp 1 ongelijk heeft, moeten ze hun achterstand op kwaliteit inhalen en veel uitgeven om hun bestaande code te herstellen.

  • Als kamp 2 ongelijk heeft, kunnen ze hun kwaliteitsinfrastructuur eenvoudig en goedkoop verwijderen.

  • Als kamp 1 gelijk heeft, hebben ze geld bespaard, maar hebben ze verder geen concurrentievoordeel tegenover kamp 2.

  • Als kamp 2 gelijk heeft, besparen ze geld én hebben ze een groot voordeel.

Codekwaliteit bereiken

Het goede nieuws is dat mensen het gevoel leken te hebben dat agentic codekwaliteit goed werkte. Dit lijkt een prima opzet:

  • Genereer code in één pijplijn, en verifieer alleen of ze werkt. Commit deze wijzigingen atomair.

  • Doe in een tweede pijplijn statische analyse op de code, met traditionele deterministische tools. Configureer ze op hun strengste instellingen, ook als dat valse positieven oplevert.

  • Voer elke code smell uit de tweede pijplijn aan een derde pijplijn. Een agent beoordeelt of de aanbeveling geldig is, en of ze de moeite waard is om op te lossen.

  • De laatste pijplijn refactort de betrokken code, één smell per keer, en doet een atomaire commit per fix.

Agentic refactoring lijkt dezelfde beperking te hebben als menselijke refactoring: je hebt hoge testdekking nodig om te garanderen dat elke refactor alleen de vorm van het systeem verandert, en niet zijn gedrag. De drijfveer voor deze meerdere pijplijnen is dat code van hoge kwaliteit genereren in één stap moeilijker is dan het proces opsplitsen. (Nieuwere modellen lijken beter geoptimaliseerd voor codekwaliteit, dus misschien is dit een tijdelijke beperking.) Merk op dat het proces op TDD lijkt: schrijf een werkende implementatie, en refactor pas daarna. Of in de woorden van wijlen de grote Joe Armstrong: "Make it work, then make it beautiful, then if you really, really have to, make it fast. Ninety percent of the time, if you make it beautiful, it will already be fast. So really, just make it beautiful!"

Softwareontwerp op hoog niveau

Als codekwaliteit automatiseerbaar is, hoe zit het dan met het ontwerp op hoog niveau? Dit zijn enkele essentiële kwaliteiten van niet-triviale, kritieke systemen:

  1. Een helder domeinmodel, uitgedrukt in alle artefacten, met inbegrip van de code, de tests, de documentatie, de gebruikersinterface en de gesprekken tussen business stakeholders en engineers

  2. Een ondubbelzinnige, goed gedefinieerde en afgesproken Ubiquitous Language, geïnspireerd op de domeintaal, die alle concepten, jargon en metaforen vastlegt.

  3. Bounded Contexts die een grens trekken rond de taal en het model, en tegelijk pragmatisch tegemoetkomen aan de noden van de systeemontwerpers.

  4. Een continu proces van taal, modellen en grenzen bijwerken, naarmate het domein evolueert en ons inzicht in het domein verbetert.

Laten we ze in omgekeerde volgorde overlopen.

Het lijkt me vrij vanzelfsprekend dat organisaties altijd evolueerbaarheid zullen willen, omdat ze essentieel is om concurrentieel te blijven. Model drift is de groeiende afstand tussen de (mentale en gedocumenteerde) domeinmodellen en hoe de code werkelijk werkt. Dat verhoogt de cognitieve belasting van engineers aanzienlijk en verhoogt de kost van verandering. Uiteraard zijn er nog weinig data over evolueerbaarheid op lange termijn met agentic development, omdat het LLM-landschap jong is en snel verandert.

Bounded Contexts lijken nuttig om dezelfde reden als het modulariteitsargument eerder: een kleinere scope betekent een kleiner contextvenster en een kleinere tokenkost. Met een gedocumenteerde definitie van die scope kunnen agents de opdracht krijgen om te waarschuwen wanneer een feature request de scope schendt.

Grenzen definiëren blijft een kunst: te groot en wijzigingen worden moeilijk; te klein en elke wijziging raakt meerdere Bounded Contexts tegelijk. Het is geen toeval dat de kunst van Bounded Contexts definiëren sterk afhangt van de kwaliteit van je modellering en het ontwerp van je Ubiquitous Language.

Maar doet taal ertoe? Ook hier is er het argument dat de machine er niet om geeft. Alle namen in je code zouden willekeurige ID's kunnen zijn zonder dat het de compiler raakt, en misschien zou het de LLM ook niet raken. Maar het argument vóór is dat taal niet alleen voor code en agents dient. Menselijke gesprekken, specificaties, diagrammen, gebruikersinterfaces, API's en MCP's moeten die taal allemaal delen. Sommige mensen op het event stelden dat we programmeertalen en talen voor communicatie tussen agents zouden kunnen maken die niet leesbaar zijn voor mensen. Het tegenargument is dat LLM's getraind zijn op enorme hoeveelheden menselijke taal, en dat er niet genoeg trainingsdata zijn voor die hypothetische nieuwe talen. LLM's simuleren menselijk redeneren.

Hebben we nog domeinmodellen nodig? In mijn eigen experimenten gaf de agent eerst een domeinmodel voeren, vóór het one-shotten van een applicatie, veel betere resultaten dan gewoon mijn vereisten prompten. Zonder model maakte de agent geregeld twijfelachtige keuzes voor de codestructuur en de databaseschema's. De code werkte, maar was voor mij moeilijker te begrijpen, en verlaagde de prestaties van de database. Deelnemers aan het event vertelden dat ze met een agent itereerden over domeinmodellen, en hem pas de opdracht gaven om code te schrijven nadat die vastlagen. Sommigen bouwden een mix van tekstuele beschrijvingen en tekstgebaseerde diagrammen (met tools als PlantUML, Mermaid…) en voerden die aan de agent.

Ook formeel modelleren zit in de lift: het is lang een kleine niche binnen software engineering geweest, met een steilere leercurve, maar agents kunnen die modellen voor ons maken en uitleggen, en ze vervolgens gebruiken om hun output te verifiëren.

Specificaties of code?

Een van de meest verdeelde vragen op het event was of code nog steeds de grondwaarheid is. Ook hier kan ik grofweg twee kampen onderscheiden:

  1. Behandel de code als de enige bron van waarheid. Itereer over code met atomaire wijzigingen. Verifieer ze met agents én met traditionele methoden zoals code reviews, geautomatiseerde tests en acceptatietests.

  2. Specificaties zijn de enige bron van waarheid. De code is niet meer voor mensen. Itereer in plaats daarvan over specificaties, en verifieer of de applicatie eraan voldoet.

Het eerste kamp behoudt de manier waarop software engineering al decennia gebeurt, en breidt ze uit met agents. Het tweede kamp staat voor een radicale verschuiving. Software engineering wordt specification engineering.

Deelnemers beschreven verschillende stijlen van specification engineering. Velen gebruikten agents op een of andere manier om te helpen bij het schrijven van specificaties, maar de meningen waren verdeeld over de vraag of de specificaties alleen tekst zijn, alleen uitvoerbare specificaties, of een mix (wat het doel van één enkele bron van waarheid ondergraaft). In elk geval is de kwaliteit en de rigueur van de specificaties cruciaal.

Een interessante vraag is dan of de code wegwerpbaar wordt. Sommigen itereren over de specificaties en laten de agent de code patchen (en gebruiken dan misschien geautomatiseerde codekwaliteitspijplijnen zoals ik hierboven beschreef). Anderen itereren over de specificaties en de code, en gooien de code weg zodra de agent moeite krijgt om ze te patchen. Dan genereren ze de code gewoon opnieuw vanuit de nieuwste specificaties. Het debat ging over de vraag of code weggooien het geheel minder deterministisch maakt, en of de tokenkost van frequent hergenereren hoger of lager ligt dan de kost van code patchen.

Je inzet bepalen

Als jarenlang voorvechter van geautomatiseerde tests voel ik een sterke aantrekkingskracht tot Spec-Driven Development met uitvoerbare specs. Ik ben een engineer en ik hou van deterministische systemen, en als we niet-deterministische agents loslaten op onze code, dan zou op zijn minst de verificatie van de code voorspelbaar fouten moeten vinden. De specificaties moeten (voldoende) leesbaar zijn voor mensen, zodat we ze kunnen verifiëren. En dus hebben ze heldere taal, modellen en grenzen nodig, of de LLM daar nu om geeft of niet. Ik ben er minder van overtuigd dat we de code kunnen weggooien en naar believen opnieuw genereren. Het lijkt erop dat hergenereren niet alleen zijn eigen kost heeft, maar ook de kost kan verhogen van het verifiëren van functionele en niet-functionele vereisten (zoals security en performantie) bij elke regeneratie. Ik weet ook niet zeker of investeren in codekwaliteit op laag niveau op zich veel zal uitmaken, los van de tokenkost. Toch zet ik erop in, om de redenen hieronder.

Mensen die dark factories runnen, meldden dat die momenteel erg moeilijk op te zetten zijn en hoogopgeleide engineers en een gevestigde engineeringcultuur van hoge kwaliteit vereisen. Iemand uitte de bezorgdheid dat veel organisaties dark factories zullen willen opzetten zonder die vaardigheden en cultuur, met het risico op hoge kosten of zelfs grote ongelukken. (Ik heb vaak een gelijkaardig argument gemaakt over Domain-Driven Design. Als je geen tests, codekwaliteit, agility, engineeringproces en communicatiekanalen met de domeinexperts hebt, zal DDD er bovenop kwakken je niet alles geven wat het belooft. Maar zelfs slechte DDD is niet zo riskant als ongeverifieerde code naar productie duwen.) Zorg eerst dat je fundamenten van kwaliteit en ontwerp in orde zijn. Zoals een deelnemer, Sam Ruby, over het event schreef: "rigor doesn't vanish when the agent writes the code — it migrates. Upstream into specifications, down into test suites treated as first-class artifacts, into type systems and constraints, into tiering code by how much damage a mistake could do."

Maar er is nog een reden waarom ik zou blijven bouwen aan systemen met hoge testdekking, degelijke modellen en grenzen, en uitstekende codekwaliteit. AI is heel nieuw, verbrandt geld, en we weten nog niet in welke mate agentic development betaalbaar en de kost waard zal zijn. Ik zou mijn organisatie willen kunnen terugbrengen van agentic codegeneratie naar menselijke engineering. Dat vereist systemen die voor mensen begrijpelijk zijn. Ik wil mijn systemen zo opzetten dat dat eenvoudig is. En om te begrijpen hoe begrijpelijke software eruitziet, heb je mensen nodig met die ervaring.

Ik wil Thoughtworks bedanken voor de uitnodiging. Ik heb enorm genoten van het debatteren over AI in termen van engineering, ontwerp, ethiek en filosofie, met een uitzonderlijke en leuke groep experts.