Multimethods
You could define the abstraction with multimethods:
1Â (ns stadig.storage.methods
2Â Â Â (:refer-clojure :exclude [get]))
3
4Â (defmulti get :backend)
5Â (defmulti put :backend)
6Â (defmulti delete :backend)
7Â (defmulti close :backend)
Implemented them for each backend:
1Â (ns stadig.storage.s3
2Â Â Â (:require
3Â Â Â Â [aws.sdk.s3 :as s3]
4Â Â Â Â [stadig.storage.methods :as methods]))
5
6Â (defmethod methods/get :s3
7Â Â Â [this bucket key]
8Â Â Â (when-not bucket
9Â Â Â Â Â (throw (ex-info "Expected bucket" {:type ::bucket-error})))
10Â Â Â (s3/get-object this bucket key))
11
12Â (defmethod methods/put :s3
13Â Â Â [this bucket key value]
14Â Â Â (when-not bucket
15Â Â Â Â Â (throw (ex-info "Expected bucket" {:type ::bucket-error})))
16Â Â Â (s3/put-object this bucket key value)...