Clean Architecture @ Summit

Dennis Achter de schermen

Voor onze nieuwe klant Summit moesten wij een architectuur kiezen voor onze services. Wij hebben gekozen voor Clean Architecture. In deze blog leg ik kort uit hoe dit er in de praktijk uit ziet!

Een aantal maanden geleden klopte Summit aan onze virtuele deur. Zij vroegen ons of wij hen konden helpen met de volgende stap maken naar een modern en volwassen systeem. ‘Natuurlijk!’ zeiden wij, en een paar weken later ben ik samen met mijn collega Joralf bij Summit aangeschoven om de Summit ontwikkelaars te helpen.

Een van de eerste beslissingen die we genomen hebben is om de bestaande monoliet op te splitsen in services. Dit zorgt voor meer op zichzelf staande onderdelen, en dat zorgt er weer voor dat het systeem overzichtelijker wordt. Erg belangrijk!

Nu moest er alleen nog besloten worden hoe we deze nieuwe services in gingen richten; we moesten een architectuur kiezen. Hier zijn er natuurlijk legio van, je kunt al je logica direct in je API-controllers stoppen, je kunt een traditionele gelaagde architectuur gebruiken, etc. Wij hebben uiteindelijk gekozen voor Clean Architecture. Dit is een idee van Uncle Bob, (een veel geziene spreker op conferenties). In dit artikel geef ik een korte introductie tot Clean Architecture en ik laat zien hoe we dit concreet toegepast hebben.

Clean Architecture?

Clean Architecture is een manier voor het structureren van een programma. De belangrijkste eigenschap van deze architectuur is dat de verschillende onderdelen van het programma goed gescheiden zijn (separation of concerns). Door dit goed toe te passen krijg je een systeem dat onafhankelijk is van frameworks en databases (dat wil zeggen, je zou in theorie vrij eenvoudig een ander web framework of een andere database kunnen gebruiken). En, doordat deze afhankelijkheden naar buiten worden geschoven, is de business logica (de belangrijkste code van een systeem) makkelijk testbaar.

In diagramvorm ziet dit er zo uit:

Zoals je kunt zien lijkt het een beetje op de klassieke gelaagde architectuur. In beide gevallen worden stukken van de codebase gegroepeerd zodat er een mooie separation of concerns is. Dit zorgt ervoor dat je businesslogica geen database queries bevat, en dat je data access code geen businesslogica bevat.

Als je wat beter kijkt, valt je misschien wat op. In een gelaagde architectuur is de database het fundament van het systeem. Hij ligt helemaal onderop en alle andere bouwen er op verder. In het Clean Architectuur plaatje ligt de database juist helemaal aan de buitenkant. Waarom is dat? Eigenlijk is het helemaal niet logisch dat database het fundament van je applicatie is, want de database is alleen maar een opslagmedium. Als de business logica afhankelijk is van de datalaag betekent dit dat een wijziging in de datalaag mogelijk wijzigingen forceert in de business laag! Dus in andere woorden, het minst belangrijke onderdeel van het systeem (opslag) bepaalt wat er gebeurt in het meest belangrijke deel (de daadwerkelijke functionaliteit)! Dit is waarom de structuur bij Clean Architecture wat anders is dan je misschien gewend bent. De meest belangrijke onderdelen liggen in het midden, en hoe verder je naar buiten gaat hoe minder belangrijk de laagjes worden. In het diagram geeft de pijl de afhankelijkheden tussen de lagen aan. Dit is wat Clean Architecture zo krachtig maakt. Nu is de datalaag afhankelijk van de businesslogica, en niet andersom!

Het hart van een systeem zijn dus de Entities en de Use Cases. Entities zijn domeinobjecten die je over meerdere applicaties binnen hetzelfde systeem kunt hergebruiken, denk bijvoorbeeld aan een Product, of een Factuur. De use cases zijn de operaties die een gebruiker in een applicatie kan uitvoeren, bijvoorbeeld ‘voeg een product toe aan een winkelmandje’, of ‘voer een betaling uit’. De volgende laag is een beetje lastig te benoemen, maar ik noem hem meestal Infrastructuur. Dit is de laag waarin de applicatie-specifieke User Interface code woont, en ook de koppelingen met externe systemen zoals APIs en databases. De laatste laag bevat de frameworks en libraries die je gebruikt, zoals bijvoorbeeld ASP.NET MVC, of SQL Server. In deze laag schrijf je meestal zelf geen code.

