Idag tänkte jag följa upp gårdagens inlägg med en vidareutveckling som också är inspirerad av boken jag just nu läser (Implementing Domain-Driven Design). Mitt förra inlägg illustrerade att vi behöver revidera vår syn på den traditionella layered architecture när vi använder oss av Dependency Injection (DI). Författaren i boken gör en tänkvärd om än aningen krystad övergång under sitt resonemang till en annan intressant arkitektur som är värd att prata om. Jag tänker här försöka mig på att ge en liknande förklaring men på mitt sätt.
Den vänstra sidan i Figur 1 nedan illustrerar den ändring av arkitekturen som mitt inlägg igår landade i. Anledningen till att vi ser Infrastructure layer överst är som vi behandlade igår att vi med hjälp av Dependency Inversion Principle (DIP) har vänt på beroenderiktningen. Författaren menar att en konsekvens av att vi använder oss av DIP är att vi hamnar i ett läge där vi inte behöver tänka på arkitekturen som en uppsättning lager. Hela applikationen är i och med DIP utformad att ha beroende mot abstraktioner (interfaces) som sedan kan implementeras på lite olika sätt. Om vi nu ändå lite krystat vill pressa in den tanken i en form av lagerarkitektur kan vi se resultatet till höger i Figur 1.

I ärlighetens namn är den högra delen av figuren inte särskilt intressant. Det borde väl ändå finnas ett bättre sätt att förhålla sig till denna nya insikt? Säg hej till Hexagonal architecture. Kärt barn har många namn; arkitekturen benämns även som Onion och Ports and Adapters. Jag plockade fram min konstnärliga sida och ritade upp ett exempel på hur denna arkitektur ser ut. I Figur 2 ser vi två hexagoner. Den inre innehåller själva applikationen och dess innehåll kan mer eller mindre likställas med det nedre lagret till höger i Figur 1.

Den yttre hexagonen är det som gör skäl för namnet Ports and Adapters. Här kan man i stort sett peta in hur många adaptrar som helst för att på så sätt kunna erbjuda olika former av kommunikation med systemet och olika implementationer av applikationens abstraktioner. Den vänstra delen av hexagonen ger exempel på två olika adaptrar för kommunikation med systemet. Vid anrop delegerar respektive adapter sina anrop till metoder i den inre hexagonen där domänmodellen lever. Den högra delen av hexagonen ger exempel på adaptrar som implementerar abstraktioner för persistering. Värt att understryka är att applikationen i den inre hexagonen inte har en aning om anropet kommer via REST eller huruvida resultatet av en operation persisteras i en minnesdatabas, detta avgör aktuell adapter.
Av Figur 2 går det att utläsa att avståndet mellan klientens anrop och själva applikationen är väldigt liten – det är bara en adapter emellan. Detta medför också flexibilitet i att det enkelt går att lägga till nya och byta ut adaptrar. Vad vi också kan se till höger i bilden är att adaptertänket även gäller för saker som persistering, ja alla infrastrukturella saker egentligen. Eftersom DDD inte främst handlar om arkitektur utan om lingvistik och domänmodeller känns arkitekturen för mig väldigt tilltalande just för DDD. Vi kan se att den inre hexagonen huserar domänmodellen och att den där kan leva i en skyddad verkstad.
Via den flexibilitet som arkitekturen erbjuder behöver vi inte lägga så mycket vikt vid teknologival. Var det en dålig idé att satsa på teknologi X? Ja kanske, vi petar in en ny adapter med teknologi Y, det kanske funkar bättre? I min hjärna ger en sådan flexibilitet mer utrymme till det som borde vara det viktigaste av allt: att vårda, förbättra och vidareutveckla domänmodellen.