From 67fce7a330501030edd6271fb4fcece9de335f8f Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Sat, 29 Aug 2026 21:35:39 +0200 Subject: [PATCH] skill info added --- skill/racket-skill.md | 227 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 skill/racket-skill.md diff --git a/skill/racket-skill.md b/skill/racket-skill.md new file mode 100644 index 0000000..4674b22 --- /dev/null +++ b/skill/racket-skill.md @@ -0,0 +1,227 @@ +--- +name: racket-programmeer-skill +description: Hiermee wordt mijn voorkeur racket programmeerstijl aangegeven. +--- + +--- +name: racket-programmeerstijl +description: Gebruik deze skill wanneer je Racket-code voor Hans schrijft, wijzigt, refactort of beoordeelt. Pas de bestaande, eenvoudige en procedurele programmeerstijl toe; voorkom over-engineering en onnodige abstracties. Gebruik deze skill niet voor algemene uitleg over Racket waarbij geen code voor zijn projecten wordt gemaakt of aangepast. +--- + +# Racket-programmeerstijl + +Gebruik deze stijl wanneer je Racket-code voor Hans schrijft of aanpast. + +## Uitgangspunt + +Het *allerbelangrijkste* uitgangspunt is dat je de programmerstijl van aangeleverde code volgt. +Als je een zip met een package aangeleverd krijgt via de prompt dan volg je de programmeerstijl die je in de aangeleverde code vindt. +Wanneer bestaande broncode beschikbaar is, heeft de stijl van die broncode voorrang. Sluit daar zo nauw mogelijk op aan. + +Schrijf eenvoudige, directe en goed leesbare Racket-code. +Kies de kleinste oplossing die het huidige probleem netjes oplost. +Bouw geen abstraheringslaag voor mogelijk toekomstig gebruik. +En maak geen helpers die alleen maar in de weg staan. + +## Structuur + +- Houd modules klein en doelgericht. +- Splits functionaliteit alleen af naar een private module wanneer die een duidelijk eigen doel heeft. +- Gebruik voor duidelijke secties bij voorkeur commentaar in deze vorm: + +```racket +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Supporting functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +``` + +of, wanneer dat beter bij de module past: + +```racket +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Internal state / functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +``` + +Voor publieke functies: + +```racket +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Provided functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +``` + +- Houd `provide` en `require` eenvoudig en overzichtelijk. +- Voeg geen extra framework, wrapperlaag of generieke infrastructuur toe zonder concrete noodzaak. + +## pre/postcondities + +Geëxporteerde functies/procedures/classes of functies/procedures/classes die daarvoor duidelijk in +aanmerking komen, d.w.z. die die provided zijn of naar verwachting zullen worden, moeten gedocumenteerd worden. +Zowel in een module scribble als in de code zelf. In het engels. + +In de code zelf: minimaal: + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; goal : +; pre : +; post : +; [result:] + +Over het algemeen wil je de internals van een functie weten. Hoe werkt het en waarom werkt het zo. + +; [internals:] +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Als een functie/procedure/class overduidelijk in aanmerking komt voor 'provide' en hij staat er nog niet in. +Verzamel dan de lijst en vraag of je ze moet toevoegen. + +## Procedures en control flow + +- Geef de voorkeur aan gewone procedures met een direct leesbare control flow. +- Gebruik van `let`, `let*`, `letrec`, `if`, `when`, `unless`, `begin` en `cond` heeft de voorkeur. +- `map`, `filter`, en dat soort constructies gaan boven meer abstracte constructies als `for/or`, etc. +- Gebruik bij voorkeur geen `define` binnen een procedure, tenzij het echt om een locale + functie definitie gaat die een dermate omvang krijgt dat het binnen de closure gerechtvaardigd is. +- `let-values` is prima om te gebruiken. +- Maak niet voor iedere kleine stap een aparte helperprocedure. +- Introduceer geen hogere-orde of functionele constructies alleen omdat dat compacter kan. +- Gebruik recursie of een named `let` wanneer dat de meest directe oplossing is. +- Gebruik bij `cond` bij voorkeur deze vorm: + +```racket +(cond + ([condition] korte body) + ([other-condition] + langere body)) + (else ... alleen als het nodig is) +``` + +## Mate van abstractie vs leesbaarheid + +Liever concreet dan abstract. + +Geef expliciete, goed leesbare constructies de voorkeur boven compacte abstracte idiomen. + +Bijvoorbeeld combinaties als (filter values (list (and condition 'symbol) ...)). +Schrijf dan liever expliciet (filter (lambda (x) x) (list (if condition 'symbol #f) ...)). +Vermijd vooral het stapelen van meerdere impliciete idiomen wanneer dat de leesbaarheid vermindert. + +## Gebruik lambda. + +Geef de voorkeur aan λ boven lambda. + +## Waarden en state + +- Gebruik `#f` als normale waarde voor "niet gevonden", "niet beschikbaar" of "nog niet geïnitialiseerd" wanneer dat natuurlijk past. +- Expliciete vergelijkingen zoals `(eq? value #f)` zijn prima wanneer dat de bedoeling duidelijk maakt. +- Houd state eenvoudig. Een gewone modulevariabele zoals `cached-git-exe` is prima wanneer daarvoor geen zwaarder mechanisme nodig is. +- Gebruik geen parameters, structs, classes of objectlagen wanneer een gewone variabele of procedure voldoende is. + +## Publieke API + +- Gebruik `define/contract` voor publieke procedures wanneer een contract nuttige documentatie en controle geeft. +- Houd publieke procedures klein en voorspelbaar. +- Verander een bestaande publieke API niet zonder noodzaak. +- Voeg geen extra publieke functies toe voor hypothetische toekomstige behoeften. + +## Fouten en interactie + +- Geef duidelijke en concrete foutmeldingen. +- Los eenvoudige interactieve invoer lokaal en procedureel op. +- Maak foutafhandeling niet generieker dan nodig. +- Als een externe executable of voorziening ontbreekt, meld precies wat ontbreekt en wat de gebruiker kan doen. + +## Configuratie + +- Bewaar lokale configuratie in een kleine, afzonderlijke private module wanneer dat de hoofdmodule eenvoudiger maakt. +- Gebruik bestaande projectvoorzieningen, zoals `simple-ini`, rechtstreeks in plaats van er een extra abstractielaag omheen te bouwen. +- Dupliceer geen configuratie die al door een extern programma zelf wordt beheerd. + +## Naamgeving en leesbaarheid + +- Kies concrete, korte namen die passen bij de bestaande code. +- Gebruik Engels voor identifiers en technische namen wanneer de bestaande code dat doet. +- Schrijf comments alleen wanneer ze iets toevoegen dat niet al vanzelf uit de code blijkt. +- Geef de voorkeur aan een paar duidelijke regels boven een compacte maar moeilijker leesbare expressie. + +## Vermijd + +Vermijd zonder concrete noodzaak: + +- over-engineering; +- generieke wrappers; +- extra abstraheringslagen; +- dynamische `require`-constructies; +- classes wanneer procedures volstaan; +- structs wanneer een eenvoudige waarde volstaat; +- configuratie-objecten of dependency-injectionpatronen; +- veel kleine helperprocedures die de control flow versnipperen; +- refactors die alleen bedoeld zijn om code "slimmer" of abstracter te maken. + +## Werkwijze bij aanpassen van bestaande code + +1. Lees eerst de omliggende module(s). +2. Neem naamgeving, inspringing, control-flow-stijl en module-indeling over. +3. Wijzig alleen wat voor de gevraagde stap nodig is. +4. Houd bestaande werkende code intact als er geen reden is die te veranderen. +5. Voeg geen volgende architectuurstappen alvast toe. +6. Controleer of de oplossing eenvoudiger is dan het probleem; zo niet, vereenvoudig. + +## Referentiestijl + +Deze vorm is representatief: + +```racket +(define cached-value #f) + +(define/contract (get-value) + (-> (or/c path? #f)) + (if (eq? cached-value #f) + (let ((value (find-value))) + (set! cached-value value) + value) + cached-value)) +``` + +Een wat langere maar direct leesbare implementatie heeft de voorkeur boven een kortere oplossing met meerdere nieuwe abstracties. + +# Schrijven van testgevallen voor modules/packages + +Een test die alleen werkt vanuit de development directory, op het development-OS of met de lokale shell/environment is geen geldige package-test. + +## Racket Package Index / build-service tests + +Behandel de Racket Package Index/build service als een aparte, strikte +en onbekende testomgeving. + +Bij packagecode en tests gelden daarom altijd de volgende regels: + +- Maak nooit aannames over `current-directory` of de directory van waaruit + code of tests worden uitgevoerd. Bepaal testdata en paden expliciet en + relocatable, bijvoorbeeld met runtime paths en tijdelijke directories. + +- Maak nooit impliciete aannames over het besturingssysteem. Vermijd + OS-specifieke paden, shells, executables en gedrag, of handel verschillen + expliciet per platform af. + +- Maak tests onafhankelijk van lokale environment state. Benodigde + environment variables moeten expliciet en bij voorkeur geïsoleerd worden + ingesteld. + +- Een succesvolle test moet stil en ondubbelzinnig succesvol zijn. + Laat geen verwachte foutmeldingen naar de echte stdout/stderr lekken, + omdat `raco test --drdr` en de Package Index dergelijke output als een + mogelijke test failure kunnen classificeren. + +- Verwachte foutoutput moet worden gecaptureerd en geassert. + +- Tests moeten hun eigen tijdelijke state en testbestanden aanmaken en + mogen geen bestanden, processen, environment changes of andere state + achterlaten. + +- Test packagewijzigingen waar mogelijk ook in een omgeving die lijkt op: + `raco setup --check-pkg-deps` en + `raco test --drdr --package `. + +