Table of Contents
Architectuur
RESTful API
Dit project implementeert een RESTful API. Hoewel dit een vereiste was van de klant, gaan wij akkoord met deze beslissing om volgende redenen:
- ✅ RESTful API's zijn stateless, waardoor het project beter schaalt, doordat er geen staat moet opgeslagen worden voor elke client.
- ✅ Door voor een RESTful API te kiezen kan er tijdens de ontwikkeling van de API teruggevallen worden op een bestaande set aan regels en richtlijnen.
- ✅ REST API's zijn een standaard.
Een alternatief zou bv. GraphQL kunnen zijn.
Object Relational Mapping (ORM) Patroon: Data Mapper
Data Mapper Patroon in plaats van Active Record Patroon
Dit project maakt gebruik van het Data Mapper Patroon.
- ✅ De backend is zo meer ontkoppeld van de database, waardoor die in de toekomst eenvoudiger uitgewisseld kan worden.
- ✅ Gebruik maken van het Data Mapper Patroon biedt meer flexibiliteit tijdens het ontwerpen van de database.
Zie ook deze vergelijking.
Technologie stack
Programmeertaal: TS
TS in plaats van JS
Dit project wordt geschreven in TypeScript (TS). De klant vroeg een project in JavaScript (JS) of TS. Er werden de volgende overwegingen gemaakt:
- ✅ Statische typering laat toe om typegerelateerde fouten at compile time op te vangen ("type safety").
- ✅ (Meer) ondersteunende tooling zorgt voor een fijnere developer-ervaring.
- ✅ Door een future-proof programmeertaal te kiezen is het project klaar voor de toekomst.
- ❎ Het team heeft een kleine leercurve te gaan, doordat niet iedereen evenveel ervaring heeft met TS.
Uiteindelijk wogen de voordelen zwaarder door dan de nadelen en werd er voor TS gekozen.
ECMAScript Modules (ESM) in plaats van CommonJS (CJS)
Dit project maakt gebruik van ESCMAScript Modules (ESM). Er wordt geen gebruik gemaakt van CommonJS (CJS) omdat:
- ✅ ESM wordt als (meer) future-proof gezien dan CJS. Zo kan dit project langer ontwikkeld worden zonder ernstig refactoring.
- ✅ ESM is deel van de ECMAScript specificatie, waardoor er tijdens de ontwikkeling teruggevallen kan worden op bestaande specificaties als dat nodig is.
Identity Provider (IDP): Keycloak
Dwengo-1 maakt gebruik van OpenID Connect om gebruikers in te loggen. Het is daarom voldoende om een compatibele provider te gebruiken.
Voorlopig werd enkel Keycloak getest, en die wordt ook gebruikt in de voorbeelden. Een overzicht van gekende OpenID Connect providers kunnen hier teruggevonden worden.
Heb je een provider getest? Laat het ons weten.
Caching: Memcached
Om herhalingen van dezelfde request naar de (langzame) dwengo.org API sneller te laten verlopen, maakt Dwengo-1 gebruik van caching. De twee meest gekende manieren om dat te doen zijn Redis en Memcached. Dit project gebruikt Memcached.
Functionaliteit | Redis | Memcached |
---|---|---|
Licentie | ❎ Tri-license | ✅ BSD 3-Clause |
Persistent na herstart | ✅ Ja | ❎ Nee |
Maximale sleutelgrootte | ✅ 2G | ❎ 250 bytes |
De licentieveranderingen bij Redis waren uiteindelijk de dealbreaker. We besloten om met de écht open source Memcached te gaan.
Frameworks
Frontend: Vue.js
De frontend van dit project is een Vue.js frontend met Vuetify componenten.
Het Vue.js framework werd gekozen omdat het team daar simpelweg de meeste ervaring in had.
Composition API in plaats van Options API
Vue biedt ondersteuning voor twee workflows. De volgende overwegingen werden gemaakt:
- ✅ Composition API biedt meer mogelijkheden tot herbruikbare code en is flexibeler.
- ✅ Bij Composition API staat alle logica relevant voor één stuk bij elkaar, in tegenstelling tot bij Options API. Zie de afbeelding hieronder als voorbeeld.
- ✅ Composition API wordt aangeraden voor grotere, complexe applicaties.
- ❎ Composition API vergt meer inzicht dan de Options API.
Uiteindelijk werd Composition API verkozen boven Options API. Er kan ook gebruik gemaakt worden van src
imports voor Single-File Components indien ultieme afsplitsing van HTML, CSS en JS gewenst is.
Vuetify in plaats van Bootstrap Vue
Voor Vue bestaan er twee grote componenten-frameworks: Bootstrap Vue en Vuetify. De keuze ging naar Vuetify omdat het modern is en hoog-level componenten aanbiedt. We geloven dat het een fijne development-workflow biedt en dat er voldoende documentatie bestaat om ons vlot te helpen tijdens de ontwikkeling van het project.
Tanstack
De frontend maakt gebruik van Tanstack om frontend state bij te houden. Meer specifiek wordt er gebruik gemaakt van Tanstack's queries en stores.
Er werden voorlopig geen alternatieven in acht genomen. Heb je een suggestie? Laat het ons weten.
Backend: ExpressJS
De backend maakt gebruik van ExpressJS.
- ✅ Het team heeft veruit de meeste ervaring met ExpressJS in vergelijking met elk ander framework.
- ✅ De documentatie van ExpressJS is uitgebreid.
- ✅ Ondersteuning voor eenvoudig routeren en verschillende HTTP methoden ondersteunen.
- ✅ Ondersteuning voor middlewares (
app.use(...)
), bv. voor logging. - ✅ Aan de hand van tools kan een Express server gegenereerd worden, vertrekkende van een OpenAPI spec, of omgekeerd.
Een mogelijk alternatief zou bv. fastify zijn.
Object-Relational-Mapping (ORM): MikroORM
MikroORM in plaats van TypeORM
Na onderzoek waren de twee kandidaten voor ORM MikroORM en TypeORM. De volgende overwegingen werden gemaakt:
- ✅ MikroORM concentreert zich op simpliciteit en developer-ervaring.
- ❎ MikroORM heeft minder (geavanceerde) functies dan TypeORM. Dit kan als positief gezien worden als je de bijhorende leercurve in acht neemt.
- ❎ TypeORM is meer robuust dan MikroORM, doordat het ouder is. TypeORM accepteert geen nieuwe feature requests en focust zich enkel nog op stabiliteit.
Uiteindelijk werd MikroORM boven TypeORM verkozen, omdat MikroROM als moderner aangezien werd en de documentatie uitgebreid genoeg is.
Andere alternatieven maken ofwel geen gebruik van Data Mapper Patroon, of ondersteunen bijvoorbeeld moeilijker ESM.
Testing: Vitest + Playwright
Unit testing: Vitest in plaats van Jest
Dit project maakt gebruik van Vitest voor unit testing. Vitest werd vergeleken met Jest en Mocha:
Vitest | Jest | Mocha |
---|---|---|
✅ Simpel op te zetten | Extra configuratie vereist | Modulair, veel extra configuratie vereist |
✅ Simpel en snel | Simpel | Complex |
✅ Biedt integratie met frontend framework Vue.js | ||
✅ Ondersteunt ESM | ESM ondersteuning is experimenteel | |
❎ Minder documentatie | Uitgebreide documentatie, wordt al gebruikt in Learning Object Repository |
Hieruit werd besloten om Vitest te gebruiken om zowel de frontend als de backend te testen.
Zie ook deze vergelijking.
Integration testing: Playwright
Voor het schrijven van integratietesten maakt dit project gebruik van Playwright, om de volgende redenen:
- ✅ Playwright ondersteunt TS natively en maakt het eenvoudig om meerdere browsers te testen.
- ✅ Uitgebreide documentatie.
- ✅ Zij die ervaring hebben met integratietesten in Node/JavaScript hebben de meest ervaring met Playwright.