SlideShare uma empresa Scribd logo
1 de 57
Baixar para ler offline
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

Mais conteúdo relacionado

Mais procurados

ES6 presentation
ES6 presentationES6 presentation
ES6 presentationritika1
 
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js +  Expres...Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js +  Expres...
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...Edureka!
 
Scylla Summit 2017: How to Use Gocql to Execute Queries and What the Driver D...
Scylla Summit 2017: How to Use Gocql to Execute Queries and What the Driver D...Scylla Summit 2017: How to Use Gocql to Execute Queries and What the Driver D...
Scylla Summit 2017: How to Use Gocql to Execute Queries and What the Driver D...ScyllaDB
 
Node.js Express
Node.js  ExpressNode.js  Express
Node.js ExpressEyal Vardi
 
Node.js Tutorial for Beginners | Node.js Web Application Tutorial | Node.js T...
Node.js Tutorial for Beginners | Node.js Web Application Tutorial | Node.js T...Node.js Tutorial for Beginners | Node.js Web Application Tutorial | Node.js T...
Node.js Tutorial for Beginners | Node.js Web Application Tutorial | Node.js T...Edureka!
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Metosin Oy
 
Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right wayThibaud Desodt
 
Fundamental of Node.JS - Internship Presentation - Week7
Fundamental of Node.JS - Internship Presentation - Week7Fundamental of Node.JS - Internship Presentation - Week7
Fundamental of Node.JS - Internship Presentation - Week7Devang Garach
 
Rethinking Best Practices
Rethinking Best PracticesRethinking Best Practices
Rethinking Best Practicesfloydophone
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Scott Wlaschin
 
The Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldThe Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldPhilip Schwarz
 
Effective Spring Transaction Management
Effective Spring Transaction ManagementEffective Spring Transaction Management
Effective Spring Transaction ManagementUMA MAHESWARI
 
[Final] ReactJS presentation
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation洪 鹏发
 
Postgres MVCC - A Developer Centric View of Multi Version Concurrency Control
Postgres MVCC - A Developer Centric View of Multi Version Concurrency ControlPostgres MVCC - A Developer Centric View of Multi Version Concurrency Control
Postgres MVCC - A Developer Centric View of Multi Version Concurrency ControlReactive.IO
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldJorge Vásquez
 
Developing and Deploying Apps with the Postgres FDW
Developing and Deploying Apps with the Postgres FDWDeveloping and Deploying Apps with the Postgres FDW
Developing and Deploying Apps with the Postgres FDWJonathan Katz
 

Mais procurados (20)

ES6 presentation
ES6 presentationES6 presentation
ES6 presentation
 
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js +  Expres...Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js +  Expres...
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
 
Intro to React
Intro to ReactIntro to React
Intro to React
 
Scylla Summit 2017: How to Use Gocql to Execute Queries and What the Driver D...
Scylla Summit 2017: How to Use Gocql to Execute Queries and What the Driver D...Scylla Summit 2017: How to Use Gocql to Execute Queries and What the Driver D...
Scylla Summit 2017: How to Use Gocql to Execute Queries and What the Driver D...
 
Node.js Express
Node.js  ExpressNode.js  Express
Node.js Express
 
Node.js Tutorial for Beginners | Node.js Web Application Tutorial | Node.js T...
Node.js Tutorial for Beginners | Node.js Web Application Tutorial | Node.js T...Node.js Tutorial for Beginners | Node.js Web Application Tutorial | Node.js T...
Node.js Tutorial for Beginners | Node.js Web Application Tutorial | Node.js T...
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019
 
ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right way
 
Fundamental of Node.JS - Internship Presentation - Week7
Fundamental of Node.JS - Internship Presentation - Week7Fundamental of Node.JS - Internship Presentation - Week7
Fundamental of Node.JS - Internship Presentation - Week7
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
Rethinking Best Practices
Rethinking Best PracticesRethinking Best Practices
Rethinking Best Practices
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)
 
Introduction à React
Introduction à ReactIntroduction à React
Introduction à React
 
The Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldThe Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and Fold
 
Effective Spring Transaction Management
Effective Spring Transaction ManagementEffective Spring Transaction Management
Effective Spring Transaction Management
 
[Final] ReactJS presentation
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation
 
Postgres MVCC - A Developer Centric View of Multi Version Concurrency Control
Postgres MVCC - A Developer Centric View of Multi Version Concurrency ControlPostgres MVCC - A Developer Centric View of Multi Version Concurrency Control
Postgres MVCC - A Developer Centric View of Multi Version Concurrency Control
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
 
Developing and Deploying Apps with the Postgres FDW
Developing and Deploying Apps with the Postgres FDWDeveloping and Deploying Apps with the Postgres FDW
Developing and Deploying Apps with the Postgres FDW
 

Destaque

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
 

Destaque (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
 

Semelhante a 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
 

Semelhante a 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
 

Mais de Debasish Ghosh

Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayDebasish 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
 
Domain Modeling in a Functional World
Domain Modeling in a Functional WorldDomain Modeling in a Functional World
Domain Modeling in a Functional WorldDebasish 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
 

Mais de Debasish Ghosh (14)

Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
 
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
 
Domain Modeling in a Functional World
Domain Modeling in a Functional WorldDomain Modeling in a Functional World
Domain Modeling in a Functional World
 
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
 

Último

Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
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
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
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
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
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
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
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 Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
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
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
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
 
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
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
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
 

Último (20)

Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
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
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
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
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
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 Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
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
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
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...
 
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
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
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
 

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