Projectstructuur¶
Het is belangrijk om bij het schrijven van code een bepaalde mappenstructuur aan te houden, daarmee dwing je onder andere af dat er op een consistente manier gewerkt wordt.
In dit artikel zal kort worden uitgelegd wat de mappenstructuur van het startproject is, en naar welke mappenstructuur je gaat toewerken.
Mappenstructuur van het startproject¶
Het startproject bestaat uit de volgende belangrijke mappen en bestanden:
package.json
beschrijft welke NPM packages er nodig zijn voor alle projecten in de Visual Studio Code omgeving(workspace).apps\web\package.json
beschrijft welke NPM packages er nodig zijn voor het Dokkie project.apps\web\src
bevat alle Dokkie-specifieke code.apps\web\tests
bevat alle Dokkie-specifieke geautomatiseerde tests.apps\web\wwwroot
bevat alle HTML-bestanden, CSS-bestanden en afbeeldingen voor Dokkie.docs
bevat één of meerdere Markdown-bestanden om een documentatiesite voor te genereren.
De wwwroot
-map¶
De conventies voor de bestanden onder de wwwroot
-map is lower-kebab-case
, bijvoorbeeld participant-add.html
.
De wwwroot
-map bevat alle HTML-pagina’s.
Daaronder bevat de assets
-map alle CSS en afbeeldingen die door de verschillende HTML-pagina’s gebruikt worden. CSS-bestanden voor een specifieke pagina hebben altijd de naam van de HTML-pagina, bijvoorbeeld participant-add.css
.
De public
-map is speciaal en bedoeld voor alle bestanden (meestal afbeeldingen) waar de broncode (src
-map) direct mee werkt. Dit gaat anders niet goed tijdens de npm build
-fase!
De src
-map¶
De conventies voor de bestanden onder de src
-map is lower-kebab-case
, bijvoorbeeld participant-add.ts
.
Daarnaast is in deze map voor elke HTML-pagina een bijbehorend .ts
-bestand te vinden.
Uiteindelijke mappenstructuur¶
In deze paragraaf wordt beschreven hoe de uiteindelijke mappenstructuur eruit komt te zien.
De wwwroot
-map¶
Geen veranderingen ten opzichte van wat hiervoor is beschreven.
De src
-map¶
De conventies voor de bestanden onder de src
-map zijn als volgt:
- Niet-classes (specifiek
pages
)- Naamgeving:
lower-kebab-case
, bijvoorbeeldparticipant-add.ts
.
- Naamgeving:
- Niet-classes (overige):
- Naamgeving:
camelCase
, bijvoorbeeldhicConfig.ts
.
- Naamgeving:
- Classes
- Naamgeving:
PascalCase
, bijvoorbeeldParticipant.ts
als die deParticipant
-class bevat. - Elk bestand bevat altijd maar één
export class
, maar kan eventeel wel types bevatten ter ondersteuning.
- Naamgeving:
De src
-map is opgedeeld in vier mappen:
pages
controllers
models
repositories
Deze mappenstructuur draagt bij aan het benaderen van een Model-View-Controller architectuur (MVC).
Toepassing MVC architectuur¶
Pages¶
Voor je met Object Oriented Programming (OOP) aan de gang gaat, zul je je werk vooral in de pages
-map doen. Voor elke HTML-pagina is er altijd een bijbehorend TypeScript-bestand in deze map te vinden, zelfs als je alleen met JavaScript werkt, bijvoorbeeld participant-add.ts
.
Als je met OOP aan de gang gaat, komen de andere mappen qua structuur om de hoek kijken.
Controllers¶
Elk cluster van CRUD-pagina’s krijgt één controller class onder de controllers
-map, bijvoorbeeld PartipantController.ts
. De bestanden onder pages
voor die pagina’s doen niks meer dan de controller instantieëren en render-functies aanroepen, vrijwel altijd in DOMContentLoaded.
Dit is de eerste refactor die je zal moeten doorvoeren: het creatief schuiven van hun origineel geschreven code naar een controller-class. Het makkelijkste wat hier gedaan kan worden is het volgende, uitgaande van participant-add.ts
en andere CRUD-acties als voorbeeld:
- Maak een
PartipantController.ts
, als deze nog niet bestaat. - Voeg een
render
-functie toe met de naam die je wilt overzetten, een goede naamgeving is:render[CRUD-actie][Entiteit-naam]Page
, bijvoorbeeldrenderAddParticipantPage
. - Knip en plak alle code uit de
participant-add.ts
in deze functie, dit zal in de meeste gevallen geen problemen geven.
De makkelijkste pagina’s om mee te beginnen zijn de index
, register
en login
.
Models¶
Bij het verplaatsen van de pagina’s ben je eigenlijk al aan het nadenken over de benodigde entiteiten.
Voor elke controller is daarom de kans groot dat er ook een model-class met die naam nodig is, zo zal de ParticipantController
een model Participant
krijgen. Deze plaats je dan in de models
-map met de naam Participant.ts
.
De afspraak voor models is dat die alleen data bevatten, geen complexe logica. Elk model heeft naast de gegevens die ze moeten vasthouden vrijwel altijd een id-attribuut en moet van correcte Encapsulation voorzien zijn.
Let op! Als je een
JSON.stringify
met een object instantie doet, worden de private attributes gebruikt, niet de getters. BijJSON.parse
moet je daar dus rekening houden met jetype
! Dit zal echter alleen een rol spelen als je kiest voorlocalStorage
-opslag, niet bij een echte database.
Repositories¶
Waar models zijn, zijn meestal ook repository-classes nodig om de data die ze vasthouden op te slaan of juist weer in te laden. Heb je een Partipant
-model, dan heb je een PartipantRepository
. Deze plaats je dan in de repositories
-map met de naam PartipantRepository.ts
.
De afspraak is dat de controllers geen weet hebben van de databron waar ze tegen praten. De repository-class is de enige die weet of data uit de localStorage
of de database komt. Het maakt de controller niet uit hoe die zijn Participant
-model instantie krijgt, als die hem maar krijgt.
De repository bevat alle functies die de controllers nodig hebben om hun werk te kunnen doen, meestal zijn dat in ieder geval de volgende acties:
getAll
getById
create
update
delete
Maar daarnaast kan je per model specifieke functies toevoegen, zo zal de UserRepostory
een login
en register
krijgen.