cmap functions, email, architecture documentation.

This commit is contained in:
2026-08-18 03:33:10 +02:00
parent 12f1ed2764
commit 63b7ca0853
33 changed files with 3974 additions and 80 deletions
+62
View File
@@ -0,0 +1,62 @@
# Modulariteit en afhankelijkheden
## Huidige modulegrenzen
De backend is functioneel opgesplitst. Configuratie, databaseverbinding, migraties, authenticatie, paginaopslag, CMap-opslag, mail, setup en vendorbeheer hebben ieder een herkenbare module. Deze modules communiceren hoofdzakelijk met gewone Racket-waarden: structs, hashes, lijsten en strings.
De belangrijkste grens is die tussen `server.rkt` en de opslagmodules. `server.rkt` hoort HTTP te begrijpen; `storage.rkt`, `cmap-storage.rkt` en `auth.rkt` horen domeinbewerkingen en database-invarianten te begrijpen. Geen opslagprocedure mag een webrequest nodig hebben.
De frontend heeft een vergelijkbare grens. `cmap-racket-wiki.js` implementeert een editorcomponent met callbacks voor openen, selectie en wijzigingen. `wiki.js` koppelt die callbacks aan routes, API's en dialoogvensters.
## Sterke punten
De volgende onderdelen zijn al goed geïsoleerd:
- `wiki-config` bundelt runtimekeuzes en voorkomt verspreide globale configuratie.
- `call-with-wiki-database` centraliseert openen en sluiten van verbindingen.
- opslagprocedures kapselen SQL en transacties in.
- de CMap-documentvorm is een expliciet JSON-contract met `schemaVersion`.
- Markdownrendering gaat via één frontendfunctie voor lezen, preview en historie.
- vertalingen hebben één effectieve bron voor backend en frontend.
- frontend-vendorbestanden worden door één module beheerd en gecontroleerd.
## Huidige concentraties
`server.rkt` bevat zowel routing als veel requestparsing en handlerlogica. `static/js/wiki.js` bevat vrijwel de hele single-page applicatie. Dat maakt zoeken eenvoudig, maar vergroot de kans dat een wijziging onverwacht een ander view- of routepad raakt.
`private/storage.rkt` combineert pagina's, historie, zoeken, bookmarks, aliases en uploads. Die onderdelen delen pagina-identiteit en transacties, maar hoeven niet onbeperkt samen te groeien.
Deze concentraties zijn technische schuld, geen automatische opdracht tot een grote opsplitsing. Een splitsing moet een concreet voordeel hebben: een kleiner contract, onafhankelijke tests of duidelijker eigenaarschap.
## Gewenste afhankelijkheidsregels
1. Een buitenste laag mag een binnenste dienst kennen; omgekeerd niet. HTTP kent opslag, opslag kent geen HTTP.
2. SQL blijft in database- en opslagmodules. JavaScript bouwt geen SQL-achtige querysemantiek na.
3. Authenticatie en autorisatie blijven server-side. UI-zichtbaarheid is alleen gebruiksgemak.
4. Cross-cutting gedrag krijgt één expliciete helper wanneer er werkelijk meerdere gebruikers zijn. Maak geen wrapper voor één triviale aanroep.
5. Een module exporteert alleen procedures en structs die een andere module werkelijk nodig heeft.
6. Gebruik geen `dynamic-require` om een heldere statische afhankelijkheid te verbergen.
7. Een nieuwe module krijgt één samenhangende reden om te wijzigen; een verzameling toevallige helpers is geen moduleontwerp.
## Waarschijnlijke toekomstige extracties
Wanneer `server.rkt` verder groeit, ligt opsplitsing per adaptergebied voor de hand: sessie/profiel, pagina's, CMaps en beheer. De centrale router kan dan dun blijven. Handlers ontvangen `config` expliciet en roepen dezelfde bestaande diensten aan.
Wanneer `wiki.js` verder groeit, zijn route/state, pagina-editor, CMap-host, graph-view en admin-views natuurlijke grenzen. Splits alleen met native ES-modules wanneer de setup- en cacheversies van alle scripts tegelijk beheerst worden.
Wanneer paginaopslag wordt aangepast, kunnen bookmarks, aliases en uploads later eigen modules krijgen. De pagina-schrijftransactie en afgeleide indices moeten daarbij als één consistente operatie behouden blijven; opsplitsing van bestanden mag geen opsplitsing van de transactie veroorzaken.
## Contracten tussen modules
Een goed contract specificeert:
- geldige invoer en normalisatie;
- welke toestand wordt gelezen of gewijzigd;
- transactiegrens en concurrencygedrag;
- resultaatvorm;
- herkenbare domeinfouten;
- maximale document- of uploadgrootte waar relevant.
De bestaande `goal / pre / post / result`-commentaren zijn hiervoor geschikt, zolang zij het niet-zichtbare contract beschrijven en niet slechts de procedurecode navertellen.
Zie [Regels bij het coderen](racket-wiki:code-regels) voor de concrete stijl en [Testbaarheid](racket-wiki:testbaarheid) voor het testen per grens.