We moeten het hebben over de "illusie van snelheid" in het tijdperk van AI.
In een tijd waarin elke post op LinkedIn lijkt te tonen dat al je concurrenten de overstap maken van traditioneel coderen naar 100% agentische softwareontwikkeling met AI, ligt de realiteit iets complexer. Hoewel AI-demo's en PoC's indrukwekkende eerste resultaten kunnen opleveren, is het inbedden van agentische softwareontwikkeling met AI in een langetermijnlevenscyclus van applicaties, met productieklare vereisten, nog altijd een heel ander spel.
Bij ACA vertrekken we vanuit het definiëren en meten van onze kwaliteitsnormen en doelstellingen, structuren, controles en guardrails. Vervolgens kunnen we, terwijl we agentische AI-capaciteiten toevoegen, de uitkomsten op een feitelijke en continu gemonitorde manier verifiëren en beheersen. Als onze AI-opzet ons helpt om binnen die grenzen te versnellen, is dat geweldig. Maar als AI onze guardrails raakt, merken we dat onmiddellijk en sturen we meteen bij.
Vandaag levert agentische softwareontwikkeling met AI ons daardoor efficiëntiewinsten op van 20 tot 50% ten opzichte van traditioneel coderen. En dat terwijl we onze kwaliteitsnormen op het vlak van performantie, veiligheid en onderhoudbaarheid behouden.
In dit artikel van Stijn Huygh gaan we dieper in op hoe we dat realiseren.
Elke ontwikkelaar heeft de eerste rush ervaren van werken met een coderende LLM. Je vraagt om een feature en seconden later heb je code. Die compileert, draait en ziet er grotendeels correct uit.
Maar snelheid kan bedrieglijk zijn.
Het grootste risico van AI-ondersteunde ontwikkeling is niet dat de code zal falen. Het is dat ze werkt terwijl ze in stilte je architectuur aantast. Zonder guardrails volgt AI je engineeringcultuur niet. Ze volgt het statistische gemiddelde van het internet. Dat is zelden wat je wilt in een productieklaar systeem.
Als je het systeem niet beheerst, beheers je de output niet.
Daarom is het belangrijk om een softwareontwikkelingslevenscyclus te ontwerpen die focust op het behouden van de integriteit van je codebase. Je wilt dat het eindresultaat performant, veilig en absoluut onderhoudbaar is.
AI begrijpt je architectuur niet; ze leest code, voorspelt patronen en geeft weer wat statistisch gezien het meest waarschijnlijke antwoord is.
Dat wordt een probleem wanneer je systeem steunt op een doordachte structuur. Het model kent je architecturale beslissingen of de redenering erachter niet. Het probeert gewoon zo goed mogelijk werkende code te genereren binnen de instructies die het krijgt.
Het resultaat is code die technisch werkt, maar langzaam wegdrijft van de architectuur die jij ontworpen hebt.
Die afwijking toont zich vaak op subtiele manieren:
Geen van deze problemen breekt de applicatie meteen. De code draait en de feature werkt, maar na verloop van tijd stapelen deze kleine afwijkingen zich op. Technische schuld die door AI wordt geïntroduceerd, kan sneller groeien dan menselijke code review realistisch kan bijbenen. En daar begint het echte probleem.
Dus hebben we de aanpak veranderd. In plaats van met AI te chatten, zijn we de beperkingen eromheen gaan engineeren.
De allereerste stap om de kwaliteit van de codebase te verbeteren, zelfs zonder AI te gebruiken om code te genereren, is bepalen hoe je wilt dat je project gestructureerd wordt. Het doel is om consistentie af te dwingen binnen je project, maar ook over al je andere projecten heen. Wanneer een ontwikkelaar de codebase opent, moet die op basis van je conventies meteen kunnen weten waar alles zich bevindt. Bepaal je applicatiearchitectuur!
De meest voorkomende fout die teams maken is vertrouwen op PDF-documentatie of een wikipagina om architectuur af te dwingen. AI (en mensen) zullen vergeten dat er een standaard is en die gewoon negeren. Het wordt een stuk makkelijker om een hoogwaardige codebase te onderhouden wanneer je architectuur ook in code wordt afgedwongen en niet alleen in documentatie.
Een van de manieren waarop wij dit afdwingen, is door onze gelaagde architectuur op te splitsen in verschillende projecten/packages. Als code niet blootgesteld wordt aan een andere laag, of de laag waarin je zit geen toegang heeft tot een specifiek package, dan zal die code niet gebruikt worden door die laag.
Zie mappen als geschilderde lijnen op een weg: het zijn suggesties waar je per ongeluk gemakkelijk overheen rijdt. Aparte projecten (of packages) zijn betonnen muren. Door je lagen te structureren als afzonderlijke packages met pubspec.YAML-regels voorkomen fysiek dat AI-code uit de verkeerde laag importeert.
Als AI probeert om de API-laag rechtstreeks in de UI te importeren, dan blokkeert de compiler dat onmiddellijk, niet een menselijke reviewer.
Onze gelaagde architectuur ziet er zo uit:
Als iets de architectuur schendt, markeert de compiler het. Dat haalt ambiguïteit weg en vermindert discussies tijdens code review.
Je applicatiearchitectuur moet ook verrijkt worden met codeerstandaarden om kwaliteit en consistentie verder te verbeteren. Enkele voorbeelden van codestandaarden die wij afdwingen:
Benaming
Complexiteitslimieten
Volledigheid
Regel voor de applicatie laag
Volgorde
De meeste van deze regels worden afgedwongen via linters en statische analyse. Het gaat hier niet om strengheid omwille van de strengheid. Het gaat om voorspelbaarheid. Wanneer de structuur voorspelbaar is, vallen afwijkingen meteen op.
Een les die we snel geleerd hebben: laat een LLM nooit je boilerplate genereren. Het wordt dan "creatief" met bestandsnamen en mapstructuren, wat leidt tot een rommelige projectboom.
Wij gebruiken "domme tools" voor structuur zodat de "slimme tools" (AI) zich op logica kunnen focussen. Tools zoals Mason laten je deterministische templates genereren met behulp van het Mustache-templatesysteem. Een commando zoals “mason make viewmodel” creëert in enkele seconden de perfecte mapstructuur, bestandsnamen en klassedefinities. De view, viewmodel, interfaces en services worden allemaal aangemaakt met exact onze projectstructuur en codeerrichtlijnen in gedachten.
De strategie: wanneer je AI integreert, vraag haar dan niet om "het bestand te schrijven". Geef AI in plaats daarvan toegang tot je CLI via het Model Context Protocol (MCP) of rechtstreeks via de terminal. AI wordt dan de operator van je scaffoldingtools en voert het mason-commando uit om 100% consistentie te garanderen nog voor ze één enkele lijn logica schrijft.
"Generieke trainingsdata produceren generieke code." Als je wilt dat AI code schrijft die eruitziet alsof ze door jouw team is geschreven, moet je de juiste context aanreiken.
Wij gebruiken een drielagig documentatiesysteem om het contextvenster efficiënt te voeden.
Een lichtgewicht bestand met niet-onderhandelbare regels. Bijvoorbeeld:
Referentiedocumenten die uitleggen:
Stap-voor-stapinstructies over hoe AI-agents moeten werken. Duidelijke documentatie vermindert ambiguïteit. Minder ambiguïteit leidt tot consistentere output.
De grootste sprong in kwaliteit komt voort uit het loslaten van één enkel chatvenster ten gunste van gespecialiseerde AI-agents. Die scheiding van verantwoordelijkheden voorkomt hallucinaties door de scope van elke agent te beperken.
In plaats van één "Coder" zetten we een team in:
AI-engineering met hoge integriteit draait niet om betere prompts te schrijven, maar om betere systemen te bouwen.
Wanneer AI herhaaldelijk dezelfde fout maakt, is de oplossing geen betere prompt. Het is een beter systeem.
Na verloop van tijd creëert dat een omgeving waarin AI een betrouwbare versneller wordt in plaats van een bron van ruis.
AI is krachtig. Maar het presteert het best binnen goed afgebakende systemen.
Structuur vertraagt je niet. Ze laat je toe om snel te bewegen met vertrouwen.