Deep Modules: de Claude Code Skill die mijn codebase redt
Ik heb de skill improve-codebase-architecture uitgevoerd voor een project waarnaar ik sinds november verzend. Sonnet 4.6 besteedde elf minuten aan het lezen van mijn code, opende een afwaarderingsrapport in mijn editor en somde zes dingen op waarvan hij dacht dat ze stilletjes onder mij aan het rotten waren.
De eerste heb ik afgewezen. Met de tweede had ik ruzie. De derde deed me huiveren, naar de keuken lopen, koffie inschenken die ik niet wilde, en terugkomen om het nog eens te lezen.
Er waren twee parallelle implementaties van hetzelfde concept gevonden – één in mijn frontend, één in mijn backend – die in totaal verschillende mappen zaten, eigendom van totaal verschillende mentale modellen, zonder een uniforme verbinding ertussen. Ze waren aan het afdrijven. Ik had drie weken eerder een bug verzonden waarvan de oorzaak precies die afwijking was. Ik had de twee gebeurtenissen niet met elkaar in verband gebracht. De skill verbond ze in een paragraaf.
Dat is het moment waarop ik stopte met het behandelen van deze skill als een nieuwe GitHub-repository en begon het te behandelen als het enige dat tussen mij en de codebase staat waar ik naartoe ga als ik met AI-snelheid blijf verzenden zonder architectonische druk.
Als je tot en met het eerste kwartaal van 2026 aan het vibe-coderen bent geweest in Claude Code en je codebase begint zwaarder aan te voelen dan zou moeten – traag om te navigeren, eng om te refactoren, vol met kleine modules die allemaal van elkaar lijken te afhankelijk op manieren die je niet op een whiteboard kunt tekenen – dan is dit bericht voor jou. De volgende 4000 woorden gaan over waarom dat gebeurt, wat John Ousterhout twintig jaar geleden ontdekte waardoor het kan worden opgelost, en hoe Matt Pococks improve-codebase-architecture-skill de oplossing in Claude Code operationeel maakt.
De echte kosten van snel shippen met AI
Dit is wat niemand op de AI-coderingsmarketingpagina's plaatst.
De reden dat Claude Code in week twee magisch aanvoelt en in maand vier zwaar aanvoelt, is niet dat het model slechter wordt. Het is dat je codebasis slechter wordt, sneller dan je hersenen het kunnen modelleren. Software heeft deze eigenschap altijd gehad; Ousterhout heeft er een heel boek omheen geschreven, A Philosophy of Software Design, waar ik zo meteen op terugkom. Maar het tarief is veranderd. AI schrijft gemiddeld geen betere of slechtere code dan ik. Het schrijft code vijf tot tien keer zo snel als ik. Elke architectonische kortere weg neem ik in vijftien minuten in plaats van twee dagen, wat de entropieverbindingen op een kalender betekent waarop mijn oordeel nooit is getraind.
De technische naam voor wat er gebeurt is software-entropie. De codevormige naam is 'modderbal'. Het gevoel, als je het hebt meegemaakt, is het moment dat je een bestand opent en beseft dat je niet langer weet wie deze functie aanroept, wat het retourneert als de invoer verkeerd is opgemaakt, en of het wijzigen ervan de testsuite of de productie of beide kapot maakt.
Dat gevoel kreeg ik bij het project dat ik hierboven noemde. Niet omdat de code slecht was: het meeste ervan was beoordeeld, het meeste was getest en het meeste was in productie voor betalende gebruikers. Het probleem was fijner van aard dan 'slechte code'. Het probleem was dat ik dertig modules had, terwijl ik er twaalf nodig had. Concepten die bij elkaar hoorden, waren over bestanden verdeeld, omdat op het moment dat ik elk stuk schreef, het splitsen schoner aanvoelde. De totale cognitieve kosten van deze splitsingen waren nu hoger dan de cognitieve kosten van de duplicatie die ze vermeden.
Dat is wat AI versnelt. De beslissing om te splitsen, te extraheren en te abstraheren is goedkoop als een agent het in twintig seconden kan doen. De beslissing is zo goedkoop dat ik hem neem zonder na te denken. Het resultaat is een codebasis in de vorm van een fractal van kleine, beleefde, individueel correcte modules zonder centrum.
Ousterhout heeft een woord voor die vorm. Hij noemt het oppervlakkig. De oplossing heeft ook een naam: deep modules. De skill waar ik je doorheen ga leiden, is het eerste hulpmiddel dat ik heb gebruikt om de oplossing te implementeren zonder dat ik elke vrijdagmiddag driehonderd pagina's van een softwareontwerpboek opnieuw hoef te lezen.
Deep Modules versus ondiepe modules - in gewoon Engels
Voordat ik de skill doorloop, heb je de woordenschat nodig. Als je het eenmaal hebt, leest de uitvoer van de skill als Engels. Zonder dit lijkt het rapport op een refactoring boodschappenlijstje.
Een module is een eenheid van uw applicatie met een duidelijke grens. In een React-app kan een module een component zijn. In een Node-service kan dit een functie, een klasse of een map zijn. Wat het tot een module maakt, is niet de grootte ervan; het is dat er een buitenkant en een binnenkant is, en dat de binnenkant verborgen is.
De interface is wat iemand moet leren om de module van buitenaf te gebruiken. Functie handtekeningen. Component rekwisieten. Publieke methoden. Documentatie. Typedefinities. Alles wat een beller in zijn hoofd moet laden om de module zijn werk te laten doen.
De implementatie is alles binnen de grens waarvan de beller niets hoeft te weten. Loops, helpers, statusmachines, databasequery's, nieuwe pogingen: het eigenlijke werk.
Nu het deel dat ertoe doet.
Een diepe module heeft een kleine interface en een complexe implementatie. Je leert er tien dingen over, en het doet duizend dingen voor je. De hefboomratio – gedrag dat toegankelijk is per eenheid geleerde interface – is hoog. Het klassieke voorbeeld van Ousterhout is de Unix-bestandssysteemaanroep read(fd, buf, n). Drie argumenten. Tientallen jaren van complexiteit van het besturingssysteem gaan erachter schuil. U denkt niet aan schijfgeometrie, paginacaches of bloktoewijzing. Je vraagt om n bytes. Je krijgt n bytes.
Een ondiepe module heeft een interface die ongeveer net zo complex is als de implementatie die hij verbergt. Je leert er tien dingen over, en het doet elf dingen voor je. Of in het ergste geval leer je er tien dingen over en doet het acht dingen voor je, omdat de interface meer lekt dan de implementatie bevat. De leverage ratio is bijna één. De module betaalt nauwelijks zijn huur.
Hier is een concreet paar. Blijf bij mij – dit is het moment waarop de woordenschat landt.
// SHALLOW: this module's interface is bigger than what it hides
export class UserAuthHelper {
hashPassword(password: string, salt: string): Promise<string>;
generateSalt(): string;
verifyPasswordAgainstHash(password: string, hash: string, salt: string): Promise<boolean>;
isPasswordStrongEnough(password: string): boolean;
getMinimumPasswordLength(): number;
getMaximumPasswordLength(): number;
generateSessionToken(userId: string): string;
validateSessionToken(token: string): { userId: string } | null;
revokeSessionToken(token: string): Promise<void>;
}
Dat lees je en je voelt het al. Om dit te kunnen gebruiken, moet ik kennis hebben van salts, hashes, sessietokens, wachtwoordregels en intrekking, allemaal implementatiedetails van geauthenticeerd worden. De interface lekt de binnenkant van de module naar de hersenen van elke beller.
Nu de diepe versie van hetzelfde.
// DEEP: small interface, the complexity is locked inside
export class Auth {
signIn(email: string, password: string): Promise<Session>;
signOut(session: Session): Promise<void>;
currentUser(session: Session): Promise<User | null>;
}
Drie methoden. Salts, hashes, sessiegeneratie, wachtwoordregels, intrekking, vervaldatum, vernieuwingstokens: dit alles bevindt zich in signIn, signOut en currentUser. De beller hoeft er niets van te weten. Als ik volgende maand van bcrypt naar argon2 wil migreren, verandert er geen beller. Als ik multi-factor authenticatie wil toevoegen, blijft de interface hetzelfde: signIn wordt alleen maar rijker achter de naad.
Dat is de beweging waar de skill naar op zoek is. Elke verdiepingsmogelijkheid is in wezen een kans om de tweede vorm aan te nemen en de eerste te verdoezelen.
Er is nog een stukje woordenschat dat je nodig hebt voordat we verder gaan.
Lokaliteit is hoe gerelateerde functionaliteit is gegroepeerd in de codebase. Hoge lokaliteit betekent dat de dingen die samen veranderen, naast elkaar leven. Lage lokaliteit betekent dat het wijzigen van één functie het bewerken van bestanden in drie mappen vereist die elkaar niet eens kennen. De ondiepe UserAuthHelper hierboven heeft een gemiddelde lokaliteit – het is tenminste één klasse. De bug die ik in mijn project aantrof had een lage lokaliteit; auth-vormige logica werd gedupliceerd in apps/web/src/lib/session.ts en services/api/src/auth/session.go, zonder gedeelde typen en zonder afgedwongen contract daartussen.
Verdieping verbetert meestal automatisch de locatie. Wanneer je drie shallow modules samenvoegt in één diepe module, wordt de bijbehorende code naar hetzelfde bestand verplaatst, wat betekent dat de volgende persoon die het bewerkt (waarschijnlijk in de toekomst, om 23.00 uur, over twee maanden) alles in één keer kan zien.
Wat de skill feitelijk doet
De improve-codebase-architecture-skill, geschreven door Matt Pocock en geleverd als onderdeel van zijn open-source skills repo, is een kleine kortingsbundel die de manier verandert waarop Claude Code uw repository leest. Je installeert het zoals elke andere skill - zet het neer in ~/.claude/skills/ of gebruik het install-commando van README - en vanaf dat moment, als je Claude Code vraagt om te zoeken naar mogelijkheden voor refactoring, doet het dat via de lens van Ousterhout in plaats van via generieke 'codegeur'-heuristieken.
Mechanisch gezien doet de skill drie dingen.
Eerst scant het de repository met een specifieke vraag in gedachten: waar zijn de shallow modules geclusterd? Het zoekt niet naar individuele slechte bestanden. Het zoekt naar clusters van kleine modules die nauw met elkaar zijn verbonden, waarbij elke module een interface heeft die bijna net zo complex is als de implementatie ervan, en waar je de wrijving kunt voelen als je tussen de modules beweegt als je de code leest.
Ten tweede levert het een lijst met verdiepende mogelijkheden op – meestal tussen de drie en tien, naar mijn ervaring – elk geschreven als een kort voorstel: welke modules moeten worden samengevoegd, hoe de nieuwe interface eruit moet zien, waar de testnaad zou moeten komen, en welke risico’s de refactor met zich meebrengt. Het voorstel is bedoeld om door een mens te worden gelezen, besproken en geaccepteerd, gewijzigd of afgewezen.
Ten derde, wanneer u een voorstel accepteert, wordt de skill in een interactieve ontwerppas opgenomen. Claude stelt de nieuwe interface voor, je gaat terug op namen en vormen, het model wordt herzien, en zodra de interface klaar is, stelt het een implementatiestrategie voor. De strategie omvat onder meer hoe bellers moeten worden gemigreerd en waar de testgrens moet worden gelegd. Wanneer je groen licht geeft, registreert de skill een GitHub-probleem (of welke issue-tracker dan ook die je hebt aangesloten), zodat het werk wordt bijgehouden, zelfs als je het die dag niet doet.
De twee dingen die ik wil onderstrepen. De skill herstructureert uw code niet zelf. Het brengt kansen naar boven en helpt je nadenken. Mensen maken elke architecturale oproep. En de skill is eigenwijs: het geeft specifiek de voorkeur aan minder, diepere modules boven meer, kleinere modules. Als jouw team een sterke culturele voorkeur in de andere richting heeft, ga je daartegen vechten.
De dag dat ik het op mijn eigen repo draaide
De repository waarop ik heb getest, was een SaaS-dashboard waar ik sinds november wekelijks naar verzend. Ongeveer 1.500 commits, voornamelijk van mij, af en toe gekoppeld aan Claude Code. TypeScript over de hele stack, React Router aan de voorkant, een Node-service aan de achterkant, een Postgres-database eronder. Echte gebruikers. Echte bugs. Echte cognitieve kosten elke keer dat ik het open.
Ik ruimde een zondagochtend op, zette koffie en voerde één prompt uit:
Gebruik de improve-codebase-architecture-skill. Scan dit repository en maak een lijst met verdiepingsmogelijkheden, gerangschikt op impact.
Elf minuten. Zes kansen.
Ik ga er drie doornemen, want de andere drie waren variaties op dezelfde patronen en je krijgt hieruit de vorm.
Kans 1: Het dubbele sessieconcept. Dit was degene waardoor ik de koffie neerzette. De skill gaf aan dat apps/web/src/lib/session.ts en services/api/src/middleware/session.go allebei implementeerden wat semantisch op dezelfde module leek: lees de sessie, valideer deze, vernieuw als deze is verlopen en retourneer null als deze ongeldig is. Ze hadden verschillende soorten. Andere naamgeving. Verschillende foutsemantiek. De frontend behandelde verlopen sessies stilletjes als 'de gebruiker afmelden'. De backend retourneerde een 401. Er was geen gedeeld contract tussen hen, wat betekende dat elke afwijking tussen de twee zich zou manifesteren als een UX-bug. Het voorstel van de skill: definieer een enkele Session-module met één interface (ingetypt in gedeeld schema), één canonieke statusmachine (uitgedrukt in OpenAPI plus een gegenereerde client) en een adapter aan elke kant die de interface implementeert in de lokale omgeving.
Twee adapters, één interface. Een echte naad. Ik had drie weken eerder een sessiegerelateerde bug verzonden. De skill wist dat niet. De skill zag de architectuur en voorspelde de vorm van de bug alleen op basis van de architectuur.
Kans 2: De gefragmenteerde logger. Ik had vier loghulpprogramma's. Een console.log-wrapper in de frontend. Een pino-configuratie in de backend. Een 'gestructureerde gebeurtenis'-helper voor analyse. Een "telemetriebereik" -helper voor tracering. Ze waren allemaal afzonderlijk toegevoegd als antwoord op een reële behoefte. Ze zagen er afzonderlijk allemaal schoon uit. Samen betekenden ze dat wanneer ik de stroom van een specifieke gebruiker over de stack wilde debuggen, ik vier sets logboeken in vier verschillende formaten moest lezen. Het voorstel van de skill: een enkele Observability-module met één interface - event(name, payload), error(err, context), span(name, fn) - en vier adapters die uitwaaieren naar de bestaande transporten. Dezelfde belsites. Dezelfde uitgangen. Eén interface die ik moet leren, met vier implementaties erachter. Dit was een pure verdieping: er ging geen functionaliteit verloren en het leven van bellers werd aanzienlijk vereenvoudigd.
Kans 3: Degene waarmee ik ruzie had. De skill markeerde mijn formuliervalidatiehelpers als een verdiepingskans. Ik had validateEmail, validatePhone, validateRequired en een half dozijn anderen, elk met een kleine pure functie. Het voorstel: vouw ze samen in één enkele Validator-module met een vloeiende API. Ik duwde terug. Pure functies zijn meestal dieper dan ze lijken: validateEmail(email) heeft een kleine interface en een niet-triviale implementatie (RFC 5322 is niet vriendelijk), en de hefboomratio is prima. Het tegenargument van de skill ging over lokaliteit: de validators werden samen, in clusters, op elk formulier gebruikt, en de omringende code moest zes verschillende functies importeren in plaats van één.
Na tien minuten heen en weer praten in de chat, gaf ik toe dat het plaatsargument reëel was, maar stelde ik een compromis voor: behoud de pure functies, voeg een Form-module toe met een vloeiende API die ze samenstelt. De skill ging akkoord, stelde de nieuwe vorm op en diende de kwestie in. Dat was het moment dat ik dit ding vertrouwde.
De andere drie mogelijkheden betroffen een router-state module waarin een state-machine was gegroeid, een betalingsintegratie die webhookdetails in de UI-code lekte, en een feature-flag-systeem dat stilletjes was veranderd in drie onafhankelijke feature-flag-systemen. Alle drie kregen voorstellen. Twee accepteerde ik; eentje heb ik uitgesteld naar het volgende kwartaal.
Naden en adapters — Waarom verdieping tests mogelijk maakt
Dit is het deel van de skill dat direct verband houdt met de vraag of je codebase testbaar is, en de reden waarom dit er allemaal toe doet is belangrijker dan alleen 'de code ziet er mooier uit'.
Een naad is een grens in uw code waar u een nep-bestand kunt vervangen door het echte werk, zonder de omringende code te wijzigen. Michael Feathers noemde het zo in Effectief werken met verouderde code – twintig jaar geleden, maar het is nog nooit zo relevant geweest als in 2026. De interface van een module is de natuurlijke naad ervan. Als de module een kleine, schone interface heeft, kunt u voor tests een nep aan de andere kant van die interface plaatsen. Als de module een uitgestrekte, lekkende interface heeft, moet elke test op twaalf verschillende manieren doen alsof het echt is, en stop je met het schrijven van tests omdat ze pijn doen.
Een adapter is de betonuitvoering die aan de andere kant van de naad leeft. De echte praat met de echte: Postgres, het netwerk, de systeemklok. De neppe retourneert wat je maar wilt voor de test.
Het schoonste voorbeeld, en degene die ik nu gebruik om dit aan mijn team te leren, is de systeemklok.
// The interface — a one-method module
interface Clock {
now(): Date;
}
// The real adapter
class SystemClock implements Clock {
now() { return new Date(); }
}
// The fake adapter, for tests
class FakeClock implements Clock {
constructor(private current: Date) {}
now() { return this.current; }
advance(ms: number) {
this.current = new Date(this.current.getTime() + ms);
}
}
Elke code die van tijd afhankelijk is, is nu afhankelijk van Clock, niet van Date.now(). In productie krijgt het de echte klok. Bij tests krijgt het een nepklok die ik een uur, een dag, een jaar vooruit kan zetten. Elke test die ik heb geschreven en die van tijd afhing, was vroeger onbetrouwbaar. Elke test die ik heb geschreven sinds ik de klok in een diepe module met twee adapters heb gehaald, is deterministisch.
De skill houdt van dit soort refactor. Wanneer het een repository scant, wordt bij elke module de volgende vraag gesteld: waar zou de testnaad naartoe gaan? Als het antwoord "nergens voor de hand liggend is - de module praat rechtstreeks met de database en het netwerk en tegelijkertijd met de klok en het bestandssysteem", dan is dat een verdiepingsmogelijkheid. De oplossing is om de afhankelijkheden in modules met hun eigen interfaces te extraheren en vervolgens adapters aan beide kanten te plaatsen. Plots wordt elke pijnlijke test gemakkelijk.
Dit is het onderdeel dat zichzelf het snelst terugbetaalt. De eerste verdieping die ik deed op basis van het rapport van de skill – de sessiemodule – bespaarde me de week daarop een volledige middag toen ik een edge-case met het verlopen van een sessie moest testen. Vóór de refactor zou ik een testdatabase hebben opgezet, de spot hebben gedreven met een HTTP-oproep en hebben gebeden. Na de refactor heb ik een nepsessie-adapter geïnstantieerd, de vervaldatum op 30 seconden geleden ingesteld en één bewering uitgevoerd.
De Legacy-Codebase-valkuil (en hoe u deze kunt vermijden)
Nu de waarschuwing, omdat ik deze fout bijna had gemaakt.
Als je deze skill uitvoert op een oudere codebase (een met fragmentarische testdekking, lage lokaliteit en overal shallow modules) is het eerste instinct om het rapport top-down te bekijken. Grijp de grootste kans op verdieping, refactor agressief, verzend.
Niet doen.
De reden dat elke senior engineer met littekens op zijn handen hetzelfde advies heeft - refactoreer geen ongeteste code - is dat shallow modules zonder tests precies de modules zijn waar verdieping dingen kapot maakt waarvan je niet wist dat ze bestonden. Bellers zijn afhankelijk van ongedocumenteerd gedrag. Randkasten verbergen zich in de scheuren tussen modules. De vorm van de bugs is precies wat de modules in de eerste plaats ondiep maakte.
De juiste zet is de niet-glamoureuze. Voordat u zich verdiept, schrijft u karakterisatietests rond de bestaande ondiepe module. Geen unittests. Geen perfecte testen. Gewoon tests die het huidige gedrag in kaart brengen – inclusief het buggy-gedrag – zodat je, als je je verdiept, een manier hebt om te weten wat er is veranderd. Het boek van Feathers is hier de canonieke referentie. De skill zelf beveelt in de README ongeveer dezelfde workflow aan voor oudere code: schrijf tests die het huidige gedrag documenteren van het cluster dat u gaat verdiepen, voer het verdiepingsvoorstel van de skill uit op basis van die tests en gebruik de testdelta's als een forceringsfunctie voor ontwerpbeslissingen.
Ik volg deze regel nu zelfs op greenfield-code. Als een verdiepingsvoorstel een module raakt die geen tests heeft, is de eerste commit in de refactor de testcommit. De verdiepingsopdracht komt op de tweede plaats. Het vertraagt me met misschien twintig minuten per refactor en bespaart me een uur later de foutopsporingssessies "wacht, waarom is het dashboard nu leeg". Handel die ik elke keer zal nemen.
Hoe vaak voer ik het nu uit (en waar het struikelt)
Ik voer de skill elke maandagochtend uit op mijn hoofdproject, en ongeveer elke vijf werkdagen op zijprojecten met een hoge commit-snelheid. Die cadans kwam voort uit een simpele observatie: bij een project waar ik dagelijks met Claude Code verzend, accumuleert de entropie zo snel dat een wekelijkse architectuurbeoordeling deze daadwerkelijk opmerkt voordat deze stolt. Bij een project dat grotendeels stabiel is, is maandelijks prima.
Het cadansadvies uit de documentatie van de skill is "elke paar dagen in snel bewegende codebases" en dat komt overeen met mijn ervaring. Als ik het twee of drie weken laat liggen, gaat het rapport van zes kansen naar vijftien, en op mijn vijftiende krijg ik beslissingsmoeheid en begin ik het rapport volledig te negeren. Zes is het juiste getal om daadwerkelijk actie op te ondernemen.
Nu het eerlijke deel: waar de skill struikelt.
Het is slecht in taalspecifieke idiomen. Toen ik het op een Go-service draaide, bleef het klassevormige ontwerpen voorstellen die niet bij Go pasten. De woordenschat van modules, interfaces en adapters vertaalt zich, maar de vorm van de voorstellen neigt naar TypeScript en Python. Als je een taal spreekt met een sterke eigen mening – Go, Rust, Elixir – besteed je de eerste vijf minuten van elk voorstel aan het vertalen van het idioom.
Het is ook blind voor de runtimekosten. Elk voorstel dat ik heb gekregen, ging over cognitieve kosten – hoe gemakkelijk is de code te begrijpen, hoe testbaar is de naad – en bij geen van hen is rekening gehouden met zaken als geheugenindeling, toewijzingspatronen of hot-path-prestaties. Voor de meeste app-code is dat prima. Voor alles wat prestatiegevoelig is, moet je je eigen oordeel er bovenop leggen.
En het derde struikelblok: er worden soms verdiepingsvoorstellen voorgesteld waarvoor ik de testsuite moet herschrijven om deze te kunnen valideren. Het voorstel ziet er op zichzelf prachtig uit, maar de kosten van de migratie – inclusief de tests die afhankelijk zijn van de huidige vorm – zijn hoger dan de waarde van de nieuwe vorm. De skill modelleert de migratiekosten niet erg goed. Ik lees nu elk voorstel met één vraag bovenaan: hoe ziet de migratie eruit en zijn de migratiekosten minder dan de invloed die ik zou krijgen? De helft van de tijd is het antwoord ja. Met de andere helft sluit ik het onderwerp.
Als je de oudere vaardigheden hebt uitgevoerd, zoals de Karpathy CLAUDE.md-installatie of een van de 32 dagelijkse Claude Code-hacks die ik vorige maand heb geschreven, staat deze skill er netjes boven. De hacks zorgen ervoor dat Claude Code sneller wordt verzonden. De architectuurskill is de architectonische druk die ervoor zorgt dat de snelheid uw codebase niet laat rotten.
De vraag die ik nu met me meedraag
Zes weken nadat ik deze skill wekelijks begon uit te voeren, is mijn codebase aanzienlijk anders dan voorheen. Niet dramatisch kleiner (ik heb niet zoveel code verwijderd) maar aanzienlijk beter navigeerbaar. De sessiemodule is één plek. De observatiemodule is één plaats. De formuliersamenstelling heeft één enkele voordeur. Als ik om 23.00 uur een bestand open om iets te debuggen, kan ik meestal het hele concept zien van het bestand waarin ik me bevind, in plaats van tussen vier bestanden heen en weer te springen en de architectuur uit het geheugen te reconstrueren.
De verandering die er meer toe doet, is die stroomopwaarts van de codebase. Wanneer ik Claude Code vraag om nu een nieuwe functie te leveren, denk ik eerst in modules. Waar komt de naad? Wat is de interface? Hoe ziet de diepe versie hiervan eruit? De skill heeft mij getraind om die vragen te stellen voordat ik de prompt schrijf, wat betekent dat de prompts zelf code produceren die al dichter in de buurt komt van wat de volgende scan van de skill zou voorstellen.
Software-entropie is eenrichtingsverkeer zonder architectonische druk. AI heeft de pijl zojuist sneller laten bewegen. De oplossing is niet langzamer AI. De oplossing is meer druk, eerder toegepast, door iets dat meegroeit met de verzendkosten. De skill improve-codebase-architecture komt volgens mij het dichtst in de buurt van die druk, en het is de enige tool voor architectuurbeoordeling in mijn workflow die de eerste maand heeft overleefd.
Als je één ding uit dit bericht overneemt, beantwoord dan de vraag die ik nu in elke Claude Code-sessie meedraag: is deze module dieper of ondieper dan wat hij vervangt? Stel deze vraag voordat je de prompt schrijft. Vraag het opnieuw als je het verschil leest. Vraag het op maandagochtend bij de koffie, terwijl een klein afwaardebestand uw repository scant en u de dingen vertelt die u al half wist, maar te moe was om onder ogen te zien.
Die vraag doet meer voor mijn code dan welke skills-, raamwerk- of refactoringtool dan ook die ik de afgelopen twee jaar heb geïnstalleerd. De codebase waarnaar u in 2027 verzendt, zal de codebase zijn die de vraag heeft gebouwd – of degene die deze niet heeft gemaakt.
Open het rapport. Lees de zes dingen. Kies er een.
Veelgestelde vragen
Wat is de improve-codebase-architecture-skill in Claude Code?
Het is een open-source skill van Matt Pocock die een repository scant op shallow modules en verdiepingsrefactoren voorstelt. Het draait binnen Claude Code, produceert een lijst met architectuurmogelijkheden en helpt u bij het interactief ontwerpen van de nieuwe interfaces. Voor het volledige overzicht van wat het op mijn repository heeft gevonden, zie "De dag dat ik het op mijn eigen repository uitvoerde" hierboven.
Wat is een diepgaande module in softwareontwerp?
Een diepe module is een module met een eenvoudige interface en een complexe implementatie, waardoor een beller heel weinig over de module leert, maar er veel gedrag voor terugkrijgt. De term komt uit John Ousterhouts A Philosophy of Software Design. Ondiepe modules hebben daarentegen interfaces die bijna net zo complex zijn als hun implementaties en bieden een lage hefboomwerking.
Hoe vaak moet ik de codebase-architectuurskill uitvoeren?
Om de paar dagen op snel veranderende codebases met dagelijkse door AI ondersteunde commits, en wekelijks tot maandelijks op stabielere repo's. De afgelopen drie weken van stilte groeit het rapport uit tot meer dan tien kansen en de beslissingsmoeheid slaat toe. Zes kansen per week zijn de goede plek om daadwerkelijk gevolg te geven aan de voorstellen.
Refactoreert de skill automatisch?
Nee, en dat is bewust. Het brengt verdiepingsmogelijkheden aan het licht en helpt je bij het ontwerpen van de nieuwe interface en naad, maar mensen maken elke architecturale beslissing en keuren elke verandering goed. Zodra u een voorstel accepteert, kan het een GitHub-probleem indienen om de refactor te volgen.
Moet ik modules in een bestaande codebase verdiepen zonder tests?
Niet direct. Schrijf eerst karakteriseringstests rond het ondiepe cluster om het bestaande gedrag vast te leggen, en verdiep je vervolgens met de tests als je vangnet. Het verdiepen van niet-geteste shallow modules is een van de snelste manieren om een regressie te verzenden.
Laten we samenwerken
Wilt u AI-systemen bouwen, workflows automatiseren of uw technische infrastructuur schalen? Ik help je graag.
- Fiverr (aangepaste builds en integraties): fiverr.com/s/EgxYmWD
- Portfolio: mejba.me
- Ramlit Limited (ondernemingsoplossingen): ramlit.com
- ColorPark (ontwerp en branding): colorpark.io
- xCyberSecurity (beveiligingsdiensten): xcybersecurity.io