2016-10-28 3 views
1

Я работаю над приложением Clojure, которое мы хотели бы иметь, чтобы работать с устаревшей базой данных и новой базой данных. Идея состоит в том, чтобы определить общие функции API баз данных в одном файле, которые сопоставляются с соответствующими функциями в старом или новом API баз данных в зависимости от настроек среды. Будучи новичком в Clojure, это то, что я придумал.Обработка нескольких слоев данных в clojure

(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))) 

Используя это, вызовы db-api/get-user будет отображаться в old-api/get-user или new-api/get-user в зависимости от значения в переменной :db-api среды.

Одно из очевидных предостережений заключается в том, что db-api должно дублировать декларацию всех функций API и что функции API не могут быть распределены по нескольким файлам, но должны находиться в db-api, old-api и new-api. Кроме того, мы используем conman, а conman/connect! и conman/bind-connection также должны подключаться/привязываться к различным базам данных/sql-файлам в зависимости от того, используется ли старый или новый API.

Вопрос в том, является ли это разумным решением или есть ли лучшие способы достижения одной и той же цели? Благодарен за любые комментарии.

ответ

1

Вы можете использовать мультиметод. https://clojuredocs.org/clojure.core/defmulti

(defmulti get-user (fn [user-id] (grab-env-var :db-api))) 

(defmethod get-user :old-api [user-id] 
    (use-old-api user-id)) 

(defmethod get-user :new-api [user-id] 
    (use-new-api user-id))