Etikettarkiv: DDD

Event storming

Detta inlägg finns även att läsa på HRM Softwares teknikblogg!

Lately I’ve spent some time catching up on what’s happening in the Domain-Driven Design (DDD) community through watching sessions recorded at the Domain-Driven Design Europe 2016 conference. The session I watched yesterday was about something called event storming – a concept that was new to me but so simple and seemingly powerful that it got me quite worked up. The purpose of this blog post is not to go into details of how event storming works, but rather to convey my initial thoughts of why the idea is worth thinking about.

When running an event storming workshop you only need a few basic things:

  • post-it notes with different colors
  • a lot of space to place the post-it notes on (e.g. a large whiteboard or a paper roll)
  • the right people

The right people are key in event storming and should involve a moderator, developers, domain experts and other people involved that can contribute when storming away at the problem at hand.

Domain events

With all these smart people gathered in a room, you start with identifying a few core domain events. A domain event is formulated as something important that can happened in the domain under analysis, e.g. ”ticket purchased” or ”seat reserved”. As you can see, domain events are always expressed in past tense. Each domain event is written down on a post-it note with a specific color – the resources I’ve found online so far suggests orange stickers by convention – and placed on the whiteboard from left to right in order of occurrence in the business process we are analysing. This means that we get a visual representation of the business process flow to see when the various domain events occur.

Commands

During the identification of domain events we also need to ask ourselves how they are triggered. For instance, the domain event ”ticket purchased” might be a consequence of a user placing an order via a web application. The act of placing an order is, in event storming terms, a command. A command is something that generate domain events and is expressed through blue post-it stickies. Commands are formulated in present tense, e.g. ”purchase ticket”, and placed on the whiteboard just before the domain event(s) that are generated as a result of the command. For example, a ”purchase ticket” command should probably be placed just before the ”ticket purchased” domain event to signal that they belong together.

The flow of the workshop

With the two core concepts of commands and domain events, the participants of the workshop keep exploring the problem area to gradually refine and expand it. As the notion of event storminig stems from DDD, we take extra care to capture the ”ubiquitous language”, i.e. we want to make sure we are naming things so that it makes sense for the business problem we are trying to solve. Participants in the workshop are encouraged to question things, no matter how trivial they may sound. Is ”ticket” really the correct word? Is it to general?

It is during the ongoing discussion, with post-its being replaced and moved around, we hope to nail the complexity of the domain problem. Suddenly, a domain expert states that there should be a way to reserve tickets. And by the way, you should be able to get a refund if you cancel your ticket purchase within a given amount of time. The complexity of the problem gradually reveals itself, captured in a process time flow and grouped by commands and domain events on a whiteboard covered with colored post-it stickies.

What do we get out of this?

It should be noted once again that I’ve not actually tried this workshop format, but in my mind it really makes sense. The idea is super simple and the potential outcome of it is interesting in several ways. First and foremost, we can express the components of a problem we are trying to solve (and how they relate to each other) with terminology that comes directly from the domain experts. Another neat thing is that commands and domain events map really well to implementation. They are a natural fit for CQRS and event sourcing, but when you think about it, commands and domain events can be mapped pretty well to any kind implementation technique. Something triggers an action (command) that produces some kind of result (domain event).

Final notes

Event storming include more stickies for e.g. highlighting actors, UIs and domain models. Moreover, as we are in the DDD world, we can map related commands and events to a particular aggregate and express that directly on the whiteboard by simply grouping them together. The same goes for bounded contexts; to group aggregates into a bounded context you just draw a line around the involves post-it stickers with a whiteboard marker.

For those of you versed in DDD, we can start drawing a context map from here, but that’s the topic of a blog post for a later time.

This blog post was authored by Martin Moberg.

DDD i befintliga system

När jag var på den där workshoppen i yoga för män för ett par veckor sedan sprang jag på en gammal kollega. Vi kom efter en stund att prata om Eric Evans idéer om Domain-Driven Design (DDD). Både min kollega och jag tycker att DDD är väldigt spännande och funderingen vi vände och vred på var om och i så fall hur man ska kunna applicera i alla fall delar av DDD i befintliga projekt. Vi klurade en kort stund innan det var dags att åka hemåt för att återgå till familjelivet igen. Vad jag inte kom ihåg under vårt samtal var att just Eric Evans hade pratat om detta i en fin liten videosnutt.

