SlideShare a Scribd company logo
Functional and Algebraic Domain
Modeling
Debasish Ghosh
@debasishg
é–ąæ•°ćž‹ă€ä»Łæ•°çš„ăȘăƒ‰ăƒĄă‚€ăƒłăƒ»ăƒąăƒ‡ăƒȘングぼæ–čæł•
Saturday, 30 January 16
Domain Modeling
ăƒ‰ăƒĄă‚€ăƒłăƒ»ăƒąăƒ‡ăƒȘング
Saturday, 30 January 16
Domain Modeling(Functional)
é–ąæ•°ćž‹ăȘăƒ‰ăƒĄă‚€ăƒłăƒ»ăƒąăƒ‡ăƒȘング
Saturday, 30 January 16
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 speciïŹc 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)
ç‰čćźšăźć•éĄŒé ˜ćŸŸă«é–ąă™ă‚‹æŠ‚ćż”ăƒąăƒ‡ăƒ«
ă‚šăƒłăƒ†ă‚Łăƒ†ă‚ŁïŒé–ąé€ŁïŒćˆ¶çŽ„ăȘă©ă‚’èš˜èż°
Saturday, 30 January 16
The Functional Lens ..
“domain API evolution through algebraic
composition”
é–ąæ•°ćž‹ăƒŹăƒłă‚ș
ä»Łæ•°çš„ćˆæˆă‚’é€šă˜ăŸăƒ‰ăƒĄă‚€ăƒł API たé€Č挖
Saturday, 30 January 16
ă€Œă‚”ăƒŒăƒă‚’é–ąæ•°ăšă—ăŠè€ƒăˆă‚‹ă€
Saturday, 30 January 16
Twitter ç€Ÿă§ăźă‚”ăƒŒăƒă‚œăƒ•ăƒˆă‚Šă‚§ă‚ąăźæ§‹æˆăŻ fp ăšćŒă˜ç†ćż”
ïŒˆäžć€‰æ€§ă€é–ąæ•°ăźćˆæˆă€ć‰Żäœœç”šăźćˆ†é›ąïŒ‰ă«ćŸșă„ă
Saturday, 30 January 16
Your domain model is a
function
ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ăŻé–ąæ•°ă§ă‚ă‚‹
Saturday, 30 January 16
Your domain model is a
function
ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ăŻé–ąæ•°ïŒˆ...であっどæŹČă—ă„ïŒ‰
Saturday, 30 January 16
Your domain model is a
collection of functions
ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ăŻé–ąæ•°ăźé›†ćˆă§ă‚ă‚‹
Saturday, 30 January 16
Your domain model is a
collection of functions
some simpler models are ..
ć…·äœ“äŸ‹ă§è€ƒăˆă‚‹ăš...
Saturday, 30 January 16
https://msdn.microsoft.com/en-us/library/jj591560.aspx
ă‚«ăƒłăƒ•ă‚ĄăƒŹăƒłă‚č知理シă‚čテム
Saturday, 30 January 16
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
ćąƒç•Œă„ă‘ă‚‰ă‚ŒăŸă‚łăƒłăƒ†ă‚­ă‚čăƒˆăŻă€ç”±äž€ă•ă‚ŒăŸèȘžćœ™ă‚’æŒă€
ăƒ‰ăƒĄă‚€ăƒłăźæŒŻă‚‹èˆžă„ăŻé–ąæ•°ă€ă‚Șăƒ–ă‚žă‚§ă‚ŻăƒˆăŻćž‹ăšă—ăŠćźŸèŁ…ă™ă‚‹Saturday, 30 January 16
Domain Model = âˆȘ(i) Bounded Context(i)
Saturday, 30 January 16
Domain Model = âˆȘ(i) Bounded Context(i)
Bounded Context = { f(x) | p(x) ∈ Domain Rules }
Saturday, 30 January 16
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
f ăŻăƒ‰ăƒĄă‚€ăƒłé–ąæ•°ă§ă€ä»–ăźé–ąæ•°ăšćˆæˆă§ăă‚‹
p はビゾネă‚čăƒ«ăƒŒăƒ«
Saturday, 30 January 16
‱ Functions / Morphisms
‱ Types / Sets
‱ Composition
‱ Rules / Laws
é–ąæ•°ăšć°„ă€ćž‹ăšé›†ćˆă€ćˆæˆă€ăƒ«ăƒŒăƒ«ăšæł•ć‰‡
Saturday, 30 January 16
‱ Functions / Morphisms
‱ Types / Sets
‱ Composition
‱ Rules / Laws
algebra
èŠăŻä»Łæ•°ăšă„ă†ă“ăš
Saturday, 30 January 16
Domain Model Algebra
ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ăźä»Łæ•°
Saturday, 30 January 16
Domain Model Algebra
(algebra of types, functions & laws)
ćž‹ăšé–ąæ•°ăšæł•ć‰‡ăźä»Łæ•°
Saturday, 30 January 16
Domain Model Algebra
(algebra of types, functions & laws)
explicit
‱ types
‱ type constraints
‱ expression in terms of other generic algebra
ă“ă‚Œă‚’æ˜Žç€șçš„ă«ă™ă‚‹ăšă€ćž‹ă€ćž‹ăźćˆ¶çŽ„ă€ä»–ăźä»Łæ•°ă‚’ç”šă„ăŸèĄšçŸ
Saturday, 30 January 16
Domain Model Algebra
(algebra of types, functions & laws)
explicit veriïŹable
‱ types
‱ type constraints
‱ expr in terms of other generic algebra
‱ type constraints
‱ more constraints if you have DT
‱ algebraic property based testing
çąșèȘćŻèƒœăȘăźăŻćž‹ćˆ¶çŽ„ă€ä»Łæ•°çš„ăƒ—ăƒ­ăƒ‘ăƒ†ă‚ŁăƒŒăƒ™ăƒŒă‚čぼテă‚čト
äŸć­˜ćž‹ăŒă‚ă‚Œă°ă‚ˆă‚ŠćŒ·ă„ćˆ¶çŽ„ă‚’æ€œèšŒă§ăă‚‹
Saturday, 30 January 16
Problem Domain
ć•éĄŒăƒ‰ăƒĄă‚€ăƒłăźäŸ‹ăšă—ăŠèšŒćˆžć–ćŒ•ćŁćș§ă‚’è€ƒćŻŸă™ă‚‹
Saturday, 30 January 16
Bank
Account
Trade
Customer
...
...
...
Problem Domain
...
entities
スンティティべăȘるぼは、揣ćș§ă€éĄ§ćźąă€ć–ćŒ•ă€éŠ€èĄŒ
Saturday, 30 January 16
Bank
Account
Trade
Customer
...
...
...
do trade
process
execution
place
order
Problem Domain
...
entities
behaviors
æŒŻă‚‹èˆžă„ăšăȘă‚‹ăźăŻă€æłšæ–‡ă€ć–ćŒ•ă€ćŸ·èĄŒć‡Šç†
Saturday, 30 January 16
Bank
Account
Trade
Customer
...
...
...
do trade
process
execution
place
order
Problem Domain
...
market
regulations
tax laws
brokerage
commission
rates
...
entities
behaviors
laws
æł•ć‰‡ăšăȘるぼはæ ȘćŒćž‚ć ŽèŠć‰‡ă€çšŽæł•ă€æ‰‹æ•°æ–™
Saturday, 30 January 16
do trade
process
execution
place
order
Solution Domain
...
behaviors
Functions
(Type => Type)
ă‚œăƒȘăƒ„ăƒŒă‚·ăƒ§ăƒłăƒ‰ăƒĄă‚€ăƒłă§ăŻă€æŒŻă‚‹èˆžă„ăŻé–ąæ•° (枋 枋)
Saturday, 30 January 16
Bank
Account
Trade
Customer
...
...
...
do trade
process
execution
place
order
Solution Domain
...
entities
behaviors
functions
(Type => Type)
algebraic data type
ă‚šăƒłăƒ†ă‚Łăƒ†ă‚ŁăŻä»Łæ•°çš„ăƒ‡ăƒŒă‚żćž‹
Saturday, 30 January 16
Bank
Account
Trade
Customer
...
...
...
do trade
process
execution
place
order
Solution Domain
...
market
regulations
tax laws
brokerage
commission
rates
...
entities
behaviors
laws
functions
(Type => Type)
algebraic data type business rules / invariants
æł•ć‰‡ăŻăƒ“ă‚žăƒă‚čăƒ»ăƒ«ăƒŒăƒ«ă‚‚ă—ăăŻäžć€‰é–ąäż‚
Saturday, 30 January 16
Bank
Account
Trade
Customer
...
...
...
do trade
process
execution
place
order
Solution Domain
...
market
regulations
tax laws
brokerage
commission
rates
...
entities
behaviors
laws
functions
(Type => Type)
algebraic data type business rules / invariants
Monoid
Monad
...
ăƒąăƒŽă‚€ăƒ‰ă‚„ăƒąăƒŠăƒ‰ăšă„ăŁăŸćž‹ă‚Żăƒ©ă‚č
Saturday, 30 January 16
Bank
Account
Trade
Customer
...
...
...
do trade
process
execution
place
order
Solution Domain
...
market
regulations
tax laws
brokerage
commission
rates
...
entities
behaviors
laws
functions
(Type => Type)
algebraic data type business rules / invariants
Monoid
Monad
...
ă“ă‚Œă‚’ć…šéƒšă‚„ă‚‹ăšăƒ‰ăƒĄă‚€ăƒłä»Łæ•°
Domain Algebra
Saturday, 30 January 16
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
ă€Œćąƒç•Œă„ă‘ă‚‰ă‚ŒăŸă‚łăƒłăƒ†ă‚­ă‚čăƒˆă€ăŻăƒ‰ăƒĄă‚€ăƒłä»Łæ•°ăźă“ăš
Saturday, 30 January 16
Client places order
- ïŹ‚exible format
1
ă‚Żăƒ©ă‚€ă‚ąăƒłăƒˆăŒæłšæ–‡ă‚’ć‡șす
ăƒ•ă‚©ăƒŒăƒžăƒƒăƒˆăŻæ§˜ă€…
Saturday, 30 January 16
Client places order
- ïŹ‚exible format
Transform to internal domain
model entity and place for execution
1 2
ć†…éƒšă§ăźăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ă‚šăƒłăƒ†ă‚Łăƒ†ă‚Łă«ć€‰æ›ă—ăŠă€
ćźŸéš›ă«æłšæ–‡ă‚’ć‡șす
Saturday, 30 January 16
Client places order
- ïŹ‚exible format
Transform to internal domain
model entity and place for execution
Trade & Allocate to
client accounts
1 2
3
ć–ćŒ•ă—ă€ç”æžœă‚’ă‚Żăƒ©ă‚€ă‚ąăƒłăƒˆăźă‚ąă‚«ă‚Šăƒłăƒˆă«çŽă„ă‘ă‚‹
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute: Market => Account => Order => List[Execution]
def allocate: List[Account] => Execution => List[Trade]
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute[Account <: BrokerAccount]: Market => Account
=> Order => List[Execution]
def allocate[Account <: TradingAccount]: List[Account]
=> Execution => List[Trade]
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute: Market => Account => Order => List[Execution]
def allocate: List[Account] => Execution => List[Trade]
Types out of thin air No implementation till now
Type names resonate domain language
どこからずもăȘăé™ăŁăŠăăŸćž‹ă€‚ä»Šăźæ‰€ćźŸèŁ…ăźè©±ăŻă‚Œăƒ­ă€‚
ćž‹ăźćć‰ăŻăƒ‰ăƒĄă‚€ăƒłèš€èȘžă‚’ćæ˜ 
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute: Market => Account => Order => List[Execution]
def allocate: List[Account] => Execution => List[Trade]
‱Types (domain entities)
‱ Functions operating on types (domain behaviors)
‱ Laws (business rules)
枋 (スンティティ)ă€é–ąæ•° (ăƒ‰ăƒĄă‚€ăƒłăźæŒŻă‚‹èˆžă„)、
æł•ć‰‡ (ビゾネă‚čăƒ»ăƒ«ăƒŒăƒ«)
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute: Market => Account => Order => List[Execution]
def allocate: List[Account] => Execution => List[Trade]
‱Types (domain entities)
‱ Functions operating on types (domain behaviors)
‱ Laws (business rules)
Algebra of the API
これが API ăźä»Łæ•°
Saturday, 30 January 16
trait Trading[Account, Trade, ClientOrderSheet, Order,
Execution, Market] {
def clientOrders: ClientOrderSheet => List[Order]
def execute: Market => Account => Order => List[Execution]
def allocate: List[Account] => Execution => List[Trade]
def tradeGeneration(market: Market, broker: Account,
clientAccounts: List[Account]) = ???
}
parameterized on typesmodule
ăƒąă‚žăƒ„ăƒŒăƒ«ă€ćž‹ăƒ‘ăƒ©ăƒĄăƒŒă‚ż
Saturday, 30 January 16
Algebraic Design
‱ The algebra is the binding contract of the
API
‱ Implementation is NOT part of the algebra
‱ An algebra can have multiple interpreters
(aka implementations)
‱ One of the core principles of functional
programming is to decouple the algebra from
the interpreter
ä»Łæ•°çš„èš­èšˆæ‰‹æł•: ä»Łæ•°ăŻ API がæș–æ‹ ă™ă‚‹ćˆ¶çŽ„
ćźŸèŁ…ăŻä»Łæ•°ă«ć«ăŸă‚Œăšă€ćźŸèŁ…ă‹ă‚‰ăŻćˆ†é›ąă•ă‚ŒăŠă„ă‚‹
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute: Market => Account => Order => List[Execution]
def allocate: List[Account] => Execution => List[Trade]
let’s do some algebra ..
ä»Łæ•°ăźç·Žçż’
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute(m: Market, broker: Account): Order => List[Execution]
def allocate(accounts: List[Account]): Execution => List[Trade]
let’s do some algebra ..
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute(m: Market, broker: Account): Order => List[Execution]
def allocate(accounts: List[Account]): Execution => List[Trade]
let’s do some algebra ..
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute(m: Market, broker: Account): Order => List[Execution]
def allocate(accounts: List[Account]): Execution => List[Trade]
let’s do some algebra ..
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute(m: Market, broker: Account): Order => List[Execution]
def allocate(accounts: List[Account]): Execution => List[Trade]
let’s do some algebra ..
Saturday, 30 January 16
def clientOrders: ClientOrderSheet => List[Order]
def execute(m: Market, broker: Account): Order => List[Execution]
def allocate(accounts: List[Account]): Execution => List[Trade]
let’s do some algebra ..
Saturday, 30 January 16
def f: A => List[B]
def g: B => List[C]
def h: C => List[D]
.. a problem of composition ..
これは ... ćˆæˆăźć•éĄŒă 
Saturday, 30 January 16
.. a problem of
composition with effects ..
def f: A => List[B]
def g: B => List[C]
def h: C => List[D]
これは ... äœœç”šä»˜ăăźćˆæˆăźć•éĄŒă 
Saturday, 30 January 16
def f[M: Monad]: A => M[B]
def g[M: Monad]: B => M[C]
def h[M: Monad]: C => M[D]
.. a problem of composition with
effects that can be generalized ..
ă“ă‚ŒăŻăƒąăƒŠăƒ‰ăšă—ăŠæŠœè±ĄćŒ–ă§ăă‚‹äœœç”šä»˜ăăźćˆæˆăźć•éĄŒă 
Saturday, 30 January 16
case class Kleisli[M[_], A, B](run: A => M[B]) {
def andThen[C](f: B => M[C])
(implicit M: Monad[M]): Kleisli[M, A, C] =
Kleisli((a: A) => M.flatMap(run(a))(f))
}
.. function composition with
Effects ..
It’s a Kleisli !
äœœç”šä»˜ăăźé–ąæ•°ăźćˆæˆăšèš€ăˆă°ă€Kleisli
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
def execute(m: Market, b: Account): Kleisli[List, Order, Execution]
def allocate(acts: List[Account]): Kleisli[List, Execution, Trade]
Follow the types
.. function composition with
Effects ..
def clientOrders: ClientOrderSheet => List[Order]
def execute(m: Market, broker: Account): Order => List[Execution]
def allocate(accounts: List[Account]): Execution => List[Trade]
ćž‹ă«ä»»ă›ăŠè€ƒăˆă‚‹
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
def execute(m: Market, b: Account): Kleisli[List, Order, Execution]
def allocate(acts: List[Account]): Kleisli[List, Execution, Trade]
Domain algebra composed with the
categorical algebra of a Kleisli Arrow
.. function composition with
Effects ..
Klieisli ć°„ă«ă‚ˆăŁăŠćˆæˆă•ă‚ŒăŸăƒ‰ăƒĄă‚€ăƒłä»Łæ•°
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
def execute(m: Market, b: Account): Kleisli[List, Order, Execution]
def allocate(acts: List[Account]): Kleisli[List, Execution, Trade]
.. that implements the semantics of our
domain algebraically ..
.. function composition with
Effects ..
ăƒ‰ăƒĄă‚€ăƒłăźæ„ć‘łè«–ă‚’ä»Łæ•°çš„ă«ćźŸèŁ…ă™ă‚‹äœœç”šä»˜ăăźé–ąæ•°ăźćˆæˆ
Saturday, 30 January 16
def tradeGeneration(
market: Market,
broker: Account,
clientAccounts: List[Account]) = {
clientOrders andThen
execute(market, broker) andThen
allocate(clientAccounts)
}
Implementation follows the speciïŹcation
.. the complete trade generation
logic ..
ćźŸèŁ…ăŻä»•æ§˜ă«ćŸ“ă†
Saturday, 30 January 16
def tradeGeneration(
market: Market,
broker: Account,
clientAccounts: List[Account]) = {
clientOrders andThen
execute(market, broker) andThen
allocate(clientAccounts)
}
Implementation follows the speciïŹcation
and we get the Ubiquitous Language for
free :-)
.. the complete trade generation
logic ..
ćźŸèŁ…ăŻä»•æ§˜ă«ćŸ“ă„ă€
そこからラビキタă‚č蚀èȘžă‚’èȘ­ăżć–ă‚‹ă“ăšăŒć‡șæ„ă‚‹
Saturday, 30 January 16
algebraic & functional
‱ Just Pure Functions. Lower cognitive load -
don’t have to think of the classes & data
members where behaviors will reside
‱ Compositional. Algebras compose - we
deïŹned the algebras of our domain APIs in
terms of existing, time tested algebras of
Kleislis and Monads
ä»Łæ•°çš„ă‹ă€é–ąæ•°ćž‹ăźèš­èšˆăŻă€
箔çČ‹é–ąæ•°ăźăżă§æ§‹æˆă™ă‚‹ă€ćˆæˆćŻèƒœăȘ蚭蚈
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
def execute(m: Market, b: Account): Kleisli[List, Order, Execution]
def allocate(acts: List[Account]): Kleisli[List, Execution, Trade]
.. our algebra still doesn’t handle errors
that may occur within our domain
behaviors ..
.. function composition with
Effects ..
ăă†èš€ăˆă°ă‚šăƒ©ăƒŒć‡Šç†ă©ă†ă™ă‚‹?
Saturday, 30 January 16
more algebra,
more types
ä»Łæ•°ăšćž‹ă€ć€§ç››ă‚Šă§èżœćŠ ïŒ
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
return type constructor
List ăŻæˆ»ă‚Šć€€ăźćž‹ă‚łăƒłă‚čăƒˆăƒ©ă‚Żă‚ż
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
return type constructor
What happens in case the operation fails ?
æŒ”çź—ăŒć€±æ•—ă—ăŸă‚‰ă©ă†ăȘる?
Saturday, 30 January 16
Error handling as an
Effect
‱ pure and functional
‱ with an explicit and published algebra
‱ stackable with existing effects
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
ăƒąăƒŠăƒ‰äœœç”šăšă—ăŠăźă‚šăƒ©ăƒŒć‡Šç†
箔çČ‹ă§é–ąæ•°ćž‹ă«ă€‚æ˜Žç€ș的ăȘä»Łæ•°ă€‚æ—ąć­˜ăźäœœç”šăšç©ăżäžŠă’ćŻèƒœă€‚
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
.. stacking of effects ..
M[List[_]]
äœœç”šăźç©ăżäžŠă’
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
.. stacking of effects ..
M[List[_]]: M is a Monad
List ă‚’ă‚šăƒ©ăƒŒć‡Šç†ăźăŸă‚ăźăƒąăƒŠăƒ‰ M でć›Čむ
Saturday, 30 January 16
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
ăƒąăƒŠăƒ‰ć€‰æ›ć­
Saturday, 30 January 16
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
Saturday, 30 January 16
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
ä»Łæ•°ăšă—ăŠæ‰±ă„ă‚„ă™ă„ăźăŻ OptionT ă‚’äœżăŁăŸæ–č
Saturday, 30 January 16
Monad Transformers
‱ collapses the stack and gives us a single
monad to deal with
‱ order of stacking is important though
ăƒąăƒŠăƒ‰ć€‰æ›ć­ăŻç©ăżäžŠă’ăŸăƒąăƒŠăƒ‰ă‚’äž€ă€ă«æœ°ă™ă“ăšăŒă§ăă‚‹
ăŸă ă—ç©ăżäžŠă’ă‚‹é †ç•ȘăŻć€§ćˆ‡
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
.. stacking of effects ..
case class ListT[M[_], A] (run: M[List[A]]) { //..
ListT ăƒąăƒŠăƒ‰ć€‰æ›ć­ă‚’äœżă†
Saturday, 30 January 16
ă“ă‚ŒăŻä»Łæ•°ă«ăšăŁăŠć°ă•ăȘäž€æ­©ă ăŒă€
ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ă«ăšăŁăŠăŻć·šć€§ăȘè·łèșă§ă‚ă‚‹
Saturday, 30 January 16
type StringOr[A] = String / A
type Valid[A] = ListT[StringOr, A]
ă“ă‚ŒăŻä»Łæ•°ă«ăšăŁăŠć°ă•ăȘäž€æ­©ă ăŒă€
ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ă«ăšăŁăŠăŻć·šć€§ăȘè·łèșă§ă‚ă‚‹
Saturday, 30 January 16
type StringOr[A] = String / A
type Valid[A] = ListT[StringOr, A]
def clientOrders: Kleisli[Valid, ClientOrderSheet, Order]
def execute(m: Market, b: Account): Kleisli[Valid, Order, Execution]
def allocate(acts: List[Account]): Kleisli[Valid, Execution, Trade]
ă“ă‚ŒăŻä»Łæ•°ă«ăšăŁăŠć°ă•ăȘäž€æ­©ă ăŒă€
ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ă«ăšăŁăŠăŻć·šć€§ăȘè·łèșă§ă‚ă‚‹
Saturday, 30 January 16
type StringOr[A] = String / A
type Valid[A] = ListT[StringOr, A]
def clientOrders: Kleisli[Valid, ClientOrderSheet, Order]
def execute(m: Market, b: Account): Kleisli[Valid, Order, Execution]
def allocate(acts: List[Account]): Kleisli[Valid, Execution, Trade]
.. a small change in algebra, a huge step
for our domain model ..
ă“ă‚ŒăŻä»Łæ•°ă«ăšăŁăŠć°ă•ăȘäž€æ­©ă ăŒă€
ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ă«ăšăŁăŠăŻć·šć€§ăȘè·łèșă§ă‚ă‚‹
Saturday, 30 January 16
def execute(market: Market, brokerAccount: Account) =
kleisli[List, Order, Execution] { order =>
order.items.map { item =>
Execution(brokerAccount, market, ..)
}
}
Saturday, 30 January 16
private def makeExecution(brokerAccount: Account,
item: LineItem, market: Market): String / Execution = //..
def execute(market: Market, brokerAccount: Account) =
kleisli[Valid, Order, Execution] { order =>
listT[StringOr](
order.items.map { item =>
makeExecution(brokerAccount, market, ..)
}.sequenceU
)
}
Saturday, 30 January 16
List
(aggregates)
Algebra of types
ćž‹ăźä»Łæ•°
集箄ぼためぼ List
Saturday, 30 January 16
List
(aggregates)
Disjunction
(error accumulation)
Algebra of types
ă‚šăƒ©ăƒŒè“„ç©ăźăŸă‚ăźDisjunction
Saturday, 30 January 16
List
(aggregates)
Disjunction
(error accumulation)
Kleisli
(dependency injection)
Algebra of types
äŸć­˜æ€§æłšć…„ăźăŸă‚ăź Kleisli
Saturday, 30 January 16
List
(aggregates)
Disjunction
(error accumulation)
Kleisli
(dependency injection)
Future
(reactive non-blocking computation)
Algebra of types
ăƒȘケクティブでノンブロッキングăȘ懩理ぼためぼ Future
Saturday, 30 January 16
List
(aggregates)
Disjunction
(error accumulation)
Kleisli
(dependency injection)
Future
(reactive non-blocking computation)
Algebra of types
Monad
ヱナド
Saturday, 30 January 16
List
(aggregates)
Disjunction
(error accumulation)
Kleisli
(dependency injection)
Future
(reactive non-blocking computation)
Algebra of types
Monad
Monoid
ăƒąăƒŽă‚€ăƒ‰
Saturday, 30 January 16
List
(aggregates)
Disjunction
(error accumulation)
Kleisli
(dependency injection)
Future
(reactive non-blocking computation)
Algebra of types
Monad
Monoid
Compositional
ćˆæˆćŻèƒœ
Saturday, 30 January 16
List
(aggregates)
Disjunction
(error accumulation)
Kleisli
(dependency injection)
Future
(reactive non-blocking computation)
Algebra of types
Monad
Monoid
Offers a suite of functional
combinators
ă•ăŸă–ăŸăȘé–ąæ•°ćž‹ă‚łăƒłăƒ“ăƒăƒŒă‚żă‚’æäŸ›ă™ă‚‹
Saturday, 30 January 16
List
(aggregates)
Disjunction
(error accumulation)
Kleisli
(dependency injection)
Future
(reactive non-blocking computation)
Algebra of types
Monad
Monoid
Handles edge cases so your
domain logic remains clean
ăƒ‰ăƒĄă‚€ăƒłăƒ­ă‚žăƒƒă‚Żă‚’ç¶șéș—äżăŠă‚‹ă‚ˆă†ă«ă€
ă‚šăƒƒă‚žă‚±ăƒŒă‚čはこっちで懩理する
Saturday, 30 January 16
List
(aggregates)
Disjunction
(error accumulation)
Kleisli
(dependency injection)
Future
(reactive non-blocking computation)
Algebra of types
Monad
Monoid
Implicitly encodes quite a bit
of domain rules
æš—é»™çš„ă«ă‹ăȘă‚Šć€šăăźăƒ‰ăƒĄă‚€ăƒłăƒ«ăƒŒăƒ«ă‚’ă‚šăƒłă‚łăƒŒăƒ‰ă™ă‚‹
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
def execute(m: Market, b: Account): Kleisli[List, Order, Execution]
def allocate(acts: List[Account]): Kleisli[List, Execution, Trade]
.. the algebra ..
ä»Łæ•°çš„ăȘè€ƒăˆæ–č
Saturday, 30 January 16
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
def execute(m: Market, b: Account): Kleisli[List, Order, Execution]
def allocate(acts: List[Account]): Kleisli[List, Execution, Trade]
.. the algebra ..
functions
é–ąæ•°
Saturday, 30 January 16
.. the algebra ..
def clientOrders: Kleisli[List, ClientOrderSheet, Order]
def execute(m: Market, b: Account): Kleisli[List, Order, Execution]
def allocate(acts: List[Account]): Kleisli[List, Execution, Trade]
types
枋
Saturday, 30 January 16
.. the algebra ..
composition
def tradeGeneration(market: Market, broker: Account,
clientAccounts: List[Account]) = {
clientOrders andThen
execute(market, broker) andThen
allocate(clientAccounts)
}
ćˆæˆ
Saturday, 30 January 16
.. the algebra ..
trait OrderLaw {
def sizeLaw: Seq[ClientOrder] => Seq[Order] => Boolean =
{ cos => orders =>
cos.size == orders.size
}
def lineItemLaw: Seq[ClientOrder] => Seq[Order] => Boolean =
{ cos => orders =>
cos.map(instrumentsInClientOrder).sum ==
orders.map(_.items.size).sum
}
}
laws of the algebra
(domain rules)
ä»Łæ•°ăźæł•ć‰‡
Saturday, 30 January 16
Domain Rules as
Algebraic Properties
‱ part of the abstraction
‱ equally important as the actual
abstraction
‱ veriïŹable as properties
ä»Łæ•°çš„ăƒ—ăƒ­ăƒ‘ăƒ†ă‚Łăšă—ăŠăźăƒ‰ăƒĄă‚€ăƒłăƒ«ăƒŒăƒ«
ăƒ—ăƒ­ăƒ‘ăƒ†ă‚Łăšă—ăŠæ€œèšŒćŻèƒœăšăȘる
Saturday, 30 January 16
.. domain rules veriïŹcation ..
property("Check Client Order laws") =
forAll((cos: Set[ClientOrder]) => {
val orders = for {
os <- clientOrders.run(cos.toList)
} yield os
sizeLaw(cos.toSeq)(orders) == true
lineItemLaw(cos.toSeq)(orders) == true
})
property based testing FTW ..
ăƒ—ăƒ­ăƒ‘ăƒ†ă‚Łăƒ™ăƒŒă‚čテă‚čăƒˆæœ€ćŒ·
Saturday, 30 January 16
https://www.manning.com/books/functional-and-reactive-
domain-modeling
æœŹæ›žă„ăŠăŸă™
Saturday, 30 January 16
ThankYou!
Saturday, 30 January 16

More Related Content

PDF
Domain Modeling with Functions - an algebraic approach
PDF
From functional to Reactive - patterns in domain modeling
PDF
An Algebraic Approach to Functional Domain Modeling
PDF
Functional Patterns in Domain Modeling
PDF
Functional and Event Driven - another approach to domain modeling
PPT
DSL - expressive syntax on top of a clean semantic model
PPT
Dependency Injection in Scala - Beyond the Cake Pattern
PDF
Architectural Patterns in Building Modular Domain Models
Domain Modeling with Functions - an algebraic approach
From functional to Reactive - patterns in domain modeling
An Algebraic Approach to Functional Domain Modeling
Functional Patterns in Domain Modeling
Functional and Event Driven - another approach to domain modeling
DSL - expressive syntax on top of a clean semantic model
Dependency Injection in Scala - Beyond the Cake Pattern
Architectural Patterns in Building Modular Domain Models

Similar to Functional and Algebraic Domain Modeling (6)

PDF
Friendly Functional Programming
PDF
Functional and Algebraic Domain Modeling
PDF
Algebraic Thinking for Evolution of Pure Functional Domain Models
PDF
Scala design pattern
PDF
Extensible Effects in Dotty
PPTX
Dsm as theory building
Friendly Functional Programming
Functional and Algebraic Domain Modeling
Algebraic Thinking for Evolution of Pure Functional Domain Models
Scala design pattern
Extensible Effects in Dotty
Dsm as theory building
Ad

More from Debasish Ghosh (8)

PDF
Effects, Algebraically Yours using Scala
PDF
Functional Domain Modeling - The ZIO 2 Way
PDF
Power of functions in a typed world
PDF
Approximation Data Structures for Streaming Applications
PDF
Mining Functional Patterns
PDF
Property based Testing - generative data & executable domain rules
PDF
Big Data - architectural concerns for the new age
PDF
Domain Modeling in a Functional World
Effects, Algebraically Yours using Scala
Functional Domain Modeling - The ZIO 2 Way
Power of functions in a typed world
Approximation Data Structures for Streaming Applications
Mining Functional Patterns
Property based Testing - generative data & executable domain rules
Big Data - architectural concerns for the new age
Domain Modeling in a Functional World
Ad

Recently uploaded (20)

PPTX
history of c programming in notes for students .pptx
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
 
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
Nekopoi APK 2025 free lastest update
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
top salesforce developer skills in 2025.pdf
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
ManageIQ - Sprint 268 Review - Slide Deck
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
Digital Strategies for Manufacturing Companies
PPTX
CHAPTER 2 - PM Management and IT Context
history of c programming in notes for students .pptx
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
 
Wondershare Filmora 15 Crack With Activation Key [2025
Navsoft: AI-Powered Business Solutions & Custom Software Development
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Nekopoi APK 2025 free lastest update
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
2025 Textile ERP Trends: SAP, Odoo & Oracle
Upgrade and Innovation Strategies for SAP ERP Customers
Design an Analysis of Algorithms I-SECS-1021-03
How to Migrate SBCGlobal Email to Yahoo Easily
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Which alternative to Crystal Reports is best for small or large businesses.pdf
top salesforce developer skills in 2025.pdf
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
ManageIQ - Sprint 268 Review - Slide Deck
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Digital Strategies for Manufacturing Companies
CHAPTER 2 - PM Management and IT Context

Functional and Algebraic Domain Modeling

  • 1. Functional and Algebraic Domain Modeling Debasish Ghosh @debasishg é–ąæ•°ćž‹ă€ä»Łæ•°çš„ăȘăƒ‰ăƒĄă‚€ăƒłăƒ»ăƒąăƒ‡ăƒȘングぼæ–čæł• Saturday, 30 January 16
  • 4. 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 speciïŹc 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) ç‰čćźšăźć•éĄŒé ˜ćŸŸă«é–ąă™ă‚‹æŠ‚ćż”ăƒąăƒ‡ăƒ« ă‚šăƒłăƒ†ă‚Łăƒ†ă‚ŁïŒé–ąé€ŁïŒćˆ¶çŽ„ăȘă©ă‚’èš˜èż° Saturday, 30 January 16
  • 5. The Functional Lens .. “domain API evolution through algebraic composition” é–ąæ•°ćž‹ăƒŹăƒłă‚ș ä»Łæ•°çš„ćˆæˆă‚’é€šă˜ăŸăƒ‰ăƒĄă‚€ăƒł API たé€Č挖 Saturday, 30 January 16
  • 7. Twitter ç€Ÿă§ăźă‚”ăƒŒăƒă‚œăƒ•ăƒˆă‚Šă‚§ă‚ąăźæ§‹æˆăŻ fp ăšćŒă˜ç†ćż” ïŒˆäžć€‰æ€§ă€é–ąæ•°ăźćˆæˆă€ć‰Żäœœç”šăźćˆ†é›ąïŒ‰ă«ćŸșă„ă Saturday, 30 January 16
  • 8. Your domain model is a function ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ăŻé–ąæ•°ă§ă‚ă‚‹ Saturday, 30 January 16
  • 9. Your domain model is a function ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ăŻé–ąæ•°ïŒˆ...であっどæŹČă—ă„ïŒ‰ Saturday, 30 January 16
  • 10. Your domain model is a collection of functions ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ăŻé–ąæ•°ăźé›†ćˆă§ă‚ă‚‹ Saturday, 30 January 16
  • 11. Your domain model is a collection of functions some simpler models are .. ć…·äœ“äŸ‹ă§è€ƒăˆă‚‹ăš... Saturday, 30 January 16
  • 13. 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 ćąƒç•Œă„ă‘ă‚‰ă‚ŒăŸă‚łăƒłăƒ†ă‚­ă‚čăƒˆăŻă€ç”±äž€ă•ă‚ŒăŸèȘžćœ™ă‚’æŒă€ ăƒ‰ăƒĄă‚€ăƒłăźæŒŻă‚‹èˆžă„ăŻé–ąæ•°ă€ă‚Șăƒ–ă‚žă‚§ă‚ŻăƒˆăŻćž‹ăšă—ăŠćźŸèŁ…ă™ă‚‹Saturday, 30 January 16
  • 14. Domain Model = âˆȘ(i) Bounded Context(i) Saturday, 30 January 16
  • 15. Domain Model = âˆȘ(i) Bounded Context(i) Bounded Context = { f(x) | p(x) ∈ Domain Rules } Saturday, 30 January 16
  • 16. 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 f ăŻăƒ‰ăƒĄă‚€ăƒłé–ąæ•°ă§ă€ä»–ăźé–ąæ•°ăšćˆæˆă§ăă‚‹ p はビゾネă‚čăƒ«ăƒŒăƒ« Saturday, 30 January 16
  • 17. ‱ Functions / Morphisms ‱ Types / Sets ‱ Composition ‱ Rules / Laws é–ąæ•°ăšć°„ă€ćž‹ăšé›†ćˆă€ćˆæˆă€ăƒ«ăƒŒăƒ«ăšæł•ć‰‡ Saturday, 30 January 16
  • 18. ‱ Functions / Morphisms ‱ Types / Sets ‱ Composition ‱ Rules / Laws algebra èŠăŻä»Łæ•°ăšă„ă†ă“ăš Saturday, 30 January 16
  • 20. Domain Model Algebra (algebra of types, functions & laws) ćž‹ăšé–ąæ•°ăšæł•ć‰‡ăźä»Łæ•° Saturday, 30 January 16
  • 21. Domain Model Algebra (algebra of types, functions & laws) explicit ‱ types ‱ type constraints ‱ expression in terms of other generic algebra ă“ă‚Œă‚’æ˜Žç€șçš„ă«ă™ă‚‹ăšă€ćž‹ă€ćž‹ăźćˆ¶çŽ„ă€ä»–ăźä»Łæ•°ă‚’ç”šă„ăŸèĄšçŸ Saturday, 30 January 16
  • 22. Domain Model Algebra (algebra of types, functions & laws) explicit veriïŹable ‱ types ‱ type constraints ‱ expr in terms of other generic algebra ‱ type constraints ‱ more constraints if you have DT ‱ algebraic property based testing çąșèȘćŻèƒœăȘăźăŻćž‹ćˆ¶çŽ„ă€ä»Łæ•°çš„ăƒ—ăƒ­ăƒ‘ăƒ†ă‚ŁăƒŒăƒ™ăƒŒă‚čぼテă‚čト äŸć­˜ćž‹ăŒă‚ă‚Œă°ă‚ˆă‚ŠćŒ·ă„ćˆ¶çŽ„ă‚’æ€œèšŒă§ăă‚‹ Saturday, 30 January 16
  • 26. Bank Account Trade Customer ... ... ... do trade process execution place order Problem Domain ... market regulations tax laws brokerage commission rates ... entities behaviors laws æł•ć‰‡ăšăȘるぼはæ ȘćŒćž‚ć ŽèŠć‰‡ă€çšŽæł•ă€æ‰‹æ•°æ–™ Saturday, 30 January 16
  • 27. do trade process execution place order Solution Domain ... behaviors Functions (Type => Type) ă‚œăƒȘăƒ„ăƒŒă‚·ăƒ§ăƒłăƒ‰ăƒĄă‚€ăƒłă§ăŻă€æŒŻă‚‹èˆžă„ăŻé–ąæ•° (枋 枋) Saturday, 30 January 16
  • 28. Bank Account Trade Customer ... ... ... do trade process execution place order Solution Domain ... entities behaviors functions (Type => Type) algebraic data type ă‚šăƒłăƒ†ă‚Łăƒ†ă‚ŁăŻä»Łæ•°çš„ăƒ‡ăƒŒă‚żćž‹ Saturday, 30 January 16
  • 29. Bank Account Trade Customer ... ... ... do trade process execution place order Solution Domain ... market regulations tax laws brokerage commission rates ... entities behaviors laws functions (Type => Type) algebraic data type business rules / invariants æł•ć‰‡ăŻăƒ“ă‚žăƒă‚čăƒ»ăƒ«ăƒŒăƒ«ă‚‚ă—ăăŻäžć€‰é–ąäż‚ Saturday, 30 January 16
  • 30. Bank Account Trade Customer ... ... ... do trade process execution place order Solution Domain ... market regulations tax laws brokerage commission rates ... entities behaviors laws functions (Type => Type) algebraic data type business rules / invariants Monoid Monad ... ăƒąăƒŽă‚€ăƒ‰ă‚„ăƒąăƒŠăƒ‰ăšă„ăŁăŸćž‹ă‚Żăƒ©ă‚č Saturday, 30 January 16
  • 31. Bank Account Trade Customer ... ... ... do trade process execution place order Solution Domain ... market regulations tax laws brokerage commission rates ... entities behaviors laws functions (Type => Type) algebraic data type business rules / invariants Monoid Monad ... ă“ă‚Œă‚’ć…šéƒšă‚„ă‚‹ăšăƒ‰ăƒĄă‚€ăƒłä»Łæ•° Domain Algebra Saturday, 30 January 16
  • 32. 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 ă€Œćąƒç•Œă„ă‘ă‚‰ă‚ŒăŸă‚łăƒłăƒ†ă‚­ă‚čăƒˆă€ăŻăƒ‰ăƒĄă‚€ăƒłä»Łæ•°ăźă“ăš Saturday, 30 January 16
  • 33. Client places order - ïŹ‚exible format 1 ă‚Żăƒ©ă‚€ă‚ąăƒłăƒˆăŒæłšæ–‡ă‚’ć‡șす ăƒ•ă‚©ăƒŒăƒžăƒƒăƒˆăŻæ§˜ă€… Saturday, 30 January 16
  • 34. Client places order - ïŹ‚exible format Transform to internal domain model entity and place for execution 1 2 ć†…éƒšă§ăźăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ă‚šăƒłăƒ†ă‚Łăƒ†ă‚Łă«ć€‰æ›ă—ăŠă€ ćźŸéš›ă«æłšæ–‡ă‚’ć‡șす Saturday, 30 January 16
  • 35. Client places order - ïŹ‚exible format Transform to internal domain model entity and place for execution Trade & Allocate to client accounts 1 2 3 ć–ćŒ•ă—ă€ç”æžœă‚’ă‚Żăƒ©ă‚€ă‚ąăƒłăƒˆăźă‚ąă‚«ă‚Šăƒłăƒˆă«çŽă„ă‘ă‚‹ Saturday, 30 January 16
  • 36. def clientOrders: ClientOrderSheet => List[Order] def execute: Market => Account => Order => List[Execution] def allocate: List[Account] => Execution => List[Trade] Saturday, 30 January 16
  • 37. def clientOrders: ClientOrderSheet => List[Order] def execute[Account <: BrokerAccount]: Market => Account => Order => List[Execution] def allocate[Account <: TradingAccount]: List[Account] => Execution => List[Trade] Saturday, 30 January 16
  • 38. def clientOrders: ClientOrderSheet => List[Order] def execute: Market => Account => Order => List[Execution] def allocate: List[Account] => Execution => List[Trade] Types out of thin air No implementation till now Type names resonate domain language どこからずもăȘăé™ăŁăŠăăŸćž‹ă€‚ä»Šăźæ‰€ćźŸèŁ…ăźè©±ăŻă‚Œăƒ­ă€‚ ćž‹ăźćć‰ăŻăƒ‰ăƒĄă‚€ăƒłèš€èȘžă‚’ćæ˜  Saturday, 30 January 16
  • 39. def clientOrders: ClientOrderSheet => List[Order] def execute: Market => Account => Order => List[Execution] def allocate: List[Account] => Execution => List[Trade] ‱Types (domain entities) ‱ Functions operating on types (domain behaviors) ‱ Laws (business rules) 枋 (スンティティ)ă€é–ąæ•° (ăƒ‰ăƒĄă‚€ăƒłăźæŒŻă‚‹èˆžă„)、 æł•ć‰‡ (ビゾネă‚čăƒ»ăƒ«ăƒŒăƒ«) Saturday, 30 January 16
  • 40. def clientOrders: ClientOrderSheet => List[Order] def execute: Market => Account => Order => List[Execution] def allocate: List[Account] => Execution => List[Trade] ‱Types (domain entities) ‱ Functions operating on types (domain behaviors) ‱ Laws (business rules) Algebra of the API これが API ăźä»Łæ•° Saturday, 30 January 16
  • 41. trait Trading[Account, Trade, ClientOrderSheet, Order, Execution, Market] { def clientOrders: ClientOrderSheet => List[Order] def execute: Market => Account => Order => List[Execution] def allocate: List[Account] => Execution => List[Trade] def tradeGeneration(market: Market, broker: Account, clientAccounts: List[Account]) = ??? } parameterized on typesmodule ăƒąă‚žăƒ„ăƒŒăƒ«ă€ćž‹ăƒ‘ăƒ©ăƒĄăƒŒă‚ż Saturday, 30 January 16
  • 42. Algebraic Design ‱ The algebra is the binding contract of the API ‱ Implementation is NOT part of the algebra ‱ An algebra can have multiple interpreters (aka implementations) ‱ One of the core principles of functional programming is to decouple the algebra from the interpreter ä»Łæ•°çš„èš­èšˆæ‰‹æł•: ä»Łæ•°ăŻ API がæș–æ‹ ă™ă‚‹ćˆ¶çŽ„ ćźŸèŁ…ăŻä»Łæ•°ă«ć«ăŸă‚Œăšă€ćźŸèŁ…ă‹ă‚‰ăŻćˆ†é›ąă•ă‚ŒăŠă„ă‚‹ Saturday, 30 January 16
  • 43. def clientOrders: ClientOrderSheet => List[Order] def execute: Market => Account => Order => List[Execution] def allocate: List[Account] => Execution => List[Trade] let’s do some algebra .. ä»Łæ•°ăźç·Žçż’ Saturday, 30 January 16
  • 44. def clientOrders: ClientOrderSheet => List[Order] def execute(m: Market, broker: Account): Order => List[Execution] def allocate(accounts: List[Account]): Execution => List[Trade] let’s do some algebra .. Saturday, 30 January 16
  • 45. def clientOrders: ClientOrderSheet => List[Order] def execute(m: Market, broker: Account): Order => List[Execution] def allocate(accounts: List[Account]): Execution => List[Trade] let’s do some algebra .. Saturday, 30 January 16
  • 46. def clientOrders: ClientOrderSheet => List[Order] def execute(m: Market, broker: Account): Order => List[Execution] def allocate(accounts: List[Account]): Execution => List[Trade] let’s do some algebra .. Saturday, 30 January 16
  • 47. def clientOrders: ClientOrderSheet => List[Order] def execute(m: Market, broker: Account): Order => List[Execution] def allocate(accounts: List[Account]): Execution => List[Trade] let’s do some algebra .. Saturday, 30 January 16
  • 48. def clientOrders: ClientOrderSheet => List[Order] def execute(m: Market, broker: Account): Order => List[Execution] def allocate(accounts: List[Account]): Execution => List[Trade] let’s do some algebra .. Saturday, 30 January 16
  • 49. def f: A => List[B] def g: B => List[C] def h: C => List[D] .. a problem of composition .. これは ... ćˆæˆăźć•éĄŒă  Saturday, 30 January 16
  • 50. .. a problem of composition with effects .. def f: A => List[B] def g: B => List[C] def h: C => List[D] これは ... äœœç”šä»˜ăăźćˆæˆăźć•éĄŒă  Saturday, 30 January 16
  • 51. def f[M: Monad]: A => M[B] def g[M: Monad]: B => M[C] def h[M: Monad]: C => M[D] .. a problem of composition with effects that can be generalized .. ă“ă‚ŒăŻăƒąăƒŠăƒ‰ăšă—ăŠæŠœè±ĄćŒ–ă§ăă‚‹äœœç”šä»˜ăăźćˆæˆăźć•éĄŒă  Saturday, 30 January 16
  • 52. case class Kleisli[M[_], A, B](run: A => M[B]) { def andThen[C](f: B => M[C]) (implicit M: Monad[M]): Kleisli[M, A, C] = Kleisli((a: A) => M.flatMap(run(a))(f)) } .. function composition with Effects .. It’s a Kleisli ! äœœç”šä»˜ăăźé–ąæ•°ăźćˆæˆăšèš€ăˆă°ă€Kleisli Saturday, 30 January 16
  • 53. def clientOrders: Kleisli[List, ClientOrderSheet, Order] def execute(m: Market, b: Account): Kleisli[List, Order, Execution] def allocate(acts: List[Account]): Kleisli[List, Execution, Trade] Follow the types .. function composition with Effects .. def clientOrders: ClientOrderSheet => List[Order] def execute(m: Market, broker: Account): Order => List[Execution] def allocate(accounts: List[Account]): Execution => List[Trade] ćž‹ă«ä»»ă›ăŠè€ƒăˆă‚‹ Saturday, 30 January 16
  • 54. def clientOrders: Kleisli[List, ClientOrderSheet, Order] def execute(m: Market, b: Account): Kleisli[List, Order, Execution] def allocate(acts: List[Account]): Kleisli[List, Execution, Trade] Domain algebra composed with the categorical algebra of a Kleisli Arrow .. function composition with Effects .. Klieisli ć°„ă«ă‚ˆăŁăŠćˆæˆă•ă‚ŒăŸăƒ‰ăƒĄă‚€ăƒłä»Łæ•° Saturday, 30 January 16
  • 55. def clientOrders: Kleisli[List, ClientOrderSheet, Order] def execute(m: Market, b: Account): Kleisli[List, Order, Execution] def allocate(acts: List[Account]): Kleisli[List, Execution, Trade] .. that implements the semantics of our domain algebraically .. .. function composition with Effects .. ăƒ‰ăƒĄă‚€ăƒłăźæ„ć‘łè«–ă‚’ä»Łæ•°çš„ă«ćźŸèŁ…ă™ă‚‹äœœç”šä»˜ăăźé–ąæ•°ăźćˆæˆ Saturday, 30 January 16
  • 56. def tradeGeneration( market: Market, broker: Account, clientAccounts: List[Account]) = { clientOrders andThen execute(market, broker) andThen allocate(clientAccounts) } Implementation follows the speciïŹcation .. the complete trade generation logic .. ćźŸèŁ…ăŻä»•æ§˜ă«ćŸ“ă† Saturday, 30 January 16
  • 57. def tradeGeneration( market: Market, broker: Account, clientAccounts: List[Account]) = { clientOrders andThen execute(market, broker) andThen allocate(clientAccounts) } Implementation follows the speciïŹcation and we get the Ubiquitous Language for free :-) .. the complete trade generation logic .. ćźŸèŁ…ăŻä»•æ§˜ă«ćŸ“ă„ă€ そこからラビキタă‚č蚀èȘžă‚’èȘ­ăżć–ă‚‹ă“ăšăŒć‡șæ„ă‚‹ Saturday, 30 January 16
  • 58. algebraic & functional ‱ Just Pure Functions. Lower cognitive load - don’t have to think of the classes & data members where behaviors will reside ‱ Compositional. Algebras compose - we deïŹned the algebras of our domain APIs in terms of existing, time tested algebras of Kleislis and Monads ä»Łæ•°çš„ă‹ă€é–ąæ•°ćž‹ăźèš­èšˆăŻă€ 箔çČ‹é–ąæ•°ăźăżă§æ§‹æˆă™ă‚‹ă€ćˆæˆćŻèƒœăȘ蚭蚈 Saturday, 30 January 16
  • 59. def clientOrders: Kleisli[List, ClientOrderSheet, Order] def execute(m: Market, b: Account): Kleisli[List, Order, Execution] def allocate(acts: List[Account]): Kleisli[List, Execution, Trade] .. our algebra still doesn’t handle errors that may occur within our domain behaviors .. .. function composition with Effects .. ăă†èš€ăˆă°ă‚šăƒ©ăƒŒć‡Šç†ă©ă†ă™ă‚‹? Saturday, 30 January 16
  • 61. def clientOrders: Kleisli[List, ClientOrderSheet, Order] return type constructor List ăŻæˆ»ă‚Šć€€ăźćž‹ă‚łăƒłă‚čăƒˆăƒ©ă‚Żă‚ż Saturday, 30 January 16
  • 62. def clientOrders: Kleisli[List, ClientOrderSheet, Order] return type constructor What happens in case the operation fails ? æŒ”çź—ăŒć€±æ•—ă—ăŸă‚‰ă©ă†ăȘる? Saturday, 30 January 16
  • 63. Error handling as an Effect ‱ pure and functional ‱ with an explicit and published algebra ‱ stackable with existing effects def clientOrders: Kleisli[List, ClientOrderSheet, Order] ăƒąăƒŠăƒ‰äœœç”šăšă—ăŠăźă‚šăƒ©ăƒŒć‡Šç† 箔çČ‹ă§é–ąæ•°ćž‹ă«ă€‚æ˜Žç€ș的ăȘä»Łæ•°ă€‚æ—ąć­˜ăźäœœç”šăšç©ăżäžŠă’ćŻèƒœă€‚ Saturday, 30 January 16
  • 64. def clientOrders: Kleisli[List, ClientOrderSheet, Order] .. stacking of effects .. M[List[_]] äœœç”šăźç©ăżäžŠă’ Saturday, 30 January 16
  • 65. def clientOrders: Kleisli[List, ClientOrderSheet, Order] .. stacking of effects .. M[List[_]]: M is a Monad List ă‚’ă‚šăƒ©ăƒŒć‡Šç†ăźăŸă‚ăźăƒąăƒŠăƒ‰ M でć›Čむ Saturday, 30 January 16
  • 66. 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 ăƒąăƒŠăƒ‰ć€‰æ›ć­ Saturday, 30 January 16
  • 67. 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 Saturday, 30 January 16
  • 68. 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 ä»Łæ•°ăšă—ăŠæ‰±ă„ă‚„ă™ă„ăźăŻ OptionT ă‚’äœżăŁăŸæ–č Saturday, 30 January 16
  • 69. Monad Transformers ‱ collapses the stack and gives us a single monad to deal with ‱ order of stacking is important though ăƒąăƒŠăƒ‰ć€‰æ›ć­ăŻç©ăżäžŠă’ăŸăƒąăƒŠăƒ‰ă‚’äž€ă€ă«æœ°ă™ă“ăšăŒă§ăă‚‹ ăŸă ă—ç©ăżäžŠă’ă‚‹é †ç•ȘăŻć€§ćˆ‡ Saturday, 30 January 16
  • 70. def clientOrders: Kleisli[List, ClientOrderSheet, Order] .. stacking of effects .. case class ListT[M[_], A] (run: M[List[A]]) { //.. ListT ăƒąăƒŠăƒ‰ć€‰æ›ć­ă‚’äœżă† Saturday, 30 January 16
  • 72. type StringOr[A] = String / A type Valid[A] = ListT[StringOr, A] ă“ă‚ŒăŻä»Łæ•°ă«ăšăŁăŠć°ă•ăȘäž€æ­©ă ăŒă€ ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ă«ăšăŁăŠăŻć·šć€§ăȘè·łèșă§ă‚ă‚‹ Saturday, 30 January 16
  • 73. type StringOr[A] = String / A type Valid[A] = ListT[StringOr, A] def clientOrders: Kleisli[Valid, ClientOrderSheet, Order] def execute(m: Market, b: Account): Kleisli[Valid, Order, Execution] def allocate(acts: List[Account]): Kleisli[Valid, Execution, Trade] ă“ă‚ŒăŻä»Łæ•°ă«ăšăŁăŠć°ă•ăȘäž€æ­©ă ăŒă€ ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ă«ăšăŁăŠăŻć·šć€§ăȘè·łèșă§ă‚ă‚‹ Saturday, 30 January 16
  • 74. type StringOr[A] = String / A type Valid[A] = ListT[StringOr, A] def clientOrders: Kleisli[Valid, ClientOrderSheet, Order] def execute(m: Market, b: Account): Kleisli[Valid, Order, Execution] def allocate(acts: List[Account]): Kleisli[Valid, Execution, Trade] .. a small change in algebra, a huge step for our domain model .. ă“ă‚ŒăŻä»Łæ•°ă«ăšăŁăŠć°ă•ăȘäž€æ­©ă ăŒă€ ăƒ‰ăƒĄă‚€ăƒłăƒąăƒ‡ăƒ«ă«ăšăŁăŠăŻć·šć€§ăȘè·łèșă§ă‚ă‚‹ Saturday, 30 January 16
  • 75. def execute(market: Market, brokerAccount: Account) = kleisli[List, Order, Execution] { order => order.items.map { item => Execution(brokerAccount, market, ..) } } Saturday, 30 January 16
  • 76. private def makeExecution(brokerAccount: Account, item: LineItem, market: Market): String / Execution = //.. def execute(market: Market, brokerAccount: Account) = kleisli[Valid, Order, Execution] { order => listT[StringOr]( order.items.map { item => makeExecution(brokerAccount, market, ..) }.sequenceU ) } Saturday, 30 January 16
  • 78. List (aggregates) Disjunction (error accumulation) Algebra of types ă‚šăƒ©ăƒŒè“„ç©ăźăŸă‚ăźDisjunction Saturday, 30 January 16
  • 79. List (aggregates) Disjunction (error accumulation) Kleisli (dependency injection) Algebra of types äŸć­˜æ€§æłšć…„ăźăŸă‚ăź Kleisli Saturday, 30 January 16
  • 80. List (aggregates) Disjunction (error accumulation) Kleisli (dependency injection) Future (reactive non-blocking computation) Algebra of types ăƒȘケクティブでノンブロッキングăȘ懩理ぼためぼ Future Saturday, 30 January 16
  • 81. List (aggregates) Disjunction (error accumulation) Kleisli (dependency injection) Future (reactive non-blocking computation) Algebra of types Monad ヱナド Saturday, 30 January 16
  • 82. List (aggregates) Disjunction (error accumulation) Kleisli (dependency injection) Future (reactive non-blocking computation) Algebra of types Monad Monoid ăƒąăƒŽă‚€ăƒ‰ Saturday, 30 January 16
  • 83. List (aggregates) Disjunction (error accumulation) Kleisli (dependency injection) Future (reactive non-blocking computation) Algebra of types Monad Monoid Compositional ćˆæˆćŻèƒœ Saturday, 30 January 16
  • 84. List (aggregates) Disjunction (error accumulation) Kleisli (dependency injection) Future (reactive non-blocking computation) Algebra of types Monad Monoid Offers a suite of functional combinators ă•ăŸă–ăŸăȘé–ąæ•°ćž‹ă‚łăƒłăƒ“ăƒăƒŒă‚żă‚’æäŸ›ă™ă‚‹ Saturday, 30 January 16
  • 85. List (aggregates) Disjunction (error accumulation) Kleisli (dependency injection) Future (reactive non-blocking computation) Algebra of types Monad Monoid Handles edge cases so your domain logic remains clean ăƒ‰ăƒĄă‚€ăƒłăƒ­ă‚žăƒƒă‚Żă‚’ç¶șéș—äżăŠă‚‹ă‚ˆă†ă«ă€ ă‚šăƒƒă‚žă‚±ăƒŒă‚čはこっちで懩理する Saturday, 30 January 16
  • 86. List (aggregates) Disjunction (error accumulation) Kleisli (dependency injection) Future (reactive non-blocking computation) Algebra of types Monad Monoid Implicitly encodes quite a bit of domain rules æš—é»™çš„ă«ă‹ăȘă‚Šć€šăăźăƒ‰ăƒĄă‚€ăƒłăƒ«ăƒŒăƒ«ă‚’ă‚šăƒłă‚łăƒŒăƒ‰ă™ă‚‹ Saturday, 30 January 16
  • 87. def clientOrders: Kleisli[List, ClientOrderSheet, Order] def execute(m: Market, b: Account): Kleisli[List, Order, Execution] def allocate(acts: List[Account]): Kleisli[List, Execution, Trade] .. the algebra .. ä»Łæ•°çš„ăȘè€ƒăˆæ–č Saturday, 30 January 16
  • 88. def clientOrders: Kleisli[List, ClientOrderSheet, Order] def execute(m: Market, b: Account): Kleisli[List, Order, Execution] def allocate(acts: List[Account]): Kleisli[List, Execution, Trade] .. the algebra .. functions é–ąæ•° Saturday, 30 January 16
  • 89. .. the algebra .. def clientOrders: Kleisli[List, ClientOrderSheet, Order] def execute(m: Market, b: Account): Kleisli[List, Order, Execution] def allocate(acts: List[Account]): Kleisli[List, Execution, Trade] types 枋 Saturday, 30 January 16
  • 90. .. the algebra .. composition def tradeGeneration(market: Market, broker: Account, clientAccounts: List[Account]) = { clientOrders andThen execute(market, broker) andThen allocate(clientAccounts) } ćˆæˆ Saturday, 30 January 16
  • 91. .. the algebra .. trait OrderLaw { def sizeLaw: Seq[ClientOrder] => Seq[Order] => Boolean = { cos => orders => cos.size == orders.size } def lineItemLaw: Seq[ClientOrder] => Seq[Order] => Boolean = { cos => orders => cos.map(instrumentsInClientOrder).sum == orders.map(_.items.size).sum } } laws of the algebra (domain rules) ä»Łæ•°ăźæł•ć‰‡ Saturday, 30 January 16
  • 92. Domain Rules as Algebraic Properties ‱ part of the abstraction ‱ equally important as the actual abstraction ‱ veriïŹable as properties ä»Łæ•°çš„ăƒ—ăƒ­ăƒ‘ăƒ†ă‚Łăšă—ăŠăźăƒ‰ăƒĄă‚€ăƒłăƒ«ăƒŒăƒ« ăƒ—ăƒ­ăƒ‘ăƒ†ă‚Łăšă—ăŠæ€œèšŒćŻèƒœăšăȘる Saturday, 30 January 16
  • 93. .. domain rules veriïŹcation .. property("Check Client Order laws") = forAll((cos: Set[ClientOrder]) => { val orders = for { os <- clientOrders.run(cos.toList) } yield os sizeLaw(cos.toSeq)(orders) == true lineItemLaw(cos.toSeq)(orders) == true }) property based testing FTW .. ăƒ—ăƒ­ăƒ‘ăƒ†ă‚Łăƒ™ăƒŒă‚čテă‚čăƒˆæœ€ćŒ· Saturday, 30 January 16