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 <colin.ya...@gmail.com> 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 clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> 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 clojure+unsubscr...@googlegroups.com.
> 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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to