Er is nog veel meer te lezen over Clean Architecture, en ik zou zeker Uncle Bob’s praatjes en blog posts aanraden als je hier meer over wil leren! Ik heb aan het eind van deze post wat linkjes gezet naar interessante pagina’s over dit onderwerp.

Clean Architecture @ Summit

Genoeg theorie, hoe ziet dit er in de praktijk uit? Een typische service binnen Summit ziet er zo uit:

Zoals je ziet is de service opgesplitst in de verschillende lagen die we eerder in het diagram zagen. En wat ik zo mooi vind aan deze opzet is dat je aan dit overzicht al kunt zien wat voor functionaliteit deze service aanbied. We kunnen wat operaties doen op Hosts en Locaties! Deze eigenschap is wat men ‘Screaming Architecture’ noemt.

Als we wat verder inzoomen op een entity class zien we dit:

Een hele simpele datastructuur waar eigenlijk geen logica in zit. Het is belangrijk om entities zo te structureren dat de business logica er makkelijk mee kan omgaan. Dat hoeft dus niet per se overeen te komen met hoe de data er uiteindelijk in de database uitziet of hoe de service uiteindelijk zijn data teruggeeft. Je zou je entity in de datalaag bijvoorbeeld kunnen vullen met data uit verschillende tabellen.

Entities worden gebruikt door de use cases:

Deze use case gebruikt een ILocationRepository om een Location entity op te halen, past er wat business logica op toe, en zorgt dat de Location weer opgeslagen wordt. Dit is pure business logica; deze class heeft geen enkel benul van waar deze data vandaan komt, en dat is goed! Dit zorgt ervoor dat deze code simpel is, en makkelijk te unit testen!

Als je in het projectoverzicht van de service kijkt zul je zien dat de ILocationRepository interface onderdeel is van de use case laag en dus niet van de datalaag. Dit is een belangrijk detail, want dit zorgt ervoor dat de use case laag bepaalt wat hij nodig heeft, en het is aan de datalaag om een implementatie aan te leveren. Dit levert mooi gescheiden code op, en het zorgt er ook voor dat de business logica (bijna) geen afhankelijkheden heeft. Het UseCases project heeft alleen maar een afhankelijkheid op het Entities project, en verder niks! Minder afhankelijkheden zorgen er voor dat de code makkelijker te testen is, en dat zorgt ervoor dat we de kwaliteit van het systeem kunnen waarborgen.

De communicatie met de database gebeurt in het DataAccess project, en dat ziet er ongeveer zo uit:

Je ziet hier dat we een implementatie hebben van de interface uit de use case laag. Het belangrijkste van dit stukje code is dat het een entity class teruggeeft, en geen database record!

Als laatste hebben we nog de controllers in het Service project. Dit zijn .NET WebApi controllers, en die zien er zo uit:

We willen zo min mogelijk logica in deze controllers hebben, want ze zijn enkel verantwoordelijk voor het vertalen van input naar bruikbare objecten voor de use cases, en voor het vertalen van de resultaten van de use cases naar een structuur die bruikbaar is voor de gebruiker van de service. We geven hier expres geen entities terug, maar converteren deze naar speciale contractobjecten zodat we complete controle hebben over hoe de informatie bij de eindgebruiker terecht komt. Een structuur die handig is voor business logica is natuurlijk niet per se de meest handige structuur voor een gebruiker van de service.

Tot slot

Dit was een kort kijkje in onze digitale keuken! Bedankt voor het lezen, en hopelijk heb je wat nieuws geleerd. Als je meer wilt weten over Infi of Clean Architecture, stuur me dan een berichtje op dennis@infi.nl!

Lees- en kijkvoer

Uncle Bob’s blogpost over clean architecture:
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

Uncle Bob vertelt over clean architecture:
https://www.youtube.com/watch?v=o_TH-Y78tt4

Uncle Bob’s clean architecture boek:
https://www.goodreads.com/book/show/18043011-clean-architecture

Een repository met een voorbeeld van een Clean Architecture implementatie (met goede uitleg)
https://github.com/mattia-battiston/clean-architecture-example

Een afspraak maken bij ons op kantoor of wil je even iemand spreken? Stuur ons een mail of geef een belletje.