SlideShare ist ein Scribd-Unternehmen logo
1 von 57
Downloaden Sie, um offline zu lesen
Functional & Event
                             Driven
                        another approach to domain modeling




Thursday 12 April 12
Debasish Ghosh

                             @debasishg on Twitter

                                            code @
                         http://github.com/debasishg

                                              blog @
                       Ruminations of a Programmer
                       http://debasishg.blogspot.com




Thursday 12 April 12
Agenda
                       • Domain Models
                       • Why Functional Domain Models
                       • Event based architectures - Event Sourcing
                       • Duality between functional models & even
                         based models
                       • A sample event sourced domain model
                         implementation


Thursday 12 April 12
Domain Modeling
                       • We limit ourselves strictly to how the
                         domain behaves internally and how it
                         responds to events that it receives from
                         the external context
                       • We think of a domain model as being
                         comprised of the core granular
                         abstractions that handle the business logic
                         and a set of coarser level services that
                         interacts with the external world

Thursday 12 April 12
Why Functional ?

                       • Pure with localization of side-effects
                       • Ability to reason about your model
                       • Expressive & Declarative
                       • Immutable

Thursday 12 April 12
A Functional Domain
                               Model
                       • Built on (mostly) pure abstractions
                       • Pure functions to model domain behaviors
                       • Immutable artifacts
                       • .. and you get some parallelism for free

Thursday 12 April 12
Immutability

                       • Algebraic Data Types for representation of
                         domain entities
                       • Immutable structures like type-lenses for
                         functional updates
                       • No in-place mutation

Thursday 12 April 12
Representation as
                            ADTs
     case class Trade(account: Account, instrument: Instrument,
       refNo: String, market: Market,
       unitPrice: BigDecimal, quantity: BigDecimal,
       tradeDate: Date = Calendar.getInstance.getTime,
       valueDate: Option[Date] = None,
       taxFees: Option[List[(TaxFeeId, BigDecimal)]] = None,
       netAmount: Option[BigDecimal] = None) {

          override def equals(that: Any) =
            refNo == that.asInstanceOf[Trade].refNo
          override def hashCode = refNo.hashCode

     }




Thursday 12 April 12
Representation as
                            ADTs
         // various tax/fees to be paid when u do a trade
         sealed trait TaxFeeId extends Serializable
         case object TradeTax extends TaxFeeId
         case object Commission extends TaxFeeId
         case object VAT extends TaxFeeId




Thursday 12 April 12
Pure functions as
                       domain behaviors
    // get the list of tax/fees applicable for this trade
    // depends on the market
    val forTrade: Trade => Option[List[TaxFeeId]] = {trade =>
      taxFeeForMarket.get(trade.market) <+> taxFeeForMarket.get(Other)
    }




Thursday 12 April 12
Pure functions as
                          domain behaviors
               // enrich a trade with tax/fees and compute net value
               val enrichTrade: Trade => Trade = {trade =>
                 val taxes = for {
                   taxFeeIds       <- forTrade // get the tax/fee ids for a trade
                   taxFeeValues    <- taxFeeCalculate // calculate tax fee values
                 }
                 yield(taxFeeIds map taxFeeValues)
                 val t = taxFeeLens.set(trade, taxes(trade))
                 netAmountLens.set(t,
                   t.taxFees.map(_.foldl(principal(t))((a, b) => a + b._2)))
               }




Thursday 12 April 12
Pure functions as
                       domain behaviors
   // combinator to value a tax/fee for a specific trade
   val valueAs:
     Trade => TaxFeeId => BigDecimal = {trade => tid =>
     ((rates get tid) map (_ * principal(trade)))
        getOrElse (BigDecimal(0))
   }

   // all tax/fees for a specific trade
   val taxFeeCalculate:
     Trade => List[TaxFeeId] => List[(TaxFeeId, BigDecimal)] = {t =>
   tids =>
     tids zip (tids map valueAs(t))
   }




Thursday 12 April 12
Composability

                       Secret sauce ? Functions compose. We can
                       pass functions as first class citizens in the
                       paradigm of functional programming. We can
                       use them as return values and if we can
                       make them pure we can treat them just as
                       mathematically as you would like to.



Thursday 12 April 12
Updating a Domain
                        Structure functionally
                       • A Type-Lens is a data structure that sets up
                         a bidirectional transformation between a
                         set of source structures S and target
                         structures T
                       • A Type-Lens is set up as a pair of functions:
                         •   get S -> T
                         •   putBack (S X T) -> S


Thursday 12 April 12
A Type Lens in Scala
               // change ref no
               val refNoLens: Lens[Trade, String] =
                 Lens((t: Trade) => t.refNo,
                         (t: Trade, r: String) => t.copy(refNo = r))



               a function that takes a
         trade and returns it’s reference no        a function that updates a
                                               trade with a supplied reference no




Thursday 12 April 12
Lens under Composition
                       • What’s the big deal with a Type Lens ?
                        ✦   Lens compose and hence gives you a cool
                            syntax to update nested structures within
                            an ADT

                   def addressL: Lens[Person, Address] = ...
                   def streetL: Lens[Address, String] = ...
                   val personStreetL: Lens[Person, String] =
                     streetL compose addressL




Thursday 12 April 12
Lens under
                         composition
     Using the personStreetL lens we may access or
     set the (indirect) street property of a Person instance

                       val str: String =
                         personStreetL get person

                       val newP: Person =
                         personStreetL set (person, "Bob_St")




Thursday 12 April 12
Functional updates using type
                                   lens
             // change ref no
             val refNoLens: Lens[Trade, String] =
               Lens((t: Trade) => t.refNo,
                    (t: Trade, r: String) => t.copy(refNo = r))

             // add tax/fees
             val taxFeeLens: Lens[Trade, Option[List[(TaxFeeId, BigDecimal)]]] =
               Lens((t: Trade) => t.taxFees,
                    (t: Trade, tfs: Option[List[(TaxFeeId, BigDecimal)]]) =>
             t.copy(taxFees = tfs))

             // add net amount
             val netAmountLens: Lens[Trade, Option[BigDecimal]] =
               Lens((t: Trade) => t.netAmount,
                    (t: Trade, n: Option[BigDecimal]) => t.copy(netAmount = n))

             // add value date
             val valueDateLens: Lens[Trade, Option[Date]] =
               Lens((t: Trade) => t.valueDate,
                    (t: Trade, d: Option[Date]) => t.copy(valueDate = d))




