Week 20: Gereedschap maken voor gereedschap
Deze week bouwde ik een WAV-cutter met waveform visualisatie, debugde een O(n²) bottleneck die 2,4 miljoen iteraties draaide, en leerde wat de 'grill me'-methode betekent voor betere software.
Er zijn weken in dit experiment waarin ik vrijwel niets bouw dat zichtbaar is voor een gebruiker. Geen nieuwe feature in de podcast website, geen AI-experiment dat ik kan demonstreren. Maar er is wél van alles gebouwd — het gereedschap waarmee ik het andere werk doe.
Dit was zo’n week.
Een WAV-cutter van nul
Het begon met een praktisch probleem. Voor de podcast gebruik ik multichannel WAV-bestanden met aparte kanalen per spreker. Die bestanden moet ik soms knippen: intros inkorten, stiltes wegsnijden, een stuk bewaren voor een audiogram. De bestaande tools zijn of te simpel (geen multichannel support) of te complex (een volledig DAW opstarten voor één knip).
Zaterdag bouwde ik een eigen oplossing: een tkinter GUI-applicatie met waveform visualisatie, een cursor-gebaseerde workflow en real-time playback. Je klikt op de waveform om de cursor te plaatsen, drukt I voor het beginpunt en O voor het eindpunt, en de applicatie exporteert automatisch naar een genummerd bestand — nooit overschrijven.
Wat me opviel tijdens het bouwen, was hoe de keuzes voor de gebruikservaring zich opstapelden. Begin met een save-dialoog? Nee, volledig automatisch opslaan. Zoom naar het midden van de view? Nee, zoom naar de cursorpositie. Multichannel afspelen? Te traag — alleen kanaal 0 afspelen, maar alle kanalen exporteren. Elke beslissing kleiner dan de vorige, maar samen bepalen ze of een tool fijn aanvoelt of niet.
De audio playback had ook crackling-problemen. Oplossing: buffer size van 1024 naar 4096 samples verhogen. Dat soort tuning doe ik normaal gesproken zelden — het vereist dat je eventjes stopt en luistert in plaats van doorproduceert.
De O(n²) die niemand had gezien
Maandag stootte ik op een performance issue in sync_episodes.py. Het script was traag geworden — zo traag dat het merkbaar was tijdens de dagelijkse run. Ik keek naar de code en vond het klassieke probleem: een geneste loop die voor elke episode alle regels van een bestand doorloopt. Bij 1091 episodes en 2204 regels resulteert dat in meer dan 2,4 miljoen iteraties.
Het was er waarschijnlijk al een tijdje, maar pas nu de dataset groot genoeg was geworden om pijnlijk te worden.
De fix was niet ingewikkeld: de binnenste loop vervangen door een dictionary lookup. Maar het debuggen van de oorzaak vroeg om systematisch denken — niet gissen. Ik traceerde het probleem terug via logs, mat de looptijd per stap, en bevestigde de diagnose voordat ik iets aanraakte.
Op dezelfde dag bleek de audio player in de podcast website ook kapot te zijn. Niet één oorzaak maar drie tegelijk: CSP-headers die audio.buzzsprout.com blokkeerden, een referrer policy die de redirect knipt, en een JavaScript-bug die Infinity:aN weergaf bij de afspeelduur. Drie lagen, elk onzichtbaar zonder de juiste tools.
Ik documenteerde beide beslissingen in ADR’s — Architecture Decision Records. Niet omdat dit zo’n groot systeem is, maar omdat ik over zes maanden wil begrijpen waarom die CSP-regels er staan.
Grill me
In de samenvatting van zaterdag staat een term die ik zelf moet hebben gebruikt: de grill-me methodiek. Systematisch alle aspecten doorvragen voordat de implementatie begint.
Het idee is simpel: voordat ik begin met bouwen, vraag ik aan Claude Code (of aan mezelf) om me te “grillen” over de requirements. Wat als de bestandsnaam al bestaat? Wat als er meer dan twee sprekers zijn? Wat als het bestand corrupt is? Niet om alle edge cases op te lossen, maar om ze bewust te kiezen of uit te sluiten.
De WAV-cutter had geen undo-functie gepland. Na de grilling realiseerde ik me dat een knipbewerking op een lang bestand makkelijk per ongeluk gedaan kan worden. Dus ik bouwde undo in. Niet elegant, maar werkend.
Grillen kost tijd aan het begin. Maar het voorkomt herwerk. En herwerk is niet alleen tijdverlies — het is ook de stilzwijgende erosie van vertrouwen in je eigen werkwijze.
Wat het met mij deed
Ik merkte deze week opnieuw hoe anders het voelt om tooling te bouwen ten opzichte van product features. Bij een feature is het doel extern: een gebruiker doet iets wat ze eerder niet konden. Bij tooling is het doel intern: jij kunt iets beter, sneller of betrouwbaarder doen.
Dat heeft een ander soort bevrediging. Minder zichtbaar, maar persistenter. De WAV-cutter gebruik ik nu elke opname. De O(n²) fix merk ik elke ochtend als de stats update in vier seconden klaar is in plaats van dertig.
Er was ook een moment van ongemak. Woensdag ontdekte ik dat de dagelijkse routine-automatisering soms een stap oversloeg zonder foutmelding — de verificatie paste zo goed aan de verwachte output dat een ontbrekend bestand simpelweg niet opgemerkt werd. Dat soort stille fouten zijn erger dan harde crashes.
Het leidde tot een inzicht dat ik nu als principe heb opgeschreven: bij geautomatiseerde workflows is verificatie belangrijker dan snelheid. Je kunt altijd langzamer zijn. Je kunt niet altijd terugdraaien.
Het patroon
Gereedschap bouwen voor gereedschap klinkt recursief. Dat is het ook. Maar het is hoe stabiele systemen groeien: niet door één grote architecturale beslissing, maar door een gestaag patroon van kleine verbeteringen die samenkomen.
Deze week was een goede week voor dat patroon.