162 lines
5.4 KiB
Markdown
162 lines
5.4 KiB
Markdown
---
|
|
name: javascript-programmeer-skill
|
|
description: Gebruik deze skill wanneer je Javascript-code voor Hans schrijft, wijzigt, refactort of beoordeelt. Pas de bestaande, eenvoudige en object georiënteerde programmeerstijl toe; voorkom over-engineering en onnodige abstracties. Gebruik deze skill niet voor algemene uitleg over javascript waarbij geen code voor zijn projecten wordt gemaakt of aangepast.
|
|
---
|
|
|
|
# javascript-programmeerstijl
|
|
|
|
Gebruik deze stijl wanneer je Javascript-code voor Hans schrijft of aanpast.
|
|
|
|
## Uitgangspunt
|
|
|
|
Schrijf code zoveel mogelijk in lijn met hoe Hans racket code schrijft. Zie daarvoor de racket skill.
|
|
|
|
Gebruik bij javascript als je een closure definitie maakt een class.
|
|
Met andere woorden: ga voor OO en class definities in plaats van property gestuurde closures.
|
|
|
|
Dus wel:
|
|
|
|
```javascript
|
|
class Rectangle {
|
|
constructor(height, width) {
|
|
this.height = height;
|
|
this.width = width;
|
|
}
|
|
// Getter
|
|
get area() {
|
|
return this.calcArea();
|
|
}
|
|
// Method
|
|
calcArea() {
|
|
return this.height * this.width;
|
|
}
|
|
*getSides() {
|
|
yield this.height;
|
|
yield this.width;
|
|
yield this.height;
|
|
yield this.width;
|
|
}
|
|
}
|
|
```
|
|
|
|
En niet:
|
|
|
|
```javascript
|
|
const Rectangle = (() => {
|
|
function Rectangle(height, width) {
|
|
this.height = height;
|
|
this.width = width;
|
|
}
|
|
|
|
Rectangle.prototype.calcArea = function () {
|
|
return this.height * this.width;
|
|
};
|
|
|
|
Object.defineProperty(Rectangle.prototype, "area", {
|
|
get: function () {
|
|
return this.calcArea();
|
|
}
|
|
});
|
|
|
|
Rectangle.prototype.getSides = function* () {
|
|
yield this.height;
|
|
yield this.width;
|
|
yield this.height;
|
|
yield this.width;
|
|
};
|
|
|
|
return Rectangle;
|
|
})();
|
|
```
|
|
|
|
## Modules / source files
|
|
|
|
Houd bronbestanden overzichtelijk.
|
|
Geen grote javascript bouwwerken.
|
|
|
|
Werk met modules en import/export.
|
|
Ga voor module gewijze code.
|
|
Zorg dat modules zoveel mogelijk een eenheid zijn.
|
|
|
|
OO is prima, en een setje OO classes in een module kan, maar als het boven de 750 regels code komt,
|
|
dan wordt het onoverzichtelijk.
|
|
|
|
Voorkom eindeloze nestingen.
|
|
Probeer dingen functioneel op te zetten, zoals dat in racket zou werken.
|
|
|
|
### Klassen en objecten
|
|
|
|
- Aanvullend bij de bovenstaande class regel. Gebruik een class wanneer een
|
|
object een eigen identiteit, levensduur, toestand en bijbehorend gedrag heeft.
|
|
- Zorg dat een constructor een direct bruikbaar object oplevert.
|
|
- Geef concrete afhankelijkheden als betekenisvolle constructorargumenten door.
|
|
Introduceer geen algemene configuratie- of dependency-container zonder
|
|
concrete noodzaak.
|
|
- Geef de voorkeur aan samenstelling. Gebruik overerving alleen wanneer
|
|
daadwerkelijk sprake is van een stabiele is-een-relatie of een gedeeld
|
|
gedragscontract.
|
|
- Een domeinobject beheert zijn eigen toestand, validatie, wijzigingsmeldingen
|
|
en serialisatie. Andere modules horen niet rechtstreeks in zijn interne
|
|
datastructuur te werken.
|
|
|
|
### Modules en API's
|
|
|
|
- Gebruik expliciete imports en exports. Exporteer alleen de publieke
|
|
onderdelen van een module.
|
|
- Modulevariabelen zijn toegestaan voor werkelijke modulebrede toestand,
|
|
zoals een singleton, cache of gedeelde wachtrij.
|
|
- Behandel interne velden en helpers als implementatiedetails, ook wanneer
|
|
JavaScript die privacy niet technisch afdwingt.
|
|
- Behoud externe veldnamen bij een API- of serialisatiegrens. Normaliseer
|
|
gegevens expliciet bij het binnenkomen en uitgaan van de applicatie.
|
|
|
|
### Domein en gebruikersinterface
|
|
|
|
- Houd domeinlogica en DOM/GUI-logica in afzonderlijke modules.
|
|
- Laat GUI-objecten de publieke methoden van domeinobjecten gebruiken.
|
|
- Een domeinobject hoort geen kennis te hebben van concrete DOM-elementen,
|
|
dialogen of widgets.
|
|
|
|
### Asynchrone bewerkingen
|
|
|
|
- Centraliseer bewerkingen waarvan volgorde belangrijk is, zoals opeenvolgende
|
|
opslagopdrachten, in een herkenbare wachtrij of coördinator.
|
|
- Gebruik binnen één workflow één duidelijke asynchrone stijl.
|
|
- Gebruik arrowfuncties wanneer lexicale `this` gewenst is. Gebruik een gewone
|
|
functie wanneer de aanroepende API bewust een eigen `this`-waarde levert.
|
|
|
|
### Omvang en samenhang
|
|
|
|
- Een groot aantal regels is een signaal, geen harde grens.
|
|
- Splits een bestand wanneer het meerdere zelfstandig benoembare en stabiele
|
|
verantwoordelijkheden bevat, niet uitsluitend omdat een regelaantal is
|
|
overschreden.
|
|
|
|
## Documentatie
|
|
|
|
- Documenteer het doel en de functionele samenhang van modules, classes en
|
|
niet-triviale publieke methoden.
|
|
- Beschrijf parameters, resultaat, neveneffecten en relevante interne
|
|
samenwerking.
|
|
- Schrijf geen commentaar dat slechts iedere programmaregel in woorden herhaalt.
|
|
- Triviale getters, setters en lokale callbacks hoeven niet afzonderlijk
|
|
gedocumenteerd te worden wanneer hun werking direct duidelijk is.
|
|
|
|
# Architectuurprincipes
|
|
|
|
## MVC patroon
|
|
|
|
Over het algemeen zal bij het bouwen van de javascript code van een website
|
|
gebruik moeten worden gemaakt van het Model-View-Controller principe.
|
|
|
|
Een model bestaat uit de de interne data-representatie van gegevens en heeft
|
|
ook als verantwoordelijkheid om de opslag ervan richting een server backend
|
|
resp. import/export ervan te regelen.
|
|
|
|
Op het model worden views gemaakt. Die views presenteren het model naar een
|
|
gegeven situatie en maken het ook mogelijk om te interacteren met het model.
|
|
|
|
De controller zorgt koppelt de model-logica en de view-logica aan elkaar en
|
|
bevat business rules t.a.v. het presenteren en bewerken van de model logica.
|
|
|