in ,

Show HN: Open sourcing a data flow engine for Clojure / Script, Hacker News


      Domino is a data flow engine that helps you organize the interactions between your data model and events. Domino allows     you to declare your business logic using a directed acyclic graph of events and effects. Whenever an external change is     transacted to the data model, the graph determines the chain of events that will be executed, and side effects triggered     as a result of the computation.   


      Without a way to formalize the interactions between different parts of the application, relationships in code become implicit.       This results in code that’s difficult to maintain because of the mental overhead involved in tracking these relationships.       Domino makes the interactions between pieces of business logic explicit and centralized.     


      Domino explicitly separates logic that makes changes to the data model from side effectful functions. Business logic     functions in Domino explicitly declare how they interact with the data model by declaring their inputs and outputs.     Domino then uses these declarations to build a graphs of related events. This approach handles cascading business logic     out of the box, and provides a data specification for relationships in code. Once the changes are transacted, the     effectful functions are called against the new state.   



    1. Requiredomino.core      

       (require '[domino.core :as domino])       

    2. Declare your schema    

Let’s take a look at a simple engine that accumulates a total. Whenever an amount is set, this value is added to the     current value of the total. If the total exceeds1337at any point, it prints out a statement that says"Woah.     


      (def schema         {: model [[:amount {:id :amount}]                     [:total {:id :total}]]         : events [{:inputs  [:amount]                     : outputs                     : handler (fn [ctx [amount] [total]]                                 [(  total amount)])}]         : effects [{: inputs [:total]                     : handler (fn [ctx [total]]                                 (when (>total 1337)                                 (js / alert "Woah. That's a lot.")))}]})     


    Thisschemadeclaration is a map containing three keys:     

  • The: modelkey declares the shape of the data     model used by Domino.

  • The: eventskey contains pure functions that represent events that are triggered when their inputs change.       The events produce updated values ​​that are persisted in the state.

  • The: effectskey contains the functions that produce side effects based on the updated state.

    Using a unified model referenced by the event functions allows us to easily tell how a particular piece of business logic is triggered.     The event engine generates a direct acyclic graph (DAG) based on the: inputkeys declared by each event that’s used to     compute the new state in a transaction. This approach removes any ambiguity regarding when and how business logic is executed.   


    Domino explicitly separates the code that modifies the state of the data from the code that causes side effects. This encourages     keeping business logic pure and keeping the effects at the edges of the application.   

    3. Initialize the engine    

      Theschemathat we declared above provides a specification for the internal data model and the code that operates on       it. Once we’ve created a schema, we will need to initialize the data flow engine.       This is done by calling thedomino / initialize!function. This function can be called by providing a schema along with       an optional initial state map. In our example, we will give it theschemathat we defined above,       and an initial value for the state with the: totalset to(0) .


      (def ctx (atom (domino / initialize! schema {: total 0})))     


Calling theinitialize!function creates a contextctxthat’s used as the initial state for the engine.       The context will contain the model, events, effects, event graph, and db (state). In our example we use an atom in order to easily       update the state of the engine.

    4. Transact your external data changes    

      We can update the state of the data by callingdomino / transactthat accepts the currentctxalong with an inputs     vector, returning the updatedctx. The input vector is a collection of path-value pairs. For example, to set the     value of: amountto10, you would pass in the following input vector[[[:amount] 10]].   


      (swap! ctx domino / transact [[[:amount] 10]])     


      The updatedctxcontains the: change-historywhich is a simple vector of all the changes as they were applied to the     data in exectution order of the events that were triggered.   


      (: change-history @ctx)     


      We can see the new context contains the updated total amount and the change history shows the order in which the changes     were applied.   


    The: domino.core / dbkey in the context will contain the updates state reflecting the changes applied by running the events.   


    (: domino.core / db @ctx)   


    Finally, let’s update the: amountto a value that triggers an effect.   


  (defn button []     [: button      {: on-click # (swap! ctx domino / transact [[[:amount]) 2000]])}      "trigger effect"])      (reagent / render-component [button] js / klipse-container)     

This wraps up everything you need to know to start using Domino. You can see a more detailed example using Domino with Reagenthere.


Brave Browser
(Read More)

What do you think?

Leave a Reply

Your email address will not be published.

GIPHY App Key not set. Please check settings

Open-source tool that uses simple textual descriptions to draw beautiful UML diagrams., Hacker News

Open-source tool that uses simple textual descriptions to draw beautiful UML diagrams., Hacker News

This is what happens to you when you sleep too much – Times of India, The Times of India

This is what happens to you when you sleep too much – Times of India, The Times of India