5.2 KiB
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 is een dunne editorfacade met callbacks voor openen, selectie en wijzigingen; hij composeert gespecialiseerde document-, geometrie-, relatie-, layout-, selectie-, interactie- en submapcontrollers. Onder static/js/wiki/cmap/ koppelt CmapWorkspaceController die editor aan routes, API's, dialogen en DOM-events. CmapStorageController beheert dirty state, autosave en de opslagvolgorde; CmapNavigationController beheert routes en browsercontext; CmapTransferController beheert import en export; CmapEditorHost beheert editorlifecycle; CmapEditorUiController beheert standaard toolbaracties; CmapMapController beheert opgeslagen kaarten en CmapConceptController beheert conceptdialogen en geselecteerde conceptbewerkingen. Zuivere referentie-, route-, Markdown- en outlinebewerkingen staan in eigen modules; BreadcrumbTrail beheert uitsluitend de per-tab paginahistorie en kent de DOM niet. routes.js herkent hashes, terwijl wiki.js eigenaar blijft van permissiecontrole en het openen van views.
Sterke punten
De volgende onderdelen zijn al goed geïsoleerd:
wiki-configbundelt runtimekeuzes en voorkomt verspreide globale configuratie.call-with-wiki-databasecentraliseert 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 nog steeds de brede single-page applicatie. De CMap-workspace is daarbinnen echter opgesplitst in eigen modules, waardoor CMap-wijzigingen niet meer in één grote editor- of workspaceklasse samenkomen.
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
- Een buitenste laag mag een binnenste dienst kennen; omgekeerd niet. HTTP kent opslag, opslag kent geen HTTP.
- SQL blijft in database- en opslagmodules. JavaScript bouwt geen SQL-achtige querysemantiek na.
- Authenticatie en autorisatie blijven server-side. UI-zichtbaarheid is alleen gebruiksgemak.
- Cross-cutting gedrag krijgt één expliciete helper wanneer er werkelijk meerdere gebruikers zijn. Maak geen wrapper voor één triviale aanroep.
- Een module exporteert alleen procedures en structs die een andere module werkelijk nodig heeft.
- Gebruik geen
dynamic-requireom een heldere statische afhankelijkheid te verbergen. - 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 en admin-views natuurlijke grenzen. De CMap-host is al als native ES-modulelaag gescheiden. Houd de workspace als coördinator; extra extracties zijn alleen zinvol bij een nieuwe zelfstandige workflow, niet voor losse DOM-hulpen.
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 voor de concrete stijl en Testbaarheid voor het testen per grens.