48
PAINTFEUD Erfarenheter

PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

PAINTFEUDErfarenheter

Page 2: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

OM OSS

Tobias Hill, Citerus

!

Jesper Hammarbäck, Citerus

KLIENT

SERVER

Page 3: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

AGENDA• VAD?

Paintfeud, Spelet

• VARFÖR?

• HUR?Arkitektur klient & server, CQRS

• ERFARENHETER

Page 4: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

VAD?

Page 5: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

PAINTFEUD

• Pictionary:ish • 2-8 spelare per spel • Spelarna turas om att rita och gissa • Vinnare koras

Page 6: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

VARFÖR?

Page 7: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

• Utmaningen • Lära & testa nya tekniker • Så kul att vi inte kan låta bli

Page 8: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

HUR?

Page 9: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

TOPOLOGICLIENTSCLIENTSiOS

KLIENTER

APACHE

JETTY MongoDB

JSON över HTTPS

PULL en gång i minuten

Page 10: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

KLIENT

Page 11: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

KLIENTRAMVERK: Appcelerator TitaniumJavascript som limspråk mot rikt API

Page 12: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

KLIENTRAMVERK: Appcelerator TitaniumPluginbaserat

Page 13: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

KLIENT

MODEL

Services

UI

Ext Updater

Server state

Observer Pattern

*service.js

UI-element

remote.js

Commands

Page 14: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

SERVER

Page 15: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

CQRS

Command Query Responsibility Segregation

• B. Meyers CQS, Command/Query SeparationAtt ställa en fråga ska aldrig ändra svaret

• Tillämpas inom ett Bounded Context

Page 16: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

CQRS”Simply the creation of two objects where there was previously only one”

-- Greg Young

• Separerar skriv från läs inom kontextetRen domänmodell på skrivsidanFlera klientanpassade modeller på lässidan

Page 17: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

EVENT SOURCINGDefinition: Capture all changes to an application state as a sequence of events

GameCreated(id1, 1)

PlayerJoined(id1, 2)

PlayerJoined(id1, 3)

RoundStarted(id1, 4)

Game

- gameId : id1 - version: 4 - state : AwaitingPainting

Page 18: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

SERVER

• Scala • Scalatra • Spring (DI, i18n, JMX etc.) • Jetty • Quartz Scheduler • Maven

Page 19: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

SERVER - GAME BC

Game Domain Model

Repository

Event Store

EventPublisher EventBus

SagaScheduler

Commands

HTTP API Command EP

Queries

Query EP

ReadModelFacadeTask Store

Read Model Store

Denormalizers

CommandHandler

Page 20: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

VARFÖR CQRS+ES?

Page 21: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

ERFARENHETER

Page 22: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

ERFARENHET 1: BRA KLIENTUPPLEVELSE

ÄR SVÅRT

Page 23: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

ANTAGANDE: “Mobilnätverk är tillräckligt bra”ANTAGANDE: “Mobilnätverk är tillräckligt bra”

Page 24: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

Ok. Jag är redo!

Ditt ord är “BIL”.

Här kommer min BIL:

Dags att gissa!

Gissar “NATT”

FEL

Din tur att rita!

Gissar “BIL”

RÄTT

Page 25: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

Här kommer min BIL.

Dags att gissa! (Rätt ord: “BIL”)

Jag gissade rätt på 24s.

Ny runda. Du ritar! Ord: “BIL”.

Page 26: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

KLIENT

MODEL

*service.js

UI-element

remote.js Updater

Services

UI

Ext

Commands Server state

Observer Pattern

FEJK

Page 27: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

STATE

SERVER !!

KLIENT !

STÖRRE UTMANING • Spelare är sist att acceptera/neka ett spel. • Spelare X gissar sist i en runda, men ritar inte i nästa. • Spelare X gissar sist i en runda, och är den som skall

rita i nästa.

EXEMPEL PÅ FEJK (för flow) • Spelare accepterar/nekar ett spel. • Spelare har just ritat eller gissat.

LOOK-AHEAD

Page 28: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

ERFARENHET 2: CQRS GER FÖRDELAR

Page 29: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

Game Domain Model

Repository

Event Store

EventPublisher EventBus

SagaScheduler

Command EP Query EP

ReadModelFacadeTask Store

Read Model Store

Denormalizers

CommandHandler

Page 30: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

