Laten we hiervoor een brusny gebruiken, dan kunnen we dit probleem vrij simpel oplossen!
Ja, goed idee!
Een brusny maken of gebruiken. Dit is een uitspraak die je bij ons op kantoor regelmatig hoort. Maar wat is in vredesnaam een Brusny? In dit blogartikel gaan we je dat uitleggen.
Brusny, brusny
Casper, de grote baas van Webenable, is een gedreven piloot en is daarom natuurlijk in het bezit van een vliegbrevet. Een vliegbrevet moet (om goede reden) iedere twee jaar verlengd worden, waarbij je aan moet tonen een minimaal aantal vlieguren te hebben gemaakt, waarvan minimaal één uur met een vlieginstructeur. Om te voldoen aan deze eis reist Casper iedere twee jaar naar Tsjechië toe, waar hij gaat vliegen met een instructeur om te voldoen aan deze eis.
Maar waarom doet Casper dit in Tsjechië, en niet gewoon in Nederland? Het klinkt namelijk als een hoop gedoe, want het ligt niet bepaald naast de deur. Toch is het minder gedoe dan dit regelen in Nederland. Want Tsjechië biedt doorgaans een sneller en minder bureaucratisch verlengingsproces voor het vliegbrevet.
Wil je in Nederland je vliegbrevet aanvragen of verlengen, dan verval je na het daadwerkelijke examen in een administratief proces dat lang kan duren. In Tsjechië daarentegen, in de woorden van Casper: "Je gaat naar een willekeurige vliegschool, je legt het examen af en als dat goed gegaan is zeg je 'brusny brusny' tegen de examinator, zegt de examinator weer 'brusny brusny' tegen een collega, worden er documenten ingevuld, opgestuurd naar de luchtvaartautoriteiten en is dit allemaal nog dezelfde dag verwerkt. En het voldoet allemaal aan precies dezelfde Europese EASA-luchtvaartregelgeving als in Nederland. Geweldig land, geweldige mensen daar." En bovendien kan het ook nog eens gecombineerd worden met een vakantie, want Casper vindt Tsjechië dus een prachtig land.
Ondergetekende is natuurlijk wat sceptisch over dit laatste, want in de praktijk is Casper ook het grootste deel van zijn 'vakantie' gewoon aan het werk. Maar het zal vast een mooi land zijn.

Dat is dus de herkomst van het woord Brusny. Maar, waarom komt deze term dan zo vaak voor bij ons op kantoor? Casper hoeft immers maar één keer in de twee jaar zijn vliegbrevet te verlengen. Zo vaak zal Casper dat verhaal dan toch niet vertellen?
Om uit te leggen waarom we het toch zo vaak op kantoor over brusny's hebben, moeten we eerst een stukje terug in de tijd. De (spreekwoordelijke) oertijd, toen de medewerkers van Webenable nog in dierenhuiden rondliepen, grottekeningen maakten en we nog met het Hydrazine 1-framework werkten.

Een concept waar nog geen naam voor bestond
Toen we jaren geleden van start gingen met de bouw van het Hydrazine 2-framework, begonnen we met het uitwerken van één van de basiscomponenten van dit framework. Dit component was een verbeterde versie van een component dat ook al bestond in het Hydrazine 1-framework: onze 'admin generator'. Ieder Hydrazine 1-project had een config/admin
directory, met daarin een lading .yaml
-bestanden, die als basis werden gebruikt voor het genereren van allerlei classes, zoals onze entities, repositories, (Sonata) admin classes en meer.

