Files
racket-wiki/architecture/pages/modulariteit.md
T

4.3 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 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 voor de concrete stijl en Testbaarheid voor het testen per grens.