Software-ontwikkelaars zijn goed in het herkennen van patronen. Misschien is het een inherente vaardigheid die ons tot dit beroep aantrekt. Of misschien is het het proces van software schrijven dat deze vaardigheid ontwikkelt. Hoe dan ook, “don’t repeat yourself” (DRY) is een natuurlijke toepassing van deze vaardigheid.
Hoewel herhaling op zichzelf niet de vijand is die dit principe doet voorkomen.
- Don’t Repeat Yourself
- Soms herhaal je jezelf
- Vragen om te stellen
- Is dit een enkel stukje kennis dat gedupliceerd is, of is dit gewoon infrastructuur die er toevallig hetzelfde uitziet?
- Hoe vaak is dit ding al herhaald?
- Zal het verminderen van doublures het moeilijker maken om in de toekomst individuele gevallen aan te passen?
- Als ik deze duplicatie reduceer, wat is dan de verhouding tussen de grootte van de abstractie en het aantal parameters dat het zal nemen?
- Conclusie
Don’t Repeat Yourself
Zo intuïtief als “don’t repeat yourself” mag zijn, zo vat The Pragmatic Programmer het als volgt samen:
Elk stuk kennis moet een enkele, ondubbelzinnige, gezaghebbende representatie hebben binnen een systeem.
Het is niet moeilijk voor te stellen wat de voordelen zijn van het verminderen of elimineren van herhalingen.
- Minder duplicatie betekent minder code om te onderhouden. En als de beste code helemaal geen code is, klinkt dit als een goede zaak.
- Een enkele bron van waarheid elimineert de mogelijkheid dat dingen niet synchroon lopen. Een of andere bedrijfsregel is veranderd? Update het op één plaats, en klaar is kees.
- Code is herbruikbaar. Heb je een proces dat door drie dingen wordt gedeeld, en je voegt een vierde toe? Het meeste werk is al gedaan.
Soms herhaal je jezelf
Te ijverig worden in het verminderen van ogenschijnlijke duplicatie kan meer problemen veroorzaken dan het oplost. Ik zeg “schijnbare duplicatie” omdat soms dingen die op elkaar lijken niet echt verwant zijn. Bijvoorbeeld, twee gegevensstructuren met identieke eigenschappen en typen kunnen structureel hetzelfde zijn, maar semantisch niet.
Een veelgebruikte strategie om dubbele code te verminderen is om de gemeenschappelijke delen eruit te halen en ze te verbergen achter een abstractie. Maar een ongewenst neveneffect hiervan is dat het alles koppelt wat de abstractie gebruikt. Elke verandering in de abstractie beïnvloedt al zijn gebruikers. En zo kan het ook gebeuren dat de abstractie moet worden omgebogen om aan de eisen van slechts één gebruiker te voldoen.
Deze toename in koppeling gaat ook gepaard met een afname in flexibiliteit. Stel dat je een proces hebt dat op drie plaatsen wordt gebruikt. Het is op alle drie de plaatsen bijna hetzelfde, met slechts een paar belangrijke verschillen. Dus je implementeert het proces als een enkele module die een paar parameters neemt om de verschillen te dekken.
Het aanpassen van het proces voor slechts een van die gebruikssituaties is nu onmogelijk: iedere wijziging in een van die drie heeft gevolgen voor alle drie. Natuurlijk kun je meer parameters toevoegen (of speciale gevallen!) naarmate de use-cases uiteenlopen. Maar het zal snel onmogelijk worden om de belangrijke delen van het proces te onderscheiden van de infrastructuur die de use cases van elkaar scheidt.
Vragen om te stellen
Bij het refactoren van bestaande code of het schrijven van nieuwe code die mogelijk gedupliceerd kan worden, vraag ik me af:
Is dit een enkel stukje kennis dat gedupliceerd is, of is dit gewoon infrastructuur die er toevallig hetzelfde uitziet?
Dus je hebt in de CSS gesnuffeld en een klasse gevonden die toevallig de stijlen heeft die je wilt hebben. Dat is waarschijnlijk geen goede reden om niet nog een klasse te definiëren.
Hoe vaak is dit ding al herhaald?
Totdat iets echt overbodigs minstens drie keer voorkomt, zou ik erg sceptisch zijn over elke herhaling-vermindering die de complexiteit verhoogt.
Zal het verminderen van doublures het moeilijker maken om in de toekomst individuele gevallen aan te passen?
Er is iets bevredigends aan het herformuleren van een hoop copy-and-paste code in iets dat meer gestroomlijnd en herbruikbaar is. Maar de code zo strak vastzetten dat elke verandering speciale gevallen introduceert, is geen goede afweging.
Als ik deze duplicatie reduceer, wat is dan de verhouding tussen de grootte van de abstractie en het aantal parameters dat het zal nemen?
Bibliotheken en frameworks zijn geweldig omdat ze herbruikbare code bieden met relatief weinig parameters voor aanpassing. Maar stel je een toepassingsspecifieke functie voor het presenteren van een dialoogvenster voor die is gegroeid en nu 20 parameters accepteert. Het voordeel van herhalingsreductie dat er was toen het nog maar 2 parameters had, is er niet meer.
Conclusie
Zoals met veel software-ontwikkelprincipes het geval is, is “val niet in herhaling” meer een richtlijn dan een mantra.