Als ik andere developers vertel dat de backend van Rozuro in kale PHP 8.2 is geschreven, zonder framework eronder, valt de reactie ruwweg in twee helften uiteen. De ene helft vindt het verfrissend en stelt vervolgvragen. De andere helft gaat ervan uit dat ik iets verkeerd doe en verandert beleefd van onderwerp. Beide reacties zijn prima. De keuze is ongebruikelijk genoeg om een echte uitleg te verdienen.
Ik heb productie-code geshipped op Laravel, Symfony, Slim, CodeIgniter, en een handvol in-house frameworks bij verschillende bureaus. Ik ben geen framework-hater. Ze zijn nuttige gereedschappen voor de projecten waar ze bij passen. Voor Rozuro kwam de rekensom er anders uit.
Het eerste wat me wegduwde van een framework was de omvang van de runtime. Moderne PHP-frameworks brengen veel infrastructuur mee. Service containers, event dispatchers, middleware pipelines, ORMs, queue-abstracties, plus de documentatie die uitlegt hoe dat allemaal in elkaar past. Voor een facturatiesysteem is negentig procent van die infrastructuur niet wat ik nodig heb. Wat ik nodig heb is een request, een router, een database-connectie, en voorspelbare validatie. De resterende tien procent van wat een framework biedt is precies het stuk dat ik binnen een jaar zou vervangen omdat het niet past bij mijn domein. De kosten van een framework waar ik tegen ga vechten op de stukken die ertoe doen, zijn hoger dan de kosten om die stukken zelf te schrijven.
De tweede reden is upgrade-churn. Ik heb te veel projecten gezien die een kwartaal kwijt waren aan een migratie van de ene major framework-versie naar de volgende, niet omdat de migratie product-waarde opleverde, maar omdat het framework verder was gegaan en de security patches stopten. Met kale PHP upgrade ik alleen mijn eigen code wanneer ik dat wil, en PHP zelf is een van de weinige language runtimes die backwards compatibility serieus neemt. Dezelfde code die ik in 8.0 schreef draait nu nog op 8.4, met ongeveer drie deprecation warnings die stuk voor stuk verbeteringen zijn.
De derde reden is dat een facturatiesysteem ongewoon strenge eisen heeft rond determinisme en audit. Ik wil precies weten wat er gebeurt tussen het moment dat een POST-request binnenkomt en het moment dat een rij in het grootboek wordt vastgelegd. Met een framework is dat pad lang en gaat het door veel magic. Met kale PHP is het een functie die een request opvangt, valideert, een transactie opent, de grootboekregels wegschrijft, en commit. Ik lees ‘m in vijftien minuten van boven naar beneden. Als er in productie iets misgaat, is dat vijftien minuten precies wat ik wil kunnen doen.
De eerlijke tegenargumenten. Ik schrijf mijn eigen validatielaag in plaats van die van een framework te gebruiken, wat betekent dat ik nadenk over edge cases waar iemand anders al over heeft nagedacht. Authenticatie en sessie-afhandeling heb ik vanaf nul gebouwd op PHP’s eigen session-library, wat prima werkt, maar betekent dat ik de hardening van een framework niet gratis krijg. Migraties zijn een hand-geschreven SQL-script met idempotente CREATE-statements in plaats van een framework-migration-tool. Elk van die dingen is meer werk dan de framework-versie.
De trade die ik gemaakt heb is meer werk vooraf in ruil voor minder werk later. Tot nu toe heeft die trade zich uitbetaald. De codebase is klein genoeg dat een nieuwe developer ‘m in een week kan lezen. De tests zijn voor het grootste deel integratie-tests tegen een echte database, omdat dat is wat ik vertrouw. De architectuur is de saaie drie lagen die je op een servet tekent: HTTP handlers, domain services, repositories. Het meest clevere stuk code is de factuurnummering, en die is clever omdat factuurnummering dat moet zijn.
Ik raad deze aanpak niet aan voor iedereen. Bouw je een CRUD-app voor een bestaande organisatie met dertig developers, dan zit je absoluut beter op Laravel of Symfony. De defaults van het framework zijn goed en de kosten van die overslaan zijn hoog. Bouw je een kleine, scherpe tool met een complex domein-kernstuk en ben je van plan ‘m tien jaar te draaien, dan is kale PHP een serieuze optie. Mensen onderschatten ‘m omdat hij niet past in het CV-gesprek. De codebase beloont je sowieso.
Heb je oorlogsverhalen van framework-loos gaan of juist weer terug, dan hoor ik die graag — neem contact op.
Liefs, Marten.