Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
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 topic...
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
• ...
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 impleme...
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 o...
• 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 oth...
Domain Model Algebra
(algebra of types, functions & laws)
explicit
verifiable
• types
• type constraints
• expression in te...
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
.....
Amount
Account
Balance
Customer
...
...
...
close
debit
open
...
market
regulations
tax laws
brokerage
commission
rates
.....
Amount
Account
Balance
Customer
...
...
...
close
debit
open
...
market
regulations
tax laws
brokerage
commission
rates
.....
Domain Model = ∪(i) Bounded Context(i)
Bounded Context = { f(x) | p(x) ∈ Domain Rules }
• domain function
• on an object o...
• Ubiquitous language
• Entities
•Value Objects
• Functions on objects
• Domain Rules
• Schema
• Operations
Algebra is the...
• Ubiquitous language
• Entities
•Value Objects
• Functions on objects
• Domain Rules
• Schema
• Operations
Algebra is the...
Conference
Reservations
Program
Management
Badge Printing
Domain Algebra A
Domain Algebra B
Domain Algebra C
• Ubiquitous ...
• Algebras don’t unify across bounded
contexts
• Decoupled in space and time
• Separate vocabulary
• Types break down
Tues...
Conference
Reservations
Program
Management
Badge Printing
Domain Algebra A
Domain Algebra B
Domain Algebra C
• Ubiquitous ...
Conference
Reservations
Program
Management
Badge Printing
Domain Algebra A
Domain Algebra B
Domain Algebra C
• Ubiquitous ...
Being Reactive
Elasticity
(responsive under
varying load)
Resilience
(responsive in the
face of failures)
Message-driven
(...
trait AccountService[Account, Amount, Balance] {
type AccountOp[A] = NonEmptyList[String] / A
def open(no: String, name: S...
trait AccountService[Account, Amount, Balance] {
type AccountOp[A] = NonEmptyList[String] / A
def open(no: String, name: S...
trait AccountService[Account, Amount, Balance] {
type AccountOp[A] = NonEmptyList[String] / A
def open(no: String, name: S...
trait AccountService[Account, Amount, Balance] {
type AccountOp[A] = NonEmptyList[String] / A
def open(no: String, name: S...
trait AccountService[Account, Amount, Balance] {
type AccountOp[A] = NonEmptyList[String] / A
def open(no: String, name: S...
trait AccountService[Account, Amount, Balance] {
type AccountOp[A] = NonEmptyList[String] / A
def open(no: String, name: S...
• Parametric - parameterized on types
• Statically Typed
• Modular and hence unit testable
• Composable
Tuesday, 6 October...
def transfer(from: String, to: String, amount: Amount)
: AccountOp[(Account, Account)] = for {
a <- debit(from, amount)
b ...
Composable
trait BankingService[Account, Amount, Balance]
extends AccountService[Account, Amount, Balance]
with InterestPo...
trait AccountService[Account, Amount, Balance] {
type AccountOp[A] = NonEmptyList[String] / A
def open(
no: String,
name: ...
trait AccountService[Account, Amount, Balance] {
type AccountOp[A] = NonEmptyList[String] / A
def open(
no: String,
name: ...
trait AccountService[Account, Amount, Balance] {
type Valid[A] = NonEmptyList[String] / A
type AccountOp[A] = Kleisli[Vali...
• Design should not have any contention or
central bottlenecks that tend to hamper
the progress of the system
Being Reacti...
• If your domain service publishes APIs that
does blocking calls to underlying databases
and blocks the central thread of ...
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
loa...
Elasticity
(responsive under
varying load)
Resilience
(responsive in the
face of failures)
Message-driven
(loose coupling,...
• 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 al...
Enter Futures ..
• A future is the essence of asynchronous non
blocking computation
• Futures compose
• Futures have an al...
• In our use case we would like to augment
our domain algebra with future based APIs
• Just like an Either or a Kleisli, w...
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 {
...
type Response[A] = String / Option[A]
val count: Response[Int] = some(10).right
for {
maybeCount <- count
} yield {
for {
...
type Response[A] = String / Option[A]
val count: Response[Int] = some(10).right
for {
maybeCount <- count
} yield {
for {
...
Monad Transformers
• collapses the stack and gives us a single
monad to deal with
• order of stacking is important though
...
trait AccountService[Account, Amount, Balance] {
type Valid[A] = EitherT[Future, NonEmptyList[String], A]
type AccountOp[A...
trait AccountService[Account, Amount, Balance] {
type Valid[A] = EitherT[Future, NonEmptyList[String], A]
type AccountOp[A...
Tuesday, 6 October 15
trait AccountService[Account, Amount, Balance] {
type Valid[A] = EitherT[Future, NonEmptyList[String], A]
type AccountOp[A...
class AccountServiceInterpreter
extends AccountService[Account, Amount, Balance] {
def open(no: String,
name: String,
rate...
class AccountServiceInterpreter
extends AccountService[Account, Amount, Balance] {
def open(no: String,
name: String,
rate...
We introduced a whole new effect of
asynchrony to implement reactive traits in our
domain model API algebra & implementati...
Advantages
• We are still in the statically typed land even
with asynchronous behaviors baked into
our APIs
• We can reaso...
for {
_ <- open(..)
_ <- credit(..)
d <- debit(..)
} yield d
Reactive & algebraic patterns in
domain modeling
Tuesday, 6 O...
for {
_ <- open(..)
_ <- credit(..)
d <- debit(..)
} yield d
Reactive & algebraic patterns in
domain modeling
• Compositio...
for {
_ <- open(..)
_ <- credit(..)
d <- debit(..)
} yield d
Reactive & algebraic patterns in
domain modeling
• Compositio...
for {
_ <- open(..)
_ <- credit(..)
d <- debit(..)
} yield d
Reactive & algebraic patterns in
domain modeling
• Compositio...
Reactive & algebraic patterns in
domain modeling
Tuesday, 6 October 15
trait PortfolioService {
type PFOperation[A] = Kleisli[Future, AccountRepository, Seq[A]]
def getCurrencyPortfolio(no: Str...
val ccyPF: Future[Seq[Balance]] =
getCurrencyPortfolio(accountNo, asOf)(AccountRepository)
val eqtPF: Future[Seq[Balance]]...
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 ...
Conference
Reservations
Program
Management
Badge Printing
Domain Algebra A
Domain Algebra B
Domain Algebra C
• Ubiquitous ...
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 reasoni...
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
...
import scala.collection.mutable.{ Map => MMap }
class Summarizer extends Actor with ActorSubscriber with Logging {
private...
Centralized Failure
Management
• Supervisor hierarchies that manages failures
• Kill, restart, suspend / resume
• No more ...
Being Reactive
Elasticity
(responsive under
varying load)
Resilience
(responsive in the
face of failures)
Message-driven
(...
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
Tuesda...
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low le...
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low le...
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low le...
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low le...
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low le...
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low le...
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low le...
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low le...
Modeling Domain
Workflows
Actor
Actor Actor
Actor Actor
Actormessage
message
message
message
message
message
message
low le...
Akka Streams
Source
Pipeline starts here. Source[+Out, +Mat] takes data
from input & has a single output
Sink Pipeline end...
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(B...
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
You’ve finished this document.
Download and read it offline.
Upcoming SlideShare
Functional Patterns in Domain Modeling
Next
Upcoming SlideShare
Functional Patterns in Domain Modeling
Next
Download to read offline and view in fullscreen.

36

Share

From functional to Reactive - patterns in domain modeling

Download to read offline

From functional to Reactive - patterns in domain modeling

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

From functional to Reactive - patterns in domain modeling

  1. 1. From Functional to Reactive patterns in domain modeling Debasish Ghosh @debasishg Tuesday, 6 October 15
  2. 2. Tuesday, 6 October 15
  3. 3. Domain Modeling Tuesday, 6 October 15
  4. 4. Domain Modeling(Functional) Tuesday, 6 October 15
  5. 5. Domain Modeling (Responsive) (Functional) Tuesday, 6 October 15
  6. 6. Domain Modeling (Responsive) (Functional) (Elastic) Tuesday, 6 October 15
  7. 7. Domain Modeling (Responsive) (Functional) (Elastic) (Resilient) Tuesday, 6 October 15
  8. 8. Domain Modeling (Responsive) (Functional) (Elastic) (Resilient) (Reactive) Tuesday, 6 October 15
  9. 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. 10. The Functional Lens .. “domain API evolution through algebraic composition” Tuesday, 6 October 15
  11. 11. The Functional Lens .. “domain API evolution through algebraic composition” (Reactive) Tuesday, 6 October 15
  12. 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
  13. 13. Tuesday, 6 October 15
  14. 14. Tuesday, 6 October 15
  15. 15. Your domain model is a function Tuesday, 6 October 15
  16. 16. Your domain model is a function Tuesday, 6 October 15
  17. 17. Your domain model is a collection of functions Tuesday, 6 October 15
  18. 18. Your domain model is a collection of functions some simpler models are .. Tuesday, 6 October 15
  19. 19. https://msdn.microsoft.com/en-us/library/jj591560.aspx Tuesday, 6 October 15
  20. 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. 21. Domain Model = ∪(i) Bounded Context(i) Tuesday, 6 October 15
  22. 22. Domain Model = ∪(i) Bounded Context(i) Bounded Context = { f(x) | p(x) ∈ Domain Rules } Tuesday, 6 October 15
  23. 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. 24. • Functions / Morphisms • Types / Sets • Composition • Rules / Laws Tuesday, 6 October 15
  25. 25. • Functions / Morphisms • Types / Sets • Composition • Rules / Laws algebra Tuesday, 6 October 15
  26. 26. Domain Model Algebra Tuesday, 6 October 15
  27. 27. Domain Model Algebra (algebra of types, functions & laws) Tuesday, 6 October 15
  28. 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. 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
  30. 30. close debit open ... Domain Behaviors Tuesday, 6 October 15
  31. 31. Amount Account Balance Customer ... ... ... close debit open ... Domain Behaviors Domain Types Tuesday, 6 October 15
  32. 32. Amount Account Balance Customer ... ... ... close debit open ... market regulations tax laws brokerage commission rates ... Domain Behaviors Domain TypesDomain Rules Tuesday, 6 October 15
  33. 33. 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
  34. 34. 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
  35. 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. 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. 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. 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. 39. • Algebras don’t unify across bounded contexts • Decoupled in space and time • Separate vocabulary • Types break down Tuesday, 6 October 15
  40. 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. 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. 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. 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. 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. 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. 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. 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. 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. 49. • Parametric - parameterized on types • Statically Typed • Modular and hence unit testable • Composable Tuesday, 6 October 15
  50. 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. 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. 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. 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. 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. 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. 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
  57. 57. Blocking Kills Tuesday, 6 October 15
  58. 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. 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. 60. • Without foregoing the benefits of algebraic reasoning with types Being Reactive Tuesday, 6 October 15
  61. 61. Enter Futures .. Tuesday, 6 October 15
  62. 62. Enter Futures .. • A future is the essence of asynchronous non blocking computation Tuesday, 6 October 15
  63. 63. Enter Futures .. • A future is the essence of asynchronous non blocking computation • Futures compose Tuesday, 6 October 15
  64. 64. Enter Futures .. • A future is the essence of asynchronous non blocking computation • Futures compose • Futures have an algebra Tuesday, 6 October 15
  65. 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. 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
  67. 67. Stacking of Effects Tuesday, 6 October 15
  68. 68. Stacking of Effects Tuesday, 6 October 15
  69. 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. 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. 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. 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. 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. 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
  75. 75. Tuesday, 6 October 15
  76. 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. 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. 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. 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. 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. 81. for { _ <- open(..) _ <- credit(..) d <- debit(..) } yield d Reactive & algebraic patterns in domain modeling Tuesday, 6 October 15
  82. 82. for { _ <- open(..) _ <- credit(..) d <- debit(..) } yield d Reactive & algebraic patterns in domain modeling • Compositional by types Tuesday, 6 October 15
  83. 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. 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. 85. Reactive & algebraic patterns in domain modeling Tuesday, 6 October 15
  86. 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. 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. 88. Be Algebraic, as long as you can .. Tuesday, 6 October 15
  89. 89. Beyond Algebra - Reactive Protocols Tuesday, 6 October 15
  90. 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. 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
  92. 92. Asynchronous Messaging Tuesday, 6 October 15
  93. 93. Asynchronous Messaging Tuesday, 6 October 15
  94. 94. Asynchronous Messaging Tuesday, 6 October 15
  95. 95. Asynchronous Messaging Tuesday, 6 October 15
  96. 96. Actors and Domain Models Tuesday, 6 October 15
  97. 97. Actors and Domain Models Powerful Tuesday, 6 October 15
  98. 98. Actors and Domain Models Powerful Un-algebraically Powerful Tuesday, 6 October 15
  99. 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. 100. Using actors indiscriminately throughout your domain model makes algebraic reasoning hard Tuesday, 6 October 15
  101. 101. fork: A => Future[A] map: (A => B) => (Future[A] => Future[B]) join: Future[Future[A]] => Future[A] Tuesday, 6 October 15
  102. 102. receive: Any => Unit Tuesday, 6 October 15
  103. 103. Use the least powerful abstraction that does the job Tuesday, 6 October 15
  104. 104. For domain model resilience, choose futures over actors when you can .. Tuesday, 6 October 15
  105. 105. • As an implementation artifact to protect shared mutable state • Centralized failure management Actors and Domain Models Tuesday, 6 October 15
  106. 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. 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. 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. 109. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message Tuesday, 6 October 15
  110. 110. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level Tuesday, 6 October 15
  111. 111. Modeling Domain Workflows Actor Actor Actor Actor Actor Actormessage message message message message message message low level untyped Tuesday, 6 October 15
  112. 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. 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. 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. 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. 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. 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. 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. 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. 120. Business Use Case - The Domain Model Tuesday, 6 October 15
  121. 121. Implementation topology with Akka Streams Tuesday, 6 October 15
  122. 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
  123. 123. graph.run() Tuesday, 6 October 15
  124. 124. https://www.manning.com/books/functional-and-reactive- domain-modeling Tuesday, 6 October 15
  125. 125. ThankYou! Tuesday, 6 October 15
  126. 126. Tuesday, 6 October 15
  • rualatngua

    Aug. 26, 2019
  • VladislavGangan

    Mar. 7, 2018
  • ksmin23

    Nov. 8, 2017
  • AngelOrtega56

    Aug. 2, 2017
  • VyacheslavFrolov

    Jun. 28, 2017
  • rfred999

    Dec. 4, 2016
  • JordiCosta3

    Oct. 2, 2016
  • greenflute

    Sep. 18, 2016
  • narendransolaisridharan

    Mar. 27, 2016
  • YangXiao7

    Feb. 9, 2016
  • SteveMyers13

    Nov. 19, 2015
  • budibudifr

    Nov. 5, 2015
  • NirmalyaSengupta

    Oct. 26, 2015
  • SamDeBacker

    Oct. 20, 2015
  • santoshgokak

    Oct. 15, 2015
  • SangKyuPark1

    Oct. 14, 2015
  • SergeyTolmachev

    Oct. 11, 2015
  • MariusBjrnstadKotsba

    Oct. 11, 2015
  • ssusere40dc2

    Oct. 9, 2015
  • VadimBondarev

    Oct. 9, 2015

From functional to Reactive - patterns in domain modeling

Views

Total views

5,478

On Slideshare

0

From embeds

0

Number of embeds

248

Actions

Downloads

160

Shares

0

Comments

0

Likes

36

×