Thursday 12 April 12
Managing States

                       • But domain objects don’t exist in isolation
                       • Need to interact with other objects
                       • .. and respond to events from the external
                         world
                       • .. changing from one state to another

Thursday 12 April 12
A day in the life of a
                             Trade object
                                                    tax/fee added

                       created   value date added                   net value computed   ssi added




     a Trade object
                                                                               ready for settlement



Thursday 12 April 12
What’s the big deal ?
       All these sound like changing states of a newly created
                           Trade object !!




Thursday 12 April 12
• but ..
                       • Changing state through in-place mutation is
                         destructive

                       • We lose temporality of the data structure
                       • The fact that a Trade is enriched with tax/
                         fee NOW does not mean it was not valued
                         at 0 tax SOME TIME BACK


Thursday 12 April 12
What if we would like to have our
                       system rolled back to THAT POINT IN
                                       TIME ?




Thursday 12 April 12
We are just being lossy

Thursday 12 April 12
• The solution is to keep information in such a
                       way that we have EVERY BIT OF DETAILS
                       stored as the object changes from one state
                       to another

                 • Enter Event Sourcing
Thursday 12 April 12
Event Sourcing
                       • Preserves the temporality of the data
                         structure
                       • Represent state NOT as a mutable object,
                         rather as a sequence of domain events that
                         took place right from the creation till the
                         current point in time
                       • Decouple the state of the object from its
                         identity. The state changes over time,
                         identity is IMMUTABLE

Thursday 12 April 12
Domain Events as
                           Behaviors
             NewTrade            AddValueDate               EnrichTrade



             state = Created     state = ValueDateAdded         state = Enriched



   persisted with timestamp t0                                  persisted with timestamp t2

                                  persisted with timestamp t1



                                    (t2 > t1 > t0)
Thursday 12 April 12
.. and since we store every event that hits the system we
       have the ability to recreate ANY previous state of the
        system starting from ANY point in time in the past




Thursday 12 April 12
Events and States
                       sealed trait TradingEvent extends Event

                       case   object   NewTrade extends TradingEvent
                       case   object   EnrichTrade extends TradingEvent
                       case   object   AddValueDate extends TradingEvent
                       case   object   SendOutContractNote extends TradingEvent

                       sealed trait TradeState extends State

                       case object Created extends TradeState
                       case object Enriched extends TradeState
                       case object ValueDateAdded extends TradeState




Thursday 12 April 12
The Current State
                       • How do you reflect the current state of the
                         domain object ?
                        ✦   start with the initial state
                        ✦   manage all state transitions
                        ✦   persist all state transitions
                        ✦   maintain a snapshot that reflects the
                            current state
                        ✦   you now have the ability to roll back to
                            any earlier state
Thursday 12 April 12
The essence of Event
                             Sourcing
                       Store the events in a durable repository.They are
                       the lowest level granular structure that model
                       the actual behavior of the domain.You can
                       always recreate any state if you store events
                       since the creation of the domain object.




Thursday 12 April 12
The Duality
                       •   Event Sourcing keeps a     •   In functional
                           trail of all events that       programming, data
                           the abstraction has            structures that keep
                           handled                        track of their history are
                                                          called persistent data
                       •   Event Sourcing does not        structures. Immutability
                                                          taken to the next level
                           ever mutate an existing
                           record
                                                      •   An immutable data
                                                          structure does not
                                                          mutate data - returns a
                                                          newer version every
                                                          time you update it


Thursday 12 April 12
Event Sourced Domain
                              Models
                       • Now we have the domain objects receiving
                         domain events which take them from state
                         A to state B
                       • Will the Trade object have all the event
                         handling logic ?
                       • What about state changes ? Use the Trade
                         object for this as well ?


Thursday 12 April 12
Separation of concerns

                       • The Trade object has the core business of
                         the trading logic. It manifests all state
                         changes in terms of what it contains as data
                       • But event handling and managing state
                         transitions is something that belongs to the
                         service layer of the domain model



Thursday 12 April 12
Separation of Concerns
                       •   The service layer          •   The core domain layer

                           ✦   receives events from       ✦   implements core
                               the context                    trading functions like
                                                              calculation of value
                           ✦   manages state                  date, trade valuation,
                               transitions                    tax/fee handling etc

                           ✦   delegates to Trade         ✦   completely oblivious
                               object for core                of the context
                               business

                           ✦   notifies other
                               subscribers
Thursday 12 April 12
The Domain Service
                              Layer
                       • Handles domain events and delegates to
                         someone who logs (sources) the events
                       • May need to maintain an in-memory
                         snapshot of the domain object’s current
                         state
                       • Delegates persistence of the snapshot to
                         other subscribers like Query Services


Thursday 12 April 12
CQRS
                       • The service layer ensures a complete
                         decoupling of how it handles updates
                         (commands) on domain objects and reads
                         (queries) on the recent snapshot
                       • Updates are persisted as events while
                         queries are served from entirely different
                         sources, typically from read slaves in an
                         RDBMS


Thursday 12 April 12
In other words, the domain
                       service layer acts as a state
                                 machine
Thursday 12 April 12
Making it Explicit
                       • Model the domain service layer as an FSM
                         (Finite State Machine) - call it the
                         TradeLifecycle, which is totally
                         segregated from the Trade domain object

                       • .. and let the FSM run within an actor
                         model based on asynchronous messaging
                       • We use Akka’s FSM implementation
Thursday 12 April 12
FSM in Akka
                       • Actor based
                        ✦   available as a mixin for the Akka actor
                        ✦   similar to Erlang gen_fsm
                            implementation
                        ✦   as a client you need to implement the
                            state transition rules using a declarative
                            syntax based DSL, all heavy lifting done by
                            Akka actors
Thursday 12 April 12
initial state

                                                match on event
                                                AddValueDate

          startWith(Created, trade)
                                                                 start state of Trade
                                                                        object
          when(Created) {
            case Event(e@AddValueDate, data) =>
              log.map(_.appendAsync(data.refNo, Created, Some(data), e))
              val trd = addValueDate(data)
              gossip(trd)
              goto(ValueDateAdded) using trd forMax(timeout)
          }

       notify observers                                                        log the event
                          move to next state
                                                update data
                           of Trade lifecycle
                                                 structure




