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