Een voorbeeld van een van de vele `config/admin` bestanden in een Hydrazine 1-project.
In de oudste versie van het Hydrazine 1-framework werden deze bestanden alleen maar gebruikt om (Sonata) adminbestanden te genereren. Voor het schrijven van (Sonata)-adminbestanden was veel boilerplate nodig, en we hadden ook vrij veel admins nodig, dus in plaats van het handmatig typen van deze honderden bestanden, werden deze bestanden gegenereerd op basis van onze .yaml-files. Omdat ze oorspronkelijk alleen bedoeld waren voor (Sonata-)admins stonden ze dus in de 'admin' directory, en noemden we deze bestanden admin.yaml-bestanden ('admin punt jammel bestanden', en uiteindelijk werd dat afgekort naar de term 'admin jammel').
Zoals dat altijd gaat bij het ontwikkelen van software, breidde en spreidde de aanwezige oplossing zich uit tot meer gebieden. Het was namelijk ook wel handig om op dezelfde manier onze entities te genereren, want die deelden toch al veel van deze informatie. En daarna ook onze repositories. En zo werd het steeds meer.
Maar omdat dit alles organisch was gegroeid (want zo gaan die dingen), liepen we regelmatig tegen allerlei limitaties aan, zoals scenario's en use cases waar we vooraf geen rekening mee hadden gehouden. De bouw van Hydrazine 2 was dus een mooie kans om dit goed op te lossen. Deze yaml bestanden zouden één van de basisblokken worden van dit nieuwe framework. We waren allemaal dolenthousiast! Maar toen liepen we vast... want niemand wist wat voor naam we ze moesten geven.
Concept naam
Dit lijkt best een triviaal probleem. Hoe kan je nou vastlopen op een naam? Bedenk gewoon iets, en ga verder met je werk! Maar, iedereen die langere tijd in software development heeft gewerkt, weet dat het niet zo simpel is. Een naam is belangrijk. Je gebruikt een naam namelijk constant - en als een naam niet correct communiceert wat ermee bedoeld wordt blijft het voortdurend problemen opleveren, van het begin tot het moment waarop de laatste byte van deze software van de laatste harde schijf verwijderd is.
Hopelijk zijn de lezers van het blog het ermee eens dat het geven van een goede naam belangrijk is. Maar waarom is dat hier dan zo moeilijk? Een van mijn collega's riep al meteen: we noemen het gewoon een entity! En ja, er worden inderdaad entity-bestanden gegenereerd vanuit deze yaml-bestanden. Maar... er worden ook controllers, repositories, view models, factories, list views, admin pages, migrations en andere dingen door gegenereerd. Je kunt ze dus geen entity noemen - want het omvat veel meer.
Mocht je dit toch doen, en als je het dan vervolgens over entities hebt, zou je niet weten of je het over de 'echte' entities hebt, of over deze yaml-bestanden. En iedere nieuwe developer die kennis mag maken met het fantastische Hydrazine 2-framework, heeft al een bestaand (en waarschijnlijk correct) idee over wat een entity is, en krijgt dus al direct een verkeerd of onvolledig beeld van het concept. Het is dus echt belangrijk om de juiste passende term, of naam, of omschrijving te vinden voor dit concept.
Maar wat is dan de naam voor dit concept? We zijn lange tijd bezig geweest met het doorlopen van alle concepten waar we zelf bekend mee waren, maar niks leek te passen. Uiteindelijk was onze conclusie: er bestaat misschien gewoon echt geen naam voor dit concept. De vraag veranderde dus van: hoe heet dit concept naar hoe gaat we dit concept noemen? We moesten er dus zelf een naam voor bedenken.
Een naam bedenken voor een concept is ook een frustrerende ervaring. Want onbewust zoek je toch naar een naam die het concept omvat. Maar we kregen het niet voor elkaar. Uiteindelijk waren we het zat. En ik zei voor de grap: we noemen het gewoon een brusny. En tot mijn verbazing was de algemene reactie: ja, ach, waarom ook niet?
En dus was de brusny geboren.

Brusnies in een tijd van AI
Brusnies zijn .yaml-bestanden die een set van data omschrijven, en op basis van deze data wordt er een flinke lading aan source-code gegenereerd, waaronder entities, (CMS) admins, validators, repositories, view models, templates, en ga zo maar door.
Generated code: er bevindt zich altijd een soort spanningsveld tussen deze aanpak, en een aanpak waarbij je dit niet doet, maar gebruik maakt van flinke lagen van abstracties. Alhoewel ik de voordelen van beide aanpakken erken, gaat mijn voorkeur toch altijd uit naar generators. We genereren straightforward leesbare code, die heel goed samenwerkt met onze IDE's en static analyzers, omdat alles netjes getypeerd is. Uit Hydrazine 1 hadden we de les geleerd dat ieder project, en zelfs bijna iedere taak, altijd wel iets unieks met zich meebrengt wat afwijkt van de bestaande tools die je al hebt. Een belangrijk aspect van Hydrazine 2 is dus dat alle gegenereerde code snel en eenvoudig te overschrijven en customizen is.
Maar deze 'brusny-techologie' was bedacht en geschreven voordat AI echt actief gebruikt werd. Hoe nuttig is het nog om code te genereren, nu een AI dat ook makkelijk kan doen? Hoeveel heb je nu nog aan deze brusnies? Onze ervaring: de brusny's zijn nog steeds bijzonder nuttig. Je kunt met AI heel eenvoudig (boilerplate) code genereren - en dat doen we ook zeker, maar AI is niet deterministisch. Het is dus goed mogelijk (en zelfs waarschijnlijk) dat de door-een-LLM-gegenereerde entities of repositories fouten bevatten, of dat er net een veld ontbreekt, of dat een bepaalde naamgevingsconventie niet is aangehouden (of nog veel gekkere dingen, we hebben van alles meegemaakt). Code die door AI gegenereerd wordt, moet eigenlijk nagelopen worden. En hierop begin je dus tijd te verliezen. Het introduceert een onzekerheidsfactor, die bij gebrek aan beter acceptabel is, maar in dit geval hebben we dus wel iets beters beschikbaar.

