Hi Jonah, This sounds very much like the model layer in DDD, which ironically is exactly what I am building.
However, in the middle of a data flow a function needs to reach out to a repository to make a decision - how does that fit in with the data flow approach? On 5 March 2015 at 13:39, Jonah Benton <[email protected]> wrote: > Hi Colin, > > Another option, other than HOFs or dynamic binding, is what might be called > a data flow approach. > > At the edge of the application are the functions that explicitly take > parameterized resources to perform edge state IO. These might be bare > functions, or they might be protocol implementations that await the delivery > of a type to perform their operation, or multimethods. > > At the center are functions that take a context map, which contains all > relevant application state- IO resources and transient state data. Those > functions are arranged in a data flow and capture the logic or state > transitions of the application independent of any specific IO commitments. > They can use schema or type annotation or pre/post conditions to enforce > invariants. > > When data flow processing arrives at a place where some edge IO should > occur, these data flow functions act as adapters to get-in the appropriate > resource or Record from the context map and call the edge functions to > perform IO. > > The result is a wider, flatter system, propagating state explicitly rather > than implicitly through the call stack. > > Jonah > > > > On Wed, Mar 4, 2015 at 12:58 PM, Colin Yates <[email protected]> wrote: >> >> Hi, >> >> I am looking for the Clojure equivalent of: >> >> class Whatever { >> @Transactional >> void doSomething(IDoSomething one, IDoSomethingElse two) { >> one.doSomething() >> two.doSomething() >> } >> } >> >> where both one and two are dependency injected with a proxy which resolves >> to a thread local database connection. In addition, one might itself have a >> collaborator which itself has a collaborator which needs a datasource. >> >> So far I have two protocols: >> >> (defprotocol IDoSomething >> (do-something [this ...]) >> >> (defprotocol IDoSomethingElse >> (do-something [this ...]) >> >> Each protocol may have a number of implementations, one of which is a JDBC >> implementation: >> >> (defrecord JdbcIDoSomething [db] >> (do-something [this ...] ...)) >> >> The problem is that the calling code only gets provided an IDoSomething >> and an IDoSomethingElse and it wants to do something like: >> >> (let [one (->JdbcDoSomething db) two (->JdbcDoSomethingElse db)] >> (with-transaction [tx db] >> (do-something one) >> (do-something-else two))) >> >> The problem here is that the implementations of do-something and >> do-something-else won't have access to the local bound 'tx', they will have >> their own 'db'. >> >> I realise the general argument is to be explicit and pass a db as the >> first argument to the protocol but this isn't appropriate in this case as >> there are validly multiple implementations. I could abstract a >> 'unit-of-work' and pass that as the first argument to the protocols but that >> seems a bit painful. >> >> Also, these protocols may be used quite far away from where the database >> code lives and passing a parameter all the way through the call stack is >> painful. >> >> I am using Stuart Sierra's components if that makes any difference. >> >> I can't be the first person to run into this but google is surprisingly >> unhelpful which makes me think I have missed something fundamental, and that >> I have something upside down. >> >> What do you all do? >> >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to [email protected] >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> [email protected] >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> For more options, visit https://groups.google.com/d/optout. > > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to [email protected] > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > [email protected] > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