Thursday 12 April 12
Handle events &
                                               process data updates and state
                                                          changes



          startWith(Created, trade)                            Log events (event sourcing)

          when(Created) {
            case Event(e@AddValueDate, data) =>
              log.map(_.appendAsync(data.refNo, Created, Some(data), e))
              val trd = addValueDate(data)
              gossip(trd)
              goto(ValueDateAdded) using trd forMax(timeout)
          }


                               Notifying Listeners




Thursday 12 April 12
State change -
                              functionally
                  // closure for adding a value date
                  val addValueDate: Trade => Trade = {trade =>
                    valueDateLens.set(trade, ..)
                  }




          pure referentially transparent implementation


Thursday 12 April 12
Notifying Listeners

        • A typical use case is to send
        updates to the Query
        subscribers as in CQRS


        • The query is rendered from a
        separate store which needs to
        be updated with all changes that
        go on in the domain model




Thursday 12 April 12
Notifications in Akka
                              FSM
               trait FSM[S, D] extends Listeners {
                 //..
               }

                             Listeners is a generic trait to implement
                                  listening capability on an Actor

                                      trait Listeners {self: Actor =>
                                        protected val listeners = ..
                                        //..
                                        protected def gossip(msg: Any) =
                                          listeners foreach (_ ! msg)
                                        //..
                                      }


Thursday 12 April 12
Event Logging

                       • Log asynchronously
                       • Persist the current state along with the
                         data at this state
                       • Log the event e
                                        log.map(_.appendAsync(data.refNo,
                                                              Created,
                                                              Some(data), e))

Thursday 12 April 12
Event Logging
            case class EventLogEntry(entryId: Long,
              objectId: String,
              inState: State,
              withData: Option[Any], event: Event)



            trait EventLog extends Iterable[EventLogEntry] {
              def iterator: Iterator[EventLogEntry]
              def iterator(fromEntryId: Long): Iterator[EventLogEntry]
              def appendAsync(id: String, state: State,
                data: Option[Any], event: Event): Future[EventLogEntry]
            }




Thursday 12 April 12
Log Anywhere
Thursday 12 April 12
Order preserving
                           logging
 class RedisEventLog(clients: RedisClientPool, as: ActorSystem)
   extends EventLog {
   val loggerActorName = "redis-event-logger"

   // need a pinned dispatcher to maintain order of log entries
   lazy val logger =
     as.actorOf(Props(new Logger(clients)).withDispatcher("my-pinned-dispatcher"),
     name = loggerActorName)
                                            akka {
   //..                                       actor {
 }                                              timeout = 20
                                                my-pinned-dispatcher {
                                                   executor = "thread-pool-executor"
                                                   type = PinnedDispatcher
                                                }
                                              }
                                            }
Thursday 12 April 12
case class LogEvent(objectId: String, state: State,
   data: Option[Any], event: Event)

 class Logger(clients: RedisClientPool) extends Actor {
   implicit val format =
     Format {case l: EventLogEntry => serializeEventLogEntry(l)}
   implicit val parseList =
     Parse[EventLogEntry](deSerializeEventLogEntry(_))

   def receive = {
     case LogEvent(id, state, data, event) =>
        val entry = EventLogEntry(RedisEventLog.nextId(), id, state,
 data, event)
        clients.withClient {client =>
          client.lpush(RedisEventLog.logName, entry)
        }
        sender ! entry
     //..
   }
   //..                                      logger is an actor that
                                                  pushes event
 }
                                                 data into Redis

Thursday 12 April 12
def appendAsync(id: String, state: State,
    data: Option[Any], event: Event): Future[EventLogEntry] =

            (logger ? LogEvent(id, state, data, event))
              .asInstanceOf[Future[EventLogEntry]]




                                                  Non-blocking : returns
                                                        a Future


Thursday 12 April 12
class TradeLifecycle(trade: Trade, timeout: Duration,
          log: Option[EventLog])
          extends Actor with FSM[TradeState, Trade] {
          import FSM._

            startWith(Created, trade)
                                                                                   domain service as
                                                                                 a Finite State Machine
            when(Created) {
              case Event(e@AddValueDate, data) =>
                log.map(_.appendAsync(data.refNo, Created, Some(data), e))   •         declarative
                val trd = addValueDate(data)                                 •        actor based
                gossip(trd)                                                  •       asynchronous
                goto(ValueDateAdded) using trd forMax(timeout)               •       event sourced
            }

            when(ValueDateAdded) {
              case Event(StateTimeout, _) =>
                stay

               case Event(e@EnrichTrade, data) =>
                 log.map(_.appendAsync(data.refNo, ValueDateAdded, None,   e))
                 val trd = enrichTrade(data)
                 gossip(trd)
                 goto(Enriched) using trd forMax(timeout)
            }
            //..
        }

Thursday 12 April 12
// 1. create the state machine
               val tlc =
                 system.actorOf(Props(
                   new TradeLifecycle(trd, timeout.duration, Some(log))))

               // 2. register listeners
               tlc ! SubscribeTransitionCallBack(qry)

               // 3. fire events
               tlc ! AddValueDate
               tlc ! EnrichTrade
               val future = tlc ? SendOutContractNote

               // 4. wait for result
               finalTrades += Await.result(future, timeout.duration)
                              .asInstanceOf[Trade]




Thursday 12 April 12
// check query store
                 val f = qry ? QueryAllTrades
                 val qtrades = Await.result(f,timeout.duration)
                                    .asInstanceOf[List[Trade]]

                 // query store in sync with the in-memory snapshot
                 qtrades should equal(finalTrades)




Thursday 12 April 12
Summary
                       • Event sourcing is an emerging trend in
                         architecting large systems
                       • Focuses on immutability and hence plays
                         along well with functional programming
                         principles
                       • Event stores are append only - hence n
                         locks, no synchronization - very fast at the
                         event storage layer


Thursday 12 April 12
Summary
                       • Complicated in-memory snapshot may have
                         some performance overhead, but can be
                         managed with a good STM implementation
                       • In designing your domain model based on
                         event sourcing, make your core model
                         abstractions meaty enough while leaving the
                         service layer with the responsibilities of
                         managing event handling and state
                         transitions

Thursday 12 April 12
Thank You!



Thursday 12 April 12

Weitere ähnliche Inhalte

Was ist angesagt?

ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022Alexander Ioffe
 
