Top Banner
From Functional to Reactive patterns in domain modeling Debasish Ghosh @debasishg Tuesday, 6 October 15
126

From functional to Reactive - patterns in domain modeling

Apr 16, 2017

Download

Software

Debasish Ghosh
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: From functional to Reactive - patterns in domain modeling

From Functional to Reactive

patterns in domain modeling

Debasish Ghosh@debasishg

Tuesday, 6 October 15

Page 2: From functional to Reactive - patterns in domain modeling

Tuesday, 6 October 15

Page 3: From functional to Reactive - patterns in domain modeling

Domain Modeling

Tuesday, 6 October 15

Page 4: From functional to Reactive - patterns in domain modeling

Domain Modeling(Functional)

Tuesday, 6 October 15

Page 5: From functional to Reactive - patterns in domain modeling

Domain Modeling

(Responsive)

(Functional)

Tuesday, 6 October 15

Page 6: From functional to Reactive - patterns in domain modeling

Domain Modeling

(Responsive)

(Functional)

(Elastic)

Tuesday, 6 October 15

Page 7: From functional to Reactive - patterns in domain modeling

Domain Modeling

(Responsive)

(Functional)

(Elastic) (Resilient)

Tuesday, 6 October 15

Page 8: From functional to Reactive - patterns in domain modeling

Domain Modeling

(Responsive)

(Functional)

(Elastic) (Resilient)

(Reactive)Tuesday, 6 October 15

Page 9: From functional to Reactive - patterns in domain modeling

What is a domain model ?

A domain model in problem solving and software engineering is a conceptual model of all the topics related to a specific problem. It describes the various entities, their attributes, roles, and relationships, plus the constraints that govern the problem domain. It does not describe the solutions to the problem.