Er komen natuurlijk nog meer voordelen bij kijken. Wij passen regelmatig bestaande brusny-bestanden aan, die dan in zeer korte tijd (want alles draait lokaal), tientallen bestanden opnieuw genereert. Een AI zou hier veel langer over doen. En soms maken we fundamentale wijzigingen aan onze generators. Denk bijvoorbeeld aan extra type-informatie toevoegen voor betere PHPStan-ondersteuning. Dit betekent dat de generator dit moet toepassen op alle bestaande bestanden, over alle projecten heen. En dan ga je het dus hebben over enorme aantallen aan bestanden. Met onze bestaande generators is dat heel snel gebeurd, maar een AI zou er heel lang mee bezig zijn (en eigenlijk moet je daarna alle duizenden bestanden nog nalopen, vanwege het non-deterministische aspect van de AI).
Wij hebben inmiddels geleerd dat het gebruiken van AI toch een laagje aan fragiliteit inbouwt. Door onze fundamentele onderdelen zelf deterministisch te genereren, weten we dat deze laag sterk en betrouwbaar is. En een AI kan daarna juist heel goed gebruik maken van deze onderdelen. Want hier wil ik nog terugkomen op het aspect van gegenereerde code tegenover abstracties: omdat al onze code zo straightforward en duidelijk is, kunnen LLM's deze code erg goed begrijpen en gebruiken.
Dit is een globalere trend die de laatste tijd steeds sterker lijkt te worden: veel complexe systemen bevatten vele abstractielagen. En dat was (vaak) een teken van een goed uitgedachte herbruikbare code. Maar complexe abstracties zijn juist de dingen waar LLM-systemen (op dit moment van schrijven) veel moeite mee hebben. Om LLM's goed te kunnen gebruiken, wil je dus de voorkeur geven aan plattere en eenvoudigere codehiërarchieën (die hierdoor wel vaak meer boilerplate bevatten). Er lijkt de laatste tijd dus een verschuiving plaats te vinden naar dit soort codestructuren - want het loont natuurlijk om zoveel mogelijk gebruik te maken van LLM's in bepaalde lagen van je applicatie.
Ons brusny-concept, gebaseerd op generators, lijkt daardoor juist extra goed te passen in een wereld waar we steeds meer doen met AI. Dit was niet het resultaat van een heel goed vooruitziende blik, maar gewoon geluk.
Conclusie
Inmiddels, jaren later, is ons concept van een brusny zo ingeburgerd dat het woord niet meer 'vreemd' is. Het is gewoon de naam geworden voor dat concept. Er gaat zelden een dag voorbij dat ik niet aan of met een brusny werk.
Tijdens een lunch kwam Peter, onze media-specialist die bijvoorbeeld de hackathon videos voor ons maakt, een keer met ons mee-lunchen. Hij is, net als Casper, een gedreven piloot met vliegbrevet, en verlengt, net als Casper, zijn vliegbrevet in Tsjechië. Tijdens de lunch ging het over hoe complex en sloom dingen in Nederland gaan. Want in Tsjechië, vertelde Peter, zeg je gewoon 'Brusny, brusny' tegen iemand, en het is zo geregeld!
Ik en mijn collega's kijken elkaar verbaasd aan. Hoe weet HIJ nou weer wat een brusny is!? Hoe kent hij dat woord!? Wij waren na al die jaren inmiddels al zo gewend aan het woord, dat we de betekenis ervan eigenlijk onwetend onszelf al hadden toegeëigend; de oorspronkelijke bron en betekenis vrijwel totaal verdrongen. Gelukkig viel na enige tijd het kwartje. Ik weet het niet zeker, maar ik denk zelfs dat Peter het persoon was die het hele woord in de eerste plaats had verzonnen! We bevonden ons dus in de aanwezigheid van een ware pionier.
En na de lunch? Gingen we natuurlijk weer verder werken aan onze brusny's.