Designing with Capabilities
Designing with CapabilitiesDesigning with Capabilities
Designing with CapabilitiesScott Wlaschin
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Philip Schwarz
 
Unit I Advanced Java Programming Course
Unit I   Advanced Java Programming CourseUnit I   Advanced Java Programming Course
Unit I Advanced Java Programming Courseparveen837153
 
Understanding Implicits in Scala
Understanding Implicits in ScalaUnderstanding Implicits in Scala
Understanding Implicits in Scaladatamantra
 
SEH overwrite and its exploitability
SEH overwrite and its exploitabilitySEH overwrite and its exploitability
SEH overwrite and its exploitabilityFFRI, Inc.
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Scott Wlaschin
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Philip Schwarz
 
C++ Memory Management
C++ Memory ManagementC++ Memory Management
C++ Memory ManagementRahul Jamwal
 
Gentle Introduction to Scala
Gentle Introduction to ScalaGentle Introduction to Scala
Gentle Introduction to ScalaFangda Wang
 
Java I/O and Object Serialization
Java I/O and Object SerializationJava I/O and Object Serialization
Java I/O and Object SerializationNavneet Prakash
 
The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsScott Wlaschin
 

Was ist angesagt? (20)

ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022
 
Designing with Capabilities
Designing with CapabilitiesDesigning with Capabilities
Designing with Capabilities
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
 
Unit I Advanced Java Programming Course
Unit I   Advanced Java Programming CourseUnit I   Advanced Java Programming Course
Unit I Advanced Java Programming Course
 
Validation controls ASP .NET
Validation controls ASP .NETValidation controls ASP .NET
Validation controls ASP .NET
 
Cookie and session
Cookie and sessionCookie and session
Cookie and session
 
ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
Understanding Implicits in Scala
Understanding Implicits in ScalaUnderstanding Implicits in Scala
Understanding Implicits in Scala
 
Android Services
Android ServicesAndroid Services
Android Services
 
SEH overwrite and its exploitability
SEH overwrite and its exploitabilitySEH overwrite and its exploitability
SEH overwrite and its exploitability
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
 
Haskell
HaskellHaskell
Haskell
 
C++ Memory Management
C++ Memory ManagementC++ Memory Management
C++ Memory Management
 
Gentle Introduction to Scala
Gentle Introduction to ScalaGentle Introduction to Scala
Gentle Introduction to Scala
 
Java I/O and Object Serialization
Java I/O and Object SerializationJava I/O and Object Serialization
Java I/O and Object Serialization
 
Functions in python
Functions in python Functions in python
Functions in python
 
The lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of testsThe lazy programmer's guide to writing thousands of tests
The lazy programmer's guide to writing thousands of tests
 
Chapter 1
Chapter 1Chapter 1
Chapter 1
 
Scala functions
Scala functionsScala functions
Scala functions
 

Andere mochten auch

Decoupling with Domain Events
Decoupling with Domain EventsDecoupling with Domain Events
Decoupling with Domain EventsSteven Smith
 
Building occasionally connected applications using event sourcing
Building occasionally connected applications using event sourcingBuilding occasionally connected applications using event sourcing
Building occasionally connected applications using event sourcingDennis Doomen
 
Functional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenFunctional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenPawel Szulc
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven DesignRyan Riley
 
Domain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCDomain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCSteven Smith
 
CQRS and Event Sourcing, An Alternative Architecture for DDD
CQRS and Event Sourcing, An Alternative Architecture for DDDCQRS and Event Sourcing, An Alternative Architecture for DDD
CQRS and Event Sourcing, An Alternative Architecture for DDDDennis Doomen
 
A Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation SlidesA Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation Slidesthinkddd
 
System Analysis and Design
System Analysis and DesignSystem Analysis and Design
System Analysis and DesignAamir Abbas
 

Andere mochten auch (11)

Decoupling with Domain Events
Decoupling with Domain EventsDecoupling with Domain Events
Decoupling with Domain Events
 
Domain Event - The Hidden Gem of DDD
Domain Event - The Hidden Gem of DDDDomain Event - The Hidden Gem of DDD
Domain Event - The Hidden Gem of DDD
 
D programming language
D programming languageD programming language
D programming language
 
Building occasionally connected applications using event sourcing
Building occasionally connected applications using event sourcingBuilding occasionally connected applications using event sourcing
Building occasionally connected applications using event sourcing
 
CQRS is not Event Sourcing
CQRS is not Event SourcingCQRS is not Event Sourcing
CQRS is not Event Sourcing
 
Functional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heavenFunctional Programming & Event Sourcing - a pair made in heaven
Functional Programming & Event Sourcing - a pair made in heaven
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Domain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCDomain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVC
 
CQRS and Event Sourcing, An Alternative Architecture for DDD
CQRS and Event Sourcing, An Alternative Architecture for DDDCQRS and Event Sourcing, An Alternative Architecture for DDD
CQRS and Event Sourcing, An Alternative Architecture for DDD
 
A Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation SlidesA Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation Slides
 
System Analysis and Design
System Analysis and DesignSystem Analysis and Design
System Analysis and Design
 

Ähnlich wie Functional and Event Driven - another approach to domain modeling

Functional Patterns in Domain Modeling
Functional Patterns in Domain ModelingFunctional Patterns in Domain Modeling
Functional Patterns in Domain ModelingDebasish Ghosh
 
Architectural Patterns in Building Modular Domain Models
Architectural Patterns in Building Modular Domain ModelsArchitectural Patterns in Building Modular Domain Models
Architectural Patterns in Building Modular Domain ModelsDebasish Ghosh
 
DSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDebasish Ghosh
 
Database Management System
Database Management SystemDatabase Management System
Database Management SystemAbishek V S
 
Python business intelligence (PyData 2012 talk)
Python business intelligence (PyData 2012 talk)Python business intelligence (PyData 2012 talk)
Python business intelligence (PyData 2012 talk)Stefan Urbanek
 
Baby steps to Domain-Driven Design
Baby steps to Domain-Driven DesignBaby steps to Domain-Driven Design
Baby steps to Domain-Driven DesignŽilvinas Kuusas
 
Modelling a complex domain with Domain-Driven Design
Modelling a complex domain with Domain-Driven DesignModelling a complex domain with Domain-Driven Design
Modelling a complex domain with Domain-Driven DesignNaeem Sarfraz
 
