Hello,

So far there have been mentions of several techniques :

=> using macro against *db-adapter* :
 * will work if *db-adapter* is set at compile-time (in a top level
expression before the macro call, or as a side effect of the invocation of
another macro before the macro call).
 * if you AOT-compile your code, you will not be able to change the choice
of the db in those environments that will use your lib (may be a feature or
a bug, depending on your use case, and whether your lib is meant to be
general or is the final artifact of a specific product).

=> using (use) at runtime
 * much more dynamic
 * works as the "one static singleton per JVM/clojure instance" pattern in
java world

=> using polymorphism
I would like to add this solution to the sandbox, since it seems to be even
more dynamic than the others, and much closer to "a-la springframework
dependency injection" for at least one use case:
 * you want to talk to different databases at the same time

I imagine that if you talk to different databases, you have some object that
holds the information concerning each database (holding connection string,
... I don't know what ...).
And that this object is used either implicitly (via dynamic binding), either
explicitly (presumably as their first argument) by the functions.

The idea is just to make these functions multimethods that will dispatch on
some "type" placed on the object representing the database.

First case : your API design uses a dynamic var to get the database object.
Your old code may look like :
;;;;
(ns oracle)
(defn connect [...] (... (.... *db*)))
;;;;
(ns mysql)
(defn connect [...] (... (... *db*)))
;;;;;
; later in user code
; some magic with 'use

With multimethods and polymorphism, your new code may then look like :
;;;;
(ns clj-database)
(defmulti connect-impl #(type %1))
(defn connect [& more] (apply connect-impl *db* more))
;;;;
(ns oracle)
(defmethod connect-impl :oracle [*db* ...] ....)
;;;;
(ns mysql)
(defmethod connect-impl :mysql [*db* ...] ....)
;;;;
; later in user code
; in initialization code
(require 'mysql) ; or (require 'oracle) or whatever more dynamic way you may
want
; what you gain is that you can 'require several db impls at the same time !
(def *mysql-db* ...) ; somehow this code will add a :type metadata on the
object (just an example, multimethods allow you to do the dispatch
_as_you_want_)
(def *oracle-db* ...)
; in regular code
(require 'clj-database)
(binding [*db* *mysql-db*]
  (connect ......))

Few.

HTH,

-- 
Laurent


2009/9/8 Chris Kent <[email protected]>

>
> James Sofra <james.sofra <at> gmail.com> writes:
>
> >
> >
> > I know that this has come up before on the group and but is this not
> > essentially dependency injection where the dependency being injected
> > is a name space that presumably follows a particular convention in
> > terms of what functions it provides?
> >
> > I remember people making it pretty clear that they didn't see the need
> > for DI in Clojure so my question is, is this a useful approach? is
> > there a better way?
> >
> > Cheers,
> > James
> >
>
> Hi
>
> I've often wondered about this in the context of testing, particular
> testing
> code with side effects.  In an OO language I'd create an interface for the
> side
> effecting code (I'm thinking of things like DAOs or messaging systems) and
> create a mock or dummy implementation for my tests.
>
> Selectively importing different namespaces that define the same set of
> functions
> is treating namespaces like classes / interfaces.  I've never been sure
> whether
> I should feel uncomfortable about this and whether there's a more idiomatic
> way
> to achieve the same thing.  It feels like such a common requirement I'm
> surprised there isn't a standard approach.  Although maybe that's the years
> of
> OO programming clouding my thinking.
>
> Cheers
> Chris
>
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to