Protocol + Client Namespace + Multimethod
You could use a protocol to define the abstraction, except connect, which is a multimethod:
1 (ns stadig.storage.protocol
2 (:refer-clojure :exclude [get]))
3
4 (defprotocol IStorage
5 (get [this bucket key])
6 (put [this bucket key value])
7 (delete [this bucket key])
8 (close [this]))
9
10 (defmulti connect :backend)
Implement the protocol and multimethod for each backend:
1 (ns stadig.storage.s3
2 (:require
3 [aws.sdk.s3 :as s3]
4 [stadig.storage.protocol :as proto]))
5
6 (defrecord S3Storage
7 [access-key secret-key]
8 proto/IStorage
9 (get [this bucket key]
10 (s3/get-object this bucket key))
11 (put [this bucket key value]
12 (s3/put-object this bucket key value...