Everything you ever wanted to know about lotus script
Everything you ever wanted to know about lotus scriptEverything you ever wanted to know about lotus script
Everything you ever wanted to know about lotus scriptBill Buchan
 
Datastage free tutorial
Datastage free tutorialDatastage free tutorial
Datastage free tutorialtekslate1
 
SPCA2013 - SharePoint Nightmares - Coding Patterns and Practices
SPCA2013 - SharePoint Nightmares - Coding Patterns and PracticesSPCA2013 - SharePoint Nightmares - Coding Patterns and Practices
SPCA2013 - SharePoint Nightmares - Coding Patterns and PracticesNCCOMMS
 
Object Oriented Views / Aki Salmi
Object Oriented Views / Aki SalmiObject Oriented Views / Aki Salmi
Object Oriented Views / Aki SalmiAki Salmi
 
Eclipse Sirius Applied to a RAD Tool in Japan
Eclipse Sirius Applied to a RAD Tool in JapanEclipse Sirius Applied to a RAD Tool in Japan
Eclipse Sirius Applied to a RAD Tool in JapanAkira Tanaka
 
[SiriusCon 2018] Eclipse Sirius applied to a RAD Tool in Japan
[SiriusCon 2018] Eclipse Sirius applied to a RAD Tool in Japan[SiriusCon 2018] Eclipse Sirius applied to a RAD Tool in Japan
[SiriusCon 2018] Eclipse Sirius applied to a RAD Tool in JapanObeo
 
Boston Spark Meetup event Slides Update
Boston Spark Meetup event Slides UpdateBoston Spark Meetup event Slides Update
Boston Spark Meetup event Slides Updatevithakur
 
Engineering Student MuleSoft Meetup#6 - Basic Understanding of DataWeave With...
Engineering Student MuleSoft Meetup#6 - Basic Understanding of DataWeave With...Engineering Student MuleSoft Meetup#6 - Basic Understanding of DataWeave With...
Engineering Student MuleSoft Meetup#6 - Basic Understanding of DataWeave With...Jitendra Bafna
 
Generating Executable Mappings from RDF Data Cube Data Structure Definitions
Generating Executable Mappings from RDF Data Cube Data Structure DefinitionsGenerating Executable Mappings from RDF Data Cube Data Structure Definitions
Generating Executable Mappings from RDF Data Cube Data Structure DefinitionsChristophe Debruyne
 
Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPA
Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPAIntegrate Spring MVC with RequireJS & Backbone.js & Spring Data JPA
Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPACheng Ta Yeh
 

Ähnlich wie Functional and Event Driven - another approach to domain modeling (20)

Functional Patterns in Domain Modeling
Functional Patterns in Domain ModelingFunctional Patterns in Domain Modeling
Functional Patterns in Domain Modeling
 
Architectural Patterns in Building Modular Domain Models
Architectural Patterns in Building Modular Domain ModelsArchitectural Patterns in Building Modular Domain Models
Architectural Patterns in Building Modular Domain Models
 
DSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic model
 
Database Management System
Database Management SystemDatabase Management System
Database Management System
 
Python business intelligence (PyData 2012 talk)
Python business intelligence (PyData 2012 talk)Python business intelligence (PyData 2012 talk)
Python business intelligence (PyData 2012 talk)
 
Baby steps to Domain-Driven Design
Baby steps to Domain-Driven DesignBaby steps to Domain-Driven Design
Baby steps to Domain-Driven Design
 
Modelling a complex domain with Domain-Driven Design
Modelling a complex domain with Domain-Driven DesignModelling a complex domain with Domain-Driven Design
Modelling a complex domain with Domain-Driven Design
 
Everything you ever wanted to know about lotus script
Everything you ever wanted to know about lotus scriptEverything you ever wanted to know about lotus script
Everything you ever wanted to know about lotus script
 
Lecture7
Lecture7Lecture7
Lecture7
 
Datastage free tutorial
Datastage free tutorialDatastage free tutorial
Datastage free tutorial
 
Ruby on rails
Ruby on railsRuby on rails
Ruby on rails
 
SPCA2013 - SharePoint Nightmares - Coding Patterns and Practices
SPCA2013 - SharePoint Nightmares - Coding Patterns and PracticesSPCA2013 - SharePoint Nightmares - Coding Patterns and Practices
SPCA2013 - SharePoint Nightmares - Coding Patterns and Practices
 
Object Oriented Views / Aki Salmi
Object Oriented Views / Aki SalmiObject Oriented Views / Aki Salmi
Object Oriented Views / Aki Salmi
 
Eclipse Sirius Applied to a RAD Tool in Japan
Eclipse Sirius Applied to a RAD Tool in JapanEclipse Sirius Applied to a RAD Tool in Japan
Eclipse Sirius Applied to a RAD Tool in Japan
 
[SiriusCon 2018] Eclipse Sirius applied to a RAD Tool in Japan
[SiriusCon 2018] Eclipse Sirius applied to a RAD Tool in Japan[SiriusCon 2018] Eclipse Sirius applied to a RAD Tool in Japan
[SiriusCon 2018] Eclipse Sirius applied to a RAD Tool in Japan
 
Boston Spark Meetup event Slides Update
Boston Spark Meetup event Slides UpdateBoston Spark Meetup event Slides Update
Boston Spark Meetup event Slides Update
 
Engineering Student MuleSoft Meetup#6 - Basic Understanding of DataWeave With...
Engineering Student MuleSoft Meetup#6 - Basic Understanding of DataWeave With...Engineering Student MuleSoft Meetup#6 - Basic Understanding of DataWeave With...
Engineering Student MuleSoft Meetup#6 - Basic Understanding of DataWeave With...
 
Generating Executable Mappings from RDF Data Cube Data Structure Definitions
Generating Executable Mappings from RDF Data Cube Data Structure DefinitionsGenerating Executable Mappings from RDF Data Cube Data Structure Definitions
Generating Executable Mappings from RDF Data Cube Data Structure Definitions
 
Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPA
Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPAIntegrate Spring MVC with RequireJS & Backbone.js & Spring Data JPA
Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPA
 
Angular Schematics
Angular SchematicsAngular Schematics
Angular Schematics
 

Mehr von Debasish Ghosh

Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsAlgebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsDebasish Ghosh
 
Power of functions in a typed world
Power of functions in a typed worldPower of functions in a typed world
Power of functions in a typed worldDebasish Ghosh
 
Approximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming ApplicationsApproximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming ApplicationsDebasish Ghosh
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingDebasish Ghosh
 
Mining Functional Patterns
Mining Functional PatternsMining Functional Patterns
Mining Functional PatternsDebasish Ghosh
 
An Algebraic Approach to Functional Domain Modeling
An Algebraic Approach to Functional Domain ModelingAn Algebraic Approach to Functional Domain Modeling
An Algebraic Approach to Functional Domain ModelingDebasish Ghosh
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingDebasish Ghosh
 
From functional to Reactive - patterns in domain modeling
From functional to Reactive - patterns in domain modelingFrom functional to Reactive - patterns in domain modeling
From functional to Reactive - patterns in domain modelingDebasish Ghosh
 
Domain Modeling with Functions - an algebraic approach
Domain Modeling with Functions - an algebraic approachDomain Modeling with Functions - an algebraic approach
Domain Modeling with Functions - an algebraic approachDebasish Ghosh
 
Property based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rulesProperty based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rulesDebasish Ghosh
 
Big Data - architectural concerns for the new age
Big Data - architectural concerns for the new ageBig Data - architectural concerns for the new age
Big Data - architectural concerns for the new ageDebasish Ghosh
 
Dependency Injection in Scala - Beyond the Cake Pattern
Dependency Injection in Scala - Beyond the Cake PatternDependency Injection in Scala - Beyond the Cake Pattern
Dependency Injection in Scala - Beyond the Cake PatternDebasish Ghosh
 

Mehr von Debasish Ghosh (12)

Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsAlgebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain Models
 
Power of functions in a typed world
Power of functions in a typed worldPower of functions in a typed world
Power of functions in a typed world
 
Approximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming ApplicationsApproximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming Applications
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
 
Mining Functional Patterns
Mining Functional PatternsMining Functional Patterns
Mining Functional Patterns
 
An Algebraic Approach to Functional Domain Modeling
An Algebraic Approach to Functional Domain ModelingAn Algebraic Approach to Functional Domain Modeling
An Algebraic Approach to Functional Domain Modeling
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
 
From functional to Reactive - patterns in domain modeling
From functional to Reactive - patterns in domain modelingFrom functional to Reactive - patterns in domain modeling
From functional to Reactive - patterns in domain modeling
 
Domain Modeling with Functions - an algebraic approach
Domain Modeling with Functions - an algebraic approachDomain Modeling with Functions - an algebraic approach
Domain Modeling with Functions - an algebraic approach
 
Property based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rulesProperty based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rules
 
Big Data - architectural concerns for the new age
Big Data - architectural concerns for the new ageBig Data - architectural concerns for the new age
Big Data - architectural concerns for the new age
 
Dependency Injection in Scala - Beyond the Cake Pattern
Dependency Injection in Scala - Beyond the Cake PatternDependency Injection in Scala - Beyond the Cake Pattern
Dependency Injection in Scala - Beyond the Cake Pattern
 

Kürzlich hochgeladen

New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 

Kürzlich hochgeladen (20)

New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 

