DDD DYSFUNCTIONAL...3/13/2019 reveal.js 1/133 DYSFUNCTIONAL DDD

133
3/13/2019 reveal.js http://localhost:8000/?print-pdf#/ 1/133 DYSFUNCTIONAL DYSFUNCTIONAL DDD DDD

Transcript of DDD DYSFUNCTIONAL...3/13/2019 reveal.js 1/133 DYSFUNCTIONAL DDD

Page 1: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 1/133

DYSFUNCTIONALDYSFUNCTIONALDDDDDD

Page 2: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 2/133

JAREKJAREKWizard, Anarchitect, Coder

Page 3: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 3/133

JAREKJAREKWizard, Anarchitect, Coder

> 25 years of coding

Page 4: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 4/133

Page 5: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 5/133

DISCLAIMERDISCLAIMER

Page 6: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 6/133

DISCLAIMERDISCLAIMERI tried not to attack anyone personally, actually I dolike my colleagues doing DDD, and I have learned alot from some of them

Page 7: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 7/133

DISCLAIMERDISCLAIMERI tried not to attack anyone personally, actually I dolike my colleagues doing DDD, and I have learned alot from some of themnot an expert, (some experience wih CQRS/ES notDDD)

Page 8: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 8/133

WHY DDD?WHY DDD?People talk about itObject orientedworldLike mixing concepts

Page 9: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 9/133

My problem with DDD

Page 10: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 10/133

DDD story resembles me

UMLwhat happened toAgile

Page 11: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 11/133

Page 12: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 12/133

cool

Page 13: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 13/133

Page 14: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 14/133

What??

Page 15: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 15/133

AGILE COOLAGILE COOLTests, TDDCI,Code overcommentscontact with user

Page 16: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 16/133

Page 17: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 17/133

AGILE REALITYAGILE REALITYboringmeetingsagile coaches,certificatesagile toolsbooksconferencestrainingsvelocity :-)

Page 18: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 18/133

Page 19: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 19/133

There is nothing wrong about money.

I work for money!

Page 20: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 20/133

But who likes marketing b...it?!

Page 21: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 21/133

Page 22: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 22/133

For years I was scared of DDD marketing

Page 23: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 23/133

BOOKSBOOKS

Page 24: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 24/133

Make logic of the system visible in code

Page 25: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 25/133

DDD GOOD PARTSDDD GOOD PARTScommunityconstantimprovementlots of patterns /ideasinteresting stories

Page 26: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 26/133

Page 27: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 27/133

DDD bad(?) parts

marketingexample projectsover-engineeringpartly toxiccommunityhard to see the point

Page 28: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 28/133

If a tool, methodology, framework makes simple casecomplex

it will probably not make a real life, complex projectsimple

Page 29: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 29/133

Page 30: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 30/133

Page 31: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 31/133

BUTBUT

Page 32: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 32/133

Page 33: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 33/133

DDDDDD

Page 34: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 34/133

HARD WAYHARD WAY

Page 35: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 35/133

Skipping some essential parts.

Like bounded context etc.

Page 36: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 36/133

DDD is mostly not about technology

Page 37: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 37/133

FINDING COMMONFINDING COMMONLANGUAGELANGUAGE

Ubiquitous Language

Page 38: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 38/133

Some concepts are useful, but have nothing to do withFP

Page 39: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 39/133

I just love to code more

Page 40: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 40/133

And you wil not pay me areal money (for a fancy car) :-(

Page 41: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 41/133

LETS PLAY SNAKELETS PLAY SNAKE(MULTIPLAYER)(MULTIPLAYER)

Page 42: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 42/133

Page 43: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 43/133

COMMANDSCOMMANDS

Page 44: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 44/133

data SnakeCommand = SetDirection { wantedDirection :: SnakeDirection } | MakeStep | Begin { initName :: String , initCell :: SnakeCell }

Page 45: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 45/133

COMMANDSCOMMANDSuser or subsytem wants to do somethingcommands may be associated withvalidation

Page 46: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 46/133

EVENTSEVENTSdata SnakeEvent = DirectionChanged { newDirection :: SnakeDirection } | StepMade | Killed | Born { bornName :: String , bornCell :: SnakeCell } deriving (Eq, Show, Generic)

Page 47: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 47/133

EVENTEVENTit has happenedno validation (it really happened)a single command is associated in 0..nevents

Page 48: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 48/133

Fact

You will not find anything about this in Eric Evans book(blue))

Even though nowadays DDD community seems to beall around those concepts

Page 49: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 49/133

EVENT SOURCINGEVENT SOURCINGWhat if just stored only events?

Page 50: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 50/133

