I'm working on a Clojure application that we would like to be able to work against a legacy database and a new database. The idea is to define general database API functions in one file that map to corresponding functions in either the old or new database API depending on environment settings. Being new to Clojure this is what I have come up with.
(ns app.db-api
(:require [app.old-api]
[app.new-api]
[app.config :refer [env]]))
;; Define placeholder functions that are later interned to point at either
;; new or old API. The corresponding functions are defined and implemented in
;; old-api and new-api
(defn get-user [user-id])
(defn create-user [user-name])
;; Iterate through defined functions in this namespace and intern
;; them to the corresponding functions in the new or old API, as
;; configured by the :db-api environment variable
(doseq [f (keys (ns-publics *ns*))]
(let [x (symbol f)
y (eval (symbol (str "app." (env :db-api) "/" f)))]
(intern *ns* x y)))
Using this, calls to db-api/get-user will be mapped to old-api/get-user or new-api/get-user depending on the setting in the :db-api environment variable.
One obvious caveat is that db-api has to duplicate the declaration of all API functions and that the API functions cannot be spread over several files but must reside in db-api, old-api, and new-api. Also, we are using conman and the conman/connect! and conman/bind-connection also have to connect/bind to different databases/sql files depending on whether the old or new API is used.
The question is whether this is a reasonable solution or if there are better ways to achieve the same goal? Grateful for any comments.