Functional and Event Driven - another approach to domain modeling

  • 1. Functional & Event Driven another approach to domain modeling Thursday 12 April 12
  • 2. Debasish Ghosh @debasishg on Twitter code @ http://github.com/debasishg blog @ Ruminations of a Programmer http://debasishg.blogspot.com Thursday 12 April 12
  • 3. Agenda • Domain Models • Why Functional Domain Models • Event based architectures - Event Sourcing • Duality between functional models & even based models • A sample event sourced domain model implementation Thursday 12 April 12
  • 4. Domain Modeling • We limit ourselves strictly to how the domain behaves internally and how it responds to events that it receives from the external context • We think of a domain model as being comprised of the core granular abstractions that handle the business logic and a set of coarser level services that interacts with the external world Thursday 12 April 12
  • 5. Why Functional ? • Pure with localization of side-effects • Ability to reason about your model • Expressive & Declarative • Immutable Thursday 12 April 12
  • 6. A Functional Domain Model • Built on (mostly) pure abstractions • Pure functions to model domain behaviors • Immutable artifacts • .. and you get some parallelism for free Thursday 12 April 12
  • 7. Immutability • Algebraic Data Types for representation of domain entities • Immutable structures like type-lenses for functional updates • No in-place mutation Thursday 12 April 12
  • 8. Representation as ADTs case class Trade(account: Account, instrument: Instrument, refNo: String, market: Market, unitPrice: BigDecimal, quantity: BigDecimal, tradeDate: Date = Calendar.getInstance.getTime, valueDate: Option[Date] = None, taxFees: Option[List[(TaxFeeId, BigDecimal)]] = None, netAmount: Option[BigDecimal] = None) { override def equals(that: Any) = refNo == that.asInstanceOf[Trade].refNo override def hashCode = refNo.hashCode } Thursday 12 April 12
  • 9. Representation as ADTs // various tax/fees to be paid when u do a trade sealed trait TaxFeeId extends Serializable case object TradeTax extends TaxFeeId case object Commission extends TaxFeeId case object VAT extends TaxFeeId Thursday 12 April 12
  • 10. Pure functions as domain behaviors // get the list of tax/fees applicable for this trade // depends on the market val forTrade: Trade => Option[List[TaxFeeId]] = {trade => taxFeeForMarket.get(trade.market) <+> taxFeeForMarket.get(Other) } Thursday 12 April 12
  • 11. Pure functions as domain behaviors // enrich a trade with tax/fees and compute net value val enrichTrade: Trade => Trade = {trade => val taxes = for { taxFeeIds <- forTrade // get the tax/fee ids for a trade taxFeeValues <- taxFeeCalculate // calculate tax fee values } yield(taxFeeIds map taxFeeValues) val t = taxFeeLens.set(trade, taxes(trade)) netAmountLens.set(t, t.taxFees.map(_.foldl(principal(t))((a, b) => a + b._2))) } Thursday 12 April 12
  • 12. Pure functions as domain behaviors // combinator to value a tax/fee for a specific trade val valueAs: Trade => TaxFeeId => BigDecimal = {trade => tid => ((rates get tid) map (_ * principal(trade))) getOrElse (BigDecimal(0)) } // all tax/fees for a specific trade val taxFeeCalculate: Trade => List[TaxFeeId] => List[(TaxFeeId, BigDecimal)] = {t => tids => tids zip (tids map valueAs(t)) } Thursday 12 April 12
  • 13. Composability Secret sauce ? Functions compose. We can pass functions as first class citizens in the paradigm of functional programming. We can use them as return values and if we can make them pure we can treat them just as mathematically as you would like to. Thursday 12 April 12
  • 14. Updating a Domain Structure functionally • A Type-Lens is a data structure that sets up a bidirectional transformation between a set of source structures S and target structures T • A Type-Lens is set up as a pair of functions: • get S -> T • putBack (S X T) -> S Thursday 12 April 12
  • 15. A Type Lens in Scala // change ref no val refNoLens: Lens[Trade, String] = Lens((t: Trade) => t.refNo, (t: Trade, r: String) => t.copy(refNo = r)) a function that takes a trade and returns it’s reference no a function that updates a trade with a supplied reference no Thursday 12 April 12
  • 16. Lens under Composition • What’s the big deal with a Type Lens ? ✦ Lens compose and hence gives you a cool syntax to update nested structures within an ADT def addressL: Lens[Person, Address] = ... def streetL: Lens[Address, String] = ... val personStreetL: Lens[Person, String] = streetL compose addressL Thursday 12 April 12
  • 17. Lens under composition Using the personStreetL lens we may access or set the (indirect) street property of a Person instance val str: String = personStreetL get person val newP: Person = personStreetL set (person, "Bob_St") Thursday 12 April 12
  • 18. Functional updates using type lens // change ref no val refNoLens: Lens[Trade, String] = Lens((t: Trade) => t.refNo, (t: Trade, r: String) => t.copy(refNo = r)) // add tax/fees val taxFeeLens: Lens[Trade, Option[List[(TaxFeeId, BigDecimal)]]] = Lens((t: Trade) => t.taxFees, (t: Trade, tfs: Option[List[(TaxFeeId, BigDecimal)]]) => t.copy(taxFees = tfs)) // add net amount val netAmountLens: Lens[Trade, Option[BigDecimal]] = Lens((t: Trade) => t.netAmount, (t: Trade, n: Option[BigDecimal]) => t.copy(netAmount = n)) // add value date val valueDateLens: Lens[Trade, Option[Date]] = Lens((t: Trade) => t.valueDate, (t: Trade, d: Option[Date]) => t.copy(valueDate = d)) Thursday 12 April 12
  • 19. Managing States • But domain objects don’t exist in isolation • Need to interact with other objects • .. and respond to events from the external world • .. changing from one state to another Thursday 12 April 12
  • 20. A day in the life of a Trade object tax/fee added created value date added net value computed ssi added a Trade object ready for settlement Thursday 12 April 12
  • 21. What’s the big deal ? All these sound like changing states of a newly created Trade object !! Thursday 12 April 12
  • 22. • but .. • Changing state through in-place mutation is destructive • We lose temporality of the data structure • The fact that a Trade is enriched with tax/ fee NOW does not mean it was not valued at 0 tax SOME TIME BACK Thursday 12 April 12
  • 23. What if we would like to have our system rolled back to THAT POINT IN TIME ? Thursday 12 April 12
  • 24. We are just being lossy Thursday 12 April 12
  • 25. • The solution is to keep information in such a way that we have EVERY BIT OF DETAILS stored as the object changes from one state to another • Enter Event Sourcing Thursday 12 April 12
  • 26. Event Sourcing • Preserves the temporality of the data structure • Represent state NOT as a mutable object, rather as a sequence of domain events that took place right from the creation till the current point in time • Decouple the state of the object from its identity. The state changes over time, identity is IMMUTABLE Thursday 12 April 12
  • 27. Domain Events as Behaviors NewTrade AddValueDate EnrichTrade state = Created state = ValueDateAdded state = Enriched persisted with timestamp t0 persisted with timestamp t2 persisted with timestamp t1 (t2 > t1 > t0) Thursday 12 April 12
  • 28. .. and since we store every event that hits the system we have the ability to recreate ANY previous state of the system starting from ANY point in time in the past Thursday 12 April 12
  • 29. Events and States sealed trait TradingEvent extends Event case object NewTrade extends TradingEvent case object EnrichTrade extends TradingEvent case object AddValueDate extends TradingEvent case object SendOutContractNote extends TradingEvent sealed trait TradeState extends State case object Created extends TradeState case object Enriched extends TradeState case object ValueDateAdded extends TradeState Thursday 12 April 12
  • 30. The Current State • How do you reflect the current state of the domain object ? ✦ start with the initial state ✦ manage all state transitions ✦ persist all state transitions ✦ maintain a snapshot that reflects the current state ✦ you now have the ability to roll back to any earlier state Thursday 12 April 12
  • 31. The essence of Event Sourcing Store the events in a durable repository.They are the lowest level granular structure that model the actual behavior of the domain.You can always recreate any state if you store events since the creation of the domain object. Thursday 12 April 12
  • 32. The Duality • Event Sourcing keeps a • In functional trail of all events that programming, data the abstraction has structures that keep handled track of their history are called persistent data • Event Sourcing does not structures. Immutability taken to the next level ever mutate an existing record • An immutable data structure does not mutate data - returns a newer version every time you update it Thursday 12 April 12
  • 33. Event Sourced Domain Models • Now we have the domain objects receiving domain events which take them from state A to state B • Will the Trade object have all the event handling logic ? • What about state changes ? Use the Trade object for this as well ? Thursday 12 April 12
  • 34. Separation of concerns • The Trade object has the core business of the trading logic. It manifests all state changes in terms of what it contains as data • But event handling and managing state transitions is something that belongs to the service layer of the domain model Thursday 12 April 12
  • 35. Separation of Concerns • The service layer • The core domain layer ✦ receives events from ✦ implements core the context trading functions like calculation of value ✦ manages state date, trade valuation, transitions tax/fee handling etc ✦ delegates to Trade ✦ completely oblivious object for core of the context business ✦ notifies other subscribers Thursday 12 April 12
  • 36. The Domain Service Layer • Handles domain events and delegates to someone who logs (sources) the events • May need to maintain an in-memory snapshot of the domain object’s current state • Delegates persistence of the snapshot to other subscribers like Query Services Thursday 12 April 12
  • 37. CQRS • The service layer ensures a complete decoupling of how it handles updates (commands) on domain objects and reads (queries) on the recent snapshot • Updates are persisted as events while queries are served from entirely different sources, typically from read slaves in an RDBMS Thursday 12 April 12
  • 38. In other words, the domain service layer acts as a state machine Thursday 12 April 12
  • 39. Making it Explicit • Model the domain service layer as an FSM (Finite State Machine) - call it the TradeLifecycle, which is totally segregated from the Trade domain object • .. and let the FSM run within an actor model based on asynchronous messaging • We use Akka’s FSM implementation Thursday 12 April 12
  • 40. FSM in Akka • Actor based ✦ available as a mixin for the Akka actor ✦ similar to Erlang gen_fsm implementation ✦ as a client you need to implement the state transition rules using a declarative syntax based DSL, all heavy lifting done by Akka actors Thursday 12 April 12
  • 41. initial state match on event AddValueDate startWith(Created, trade) start state of Trade object when(Created) { case Event(e@AddValueDate, data) => log.map(_.appendAsync(data.refNo, Created, Some(data), e)) val trd = addValueDate(data) gossip(trd) goto(ValueDateAdded) using trd forMax(timeout) } notify observers log the event move to next state update data of Trade lifecycle structure Thursday 12 April 12
  • 42. Handle events & process data updates and state changes startWith(Created, trade) Log events (event sourcing) when(Created) { case Event(e@AddValueDate, data) => log.map(_.appendAsync(data.refNo, Created, Some(data), e)) val trd = addValueDate(data) gossip(trd) goto(ValueDateAdded) using trd forMax(timeout) } Notifying Listeners Thursday 12 April 12
  • 43. State change - functionally // closure for adding a value date val addValueDate: Trade => Trade = {trade => valueDateLens.set(trade, ..) } pure referentially transparent implementation Thursday 12 April 12
  • 44. Notifying Listeners • A typical use case is to send updates to the Query subscribers as in CQRS • The query is rendered from a separate store which needs to be updated with all changes that go on in the domain model Thursday 12 April 12
  • 45. Notifications in Akka FSM trait FSM[S, D] extends Listeners { //.. } Listeners is a generic trait to implement listening capability on an Actor trait Listeners {self: Actor => protected val listeners = .. //.. protected def gossip(msg: Any) = listeners foreach (_ ! msg) //.. } Thursday 12 April 12
  • 46. Event Logging • Log asynchronously • Persist the current state along with the data at this state • Log the event e log.map(_.appendAsync(data.refNo, Created, Some(data), e)) Thursday 12 April 12
  • 47. Event Logging case class EventLogEntry(entryId: Long, objectId: String, inState: State, withData: Option[Any], event: Event) trait EventLog extends Iterable[EventLogEntry] { def iterator: Iterator[EventLogEntry] def iterator(fromEntryId: Long): Iterator[EventLogEntry] def appendAsync(id: String, state: State, data: Option[Any], event: Event): Future[EventLogEntry] } Thursday 12 April 12
  • 49. Order preserving logging class RedisEventLog(clients: RedisClientPool, as: ActorSystem) extends EventLog { val loggerActorName = "redis-event-logger" // need a pinned dispatcher to maintain order of log entries lazy val logger = as.actorOf(Props(new Logger(clients)).withDispatcher("my-pinned-dispatcher"), name = loggerActorName) akka { //.. actor { } timeout = 20 my-pinned-dispatcher { executor = "thread-pool-executor" type = PinnedDispatcher } } } Thursday 12 April 12
  • 50. case class LogEvent(objectId: String, state: State, data: Option[Any], event: Event) class Logger(clients: RedisClientPool) extends Actor { implicit val format = Format {case l: EventLogEntry => serializeEventLogEntry(l)} implicit val parseList = Parse[EventLogEntry](deSerializeEventLogEntry(_)) def receive = { case LogEvent(id, state, data, event) => val entry = EventLogEntry(RedisEventLog.nextId(), id, state, data, event) clients.withClient {client => client.lpush(RedisEventLog.logName, entry) } sender ! entry //.. } //.. logger is an actor that pushes event } data into Redis Thursday 12 April 12
  • 51. def appendAsync(id: String, state: State, data: Option[Any], event: Event): Future[EventLogEntry] = (logger ? LogEvent(id, state, data, event)) .asInstanceOf[Future[EventLogEntry]] Non-blocking : returns a Future Thursday 12 April 12
  • 52. class TradeLifecycle(trade: Trade, timeout: Duration, log: Option[EventLog]) extends Actor with FSM[TradeState, Trade] { import FSM._ startWith(Created, trade) domain service as a Finite State Machine when(Created) { case Event(e@AddValueDate, data) => log.map(_.appendAsync(data.refNo, Created, Some(data), e)) • declarative val trd = addValueDate(data) • actor based gossip(trd) • asynchronous goto(ValueDateAdded) using trd forMax(timeout) • event sourced } when(ValueDateAdded) { case Event(StateTimeout, _) => stay case Event(e@EnrichTrade, data) => log.map(_.appendAsync(data.refNo, ValueDateAdded, None, e)) val trd = enrichTrade(data) gossip(trd) goto(Enriched) using trd forMax(timeout) } //.. } Thursday 12 April 12
  • 53. // 1. create the state machine val tlc = system.actorOf(Props( new TradeLifecycle(trd, timeout.duration, Some(log)))) // 2. register listeners tlc ! SubscribeTransitionCallBack(qry) // 3. fire events tlc ! AddValueDate tlc ! EnrichTrade val future = tlc ? SendOutContractNote // 4. wait for result finalTrades += Await.result(future, timeout.duration) .asInstanceOf[Trade] Thursday 12 April 12
  • 54. // check query store val f = qry ? QueryAllTrades val qtrades = Await.result(f,timeout.duration) .asInstanceOf[List[Trade]] // query store in sync with the in-memory snapshot qtrades should equal(finalTrades) Thursday 12 April 12
  • 55. Summary • Event sourcing is an emerging trend in architecting large systems • Focuses on immutability and hence plays along well with functional programming principles • Event stores are append only - hence n locks, no synchronization - very fast at the event storage layer Thursday 12 April 12
  • 56. Summary • Complicated in-memory snapshot may have some performance overhead, but can be managed with a good STM implementation • In designing your domain model based on event sourcing, make your core model abstractions meaty enough while leaving the service layer with the responsibilities of managing event handling and state transitions Thursday 12 April 12