SlideShare a Scribd company logo
From Functional to
Reactive
patterns in domain modeling
Debasish Ghosh
@debasishg
Tuesday, 6 October 15
Tuesday, 6 October 15
Domain Modeling
Tuesday, 6 October 15
Domain Modeling(Functional)
Tuesday, 6 October 15
Domain Modeling
(Responsive)
(Functional)
Tuesday, 6 October 15
Domain Modeling
(Responsive)
(Functional)
(Elastic)
Tuesday, 6 October 15
Domain Modeling
(Responsive)
(Functional)
(Elastic) (Resilient)
Tuesday, 6 October 15
Domain Modeling
(Responsive)
(Functional)
(Elastic) (Resilient)
(Reactive)
Tuesday, 6 October 15
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
The Functional Lens ..
“domain API evolution through algebraic
composition”
Tuesday, 6 October 15
The Functional Lens ..
“domain API evolution through algebraic
composition”
(Reactive)
Tuesday, 6 October 15
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
Tuesday, 6 October 15
Tuesday, 6 October 15
Your domain model is a
function
Tuesday, 6 October 15
Your domain model is a
function
Tuesday, 6 October 15
Your domain model is a
collection of functions
Tuesday, 6 October 15
Your domain model is a
collection of functions
some simpler models are ..
Tuesday, 6 October 15
https://msdn.microsoft.com/en-us/library/jj591560.aspx
Tuesday, 6 October 15
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
Domain Model = ∪(i) Bounded Context(i)
Tuesday, 6 October 15
Domain Model = ∪(i) Bounded Context(i)
Bounded Context = { f(x) | p(x) ∈ Domain Rules }
Tuesday, 6 October 15
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
• Functions / Morphisms
• Types / Sets
• Composition
• Rules / Laws
Tuesday, 6 October 15
• Functions / Morphisms
• Types / Sets
• Composition
• Rules / Laws
algebra
Tuesday, 6 October 15
Domain Model Algebra
Tuesday, 6 October 15
Domain Model Algebra
(algebra of types, functions & laws)
Tuesday, 6 October 15
Domain Model Algebra
(algebra of types, functions & laws)
explicit
• types
• type constraints
• expression in terms of other generic algebra
Tuesday, 6 October 15
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
close
debit
open
...
Domain
Behaviors
Tuesday, 6 October 15
Amount
Account
Balance
Customer
...
...
...
close
debit
open
...
Domain
Behaviors
Domain Types
Tuesday, 6 October 15
Amount
Account
Balance
Customer
...
...
...
close
debit
open
...
market
regulations
tax laws
brokerage
commission
rates
...
Domain
Behaviors
Domain TypesDomain Rules
Tuesday, 6 October 15
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
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
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
• Ubiquitous language
• Entities
•Value Objects
• Functions on objects
• Domain Rules
• Schema
• Operations
Algebra is the binding
contract
Bounded Context
Tuesday, 6 October 15
• Ubiquitous language
• Entities
•Value Objects
• Functions on objects
• Domain Rules
• Schema
• Operations
Algebra is the binding
contract
Bounded Context
Reactive
Tuesday, 6 October 15
Conference
Reservations
Program
Management
Badge Printing
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
• Algebras don’t unify across bounded
contexts
• Decoupled in space and time
• Separate vocabulary
• Types break down
Tuesday, 6 October 15
Conference
Reservations
Program
Management
Badge Printing
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
Conference
Reservations
Program
Management
Badge Printing
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
Reactive
Tuesday, 6 October 15
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
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
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
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
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
Operation return type - either
a successfully constructed type
or a list of errors
Tuesday, 6 October 15
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
Operation return type - either
a successfully constructed type
or a list of errors
Operations - domain behaviors
Tuesday, 6 October 15
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
Operation return type - either
a successfully constructed type
or a list of errors
Operations - domain behaviors explicit & verifiable algebra
Tuesday, 6 October 15
• Parametric - parameterized on types
• Statically Typed
• Modular and hence unit testable
• Composable
Tuesday, 6 October 15
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
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
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
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
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
• Design should not have any contention or
central bottlenecks that tend to hamper
the progress of the system
Being Reactive
Tuesday, 6 October 15
• 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
Blocking Kills
Tuesday, 6 October 15
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
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
• Without foregoing the benefits of algebraic
reasoning with types
Being Reactive
Tuesday, 6 October 15
Enter Futures ..
Tuesday, 6 October 15
Enter Futures ..
• A future is the essence of asynchronous non
blocking computation
Tuesday, 6 October 15
Enter Futures ..
• A future is the essence of asynchronous non
blocking computation
• Futures compose
Tuesday, 6 October 15
Enter Futures ..
• A future is the essence of asynchronous non
blocking computation
• Futures compose
• Futures have an algebra
Tuesday, 6 October 15
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
• 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
Stacking of Effects
Tuesday, 6 October 15
Stacking of Effects
Tuesday, 6 October 15
type Response[A] = String / Option[A]
val count: Response[Int] = some(10).right
for {
maybeCount <- count
} yield {
for {
c <- maybeCount
// use c
} yield c
}
Monad Transformers
Tuesday, 6 October 15
type Response[A] = String / Option[A]
val count: Response[Int] = some(10).right
for {
maybeCount <- count
} yield {
for {
c <- maybeCount
// use c
} yield c
}
type Error[A] = String / A
type 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
type Response[A] = String / Option[A]
val count: Response[Int] = some(10).right
for {
maybeCount <- count
} yield {
for {
c <- maybeCount
// use c
} yield c
}
type Error[A] = String / A
type 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
Monad Transformers
• collapses the stack and gives us a single
monad to deal with
• order of stacking is important though
Tuesday, 6 October 15
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
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
Tuesday, 6 October 15
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
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
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
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
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
for {
_ <- open(..)
_ <- credit(..)
d <- debit(..)
} yield d
Reactive & algebraic patterns in
domain modeling
Tuesday, 6 October 15
for {
_ <- open(..)
_ <- credit(..)
d <- debit(..)
} yield d
Reactive & algebraic patterns in
domain modeling
• Compositional by types
Tuesday, 6 October 15
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
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
Reactive & algebraic patterns in
domain modeling
Tuesday, 6 October 15
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
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
Be Algebraic, as long as
you can ..
Tuesday, 6 October 15
Beyond Algebra -
Reactive Protocols
Tuesday, 6 October 15
Conference
Reservations
Program
Management
Badge Printing
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
Reactive
Tuesday, 6 October 15
Conference
Reservations
Program
Management
Badge Printing
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
ReactiveElasticity
(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
Asynchronous Messaging
Tuesday, 6 October 15
Asynchronous Messaging
Tuesday, 6 October 15
Asynchronous Messaging
Tuesday, 6 October 15
Asynchronous Messaging
Tuesday, 6 October 15
Actors and Domain
Models
Tuesday, 6 October 15
Actors and Domain
Models
Powerful
Tuesday, 6 October 15
Actors and Domain
Models
Powerful
Un-algebraically Powerful
Tuesday, 6 October 15
Actors and Domain
Models
Powerful
Un-algebraically Powerful
Gain power at one semantic level but
lose the power of reasoning
Tuesday, 6 October 15
Using actors indiscriminately
throughout your domain model
makes algebraic reasoning hard
Tuesday, 6 October 15
fork:
A => Future[A]
map:
(A => B) => (Future[A] => Future[B])
join:
Future[Future[A]] => Future[A]
Tuesday, 6 October 15
receive: Any => Unit
Tuesday, 6 October 15
Use the least powerful abstraction
that does the job
Tuesday, 6 October 15
For domain model resilience,
choose futures over actors when you
can ..
Tuesday, 6 October 15
• As an implementation artifact to protect
shared mutable state
• Centralized failure management
Actors and Domain
Models
Tuesday, 6 October 15
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
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
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
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
Tuesday, 6 October 15
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low level
Tuesday, 6 October 15
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low level
untyped
Tuesday, 6 October 15
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low level
untyped
non-compositional
Tuesday, 6 October 15
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low level
untyped
non-compositional
un-algebraic
Tuesday, 6 October 15
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low level
untyped
non-compositional
un-algebraic
higher
Tuesday, 6 October 15
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low level
untyped
non-compositional
un-algebraic
higher
dsl
Tuesday, 6 October 15
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low level
untyped
non-compositional
un-algebraic
higher
dsl
flow as first class
abstraction
Tuesday, 6 October 15
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low level
untyped
non-compositional
un-algebraic
higher
dsl
flow as first class
abstraction
separate definition from execution
Tuesday, 6 October 15
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low level
untyped
non-compositional
un-algebraic
higher
dsl
flow as first class
abstraction
separate definition from execution
Reactive Streams
Tuesday, 6 October 15
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
Flow
Basic 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
Business Use Case - The Domain Model
Tuesday, 6 October 15
Implementation topology with Akka
Streams
Tuesday, 6 October 15
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
graph.run()
Tuesday, 6 October 15
https://www.manning.com/books/functional-and-reactive-
domain-modeling
Tuesday, 6 October 15
ThankYou!
Tuesday, 6 October 15
Tuesday, 6 October 15

More Related Content

PDF
An Algebraic Approach to Functional Domain Modeling
PDF
Functional and Algebraic Domain Modeling
PDF
Domain Modeling with Functions - an algebraic approach
PDF
Functional Patterns in Domain Modeling
PDF
Functional and Event Driven - another approach to domain modeling
PDF
Architectural Patterns in Building Modular Domain Models
PDF
Algebraic Thinking for Evolution of Pure Functional Domain Models
PPT
DSL - expressive syntax on top of a clean semantic model
An Algebraic Approach to Functional Domain Modeling
Functional and Algebraic Domain Modeling
Domain Modeling with Functions - an algebraic approach
Functional Patterns in Domain Modeling
Functional and Event Driven - another approach to domain modeling
Architectural Patterns in Building Modular Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain Models
DSL - expressive syntax on top of a clean semantic model

What's hot (20)

PDF
Power of functions in a typed world
PDF
Domain Modeling in a Functional World
PDF
Functional and Algebraic Domain Modeling
PDF
Mining Functional Patterns
PPT
Dependency Injection in Scala - Beyond the Cake Pattern
PDF
Approximation Data Structures for Streaming Applications
PPT
JavaScript Data Types
PDF
Value objects in JS - an ES7 work in progress
PDF
Session 2 - Objective-C basics
PDF
Session 3 - Object oriented programming with Objective-C (part 1)
PDF
JavaScript objects and functions
PDF
Reflection in Go
ODP
Datatype in JavaScript
PPTX
PDF
PDF
JS Fest 2019. Mauricio Palma. You can’t read this sentence - A11y automation
PDF
Software Developer Training
PPTX
Overview of c (2)
PDF
DIDUCE: ICSE-2002 presentation
PDF
Programming for Problem Solving Unit 1
Power of functions in a typed world
Domain Modeling in a Functional World
Functional and Algebraic Domain Modeling
Mining Functional Patterns
Dependency Injection in Scala - Beyond the Cake Pattern
Approximation Data Structures for Streaming Applications
JavaScript Data Types
Value objects in JS - an ES7 work in progress
Session 2 - Objective-C basics
Session 3 - Object oriented programming with Objective-C (part 1)
JavaScript objects and functions
Reflection in Go
Datatype in JavaScript
JS Fest 2019. Mauricio Palma. You can’t read this sentence - A11y automation
Software Developer Training
Overview of c (2)
DIDUCE: ICSE-2002 presentation
Programming for Problem Solving Unit 1
Ad

Viewers also liked (12)

PPTX
Actor Model & Reactive Manifesto
PDF
Beyond Scala Lens
PDF
API Centric Patterns
PDF
Domain-driven design
PPTX
Purely Functional Data Structures in Scala
PDF
Microservices: Architecture for the Real-time Organization
PDF
Fifty Shades of the Common Core for ELA: Revised
PDF
From object oriented to functional domain modeling
PDF
Concurrent Mark-Sweep Garbage Collection #jjug_ccc
PDF
Reactive Streams 1.0.0 and Why You Should Care (webinar)
PDF
Using the Actor Model with Domain-Driven Design (DDD) in Reactive Systems - w...
PDF
Embulk 20150411
Actor Model & Reactive Manifesto
Beyond Scala Lens
API Centric Patterns
Domain-driven design
Purely Functional Data Structures in Scala
Microservices: Architecture for the Real-time Organization
Fifty Shades of the Common Core for ELA: Revised
From object oriented to functional domain modeling
Concurrent Mark-Sweep Garbage Collection #jjug_ccc
Reactive Streams 1.0.0 and Why You Should Care (webinar)
Using the Actor Model with Domain-Driven Design (DDD) in Reactive Systems - w...
Embulk 20150411
Ad

Similar to From functional to Reactive - patterns in domain modeling (20)

PPTX
lecture_for programming and computing basics
PDF
NoSQL Now 2013 Presentation
PPTX
PDF
Functional Domain Modeling - The ZIO 2 Way
PDF
Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications"
PPTX
Implementing a JavaScript Engine
PDF
An R primer for SQL folks
PDF
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
PDF
JavaScript Interview Questions Part - 1.pdf
PPTX
Review of object orientation
PDF
How Graph Databases efficiently store, manage and query connected data at s...
PDF
Lecture 1 (bce-7)
PDF
A Deep Dive into Javascript
PPTX
Big data analytics with R tool.pptx
PDF
PPTX
COMP111-Week-1_138439.pptx
PDF
Software Architecture: Principles, Patterns and Practices
PDF
Everything you ever wanted to know about lotus script
PDF
Angular
PPTX
The openCypher Project - An Open Graph Query Language
lecture_for programming and computing basics
NoSQL Now 2013 Presentation
Functional Domain Modeling - The ZIO 2 Way
Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications"
Implementing a JavaScript Engine
An R primer for SQL folks
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
JavaScript Interview Questions Part - 1.pdf
Review of object orientation
How Graph Databases efficiently store, manage and query connected data at s...
Lecture 1 (bce-7)
A Deep Dive into Javascript
Big data analytics with R tool.pptx
COMP111-Week-1_138439.pptx
Software Architecture: Principles, Patterns and Practices
Everything you ever wanted to know about lotus script
Angular
The openCypher Project - An Open Graph Query Language

Recently uploaded (20)

PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
ManageIQ - Sprint 268 Review - Slide Deck
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
Transform Your Business with a Software ERP System
PPTX
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
PPTX
Operating system designcfffgfgggggggvggggggggg
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PPT
Introduction Database Management System for Course Database
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
ISO 45001 Occupational Health and Safety Management System
PPTX
Introduction to Artificial Intelligence
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
System and Network Administration Chapter 2
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
AI in Product Development-omnex systems
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
medical staffing services at VALiNTRY
Internet Downloader Manager (IDM) Crack 6.42 Build 41
ManageIQ - Sprint 268 Review - Slide Deck
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Transform Your Business with a Software ERP System
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
Operating system designcfffgfgggggggvggggggggg
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Introduction Database Management System for Course Database
Softaken Excel to vCard Converter Software.pdf
ISO 45001 Occupational Health and Safety Management System
Introduction to Artificial Intelligence
Which alternative to Crystal Reports is best for small or large businesses.pdf
System and Network Administration Chapter 2
How to Choose the Right IT Partner for Your Business in Malaysia
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
AI in Product Development-omnex systems
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Upgrade and Innovation Strategies for SAP ERP Customers
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
medical staffing services at VALiNTRY

From functional to Reactive - patterns in domain modeling

  • 1. From Functional to Reactive patterns in domain modeling Debasish Ghosh @debasishg Tuesday, 6 October 15
  • 9. 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
  • 10. The Functional Lens .. “domain API evolution through algebraic composition” Tuesday, 6 October 15
  • 11. The Functional Lens .. “domain API evolution through algebraic composition” (Reactive) Tuesday, 6 October 15
  • 12. 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
  • 15. Your domain model is a function Tuesday, 6 October 15
  • 16. Your domain model is a function Tuesday, 6 October 15
  • 17. Your domain model is a collection of functions Tuesday, 6 October 15
  • 18. Your domain model is a collection of functions some simpler models are .. Tuesday, 6 October 15
  • 20. 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
  • 21. Domain Model = ∪(i) Bounded Context(i) Tuesday, 6 October 15
  • 22. Domain Model = ∪(i) Bounded Context(i) Bounded Context = { f(x) | p(x) ∈ Domain Rules } Tuesday, 6 October 15
  • 23. 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
  • 24. • Functions / Morphisms • Types / Sets • Composition • Rules / Laws Tuesday, 6 October 15
  • 25. • Functions / Morphisms • Types / Sets • Composition • Rules / Laws algebra Tuesday, 6 October 15
  • 27. Domain Model Algebra (algebra of types, functions & laws) Tuesday, 6 October 15
  • 28. Domain Model Algebra (algebra of types, functions & laws) explicit • types • type constraints • expression in terms of other generic algebra Tuesday, 6 October 15
  • 29. 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
  • 35. 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
  • 36. • Ubiquitous language • Entities •Value Objects • Functions on objects • Domain Rules • Schema • Operations Algebra is the binding contract Bounded Context Tuesday, 6 October 15
  • 37. • Ubiquitous language • Entities •Value Objects • Functions on objects • Domain Rules • Schema • Operations Algebra is the binding contract Bounded Context Reactive Tuesday, 6 October 15
  • 38. Conference Reservations Program Management Badge Printing 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
  • 39. • Algebras don’t unify across bounded contexts • Decoupled in space and time • Separate vocabulary • Types break down Tuesday, 6 October 15
  • 40. Conference Reservations Program Management Badge Printing 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
  • 41. Conference Reservations Program Management Badge Printing 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 Reactive Tuesday, 6 October 15
  • 42. 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
  • 43. 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
  • 44. 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
  • 45. 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
  • 46. 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 Operation return type - either a successfully constructed type or a list of errors Tuesday, 6 October 15
  • 47. 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 Operation return type - either a successfully constructed type or a list of errors Operations - domain behaviors Tuesday, 6 October 15
  • 48. 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 Operation return type - either a successfully constructed type or a list of errors Operations - domain behaviors explicit & verifiable algebra Tuesday, 6 October 15
  • 49. • Parametric - parameterized on types • Statically Typed • Modular and hence unit testable • Composable Tuesday, 6 October 15
  • 50. 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
  • 51. 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
  • 52. 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
  • 53. 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
  • 54. 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
  • 55. • Design should not have any contention or central bottlenecks that tend to hamper the progress of the system Being Reactive Tuesday, 6 October 15
  • 56. • 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
  • 58. 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
  • 59. 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
  • 60. • Without foregoing the benefits of algebraic reasoning with types Being Reactive Tuesday, 6 October 15
  • 62. Enter Futures .. • A future is the essence of asynchronous non blocking computation Tuesday, 6 October 15
  • 63. Enter Futures .. • A future is the essence of asynchronous non blocking computation • Futures compose Tuesday, 6 October 15
  • 64. Enter Futures .. • A future is the essence of asynchronous non blocking computation • Futures compose • Futures have an algebra Tuesday, 6 October 15
  • 65. 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
  • 66. • 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
  • 69. type Response[A] = String / Option[A] val count: Response[Int] = some(10).right for { maybeCount <- count } yield { for { c <- maybeCount // use c } yield c } Monad Transformers Tuesday, 6 October 15
  • 70. type Response[A] = String / Option[A] val count: Response[Int] = some(10).right for { maybeCount <- count } yield { for { c <- maybeCount // use c } yield c } type Error[A] = String / A type 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
  • 71. type Response[A] = String / Option[A] val count: Response[Int] = some(10).right for { maybeCount <- count } yield { for { c <- maybeCount // use c } yield c } type Error[A] = String / A type 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
  • 72. Monad Transformers • collapses the stack and gives us a single monad to deal with • order of stacking is important though Tuesday, 6 October 15
  • 73. 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
  • 74. 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
  • 76. 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
  • 77. 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
  • 78. 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
  • 79. 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
  • 80. 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
  • 81. for { _ <- open(..) _ <- credit(..) d <- debit(..) } yield d Reactive & algebraic patterns in domain modeling Tuesday, 6 October 15
  • 82. for { _ <- open(..) _ <- credit(..) d <- debit(..) } yield d Reactive & algebraic patterns in domain modeling • Compositional by types Tuesday, 6 October 15
  • 83. 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
  • 84. 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
  • 85. Reactive & algebraic patterns in domain modeling Tuesday, 6 October 15
  • 86. 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
  • 87. 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
  • 88. Be Algebraic, as long as you can .. Tuesday, 6 October 15
  • 89. Beyond Algebra - Reactive Protocols Tuesday, 6 October 15
  • 90. Conference Reservations Program Management Badge Printing 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 Reactive Tuesday, 6 October 15
  • 91. Conference Reservations Program Management Badge Printing 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 ReactiveElasticity (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
  • 98. Actors and Domain Models Powerful Un-algebraically Powerful Tuesday, 6 October 15
  • 99. Actors and Domain Models Powerful Un-algebraically Powerful Gain power at one semantic level but lose the power of reasoning Tuesday, 6 October 15
  • 100. Using actors indiscriminately throughout your domain model makes algebraic reasoning hard Tuesday, 6 October 15
  • 101. fork: A => Future[A] map: (A => B) => (Future[A] => Future[B]) join: Future[Future[A]] => Future[A] Tuesday, 6 October 15
  • 102. receive: Any => Unit Tuesday, 6 October 15
  • 103. Use the least powerful abstraction that does the job Tuesday, 6 October 15
  • 104. For domain model resilience, choose futures over actors when you can .. Tuesday, 6 October 15
  • 105. • As an implementation artifact to protect shared mutable state • Centralized failure management Actors and Domain Models Tuesday, 6 October 15
  • 106. 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
  • 107. 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
  • 108. 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
  • 109. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message Tuesday, 6 October 15
  • 110. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level Tuesday, 6 October 15
  • 111. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level untyped Tuesday, 6 October 15
  • 112. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level untyped non-compositional Tuesday, 6 October 15
  • 113. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level untyped non-compositional un-algebraic Tuesday, 6 October 15
  • 114. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level untyped non-compositional un-algebraic higher Tuesday, 6 October 15
  • 115. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level untyped non-compositional un-algebraic higher dsl Tuesday, 6 October 15
  • 116. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level untyped non-compositional un-algebraic higher dsl flow as first class abstraction Tuesday, 6 October 15
  • 117. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level untyped non-compositional un-algebraic higher dsl flow as first class abstraction separate definition from execution Tuesday, 6 October 15
  • 118. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level untyped non-compositional un-algebraic higher dsl flow as first class abstraction separate definition from execution Reactive Streams Tuesday, 6 October 15
  • 119. 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 Flow Basic 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
  • 120. Business Use Case - The Domain Model Tuesday, 6 October 15
  • 121. Implementation topology with Akka Streams Tuesday, 6 October 15
  • 122. 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