Om jag inte minns fel utgick han ifrån en arkitekturell verklighet som säkert är väldigt bekant för många av oss: Big ball of mud. Hans poäng i videon (spoiler alert) är att introducera ett slags ”växthus” för de funktioner man avser lägga till eller förändra. All kommunikation mellan växthuset och resten av systemet sker genom något som i DDD kallas för Anti Corruption Layers (ACL), vilket är ett fint begrepp för datamappning som syftar till att bibehålla den interna modellen i växthuset isolerad från resten av systemet. Ett sådant upplägg gör att man i växthuset kan modellera och bygga upp någonting vackert och kanske lite sagolikt – vad vet jag.

För en systemutvecklare som har harvat runt bland svårbegriplig kod år efter år låter detta smått fantastiskt – tänk att få skapa en perfekt verklighet i en liten fin bubbla. Jag blev själv hänförd när jag såg presentationen och jag tycker fortfarande att idén är intressant, men jag tror att jag tänker på den nyktrare nu. Att bygga ett växthus mitt i en kodbas innebär ett avbräck från den befintliga arkitekturen. Jag menar att även en big ball of mud har en arkitektur, en tanke eller en ”såhär brukar vi göra” som man som utvecklare snällt har fått lära sig. Ett växthus innebär att man skapar en liten arkitektur i arkitekturen så att säga. Alla involverade måste lära sig den nya arkitekturen och förstå den för att inte kvadda den under det pågående förändringsarbete av kod som är systemutveckling. Det kräver engagemang och disciplin hos alla för att fungera.

Dessutom kan man aningen motsägelsefullt se det som att man gör koden mer svår att förstå om man ser på hela systemets kodbas sammantaget. Växthuset bryter jargongen som finns, det blir lite som att en författare helt byter sitt språkbruk för ett kapitel i en bok. Hur vacker prosan än må vara i just det kapitlet sticker det ut som förvirrande i det att det skiljer sig från resterande innehåll. Om vi sedan tänker oss att vi slänger in ett par sådana växthus med viss skillnad i arkitektur finns det risk att vi har skapat oss ett förvaltningshelvete.

Utan att vara framme vid någon slutsats tänker jag att Evans idé är väldigt djärv och att det gäller att vara sjukt säker på sin sak innan man ger sig på en sådan grej. Koden måste kommunicera bra och det gör den bäst när den är konsekvent, vacker eller ej.

Kod är kommunikation – DDD style

Av någon anledning har jag alltid varit mer intresserad av att koden kommunicerar bra än all den där teknologin som finns runtomkring. Den ser jag mest som något nödvändigt ont som behövs för att få saker och ting att snurra. Visst kan jag emellanåt bli hänförd av coola tekniska lösningar, men i slutändan tappar de sin glans och jag faller tillbaka på det som gör mig sådär löjligt förtjust – att hitta rätt benämningar och modellera med dessa på ett lättförståeligt sätt som i slutändan hjälper till att lösa de problem man har.

Om en systemutvecklares intresse lutar mer åt det lingvistiska hållet finns det knappast något som gör henom så glad som Domain-Driven Design (DDD). En av de riktigt fundamentala delarna i DDD är något som kallas för Ubiquitous Language. Tanken här är att man innan ett systemutvecklingsarbete påbörjas sätter sig ner och fångar upp begrepp som återfinns inom det problemområde den tänkta lösningen avser. Detta arbete utförs av de utvecklare som ska arbeta med systemet och en eller flera domänexperter. Ut ur denna process kommer en uppsättning initiala begrepp som mappar ett till ett med verksamhetens begrepp och som sammantaget utgör ett Ubiquitous Language.

Från början behöver språket inte vara komplett eller perfekt; språket utvidgas och förfinas iterativt allt eftersom utvecklingen fortskrider. Detta språk används sedan uteslutande i systemets domänmodell – det vill säga i de klasser och konstruktioner som utgör hjärtat i systemet – för att göra den begriplig både för utvecklare och domänexperter. Den kommunikation man investerar mellan utvecklare och domänexperter har då potentialen att leda till kod som kommunicerar vertikalt  – från ledning ner till enskild utvecklare – i en organisation. Visst är det vackert?

