ousterhout-quality-program
Wat het doet
Gebruik altijd wanneer code die wordt geschreven of beoordeeld een grens creëert of verandert — een nieuwe module, klasse, component, helper, hook, service of wrapper; elke extractie of centralisatie van gedeelde code; elk moment van "laten we dit herbruikbaar maken" — en bij expliciete beoordeling, refactoring of ontwerp van een module. Beoordeelt of een abstractie zijn waarde bewijst: modulediepte, of een ontwerpbeslissing verborgen moet worden, of gedupliceerde code een gedeelde invariant beschermt of slechts rijmt, of een interface stabiel is. Voorkomt mechanische SOLID/Clean Code die veel ondiepe klassen oplevert. Definieert ook de leeskosttest (code die goedkoop is voor mensen en agents om te lezen en te wijzigen) en de procedure voor het refactoren van een bestaande codebase naar deze standaard.
Installeren opent dit item in je AgentsRoom-desktopapp. Is de app nog niet geïnstalleerd, dan word je naar de downloadpagina gestuurd.
SKILL.md
---
name: ousterhout-quality-program
description: Gebruik altijd wanneer code die wordt geschreven of beoordeeld een grens creëert of verandert — een nieuwe module, klasse, component, helper, hook, service of wrapper; elke extractie of centralisatie van gedeelde code; elk moment van "laten we dit herbruikbaar maken" — en bij expliciete beoordeling, refactoring of ontwerp van een module. Beoordeelt of een abstractie zijn waarde bewijst: modulediepte, of een ontwerpbeslissing verborgen moet worden, of gedupliceerde code een gedeelde invariant beschermt of slechts rijmt, of een interface stabiel is. Voorkomt mechanische SOLID/Clean Code die veel ondiepe klassen oplevert. Definieert ook de leeskosttest (code die goedkoop is voor mensen en agents om te lezen en te wijzigen) en de procedure voor het refactoren van een bestaande codebase naar deze standaard.
---
# Ousterhout Kwaliteitsprogramma
## Overzicht
De taak van een module is om complexiteit te verbergen achter een kleine interface. De kernmaatstaf is **diepte**: een diepe module biedt een eenvoudige interface over aanzienlijke functionaliteit; de interface van een ondiepe module is bijna net zo complex als de implementatie, dus die betaalt zich nergens voor terug. Complexiteit is wat je voelt wanneer een wijziging je dwingt code te begrijpen of aan te passen die je niet had verwacht — Ousterhout noemt twee bronnen: **afhankelijkheden** (je kunt A niet veranderen zonder B te veranderen) en **onduidelijkheid** (de belangrijke informatie is niet duidelijk).
Ousterhout alleen vertelt je hoe een goede module *voelt*. Het is het sterkst in combinatie met een paar andere lenzen die je vertellen waar de grenzen horen te liggen en hoe je er veilig naartoe kunt bewegen. Deze skill is die gecombineerde lens.
## Waar reviews echt misgaan
De twee fouten die deze skill wil corrigeren — herhaaldelijk waargenomen in door agents geschreven code — zitten in het **oplossing**, niet in het oordeel split/niet-split zelf:
1. **De ondiepe oplossing.** Gegeven zes `as unknown as` casts, centraliseert de niet-ondersteunde reviewer ze in één generieke `castRows<T>()` helper — netter, maar de onduidelijkheid blijft bestaan. De diepe oplossing is getypte rij→domein mappers met eerst vastgezette tests (toepassing van Parnas: een cast is de geur van een ontbrekende grens; Beck: bewijs de mapping voordat je hem verplaatst). Het netter maken van een geur is het niet verwijderen ervan.
2. **De reflexmatige extractie.** Gegeven dezelfde update-logica die in drie zustercomponenten wordt herhaald, zei elke niet-ondersteunde reviewer "extraheer een gedeelde helper" — de DRY-reflex. De regel van dit programma, voortbouwend op Metz: wacht op de invariant, niet op de derde gelijkenis — centraliseer wanneer de code een gedeelde regel beschermt, niet wanneer het rijmt.
Wanneer je jezelf een oplossing ziet aanbevelen, toets die dan aan beide: verwijdert het de onduidelijkheid of verplaatst het die alleen, en beschermt de extractie een invariant of dedupliceert het alleen een vorm?
## Proportionaliteitspoort
Sla de lens over wanneer een wijziging geen nieuwe geëxporteerde/importeerbare naam toevoegt, geen nieuwe module/klasse/component/helper/hook/service/wrapper creëert en niets centraliseert. Pure hernoemingen, mechanische codemods, config/data-bewerkingen en eendelige fixes zijn vrijgesteld. Bij twijfel voer je alleen de twee kerntesten uit (diepte, invariant) en stop je daar.
## De regel in zijn geheel
Elk stuk gegenereerde of gereviewde code gaat door de Ousterhout-lens voordat de taak als voltooid wordt beschouwd — niet alleen expliciete designreviews — behalve wijzigingen onder de proportionaliteitspoort (geen nieuwe grens, geen centralisatie: hernoemingen, codemods, config-bewerkingen). Twee testen: (1) **Diepte** — een nieuwe interface moet substantieel meer verbergen dan het blootlegt; een interface die net zo complex is als wat het omhult betaalt zich nergens voor terug. (2) **Invariant** — extraheer gedeelde code alleen wanneer het een gedeelde regel beschermt, nooit omdat drie plekken rijmen; en een oplossing moet onduidelijkheid verwijderen, niet verplaatsen (zes casts centraliseren in één helper zijn nog steeds zes casts). Wanneer een wijziging een grens creëert of hervormt, zoek dan eerst hoe een gevestigd product een probleem van deze vorm en schaal oplost en neem diens conventies over tenzij er een uitgesproken reden is om dat niet te doen (een patroon dat je uit training herinnert is een claim, geen bron), en voer dan de onderstaande controles uit.
## Wanneer te gebruiken
- Beslissen of een nieuwe klasse/functie/hook zijn interface waard is, of slechts een ondiepe doorgeefluik.
- Een bestand overschrijdt een groottegrens en je beslist *hoe* je het splitst, niet alleen dat je het moet doen.
- Herhaalde code verleidt je tot het extraheren van een gedeelde helper.
- Ontwerpen of reviewen van een grens rond een zakelijke regel (een autorisatiescope-check, een geld-/afrondingsregel, een toestandsmachine-transitiebeveiliging, een data-retentie-regel).
- Een interface staat op het punt een parameter of een speciaal geval te krijgen.
- Een bestaande codebase naar deze standaard brengen — zie "Refactoring an Existing Codebase to This Standard" hieronder.
**Niet voor:** triviale mechanische bewerkingen, of wanneer een projectconventie de structuur al voorschrijft — zie de Proportionaliteitspoort hierboven. Volg `karpathy-guidelines` voor discipline bij chirurgische wijzigingen en een test-driven-development skill als vangnet voor refactorveiligheid, wanneer die beschikbaar zijn.
## De lenzen
Elke lens voegt precies één vraag toe. Ousterhout is de ruggengraat; de anderen corrigeren zijn blinde vlekken.
| Lens | De ene vraag die het toevoegt | Wanneer het overschrijft |
|---|---|---|
| **Ousterhout** — diepe modules | Verbergt deze interface meer dan het blootlegt? | Standaard ruggengraat. |
| **Parnas** — informatie verbergen | Welke ontwerpbeslissing (waarschijnlijk te veranderen) verbergt deze module? | De *reden* waarom een module diep zou moeten zijn. Als het niets verbergt dat verandert, is diepte cosmetisch. |
| **Brooks** — essentieel versus toevallig | Verwijdert dit toevallige complexiteit, of verplaatst het alleen essentiële domeincomplexiteit? | Doodt "refactors" die de rommel verplaatsen zonder het te verkleinen. |
| **Evans** — Domain-Driven Design | Is deze grens benoemd in domeintaal, niet in generieke hulpprogrammataal? | Hernoem `utils`/`helpers` — noem de grens naar de invariant die deze repo daadwerkelijk heeft. |
| **Fowler** — refactoring / geuren | Wat is de kleinste veilige stap naar het diepere ontwerp? | Zet "zou dieper moeten zijn" om in concrete stappen achter geslaagde tests. |
| **Beck** — eenvoudig ontwerp, test-eerst | Heb ik het huidige gedrag bewezen voordat ik de naad verdiep? | Een rem op voortijdige architectuur. Laat het eerst werken en getest zijn, verdiep dan de juiste naad. |
| **Hickey** — eenvoudig versus makkelijk | Vermengt dit niet-verwante concepten, of is het echt één concept? | Een ondiepe helper is meestal *makkelijk* (dichtbij, snel), niet *eenvoudig* (weinig vermengde concepten). Geef de voorkeur aan eenvoudig. |
| **Metz** — duplicatie boven verkeerde abstractie | Beschermt deze herhaalde code een gedeelde invariant, of lijkt het alleen maar op elkaar (de regel van dit programma, uitbreiding van Metz)? | Metz: duplicatie is goedkoper dan de verkeerde abstractie — inline een verkeerde abstractie terug in plaats van het te buigen. Dit programma breidt haar uit: centraliseer **niet** omdat het herhaalt; centraliseer alleen als het een echte invariant beschermt. Tolereren duplicatie totdat de invariant zich onthult. |
| **Hyrum's Law** — observeerbaar gedrag | Zullen aanroepers afhankelijk zijn van gedrag buiten het contract van deze interface? | Pleit voor kleine, stabiele interfaces: elk observeerbaar gedrag wordt uiteindelijk dragend. |
## Het Combinatie Recept
Pas toe in deze volgorde — latere lenzen zijn alleen van belang als de eerdere slagen:
1. **Metz — de toegangscontrole.** Verdient deze grens/abstractie überhaupt bestaan? De regel van dit programma, uitbreiding van Metz: extraheer alleen als de code een gedeelde regel beschermt — drie gelijken zijn geen onthulde invariant. Zo niet, stop hier.
2. **Parnas / Ousterhout** — Verberg de vluchtige beslissing (autorisatiescope, afrondingsregel, overgangsbewaker, bewaartermijnregel) achter een diepe module.
3. **Evans** — Noem die module in domeintaal, niet `utils`.
4. **Beck / Fowler** — Voor bestaande code, veranker het huidige gedrag met tests, refactor dan ernaartoe in kleine veilige stappen. Voor vers gegenereerde code is er geen huidig gedrag om te verankeren — schrijf in plaats daarvan de test die het bedoelde gedrag definieert.
5. **Hickey** — Verwerp interfaces die niet-verwante concepten mengen alleen omdat de workflows er vergelijkbaar uitzien.
## Het Structurele Anti-Patroon
**Mechanische SOLID / Clean Code produceert ondiepe modules.** Een dogmatische lezing —
een klasse per verantwoordelijkheid, elke functie extraheren, alles klein houden —
leidt tot een zwerm klassen waarvan de interfaces net zo complex zijn als hun lichamen. Wanneer
een regel zegt "splits dit," vraag dan welke *beslissing* de splitsing verbergt (Parnas) en
of het meer verbergt dan blootlegt (Ousterhout). Als het niets verbergt dat
verandert, splits dan niet. Deze bewaking is het belangrijkst onder refactor-druk ("maak dit schoon", "dit bestand is te groot") — bij rustige analyse verzetten beoordelaars zich er al tegen; midden in een refactor, met een mandaat om zichtbare verandering te produceren, wordt de zwerm ondiepe bestanden geschreven.
## Veelvoorkomende Fouten
- **Splitsen alleen op grootte.** Een querymodule van 400 regels die één samenhangende beslissing verbergt kan dieper zijn dan vier modules van 100 regels die elk dezelfde joins lekken.
- **De splitsing `helpers`/`utils` noemen.** Als je het niet in domeintaal kunt noemen (Evans), is de grens waarschijnlijk verkeerd.
- **Extraheren bij de tweede keer.** De regel van dit programma, uitbreiding van Metz: wacht op de invariant, niet op de derde gelijkenis.
- **Verdiepen voordat gedrag verankerd is.** Beck: zonder een test die het huidige gedrag bewijst, is een "verdiepende" refactor een herschrijving.
- **Een doorgeefluik als module tellen.** Een wrapper die zijn argumenten doorgeeft voegt een interface toe en verbergt niets — ondiep per definitie.
- **Een rijm verwarren met een invariant.** Het beste bewijs van een gedeelde invariant is co-verandering: de kopieën zijn samen in de geschiedenis gefixt of veranderd (dezelfde bug op twee plaatsen opgelost). Gelijken die onafhankelijk veranderen zijn rijmen; laat ze gedupliceerd.
- **Een geur netjes maken in plaats van verwijderen.** Het centraliseren van zes casts in één generieke cast-helper is de nette versie van dezelfde onduidelijkheid. De diepe oplossing benoemt de grens die de cast verborg.
## Lezerskosten: de Derde Test
Diepte en invariant bepalen of een grens zou moeten bestaan. Lezerskosten
bepalen of de code eromheen goedkoop te veranderen is. De volgende lezer, mens
of agent, betaalt voor elke regel die ze moeten laden om iets veilig te veranderen.
Agents betalen in tokens en navigeren via tekstzoekopdrachten, gedeeltelijke lezingen en
typecheck/test-lussen, dus dezelfde defecten kosten hen meer. Vraag:
- **Vindbaar?** Eén naam per concept, overal hetzelfde gespeld, bereikbaar via gewone tekstzoekopdracht. Defecten: namen samengesteld uit strings, koppeling via import-neveneffect, herexportketens die de definitie verbergen, twee namen voor één concept.
- **Kan de lezer vroeg stoppen?** Het contract staat bovenaan het bestand of boven de export: wat het belooft, wat het verbergt, wat het nooit doet. Defect: het contract kan alleen worden afgeleid door de body te lezen.
- **Machinecontroleerbaar?** Precieze types in en uit elke grens, zodat een typecheck het lezen van aanroepen vervangt. Defecten: `any`, kale dictionaries, booleaanse vlaggen waarvan de betekenis in de body leeft.
- **Is koppeling zichtbaar?** Plaatsen die samen moeten veranderen worden afgedwongen (een gedeeld type, een test, een enkele bron) of, bij gebrek daaraan, op beide plekken gemarkeerd. Het bewijs van verborgen koppeling is co-verandering in de geschiedenis die nergens in de code wordt genoemd.
- **Ruisvrij?** Geen commentaar dat de code herhaalt, geen uitgecommentarieerde code, geen dode takken, geen commentaar over wijzigingsgeschiedenis, geen verouderd pad naast de vervanging.
- **Voorspelbaar?** Layout volgt het bestaande patroon van de repo; de test is waar een lezer zal zoeken en draait zelfstandig.
Bestandsgrootte is bewust afwezig. Een heel groot bestand is een reden om te zoeken naar een tweede verborgen beslissing, nooit een reden om te knippen: lezers kunnen zoeken en een bereik lezen, en een splitsing die niets verbergt voegt interfaces toe zonder belasting te verwijderen.
Voor in-code markers en een repo-codemap, gebruik `context-audit` waar beschikbaar: de `AIDEV-NOTE:` anker (één niet-herstelbaar feit plus een herkomstverwijzing, maximaal twee regels, op de plek zelf) is de conventie voor koppeling die niet kan worden afgedwongen.
## Refactoren van een bestaande codebase naar deze standaard
Een retrofit wordt op dezelfde manier beoordeeld als nieuwe code; wat verschilt is volgorde en terughoudendheid. Het grootste deel van een codebase moet ongemoeid worden gelaten.
1. **Census, alleen-lezen.** Maak een lijst van de grenzen (modules, services, gedeelde helpers). Voor elk record: de beslissing die het verbergt, of "geen"; interfacegrootte versus body; co-veranderpartners uit de geschiedenis; lezer-kosten defecten. Verander nog niets.
2. **Rangschik op churn, niet op lelijkheid.** Prioriteit is hoe vaak de code verandert maal wat het kost om te lezen. Koude code die werkt blijft zoals het is, hoe oppervlakkig ook. Essentiële domeincomplexiteit blijft waar het is (Brooks).
3. **Ken één remedie toe per bevinding:**
- doorgeeflaag of wrapper die niets verbergt: verwijder het, aanroepen gebruiken wat het wikkelde;
- verkeerde abstractie verbogen door vlaggen en speciale gevallen: inline terug (Metz), zoek dan de echte invariant;
- oppervlakkige broers die één beslissing delen: voeg ze samen achter één interface;
- gelekte beslissing (aanroepen kennen het formaat, de regel, het schema): trek het naar beneden in de module die het bezit;
- generieke naam (`utils`, `helpers`, `manager`): hernoem naar de beslissing die het verbergt, of los het op in zijn aanroepen;
- ongetypeerde grens: typeer het, en vervang casts door de mapper die ze camoufleerden;
- verborgen koppeling: dwing het af, of markeer beide plekken;
- ruis: verwijder het.
Rijm die onafhankelijk veranderen krijgen geen remedie.
4. **Pin gedrag eerst.** Geen remedie start totdat een test het huidige gedrag van de code die het raakt bewijst (Beck). Refactors behouden gedrag; een gedragsverandering is een aparte commit.
5. **Snijd het werk in eenheden die één agent alleen kan afmaken.** Eén grens per eenheid. Elke eenheid noemt de bestanden die het bezit, het contract dat het moet behouden, en het commando dat het zelfstandig bewijst. Geen twee gelijktijdige eenheden schrijven hetzelfde bestand; gedeelde bestanden (barrels, registries, routetabellen) krijgen één eigenaar of wachten op integratie. Interfacewijzigingen waar meerdere eenheden van afhankelijk zijn landen eerst, als eigen eenheid.
6. **Meet het resultaat.** Kies een representatieve wijziging voor het starten en tel de bestanden en regels die een lezer moet laden om het te maken; tel opnieuw daarna. Geëxporteerde namen en totaal aantal regels moeten dalen of gelijk blijven. Een refactor die interfaces toevoegt moet een opgegeven reden geven.
7. **Stop** wanneer wat overblijft koud, essentieel of een rijm is.
Gerelateerde skills, waar beschikbaar: `repo-review` (ontwerp type) produceert de census als een advies-alleen artefact; `design-cleanup` voert de fix-en-her-scan lus uit voor toevallige complexiteit; `context-audit` voegt ankers en de codemap toe; `ousterhout-build-deep` is de checklist voor de auteurstijd voor de agents die de eenheden doen.
## Waar dit zit
Deze skill is de review- en beoordelingslaag: gebruik het om te beslissen of een abstractie diep is, genoemd naar de juiste beslissing, en het waard is om te extraheren. `find-shared-code` gebruikt het als toelatingstest bij het doorzoeken van recente geschiedenis naar code die het delen waard is. De bijlage hieronder geeft de redenering van elke auteur.
---
## Bijlage: De lenzen in detail
De faalmodus die elke auteur vangt, en de ene zet die elk je geeft. De tabel hierboven is de snelle referentie; dit is de redenering erachter.
### Ousterhout — Diepe modules (de ruggengraat)
*Een Filosofie van Softwareontwerp.*
- **Diepte** = voordeel (verborgen functionaliteit) ÷ kosten (interfacecomplexiteit). Een diepe module verbergt veel achter weinig. De interface van een ondiepe module is bijna net zo complex als de body, dus verdient niets.
- **Complexiteit** is alles aan het systeem dat het moeilijk maakt te begrijpen of te wijzigen. Twee bronnen:
- **Afhankelijkheden** — je kunt het ene stuk niet veranderen zonder het andere aan te raken.
- **Onduidelijkheid** — de belangrijke informatie is niet duidelijk uit de code.
- **Symptomen:** versterking van veranderingen (één beslissing, veel bewerkingen), cognitieve belasting (hoeveel je in je hoofd moet houden), onbekende onbekenden (je kunt niet zeggen welke code een wijziging zal raken).
- **Belangrijke zet:** trek complexiteit *omlaag* — de module absorbeert het moeilijke geval zodat aanroepen dat niet hoeven. Configuratieparameters en doorgeeflagen duwen complexiteit *omhoog* naar de aanroeper; dat is ondiepte.
Vangt: interfaces die hun implementatie lekken; helpers die niet helpen.
### Parnas — Informatieverberging (waarom diepte ertoe doet)
*Over de criteria die gebruikt moeten worden bij het decomponeren van systemen in modules (1972).*
- Decomposeer rond **ontwerpbeslissingen die waarschijnlijk zullen veranderen**, niet rond de stappen van
een berekening. Elk module verbergt zo'n beslissing.
- Dit is de directe voorloper van de diepe module. Een module is diep *omdat* het
een beslissing verbergt die anders door de aanroepers zou doorwerken.
Valkuilen: een "module" die niets vluchtigs verbergt — de diepte is cosmetisch. Vraag:
wat verandert er achter deze interface dat aanroepers nooit zien? Als het antwoord is
"niets," is de grens decoratie.
### Brooks — Essentiële versus toevallige complexiteit
*No Silver Bullet.*
- **Essentiële** complexiteit is inherent aan het domein (taxatie is echt zo
ingewikkeld). **Toevallige** complexiteit is wat onze tools en structuur opleggen.
- Alleen toevallige complexiteit is verwijderbaar. Een refactor die "opschoont" door essentiële domeincomplexiteit van het ene bestand naar het andere te verplaatsen, heeft niets gedaan.
Valkuilen: herschikkingen die zich voordoen als vereenvoudiging. Vraag: is de totale complexiteit gedaald,
of is die alleen verplaatst?
### Evans — Domain-Driven Design
*Domain-Driven Design.*
- Grenzen moeten worden benoemd in de **ubiquitaire taal** van het domein, niet in
generieke utility-termen. Een module genaamd `helpers` zegt niets; een module genaamd
`AccessScope` of `PricingPolicy` benoemt een invariant.
- Bounded contexts voorkomen dat zakelijke invarianten lekken over grenzen heen.
Valkuilen: correcte decompositie met betekenisloze namen. Als je de module niet in domeintaal kunt benoemen,
heb je waarschijnlijk de grens op de verkeerde plek gesneden.
### Fowler — Refactoring en Code Smells
*Refactoring.*
- Biedt concrete, veilige, benoemde stappen (Extract Function, Move Field, Replace
Conditional with Polymorphism) om van het huidige ontwerp naar het diepere te komen.
- Elke stap behoudt het gedrag en is klein, zodat het omkeerbaar blijft.
Valkuilen: de kloof tussen "dit zou dieper moeten" en weten wat de volgende commit is.
Ousterhout stelt het doel; Fowler is de weg ernaartoe.
### Beck — Simpel Ontwerp, Test-First
*Test-Driven Development; XP.*
- Vier regels van simpel ontwerp, in de gepubliceerde volgorde van Beck: slaagt voor tests, geen
duplicatie, onthult intentie, zo min mogelijk elementen. Dit programma volgt de
latere herordening van Fowler/Haines — intentie vóór duplicatie — omdat het
dient voor de Metz-uitbreidende invariantregel van dit programma (zie Metz, hieronder):
handel niet op duplicatie totdat je de intentie kunt benoemen die het beschermt.
- Test-first is een rem tegen voortijdige architectuur. Laat het eerst werken en bewijs
het gedrag *eerst*, verdiep dan de naad die de tests nu beschermen.
Valkuilen: architectuur gebouwd voordat gedrag is vastgelegd. Zonder een test die het
huidige gedrag bewijst, is een "verdiepende" refactor een niet-geverifieerde herschrijving.
### Hickey — Simpel versus Makkelijk
*Simple Made Easy.*
- **Simpel** = niet verstrengeld: één concept, niet vermengd met anderen (objectief).
- **Makkelijk** = dichtbij, vertrouwd, snel te bereiken (relatief tot jou).
- De twee zijn onafhankelijk. Een ondiepe helper is meestal *makkelijk* — snel te schrijven,
dichtbij — maar niet *simpel* als het ongepaste zorgen vermengt.
Valkuilen: gemak dat zich voordoet als ontwerp. Geef de voorkeur aan constructies die concepten
onverstrengeld houden, ook al is een verstrengelde sneller te typen.
### Metz — Geef de voorkeur aan duplicatie boven de verkeerde abstractie
*"The Wrong Abstraction" (2016).*
- Duplicatie is veel goedkoper dan de verkeerde abstractie. Een abstractie die te vroeg wordt geëxtraheerd,
dwingt elke toekomstige aanroeper om zich aan te passen aan aannames die nooit voor allemaal waar waren.
- Wanneer een abstractie verkeerd blijkt, is Metz' remedie om deze weer inline te plaatsen en de duplicatie terug te laten keren,
in plaats van het te buigen om te passen bij een geval waarvoor het nooit gebouwd was.
- **De regel van dit programma, die Metz uitbreidt: centraliseer niet omdat code zich herhaalt.
Centraliseer wanneer het een echte, gedeelde invariant beschermt.** Totdat de invariant zich openbaart,
tolereer de duplicatie.
Valkuilen: overcentralisatie — de ondiepe gedeelde helper waar iedereen nu omheen moet werken.
Dit is het tegenwicht tegen een mechanische "DRY koste wat kost."
### Hyrum's Law — Observeerbaar gedrag wordt contract
*"Met een voldoende aantal gebruikers zal elk observeerbaar gedrag van je systeem
worden gebruikt door iemand."*
- Wat een interface *toevallig* doet — ordening, timing, fouttekst — zal uiteindelijk door iemand worden vertrouwd.
Dus het oppervlak dat je blootstelt is groter dan het oppervlak dat je hebt gedocumenteerd.
- Dit ondersteunt Ousterhout's voorkeur voor **kleine, stabiele interfaces**: hoe minder je blootstelt,
hoe minder per ongeluk dragend kan worden.
Valkuilen: brede interfaces die zullen verstenen. Elke extra observeerbare wordt een toekomstige beperking.
### Hoe ze samenhangen
- **Parnas → Ousterhout:** verberg een vluchtige beslissing → de module is diep.
- **Brooks:** bevestig dat de diepte complexiteit verwijderde in plaats van verplaatste.
- **Evans:** benoem de grens in domeintaal.
- **Beck → Fowler:** leg gedrag vast, refactor dan in kleine veilige stappen.
- **Metz:** weersta centralisatie totdat de invariant echt is.
- **Hickey:** houd de interface tot één concept.
- **Hyrum:** houd die interface klein zodat die stabiel kan blijven.
Het gevaar is Ousterhout te mengen met een mechanische interpretatie van SOLID of Clean Code:
dat produceert veel kleine klassen en functies met ondiepe interfaces — het exacte tegenovergestelde van diepe modules.
Ousterhout, met Metz als tegenwicht, is het tegengif.
Tags
Meer over dit onderwerp
Claude Ads: de Claude Code vaardigheid die je advertentieaccounts controleert
Claude Ads is een open source vaardigheid voor Claude Code: 250+ controles op Google, Meta, LinkedIn, TikTok of Amazon Ads, een score uit 100 en een geprioriteerd actieplan, in ongeveer tien minuten. Installeren, commando's, limieten, en hoe het te orkestreren in AgentsRoom.
AGENTS.md: Eén contextbestand voor elke coderingagent (Codex, Antigravity, Claude)
AGENTS.md is het draagbare instructiebestand dat je AI-coderingsagents lezen voordat ze je code aanraken. Wat erin te zetten, hoe het verschilt van CLAUDE.md, en hoe je één context behoudt over Codex, Antigravity en Claude.
Download AgentsRoom
Draai al je AI-agenten, op al je projecten, vanuit één enkel venster.
Companion-app: houd je agents onderweg in de gaten
Breng je eigen: Claude, Codex, Antigravity CLI of andere AI-provider.
Stuur bugs en verzoeken direct naar je openbare backlog.