HTTP-APIpost("/:gameId/join") { ! // May cause IllegalArgumentException -> SC_BAD_REQUEST (400) val gameId = GameId(params("gameId")) val sessionId = SessionId(params("sessionId")) ! // May cause NoSessionException -> SC_UNAUTHORIZED (401) val playerId = sessionRepository.get(sessionId) ! commandHandler ! JoinPlayer(gameId, playerId) status(SC_OK) }

Page 31: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

Game Domain Model

Repository

Event Store

EventPublisher EventBus

SagaScheduler

Command EP Query EP

ReadModelFacadeTask Store

Read Model Store

Denormalizers

CommandHandler

Page 32: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

CommandHandler (Actor)

case JoinPlayer(gameId, playerId) => { val game = repository.load(gameId) game.joinPlayer(playerId) repository.save(game) }

Page 33: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

Game Domain Model

Repository

Event Store

EventPublisher EventBus

SagaScheduler

Command EP Query EP

ReadModelFacadeTask Store

Read Model Store

Denormalizers

CommandHandler

Page 34: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

GAME - AGGREGATROTclass Game extends AggregateRoot { ! private val joinedPlayers = new LinkedHashSet[PlayerId] ! def joinPlayer(playerId: PlayerId) { assertIsInvited(playerId) if (!hasAlreadyJoined(playerId)) { applyChange(PlayerJoined(gameId, nextVersion(), now(), playerId)) if (hasReceivedAllInvitationResponses) { applyChange(RoundStarted(gameId, nextVersion(), now(), creator, nextWord())) } } } !!!!!}

! def handleEvent(event: PlayerJoined) { version = event.version lastUpdated = event.timestamp joinedPlayers += event.playerId }

Page 35: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

GAME - AR TRAITtrait AggregateRoot { ! private val uncommittedEvents = new ListBuffer[GameEvent] ! def applyChange(e: GameEvent, isNew : Boolean = true) { getClass.getMethod("handleEvent", e.getClass).invoke(this, e) if (isNew) uncommittedEvents += event

def loadFromHistory(history: List[GameEvent]) { history.foreach(applyChange(_, isNew = false)) } !}

Page 36: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

EN REN MODELL ÄR LÄTT ATT TESTA

Page 37: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

Game Domain Model

Repository

Event Store

EventPublisher EventBus

SagaScheduler

Command EP Query EP

ReadModelFacadeTask Store

Read Model Store

Denormalizers

CommandHandler

Page 38: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

QUERY-SIDAN - DENORMALIZERS

• Enkelt att lägga till nya vid behov • Undvik beroenden mellan denormalizers • Bygg upp nya modeller mha återpublicering

Page 39: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

ERFARENHET 3: ACTORS FÖRENKLAR

Page 40: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

ACTORS

! def getHandler(id: GameId) = { handlerPool(math.abs(id.hashCode % numberOfHandlers)) }

Mailbox

Page 41: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

ERFARENHET 4: DYNAMISKT DATA

Page 42: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

• Lägg till dynamisk data vid query-tillfället !

• Avatar, antal chattmeddelanden etc.

Page 43: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

ERFARENHET 5: EVOLVERANDE LOGIK

Page 44: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

FÖRÄNDRING AV EVENTS • Scalas Option (JSON-deserialiseraren använder None) • Ny konstruktor (JSON-deserialiseraren väljer den som passar) • Nytt event, t.ex PlayerJoinedWithLocale

Page 45: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

ERFARENHET 6: VERSIONSHANTERAT API

Page 46: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

• Undvik om möjligt, pga ökad komplexitet • JSON är naturligt förändringståligt • Vi versionshanterar mha HTTP Accept header

Page 47: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

POST /login application/vnd.com.paintfeud-v1.0+json

HTTP 406, NOT_ACCEPTABLE (Hämta en ny från AppStore)

HTTP 200, OK (Nu kör vi!)

POST /login application/vnd.com.paintfeud-v1.2+json

minimumSupportedVersion = 1.1

Page 48: PF - Lessons learned (split) · 2019-09-11 · Command Query Responsibility Segregation • B. Meyers CQS, Command/Query Separation

SAMMANFATTNING

Tobias Hill [email protected] Spelarnamn i Paintfeud: tobias

Jesper Hammarbäck [email protected] Spelarnamn i Paintfeud: jesper