Why Are We Settling for this in Clojure

I did a quick Github search to find instances of people passing around global database connections. It didn’t take long for me to find a bunch of examples of this.

(def ^:dynamic ^java.sql.Connection *db* nil)

(def *db*
  {:subprotocol "postgresql"
  :subname "//localhost:5432/blogjr"
  :username "blogjr"

(def ^{:doc "The binding contains the database connection settings."}
  *db* {:classname "com.mysql.jdbc.Driver"})

Why are we okay with this? This isn’t the post global state future we were promised. If you are using this technique, there are a limited number of options to swap out your database. You can either redefine a dynamic variable or using with-bindings. I had a conversation on Twitter recently with one of the few people I know who has actually been paid to write Clojure about this topic:

A dynamic var is as injectable as I’ve ever needed. Can set a default and override using with-bindings/with-redefs

I think in most applications, a database connection is a perfectly acceptable piece of global state, esp. for pooled conns.

I’m quick to believe that there is an issue with what I’m about to propose. It’s very likely in fact. I have never done serious work in Clojure. The largest app I’ve written in Clojure is maybe 300 LoC. So take this with the world’s largest grain of salt (#OXYMORON #ALERT).

We’re going to take advantage of one of the primitive functional programming techniques – currying. Currying is a process whereby a function with multiple arguments is transformed into a function which takes one argument returning a function takes a single argument and so on… For example,

(defn foo [a b c] (+ a b c))

(defn foo-curried [a] (fn [b] (fn [c] (+ a b c))))

(= (foo 1 2 3) (((foo-curried 1) 2) 3))

So we write our actions like this:

(defn create-bid [db]
  (fn [request]
    (transact db tx-data)

In starting the web server, I create the database connection and initialize the web handler like so.

(defn build-routes [db]
  (defroutes routes
    (POST "/bids" [] (actions/create-bid db))
    (resources "/")))

(defn create-handler [db]
  (build-routes db)
  (-> (var routes)

I like this. I much prefer it to dealing with the global database connection. Am I missing something? Is there a reason that this isn’t preferable? Is it overkill?

I likely feel uncomfortable with the status quo because there are a lot of things left in Clojure I don’t understand. I don’t really get what it means to reassign these global variables. I don’t know what the best way is to do this. I do understand how to pass arguments to functions. I’ve been doing that since I first touched a Lisp in my first year of college 7 years ago. If I understood things better, I would probably feel more comfortable with this than I do, but I don’t know much.