Wikipedia (http://en.wikipedia.org/wiki/Domain_model)

Tuesday, 6 October 15

Page 10: From functional to Reactive - patterns in domain modeling

The Functional Lens ..

“domain API evolution through algebraic composition”

Tuesday, 6 October 15

Page 11: From functional to Reactive - patterns in domain modeling

The Functional Lens ..

“domain API evolution through algebraic composition”

(Reactive)

Tuesday, 6 October 15

Page 12: From functional to Reactive - patterns in domain modeling

Agenda

• Formalizing a domain model

• Domain model algebra

• From functional to algebraically reactive

• Beyond algebra

• Actors and domain models

• Reactive streams - typesafe & compositional

Tuesday, 6 October 15

Page 13: From functional to Reactive - patterns in domain modeling

Tuesday, 6 October 15

Page 14: From functional to Reactive - patterns in domain modeling

Tuesday, 6 October 15

Page 15: From functional to Reactive - patterns in domain modeling

Your domain model is a function

Tuesday, 6 October 15

Page 16: From functional to Reactive - patterns in domain modeling

Your domain model is a function

Tuesday, 6 October 15

Page 17: From functional to Reactive - patterns in domain modeling

Your domain model is a collection of functions

Tuesday, 6 October 15

Page 18: From functional to Reactive - patterns in domain modeling

Your domain model is a collection of functions

some simpler models are ..

Tuesday, 6 October 15

Page 19: From functional to Reactive - patterns in domain modeling

https://msdn.microsoft.com/en-us/library/jj591560.aspx

Tuesday, 6 October 15

Page 20: From functional to Reactive - patterns in domain modeling

A Bounded Context

• has a consistent vocabulary

• a set of domain behaviors modeled as functions on domain objects implemented as types

• related behaviors grouped as modules

Tuesday, 6 October 15

Page 21: From functional to Reactive - patterns in domain modeling

Domain Model = ∪(i) Bounded Context(i)

Tuesday, 6 October 15

Page 22: From functional to Reactive - patterns in domain modeling

Domain Model = ∪(i) Bounded Context(i)

Bounded Context = { f(x) | p(x) ∈ Domain Rules }

Tuesday, 6 October 15

Page 23: From functional to Reactive - patterns in domain modeling

Domain Model = ∪(i) Bounded Context(i)

Bounded Context = { f(x) | p(x) ∈ Domain Rules }

• domain function• on an object of type x• composes with other functions• closed under composition

• business rules

Tuesday, 6 October 15

Page 24: From functional to Reactive - patterns in domain modeling

• Functions / Morphisms

• Types / Sets

• Composition

• Rules / Laws

Tuesday, 6 October 15

Page 25: From functional to Reactive - patterns in domain modeling

• Functions / Morphisms

• Types / Sets

• Composition

• Rules / Laws

algebraTuesday, 6 October 15

Page 26: From functional to Reactive - patterns in domain modeling

Domain Model Algebra

Tuesday, 6 October 15

Page 27: From functional to Reactive - patterns in domain modeling

Domain Model Algebra

(algebra of types, functions & laws)

Tuesday, 6 October 15

Page 28: From functional to Reactive - patterns in domain modeling

Domain Model Algebra

(algebra of types, functions & laws)

explicit• types• type constraints• expression in terms of other generic algebra

Tuesday, 6 October 15

Page 29: From functional to Reactive - patterns in domain modeling

Domain Model Algebra

(algebra of types, functions & laws)

explicit

verifiable

• types• type constraints• expression in terms of other generic algebra

• type constraints• more constraints if you have DT• algebraic property based testing

Tuesday, 6 October 15

Page 30: From functional to Reactive - patterns in domain modeling

close

debit

open

...

Domain Behaviors

Tuesday, 6 October 15

Page 31: From functional to Reactive - patterns in domain modeling

Amount

Account

Balance

Customer

......

...close

debit

open

...

Domain Behaviors Domain Types

Tuesday, 6 October 15

Page 32: From functional to Reactive - patterns in domain modeling

Amount

Account

Balance

Customer

......

...close

debit

open

...

market regulations

tax laws

brokerage commission

rates

...

Domain Behaviors Domain TypesDomain Rules

Tuesday, 6 October 15

Page 33: From functional to Reactive - patterns in domain modeling

Amount

Account

Balance

Customer

......

...close

debit

open

...

market regulations

tax laws

brokerage commission

rates

...

Domain Behaviors Domain TypesDomain Rules

Monoid Monad ...

Generic Algebraic Structures

Tuesday, 6 October 15

Page 34: From functional to Reactive - patterns in domain modeling

Amount

Account

Balance

Customer

......

...close

debit

open

...

market regulations

tax laws

brokerage commission

rates

...

Domain Behaviors Domain TypesDomain Rules

Monoid Monad ...

Generic Algebraic Structures

Domain Algebra

Tuesday, 6 October 15

Page 35: From functional to Reactive - patterns in domain modeling

Domain Model = ∪(i) Bounded Context(i)

Bounded Context = { f(x) | p(x) ∈ Domain Rules }

• domain function• on an object of type x• composes with other functions• closed under composition

• business rules

Domain Algebra

Domain Algebra

Tuesday, 6 October 15

Page 36: From functional to Reactive - patterns in domain modeling

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

Algebra is the binding contract

Bounded Context

Tuesday, 6 October 15

Page 37: From functional to Reactive - patterns in domain modeling

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

Algebra is the binding contract

Bounded Context

Reactive

Tuesday, 6 October 15

Page 38: From functional to Reactive - patterns in domain modeling

Conference Reservations

ProgramManagement

Badge Printing

Conference ReservationsConference Reservations

Domain Algebra A

Domain Algebra B

Domain Algebra C

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

Tuesday, 6 October 15

Page 39: From functional to Reactive - patterns in domain modeling

• Algebras don’t unify across bounded contexts

• Decoupled in space and time

• Separate vocabulary

• Types break down

Tuesday, 6 October 15

Page 40: From functional to Reactive - patterns in domain modeling

Conference Reservations

ProgramManagement

Badge Printing

Conference ReservationsConference Reservations

Domain Algebra A

Domain Algebra B

Domain Algebra C

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

Protocols

Tuesday, 6 October 15

Page 41: From functional to Reactive - patterns in domain modeling

Conference Reservations

ProgramManagement

Badge Printing

Conference ReservationsConference Reservations

Domain Algebra A

Domain Algebra B

Domain Algebra C

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

ProtocolsReacti

ve

Tuesday, 6 October 15

Page 42: From functional to Reactive - patterns in domain modeling

Being Reactive

Elasticity(responsive under

varying load)

Resilience(responsive in the face of failures)

Message-driven(loose coupling, isolation thru async message

passing)

Responsive (through bounded

latency)

Tuesday, 6 October 15

Page 43: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type AccountOp[A] = NonEmptyList[String] \/ A

def open(no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType): AccountOp[Account]

def close(no: String, closeDate: Option[Date]): AccountOp[Account]

def debit(no: String, amount: Amount): AccountOp[Account]

def credit(no: String, amount: Amount): AccountOp[Account]

//..}

Tuesday, 6 October 15

Page 44: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type AccountOp[A] = NonEmptyList[String] \/ A

def open(no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType): AccountOp[Account]

def close(no: String, closeDate: Option[Date]): AccountOp[Account]

def debit(no: String, amount: Amount): AccountOp[Account]

def credit(no: String, amount: Amount): AccountOp[Account]

//..}

Module Name

Tuesday, 6 October 15

Page 45: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type AccountOp[A] = NonEmptyList[String] \/ A

def open(no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType): AccountOp[Account]

def close(no: String, closeDate: Option[Date]): AccountOp[Account]

def debit(no: String, amount: Amount): AccountOp[Account]

def credit(no: String, amount: Amount): AccountOp[Account]

//..}

Module Name Parameterized on types

Tuesday, 6 October 15

Page 46: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type AccountOp[A] = NonEmptyList[String] \/ A

def open(no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType): AccountOp[Account]

def close(no: String, closeDate: Option[Date]): AccountOp[Account]

def debit(no: String, amount: Amount): AccountOp[Account]

def credit(no: String, amount: Amount): AccountOp[Account]

//..}

Module Name Parameterized on typesOperation return type - eithera successfully constructed type

or a list of errors

Tuesday, 6 October 15

Page 47: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type AccountOp[A] = NonEmptyList[String] \/ A

def open(no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType): AccountOp[Account]

def close(no: String, closeDate: Option[Date]): AccountOp[Account]

def debit(no: String, amount: Amount): AccountOp[Account]

def credit(no: String, amount: Amount): AccountOp[Account]

//..}

Module Name Parameterized on typesOperation return type - eithera successfully constructed type

or a list of errors

Operations - domain behaviors

Tuesday, 6 October 15

Page 48: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type AccountOp[A] = NonEmptyList[String] \/ A

def open(no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType): AccountOp[Account]

def close(no: String, closeDate: Option[Date]): AccountOp[Account]

def debit(no: String, amount: Amount): AccountOp[Account]

def credit(no: String, amount: Amount): AccountOp[Account]

//..}

Module Name Parameterized on typesOperation return type - eithera successfully constructed type

or a list of errors

Operations - domain behaviors explicit & verifiable algebra

Tuesday, 6 October 15

Page 49: From functional to Reactive - patterns in domain modeling

• Parametric - parameterized on types

• Statically Typed

• Modular and hence unit testable

• Composable

Tuesday, 6 October 15

Page 50: From functional to Reactive - patterns in domain modeling

def transfer(from: String, to: String, amount: Amount) : AccountOp[(Account, Account)] = for {

a <- debit(from, amount) b <- credit(to, amount)

} yield ((a, b))

Composable

Tuesday, 6 October 15

Page 51: From functional to Reactive - patterns in domain modeling

Composable

trait BankingService[Account, Amount, Balance]

extends AccountService[Account, Amount, Balance]

with InterestPostingService[Account, Amount]

with InterestCalculation[Account, Amount]

with TaxCalculation[Amount]

Tuesday, 6 October 15

Page 52: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type AccountOp[A] = NonEmptyList[String] \/ A

def open(

no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType

): AccountRepository => AccountOp[Account]

//..}

Tuesday, 6 October 15

Page 53: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type AccountOp[A] = NonEmptyList[String] \/ A

def open(

no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType

): AccountRepository => AccountOp[Account]

//..}

change the algebra to add functionality

Tuesday, 6 October 15

Page 54: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type Valid[A] = NonEmptyList[String] \/ A

type AccountOp[A] = Kleisli[Valid, AccountRepository, A]

def open(

no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType

): AccountOp[Account]

//..}

more algebra, more functionality, more succinct

Tuesday, 6 October 15

Page 55: From functional to Reactive - patterns in domain modeling

• Design should not have any contention or central bottlenecks that tend to hamper the progress of the system

Being Reactive

Tuesday, 6 October 15

Page 56: From functional to Reactive - patterns in domain modeling

• If your domain service publishes APIs that does blocking calls to underlying databases and blocks the central thread of user interaction, you face the specter of unbounded latency

Being Reactive

Tuesday, 6 October 15

Page 57: From functional to Reactive - patterns in domain modeling

Blocking Kills

Tuesday, 6 October 15

Page 58: From functional to Reactive - patterns in domain modeling

Blocking Kills

Make your APIs elastic enough so that the perceived response to the user is not affected by the current load on the system

Tuesday, 6 October 15

Page 59: From functional to Reactive - patterns in domain modeling

Elasticity(responsive under

varying load)

Resilience(responsive in the face of failures)

Message-driven(loose coupling, isolation thru async message

passing)

Responsive (through bounded

latency)

Tuesday, 6 October 15

Page 60: From functional to Reactive - patterns in domain modeling

• Without foregoing the benefits of algebraic reasoning with types

Being Reactive

Tuesday, 6 October 15

Page 61: From functional to Reactive - patterns in domain modeling

Enter Futures ..

Tuesday, 6 October 15

Page 62: From functional to Reactive - patterns in domain modeling

Enter Futures ..

• A future is the essence of asynchronous non blocking computation

Tuesday, 6 October 15

Page 63: From functional to Reactive - patterns in domain modeling

Enter Futures ..

• A future is the essence of asynchronous non blocking computation

• Futures compose

Tuesday, 6 October 15

Page 64: From functional to Reactive - patterns in domain modeling

Enter Futures ..

• A future is the essence of asynchronous non blocking computation

• Futures compose

• Futures have an algebra

Tuesday, 6 October 15

Page 65: From functional to Reactive - patterns in domain modeling

Enter Futures ..

• A future is the essence of asynchronous non blocking computation

• Futures compose

• Futures have an algebra

• Organize concurrent code around futures safely and in a compositional way

Tuesday, 6 October 15

Page 66: From functional to Reactive - patterns in domain modeling

• In our use case we would like to augment our domain algebra with future based APIs

• Just like an Either or a Kleisli, we would like to have asynchrony as yet another stackable effect within our computation

Goals towards Reactive API

Tuesday, 6 October 15

Page 67: From functional to Reactive - patterns in domain modeling

Stacking of EffectsTuesday, 6 October 15

Page 68: From functional to Reactive - patterns in domain modeling

Stacking of EffectsTuesday, 6 October 15

Page 69: From functional to Reactive - patterns in domain modeling

type Response[A] = String \/ Option[A]

val count: Response[Int] = some(10).rightfor { maybeCount <- count} yield { for { c <- maybeCount // use c } yield c}

Monad Transformers

Tuesday, 6 October 15

Page 70: From functional to Reactive - patterns in domain modeling

type Response[A] = String \/ Option[A]

val count: Response[Int] = some(10).rightfor { maybeCount <- count} yield { for { c <- maybeCount // use c } yield c}

type Error[A] = String \/ Atype Response[A] = OptionT[Error, A]

val count: Response[Int] = 10.point[Response]for { c <- count // use c : c is an Int here} yield (())

Monad Transformers

Tuesday, 6 October 15

Page 71: From functional to Reactive - patterns in domain modeling

type Response[A] = String \/ Option[A]

val count: Response[Int] = some(10).rightfor { maybeCount <- count} yield { for { c <- maybeCount // use c } yield c}

type Error[A] = String \/ Atype Response[A] = OptionT[Error, A]

val count: Response[Int] = 10.point[Response]for{ c <- count // use c : c is an Int here} yield (())

Monad Transformers

richer algebra

Tuesday, 6 October 15

Page 72: From functional to Reactive - patterns in domain modeling

Monad Transformers

• collapses the stack and gives us a single monad to deal with

• order of stacking is important though

Tuesday, 6 October 15

Page 73: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type Valid[A] = EitherT[Future, NonEmptyList[String], A]

type AccountOp[A] = Kleisli[Valid, AccountRepository, A]

def open(

no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType

): AccountOp[Account]

//..}

Tuesday, 6 October 15

Page 74: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type Valid[A] = EitherT[Future, NonEmptyList[String], A]

type AccountOp[A] = Kleisli[Valid, AccountRepository, A]

def open(

no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType

): AccountOp[Account]

//..}

Tuesday, 6 October 15

Page 75: From functional to Reactive - patterns in domain modeling

Tuesday, 6 October 15

Page 76: From functional to Reactive - patterns in domain modeling

trait AccountService[Account, Amount, Balance] {

type Valid[A] = EitherT[Future, NonEmptyList[String], A]

type AccountOp[A] = Kleisli[Valid, AccountRepository, A]

def open(

no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType

): AccountOp[Account]

//..}

Reactive ..

Algebraically

Tuesday, 6 October 15

Page 77: From functional to Reactive - patterns in domain modeling

class AccountServiceInterpreter extends AccountService[Account, Amount, Balance] {

def open(no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType) =

kleisli[Valid, AccountRepository, Account] { (repo: AccountRepository) =>

EitherT { Future { repo.query(no) match { //.. } } } } //..}

Tuesday, 6 October 15

Page 78: From functional to Reactive - patterns in domain modeling

class AccountServiceInterpreter extends AccountService[Account, Amount, Balance] {

def open(no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date], accountType: AccountType) =

kleisli[Valid, AccountRepository, Account] { (repo: AccountRepository) =>

EitherT { Future { repo.query(no) match { //.. } } } } //..}

normal logic

Tuesday, 6 October 15

Page 79: From functional to Reactive - patterns in domain modeling

We introduced a whole new effect of asynchrony to implement reactive traits in our domain model API algebra & implementation just by composing with another type without any change in the core domain logic. This is the essence of typed functional programming. We have types that model effects functionally and we can just stack them up in the proper order that we need.

Tuesday, 6 October 15

Page 80: From functional to Reactive - patterns in domain modeling

Advantages

• We are still in the statically typed land even with asynchronous behaviors baked into our APIs

• We can reason about our program statically

• We can compose asynchronous components to form larger abstractions

Tuesday, 6 October 15

Page 81: From functional to Reactive - patterns in domain modeling

for { _ <- open(..) _ <- credit(..) d <- debit(..)

} yield d

Reactive & algebraic patterns in domain modeling

Tuesday, 6 October 15

Page 82: From functional to Reactive - patterns in domain modeling

for { _ <- open(..) _ <- credit(..) d <- debit(..)

} yield d

Reactive & algebraic patterns in domain modeling

• Compositional by types

Tuesday, 6 October 15

Page 83: From functional to Reactive - patterns in domain modeling

for { _ <- open(..) _ <- credit(..) d <- debit(..)

} yield d

Reactive & algebraic patterns in domain modeling

• Compositional by types

• Individual operations sequential as they thread through the comprehension

Tuesday, 6 October 15

Page 84: From functional to Reactive - patterns in domain modeling

for { _ <- open(..) _ <- credit(..) d <- debit(..)

} yield d

Reactive & algebraic patterns in domain modeling

• Compositional by types

• Individual operations sequential as they thread through the comprehension

• Composed operation doesn’t block the main thread of execution

Tuesday, 6 October 15

Page 85: From functional to Reactive - patterns in domain modeling

Reactive & algebraic patterns in domain modeling

Tuesday, 6 October 15

Page 86: From functional to Reactive - patterns in domain modeling

trait PortfolioService { type PFOperation[A] = Kleisli[Future, AccountRepository, Seq[A]]

def getCurrencyPortfolio(no: String, asOf: Date) : PFOperation[Balance]

def getEquityPortfolio(no: String, asOf: Date) : PFOperation[Balance]

def getFixedIncomePortfolio(no: String, asOf: Date) : PFOperation[Balance]}

Reactive & algebraic patterns in domain modeling

Tuesday, 6 October 15

Page 87: From functional to Reactive - patterns in domain modeling

val ccyPF: Future[Seq[Balance]] = getCurrencyPortfolio(accountNo, asOf)(AccountRepository)

val eqtPF: Future[Seq[Balance]] = getEquityPortfolio(accountNo, asOf)(AccountRepository)

val fixPF: Future[Seq[Balance]] = getFixedIncomePortfolio(accountNo, asOf)(AccountRepository)

val portfolio: Future[Portfolio] = for { c <- ccyPF e <- eqtPF f <- fixPF} yield CustomerPortfolio(accountNo, asOf, c ++ e ++ f)

Reactive & algebraic patterns in domain modeling

Tuesday, 6 October 15

Page 88: From functional to Reactive - patterns in domain modeling

Be Algebraic, as long as you can ..

Tuesday, 6 October 15

Page 89: From functional to Reactive - patterns in domain modeling

Beyond Algebra - Reactive Protocols

Tuesday, 6 October 15

Page 90: From functional to Reactive - patterns in domain modeling

Conference Reservations

ProgramManagement

Badge Printing

Conference ReservationsConference Reservations

Domain Algebra A

Domain Algebra B

Domain Algebra C

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

ProtocolsReacti

ve

Tuesday, 6 October 15

Page 91: From functional to Reactive - patterns in domain modeling

Conference Reservations

ProgramManagement

Badge Printing

Conference Conference

Domain Algebra A

Domain Algebra B

Domain Algebra C

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

• Ubiquitous language• Entities• Value Objects• Functions on objects• Domain Rules• Schema• Operations

ProtocolsReacti

veElasticity(responsive under

varying load)

Resilience(responsive in the face of failures)

Message-driven(loose coupling, isolation thru async message

passing)

Responsive (through bounded

latency)

Tuesday, 6 October 15

Page 92: From functional to Reactive - patterns in domain modeling

Asynchronous Messaging

Tuesday, 6 October 15

Page 93: From functional to Reactive - patterns in domain modeling

Asynchronous Messaging

Tuesday, 6 October 15

Page 94: From functional to Reactive - patterns in domain modeling

Asynchronous Messaging

Tuesday, 6 October 15

Page 95: From functional to Reactive - patterns in domain modeling

Asynchronous Messaging

Tuesday, 6 October 15

Page 96: From functional to Reactive - patterns in domain modeling

Actors and Domain Models

Tuesday, 6 October 15

Page 97: From functional to Reactive - patterns in domain modeling

Actors and Domain Models

Powerful

Tuesday, 6 October 15

Page 98: From functional to Reactive - patterns in domain modeling

Actors and Domain Models

Powerful

Un-algebraically Powerful

Tuesday, 6 October 15

Page 99: From functional to Reactive - patterns in domain modeling

Actors and Domain Models

Powerful

Un-algebraically Powerful

Gain power at one semantic level but lose the power of reasoning

Tuesday, 6 October 15

Page 100: From functional to Reactive - patterns in domain modeling

Using actors indiscriminately throughout your domain model makes algebraic reasoning hard

Tuesday, 6 October 15

Page 101: From functional to Reactive - patterns in domain modeling

fork: A => Future[A]

map: (A => B) => (Future[A] => Future[B])

join: Future[Future[A]] => Future[A]

Tuesday, 6 October 15

Page 102: From functional to Reactive - patterns in domain modeling

receive: Any => Unit

Tuesday, 6 October 15

Page 103: From functional to Reactive - patterns in domain modeling

Use the least powerful abstraction that does the job

Tuesday, 6 October 15

Page 104: From functional to Reactive - patterns in domain modeling

For domain model resilience, choose futures over actors when you can ..

Tuesday, 6 October 15

Page 105: From functional to Reactive - patterns in domain modeling

• As an implementation artifact to protect shared mutable state

• Centralized failure management

Actors and Domain Models

Tuesday, 6 October 15

Page 106: From functional to Reactive - patterns in domain modeling

import scala.collection.mutable.{ Map => MMap }

class Summarizer extends Actor with ActorSubscriber with Logging {

private val balance = MMap.empty[String, Balance]

def receive = { case OnNext(data: Transaction) => updateBalance(data)

case LogSummaryBalance => logger.info("Balance: " + balance) }

def updateBalance(data: Transaction) = balance.get(data.accountNo).fold { balance += .. } { b => balance += .. }}

shared mutable state here

updated

Tuesday, 6 October 15

Page 107: From functional to Reactive - patterns in domain modeling

Centralized Failure Management

• Supervisor hierarchies that manages failures

• Kill, restart, suspend / resume

• No more messy failure handling code scattered throughout

• Requires careful upfront design though

Tuesday, 6 October 15

Page 108: From functional to Reactive - patterns in domain modeling

Being Reactive

Elasticity(responsive under

varying load)

Resilience(responsive in the face of failures)

Message-driven(loose coupling, isolation thru async message

passing)

Responsive (through bounded

latency)

Tuesday, 6 October 15

Page 109: From functional to Reactive - patterns in domain modeling

Modeling Domain Workflows

Actor

Actor Actor

Actor Actor

Actormessage

message

message

message

message

message

message

Tuesday, 6 October 15

Page 110: From functional to Reactive - patterns in domain modeling

Modeling Domain Workflows

Actor

Actor Actor

Actor Actor

Actormessage

message

message

message

message

message

message

low level

low levelTuesday, 6 October 15

Page 111: From functional to Reactive - patterns in domain modeling

Modeling Domain Workflows

Actor

Actor Actor

Actor Actor

Actormessage

message

message

message

message

message

message

low level

untyped

low levelTuesday, 6 October 15

Page 112: From functional to Reactive - patterns in domain modeling

Modeling Domain Workflows

Actor

Actor Actor

Actor Actor

Actormessage

message

message

message

message

message

message

low level

untyped

non-compositional

low levelTuesday, 6 October 15

Page 113: From functional to Reactive - patterns in domain modeling

Modeling Domain Workflows

Actor

Actor Actor

Actor Actor

Actormessage

message

message

message

message

message

message

low level

untyped

non-compositional

low level

un-algebraic

Tuesday, 6 October 15

Page 114: From functional to Reactive - patterns in domain modeling

Modeling Domain Workflows

Actor

Actor Actor

Actor Actor

Actormessage

message

message

message

message

message

message

low level

untyped

non-compositional

low level

un-algebraic

higher

Tuesday, 6 October 15

Page 115: From functional to Reactive - patterns in domain modeling

Modeling Domain Workflows

Actor

Actor Actor

Actor Actor

Actormessage

message

message

message

message

message

message

low level

untyped

non-compositional

low level

un-algebraic

higher

dsl

Tuesday, 6 October 15

Page 116: From functional to Reactive - patterns in domain modeling

Modeling Domain Workflows

Actor

Actor Actor

Actor Actor

Actormessage

message

message

message

message

message

message

low level

untyped

non-compositional

low level

un-algebraic

higher

dsl

flow as first class abstraction

Tuesday, 6 October 15

Page 117: From functional to Reactive - patterns in domain modeling

Modeling Domain Workflows

Actor

Actor Actor

Actor Actor

Actormessage

message

message

message

message

message

message

low level

untyped

non-compositional

low level

un-algebraic

higher

dsl

flow as first class abstraction

separate definition from execution

Tuesday, 6 October 15

Page 118: From functional to Reactive - patterns in domain modeling

Modeling Domain Workflows

Actor

Actor Actor

Actor Actor

Actormessage

message

message

message

message

message

message

low level

untyped

non-compositional

low level

un-algebraic

higher

dsl

flow as first class abstraction

separate definition from execution

Reactive Streams

Tuesday, 6 October 15

Page 119: From functional to Reactive - patterns in domain modeling

Akka Streams

Source Pipeline starts here. Source[+Out, +Mat] takes data from input & has a single output

Sink Pipeline ends here. Sink[+In, +Mat] has a single input to be written into

FlowBasic transformation abstraction. Flow[-In, +Out, +Mat] has 1 input & 1 output. Mat is the actor

materializer

Runnable Graph

The entire topology ready to run

Tuesday, 6 October 15

Page 120: From functional to Reactive - patterns in domain modeling

Business Use Case - The Domain Model

Tuesday, 6 October 15

Page 121: From functional to Reactive - patterns in domain modeling

Implementation topology with Akka Streams

Tuesday, 6 October 15

Page 122: From functional to Reactive - patterns in domain modeling

val graph = FlowGraph.closed(netTxnSink) { implicit b => ns => import FlowGraph.Implicits._

val accountBroadcast = b.add(Broadcast[Account](2)) val txnBroadcast = b.add(Broadcast[Transaction](2)) val merge = b.add(Merge[Transaction](2))

val accounts = Flow[String].map(queryAccount(_, AccountRepository))

val bankingTxns = Flow[Account].mapConcat(getBankingTransactions) val settlementTxns = Flow[Account].mapConcat(getSettlementTransactions)

val validation = Flow[Transaction].map(validate)

accountNos ~> accounts ~> accountBroadcast ~> bankingTxns ~> merge ~> validation ~> txnBroadcast ~> ns accountBroadcast ~> settlementTxns ~> merge txnBroadcast ~> audit}

Tuesday, 6 October 15

Page 123: From functional to Reactive - patterns in domain modeling

graph.run()

Tuesday, 6 October 15

Page 125: From functional to Reactive - patterns in domain modeling

Thank You!

Tuesday, 6 October 15

Page 126: From functional to Reactive - patterns in domain modeling

Tuesday, 6 October 15