Utökad förståelse

Så långt var jag med redan innan jag satte tänderna i Vaughn Vernons bok Implementing Domain-Driven Design. Det jag tänkte ta upp här är lite om den utökade förståelsen av DDD som jag fått i och med att jag läst boken. Lämpligt nog för detta inlägg har det just med Ubiquitous Language att göra.

Ubiquitous Languages existerar alltid i något man i DDD-termer kallar för Bounded Contexts. Man kan se dessa som partitioner i systemet i vilket ett visst Ubiquitous Language har mening. Att ett begrepps innebörd bestäms utifrån den kontext det används i är egentligen inget märkvärdigt. Det är ju så våra vanliga språk fungerar när vi kommunicerar människor emellan; med ordet ”hammare” menas förmodligen olika saker beroende på om man pratar med en snickare eller med en öronläkare.

Enligt författaren har i regel även enkla system flertalet Bounded Contexts, vilket då betyder att det i ett och samma system finns flera modeller som hålls åtskilda från varandra. Genom att man skyddar den interna modellen i en Bounded Context från att läcka ut kan den refaktoreras efter behov utan att omvärlden – det vill säga andra Bounded Contexts – behöver påverkas nämnvärt. Det gör också att modellen kan tillåtas att vara fokuserad eftersom den inte används för att lösa världens alla problem. Hur många gånger har man inte vågat ändra på en klass eftersom man då riskerar att förstöra någon helt annan del av applikationen? När jag då tänker på Bounded Context i samband med saker som Single Responsibility Principle blir jag nästan lite tårögd. 😉

Broar mellan öarna

Hur är det då tänkt att dessa isolerade ”öar” av Bounded Contexts ska hänga ihop om de inte får ta del av varandras modeller? För att förklara detta har jag skapat ett fiktivt exempel i form av en Context Map. Context Maps i DDD används för att hitta och synliggöra inbördes beroenden mellan olika Bounded Contexts. I mitt exempel (Figur 1) finner vi tre påhittade Bounded Contexts: Person registry context, Patient context och Billing context. Exemplet blir lite krystat eftersom vi inte har någon som helst insikt i domänen, men för mitt resonemang är det inte hela världen.

Figur 1
Figur 1: Context Map

Vi skulle kunna tänka oss att Figur 1 avser en Context Map för ett system inom sjukvården. U och D står för Upstream och Downstream respektive – analogin här är att upstream rinner downstream – och kan utläsas som att Patient context är beroende av Person registry context. I Person registry context – som jag tänker mig är en enkel CRUD-applikation för att registrera personuppgifter – hittar vi ett Ubiquitous Language som bland annat innehåller begrepp som ”Person” och ”Address”.

Men i Patient context finns inte begreppet ”Person” – här pratar man istället om ”Patient”. I DDD kastar man inte in begrepp bara för att det underlättar rent tekniskt – om personbegreppet inte passar in har det helt enkelt inte där att göra. Vidare ser vi att Billing context har ett beroende av både Person registry context och Patient context. I vårt exempel hämtas personinformation från Person registry context och underlag för fakturering från Patient context. I Billing context finner vi inte begrepp som ”Person” eller ”Patient” – här används istället termen InvoiceReceiver för att modellera räkningsmottagaren. Värt att notera är att både Patient och InvoiceReceiver kan ses som olika roller som kan antas av en Person. Det är tänkbart att dessa roller förmodligen håller en id-referens till aktuell Person i Person registry context.

Oavsett hur systemets Bounded Contexts hänger ihop rent tekniskt – man skulle till exempel kunna tänka sig web services – är min poäng att de aldrig, aldrig, aldrig exponerar sin interna modell. Och det finns ingen egentlig mening med det eftersom modellerna inte ska ha någon innebörd utanför sin kontext. För kommunikation mellan Bounded Contexts kan man använda Data Transfer Objects (DTOs) eller något motsvarande som endast syftar till dataöverföring. Mappning till det interna formatet sker via något som man i DDD-termer kallar för Anti Corruption Layer (ACL). Namnet låter finare än vad det egentligen är; med ACL menar vi helt enkelt ett lager som hanterar mappning från ett externt till ett internt format.