[ { "event": { "tag": "Born", "bornName": "aa", "bornCell": { "cellY": 18, "cellX": 14 } }, "snakeId": "4d09ac06-0375-4cb0-ad08-c70d14968677" }, { "event": { "tag": "DirectionChanged",

Page 51: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 51/133

COMMANDCOMMANDSOURCING?SOURCING?

Also possible... but in fact harder - validation is aproblem

Page 52: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 52/133

VALUE OBJECTVALUE OBJECTimmutable...represents value (from reallife)has no identityproperties define equality

Page 53: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 53/133

type SnekeId = String type NickName = Text data SnakeDirection = SnakeUp | SnakeRight | SnakeDown | SnakeLeft

Page 54: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 54/133

ENTITYENTITYhas identityin OOP may be mutableID defines equalityentity may contain valueobjects

entity may contain entities

Page 55: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 55/133

data SnakeCell = SnakeCell { cellX :: Int , cellY :: Int } data SnakeState = Alive { direction :: SnakeDirection , cells :: [SnakeCell] , maxLength :: Int } | Dead | Init data Snake = Snake { name :: String

Page 56: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 56/133

Easy?

Page 57: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 57/133

SnakeCell(x,y) is value object orentity?

Page 58: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 58/133

To think

I have never introduced type SnakeEntity =(SnakeId, Snake)

Only have SnakeState which does not (physically)contain Id

Page 59: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 59/133

To think

I have never introduced type SnakeEntity =(SnakeId, Snake)

Only have SnakeState which does not (physically)contain Id

an Entity without id??

Page 60: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 60/133

Some DDD concepts may not be explicitly existing incode

(SnakeId, Snake)

Page 61: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 61/133

It gets worse

Page 62: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 62/133

AGGREGATEAGGREGATE

Page 63: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 63/133

Cluster of objects (entities, value objects, + )

Page 64: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 64/133

Aggregate remains consistent

Page 65: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 65/133

Keeps invariants

Page 66: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 66/133

Transactions should not cross aggregates

Page 67: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 67/133

AGGREGATE ROOTAGGREGATE ROOTSelected entity from Aggregate (root)outside world communicates with it (sendscommands)outside world only keeps reference to this rootobject

command handlerevent handler

Page 68: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 68/133

Typeclass source:

class Aggregate s where data Error s :: * data Command s :: * data Event s :: * execute :: s -> Command s -> Either (Error s) (Event s) apply :: s -> Event s -> s seed :: s

https://gist.github.com/Fristi/7327904

Page 69: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 69/133

COMMAND HANDLERCOMMAND HANDLERexecuteCommand :: Snake -> SnakeCommand -> [SnakeEvent]

Page 70: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 70/133

BETTER COMMANDBETTER COMMANDHANDLERHANDLER

executeCommand :: Snake -> SnakeCommand -> Either MyError [SnakeEvent]

Page 71: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 71/133

EVENT HANDLEREVENT HANDLERapplyEvent::Snake-> SnakeEvent -> Snake

Page 72: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 72/133

SUMMARYSUMMARYdefine commandsdefine eventsselect root Entitydefine commandshandlerdefine events handler

Page 73: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 73/133

Real Command handler

executeCommand :: SnakeData -> SnakeCommand -> [SnakeEvent] executeCommand SnakeData {state = Alive {}} MakeStep = [StepMaexecuteCommand _ MakeStep = [] executeCommand SnakeData {state = Alive {direction = od}} SetD | opposite = [] | otherwise = [DirectionChanged {newDirection = nd}] where opposite = V.dirIs0 $ V.dirPlus newVec currentVec newVec = V.dirVector nd currentVec = V.dirVector od executeCommand anySnake SetDirection {} = [] executeCommand SnakeData {state = Alive {}} Die = [Killed] executeCommand _ Die = [] executeCommand SnakeData {state = Init} Begin {initName = d, iexecuteCommand _ Begin {} = []

Page 74: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 74/133

Real event handler

applyEventX snake@(SnakeData {state = alive@Alive {}}) Directi makeRes $ snake { state = alive{direction = nd} } applyEventX snake@(SnakeData {state = Alive {}}) Killed = makeapplyEventX SnakeData {state = Init} Born {bornName = nm, born newSnake = SnakeData { name = nm , state = initial newCells = [cell], removedCells = [] } where initialState = Alive { direction = SnakeUp, cells = [applyEventX snake@(SnakeData {state = alive@Alive {maxLength = makeRes snake { state = alive { maxLength = n+3} } applyEventX _ _ = error "todo"

Page 75: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 75/133

Modelling with events, commands is not needed inDDD

It was not even considered in an original DDD book

behaviour first seem to be quite efficient

Page 76: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 76/133

Event storming

Page 77: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 77/133

Alternative to command handler / Aggregate

Page 78: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 78/133

Commands

data SnakeCommand = SetDirection { wantedDirection :: SnakeDirection } | MakeStep | Begin { initName :: String , initCell :: SnakeCell } | Die

Page 79: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 79/133

Have You seen that before?

data SnakeCommand next = SetDirection { wantedDirection :: SnakeDirection } | MakeStep next | Begin { initName :: String , initCell :: SnakeCell } next | Die

Page 80: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 80/133

Free monad DSL

Page 81: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 81/133

Seems to be more usable in sequencing

Page 82: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 82/133

In typical REST we have one http call -> onecommand. Sequencing is not that needed.

Page 83: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 83/133

HOW TO FINDHOW TO FINDAGGREGATES?AGGREGATES?

Page 84: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 84/133

Whole system as an aggregate?

(One Big Aggregate)

Page 85: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 85/133

REPOSITORYREPOSITORY

Page 86: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 86/133

Remember DAO?

Page 87: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 87/133

Magic...

Page 88: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 88/133

Page 89: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 89/133

loadEntity::Id->IO EntitysaveEntity::Id->Entity->IO()etc...

Page 90: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 90/133

Fact Lots of magic Java frameworks trace state ofobjects and automatically persist changes to database

This means that a sensible repository save methodmay look like:

Page 91: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 91/133

void save(MyObject t) { }

Page 92: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 92/133

Yep, this works. There are lot of such projects.

void save(MyObject t) { }

Page 93: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 93/133

But what in case of event sourcing?

Page 94: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 94/133

data SnakeAggregate = SnakeAggregate { state :: SnakeState, uncommittedEvents :: [SnakeEvent] }

Page 95: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 95/133

Common pattern in DDD style event sourcing is to savethose uncommited events

Page 96: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 96/133

I find it unnatural

Page 97: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 97/133

I started to send commands to a Repository

Page 98: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 98/133

applyCommand :: SnakesRepo-> SnakeId -> Snake.SnakeCommand -> IO SnakesRepo

Page 99: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 99/133

This is so unDDD

applyCommand :: SnakesRepo-> SnakeId -> Snake.SnakeCommand -> IO SnakesRepo

Page 100: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 100/133

Makes for more sense than repeating a code with saveevents

In my aggregates I do not have those uncommitedevents (is this a domain?)

Page 101: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 101/133

CQSCQSCommand Query separation

Page 102: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 102/133

If you ask (Query) do not change the state

Page 103: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 103/133

If You change state (Command) do not expect result

Page 104: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 104/133

A Stackvoid stack.push( T t); T stack.pop();

Page 105: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 105/133

A CQS Stackvoid stack.push( T t); T stack.top(); void stack.pop();

Page 106: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 106/133

Simple?

Page 107: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 107/133

what if called on empty stack?void stack.pop(); // boom

Page 108: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 108/133

OO world consensus:

commands may return exceptions, some status, etc.

Page 109: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 109/133

Is an error not a result?

Page 110: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 110/133

In FP world

Page 111: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 111/133

push::Stack a->a->Stack a top::Stack a->a pop::Stack a->Stack a

Page 112: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 112/133

In FP world each operation gives a result

Page 113: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 113/133

IO ()

Page 114: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 114/133

Is it really bad?

whatAPop::Stack a->(Stack a, a)

Page 115: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 115/133

Actually I do not see much sense in classical CQS

nice to have separated queriesError/Exception is an resultIt only makes API easier to use ... in some mediocrelanguagesasync?

Page 116: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 116/133

push::Stack a -> MonadAsync (Stack a)

Page 117: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 117/133

CQRSCQRSCommand Query Response Segregation

Page 118: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 118/133

CQRS ~ CQS on a higher level

Page 119: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 119/133

Write/Command model - Aggregates

Page 120: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 120/133

Read/Query model - Projections

Page 121: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 121/133

Page 122: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 122/133

Some CQRS principles

Critical: Events application cannot use any externaldata (projection)So�er: Commands should not use projection toproduce EventsYou can always recreate Aggregates using eventsYou can always recreate multiple projections usingevents

Page 123: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 123/133

Fact

In less impure languages it is easy to make amistake

LocalDate.now() someRandom.nextInt()

Page 124: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 124/133

Fact

In typical Event souring operations likefindMeIdsOfAllAggregates are performed

using projections

Page 125: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 125/133

My game field projection

data PlaneState = PlaneState { allSnakes :: Repo.SnakesMap , allCells :: CellsMap , changes :: Changes } deriving (Show, Generic) -- projection applyEvent :: PlaneState -> Repo.SnakeQualifiedEvent -> (Plane

Page 126: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 126/133

Used by browser

Page 127: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 127/133

Projections are great:

potentialperformancemake UI code simpler

Page 128: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 128/133

I use them to detect collisions

If I find collision on a gameField I send Die commandto snake

I read few times this is wrong...

But I do not see better solution (other than One BigAggregate)

Page 129: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 129/133

In CQRS some operations are quite hardnextId::Sequence->Int

Page 130: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 130/133

CODECODEdsnake - haskell rest server, (yesod)

Work in progress

Please, do not use it as a sensible DDD exampleresource (yet)

https://github.com/jarekratajski/dysfunctional_ddd

Page 131: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 131/133

RESOURCES ONRESOURCES ONDDD/CQRSDDD/CQRS

Bottega presentations

"The" books

http://CQRS.nu (FAQ) page

https://github.com/ddd-by-

examples/event-source-cqrs-sample byKuba Nabrdalik

Page 132: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 132/133

https://github.com/vlingo vlingo platform

Page 133: DDD DYSFUNCTIONAL...3/13/2019 reveal.js  1/133 DYSFUNCTIONAL DDD

3/13/2019 reveal.js

http://localhost:8000/?print-pdf#/ 133/133

Q?Q?