Design patterns FTW

Als ontwikkelaar ken je het vast wel: je hebt een complex probleem dat je moet oplossen met code. Je begint vol goede moed aan de implementatie, maar al snel loop je vast in een wirwar van logica. Hoe zorg je ervoor dat je code overzichtelijk blijft en gemakkelijk te begrijpen is, ook voor andere ontwikkelaars? Een oplossing hiervoor is het gebruik van design patterns.

Design patterns zijn herbruikbare oplossingen voor veelvoorkomende problemen in de softwareontwikkeling. Door het gebruik van design patterns kun je complexe code vereenvoudigen en gestructureerd implementeren. In deze blog bespreek ik twee design patterns, de strategy- en visitor-pattern, en laat ik zien hoe we deze hebben gebruikt om een complexe functionaliteit te implementeren in onze applicatie Clientbox. Ik leg uit hoe we de logica voor het afhandelen van het budget hebben geabstraheerd met een façade, en laat zien hoe dit alles heeft bijgedragen aan een schaalbare en onderhoudbare codebase.

Achtergrond en uitdaging

In Clientbox hebben we een abonnementen module, met abonnementen laat je opdrachten en facturen periodiek automatisch genereren. Hierbij zitten nog een hoop opties, zoals automatisch versturen van de factuur. Nu had ik de uitdaging om het afhandelen van het budget in vergelijking met de vorige periode toe te voegen.

Stel dat we een abonnement hebben dat wekelijks een opdracht aanmaakt met de volgende diensten:
• 3 uur gamen
• 2 uur sporten

In de eerste week hebben we 5 uur besteed aan gamen. Het nettoresultaat is dan:
• 2 uur overschrijdend game budget
• 2 uur resterend sport budget

Via het abonnement kan de klant instellen hoe er met dit budget moet worden omgegaan. We kunnen het verschil direct doorberekenen, wat mooi zou zijn, want dan hoeven we in ieder geval niet meer te sporten. We kunnen het verschil ook doorzetten naar de volgende week of de overschrijdende uren direct afboeken. Zoals je je kunt voorstellen, kunnen de mogelijkheden voor het afhandelen vrij complex en uitgebreid worden

Software engineering skills to the rescue

In de code moet de implementatie van onderdelen nog steeds gemakkelijk en inzichtelijk blijven. De verschillende manieren om het budget te maken, heb ik via de strategy- en visitor-patterns geïmplementeerd. Zie https://refactoring.guru/design-patterns/strategy en https://refactoring.guru/design-patterns/visitor voor uitleg over deze designpatterns.

Hieronder zie je de verschillende implementaties van de Budget Strategie. Door de interface abstractie blijft de manier van aanroepen van de verschillende implementaties hetzelfde. Hierdoor zijn de zorgen weggenomen van de code die budget overzetten werkelijk gaat uitvoeren.

Met behulp van de strategie-pattern blijft de complexiteit laag en iedereen met wat boerenverstand snapt wat hier gebeurt. Iemand met achtergrondkennis van de applicatie die waarschijnlijk denkt: “Ammehoela, dat gaat nooit zo simpel gebeuren. Waar komt ‘budgetLeft’ vandaan? Als we het over tijd hebben zijn het de geboekte uren, maar bij geld of producten dan? Zijn het dan alleen de goedgekeurde uren? Hoe boeken we af?”

Gelukkig hebben wij hiervoor weer een Design Pattern. We maken een abstractie die de onderliggende complexiteit versimpelt, genaamd een façade (https://refactoring.guru/design-patterns/facade), zodat de strategie zich geen zorgen hoeft te maken over hoe dit afgehandeld wordt. We kunnen voor uren zelfs verschillende hebben. Eén voor alle gemaakte uren of één voor alleen de goedgekeurde uren. De budgetstrategie implementatie voor “BudgetAfboeken” blijft hierdoor volledig zichzelf, lekker simpel. Bijkomend voordeel is dat we gemaakte façades kunnen hergebruiken in andere budget-strategieën.

Voorbeelden versus werkelijkheid

Ik moet nog wel even opbiechten dat de voorbeelden uit deze blog qua naamgeving niet overeenkomen met de werkelijkheid. We zijn continu aan het ontwikkelen en leren wat wel werkt of niet. Hiervoor hebben we vaak domein-termen zoals afboeken vertaald naar het Engels, om vervolgens volledige verwarring te scheppen onder developers en de klant. Of snap jij direct wat ‘write off’ betekent? De naamgeving voor classes leggen we nu dichter bij de business in gewoon Nederlands.

Design patterns zijn een nuttig hulpmiddel om complexe code eenvoudiger en inzichtelijker te maken. In dit geval hebben we de strategy- en visitor-patterns gebruikt om de verschillende manieren van budgettering te implementeren en de logica voor het afboeken van budget geabstraheerd met een façade. Dit maakt het niet alleen eenvoudiger om nieuwe budgetteringsmethoden toe te voegen, maar ook om de code te testen. Door het gebruik van design patterns kunnen we deze functionaliteit op een schaalbare en onderhoudbare manier implementeren.

Eric Pinxteren
Technologie