Principes die iedere front-end developer zou moeten weten

Tijdens een van mijn laatste projecten heb ik een aantal dingen geleerd, die elke front-end developer zou moeten weten. Ik noem nadrukkelijk front-end, omdat de principes voor een back-end developer nogal triviaal kunnen zijn, terwijl ze voor een front-end developer helemaal niet vanzelfsprekend zijn. Het project waar ik aan werkte is een uitgebreide AngularJS applicatie, maar de dingen die ik uit wil lichten zijn algemene principes en staan los van Angular:

  • Modulair (component)
  • Object i.p.v. array
  • Hergebruik en conditionele functionaliteit

Directive (component)

In AngularJS kan een directive (component) met een template worden gebruikt als dat stukje functionaliteit op verschillende plekken in de applicatie terugkomt. Een directive wordt op 1 plek onderhouden, maar kan op meerdere plaatsen worden gebruikt.

In mijn laatste project kwam een blok met ‘laatste producten’ op verschillende pagina’s terug. Daarom maakte ik een directive voor dat blok. De data voor de producten haalde ik in de directive op met een call naar een back-end.

Probleem

Het project waar ik aan werkte bestond uit een aantal fasen en elke fase bestond uit nieuwe functionaliteit en dus ook nieuwe designs. Toen de designer aankwam met een nieuwe pagina waar het blok met laatste producten opeens 3 i.p.v. 4 producten bevatte, kon ik dat nog oplossen door de directive uit te breiden met een eigenschap ‘het aantal te tonen blokjes’. De ng-repeat die ik in de directive template gebruikte voor de producten, kon zo uitgebreid worden met een limitTo: 3. Maar toen onder het blok met laatste producten een blok moest komen met gerelateerde producten die er hetzelfde uitzagen, had ik een probleem. De data voor de producten werd in de directive opgehaald. Ik kon dat opnieuw oplossen door een eigenschap mee te geven voor welke type de directive data moest ophalen, maar de code werd zo een ondoorzichtige puinhoop.

Oplossing

De directive was verantwoordelijk voor meer dan 1 items i.p.v. voor 1 item!

I.p.v. een directive te maken voor 4 of 3 producten van een gegeven type, kon ik beter een directive maken voor 1 product. De ng-repeat die ik in de directive gebruikte, kon ik beter verplaatsen naar de pagina die de directive gebruikte. Op deze manier werd de directive verantwoordelijk voor 1 ding.

De data werd ook niet meer in de directive opgehaald, maar in de pagina die de directive gebruikt. Daarmee bepaalt de pagina of en hoeveel laatste of gerelateerde producten getoond moeten worden m.b.v. de directive.

Dus de directive toont 1 item, de parent bepaalt hoe een lijst met items op de pagina getoond wordt (in 3 of 4 kolommen, of links, of rechts, nieuwste of gerelateerde, etc.)

Object i.p.v. array

Een array is een lijst van items. Bij het definiëren van data voor bijvoorbeeld een lijst met producten lijkt het voor de hand liggend om die producten aan te leveren als array:

maar als je nu het tweede item nodig hebt, moet je die op gaan zoeken door over alle items van de lijst te loopen:

Met een object i.p.v. array is het makkelijker om een item te vinden:

Een ander voorbeeld waarbij een object overzichtelijker is dan een array; het tonen van een item van de ene lijst in een andere lijst.
Array:

Object:

Dit is slechts een 2 level diepe lijst. Hoe ongelukkig worden de for-loops van de array ten opzichte van een object als het gaat om een 6 of meer level diepe lijst (wat het geval was in mijn laatste project)!?

Hergebruik en conditionele functionaliteit

Opsplitsen in componenten zorgt voor herbruikbaarheid en is daardoor onderhoudbaarder.
Dus een component kan op de ene plek voor de nieuwste items worden gebruikt en op een andere plek voor gerelateerde of populaire items. Dat klinkt mooi, maar de verleiding is groot om conditionele functionaliteit in de modules en templates te verwerken. Wat als componenten veel op elkaar lijken, maar op 1 puntje van elkaar verschillen? Ga je dan voor een nieuwe component en dus duplicate code, of voor een eigenschap waarmee het verschil tussen de 2 typen kan worden opgelost (conditionele functionaliteit)?

Probleem

Stel dat een directive voor een nieuwste product uit de volgende elementen bestaat;

  • naam,
  • plaatje,
  • stip met nieuw erin
  • bestel snel knop

En dat een directive voor een uitverkocht product uit de volgende elementen bestaat:

  • naam
  • inactieve ‘bestel’-knop
  • een popup om het product voor een andere datum te bestellen

Conditionele functionaliteit zou de directive voor het nieuwe product vervuilen met allerlei functionaliteit om het product voor een andere datum te bestellen, wat voor een nieuw product misschien wel helemaal niet kan. Andersom vervuilt conditionele functionaliteit de directive voor het uitverkochte product met allerlei html elementen, die helemaal niet worden gebruikt.
De directive is zo niet meer verantwoordelijk voor 1 item (functie), maar voor 2 type items.

Oplossing

Houd een component (directive) zo klein mogelijk en gebruik deze niet voor verschillende functionaliteit. Als voor het nieuwste en uitverkochte product dezelfde directive wordt gebruikt, moet de functionaliteit en template gelijk zijn voor beide items.
Als een item afwijkt qua functionaliteit of structuur, moet voor dit type een nieuwe component worden gemaakt. Zo blijft de code schoon en leesbaar en is de kans op de weg kwijt raken in allerlei if statements een stuk kleiner.

Extenden

Het kan natuurlijk zijn dat verschillende grotere componenten onderdelen bevatten die overeenkomen. Dan kan voor dat onderdeel een nieuwe kleinere component worden gemaakt, of beide componenten kunnen een basis-component extenden met gedeelde functionaliteit.
Ook een template kan door verschillende componenten worden hergebruikt, als de html voor beide items hetzelfde is, maar bijvoorbeeld de functionaliteit niet. Dit kan zolang de templates niet vervuild worden met conditionele functionaliteit.

En meer

De voorgaande 3 principes zijn uitgelicht met voorbeelden van AngularJS. Toch gelden deze principes in het algemeen. Het is een denkwijze, een manier van code schrijven. In een volgend artikel wil ik stilstaan bij twee andere principes die wel AngularJS-specifiek zijn;

  • scope.$watch
  • singleton
Tweet about this on TwitterShare on LinkedIn

Reacties

Het e-mailadres wordt niet gepubliceerd.

*