Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

From functional to Reactive - patterns in domain modeling

4.983 visualizaciones

Publicado el

From functional to Reactive - patterns in domain modeling

Publicado en: Software

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

×