Den kritiske läsaren kanske tänker att upplägget jag beskrivit och illustrerat i Figur 1 inte är revolutionerande rent arkitektoniskt. En annan rimlig reflektion är att exemplet i Figur 1 inte heller är revolutionerande rent tekniskt. Här håller jag helt med. Vad som däremot kan anses som revolutionerande är att vi med DDD sätter lingvistik i första rummet, före coola tekniska lösningar. Om man som jag främst ser kod som kommunikation är detta perspektiv på systemutveckling oerhört intressant.

En arkitekturell insikt, del 2

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.

Figur 1
Figur 1: En krystad övergång

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.

Figure 2
Figur 2: Hexagonal architecture

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.

En arkitekturell insikt

Den lilla tid jag har fått över de senaste dagarna har i stort sett gått till att läsa i den alldeles eminenta boken Implementing Domain-Driven Design. Boken bygger på sätt och vis vidare på Evans tidlösa bok genom att ta upp nya insikter som har framkommit samt hur DDD kan implementeras med modern teknologi. Den är en rejäl bok att sätta tänderna i och det vore att skryta om jag sa att jag har kommit halvvägs. Hittills har den bjudit på många handfasta tips på hur man ska förhålla sig till DDD rent praktiskt. Redan såhär långt har flera av mina frågetecken kring DDD rätats ut och fler lär det bli om boken fortsätter att leverera. Tidigare idag när jag bläddrade i ett kapitel om arkitekturer sprang jag på något som inte direkt är relaterat till DDD men som ändå var värdefullt för mig. Detta tänker jag skriva av mig om här och nu.

När jag sitter och hackar i mina hemmaprojekt brukar jag nog tänka på strukturen som en layered architecture (i brist på en vettig svensk benämning). I denna ”klassiker” ser man arkitekturellt på systemet i flera lager där varje lager endast känner till det lager som finns direkt under lagret i fråga (Figur 1). Alltså känner bara Domain layer i Figur 1 till Infrastructure layer. Nu brukar man inte vara så bokstavstrogen – som jag har förstått det är det vanligast att ett lager känner till samtliga underliggande lager. Denna form av layered architecture kallar man för relaxed.

Figur 1
Figur 1: Layered architecture

Samtidigt har jag som förmodligen alla andra Javautvecklare under många år ägnat mig åt Dependency Injection (DI), i mitt fall via Spring. Att utveckla mot abstraktioner när det gäller saker som till exempel persistering sitter så i märgen på mig att jag knappt inte skulle kunna tänka mig att utveckla på något annat vis. DI är ett av flera sätt att realisera något som kallas för Dependency Inversion Principle (DIP). Väldigt förenklat kan man säga att principen innebär att man vänder på beroenderiktningen, att högnivåkomponenter inte är beroende av infrastrukturella saker. Detta rimmar illa med vad vi ser i Figur 1; enligt den traditionella layered architecture känner alla lager till Infrastructure layer. I alla fall om man tänker på varianten relaxed.

Som boken föreslår behöver vi om vi praktiserar DIP revidera Figur 1 för att bilden ska stämma med verkligheten. Jag låter mig här bli skamlöst inspirerad och min version av denna reviderade layered architecture kan ses i Figur 2. Den enda egentliga skillnaden mot innan är att Infrastructure layer nu finns att finna överst. Rent grafiskt kan man tycka att skillnaden är liten men konsekvensen av förändringen är stor. Figuren säger att det är okej för infrastrukturkomponenter att känna till abstraktioner (dvs gränssnitt) i till exempel applikations- och domänlagret. I verkligheten är det ju så vi hela tiden har arbetat med DI, att vi implementerar gränssnitt och dessa implementationer injectas in i programmet med hjälp av ramverk såsom Spring. Men den verkligheten stämmer inte överens med Figur 1.

Figur 2
Figur 2: DIP layered architecture

För mig var det en ögonöppnare. Nu förstår jag varför jag har haft svårt att hitta en naturlig plats för infrastrukturklasser (tänk till exempel en HibernateAnimalRepository) i mina projekt. Den faktiska arkitekturen (Figur 2) matchade inte min mentala bild (Figur 1).