How can we directly call `(repo/get-cust-by-id id)`, instead of `((:get-cust-by-id sys-map) id)` when using component libraries?

The answer is protocols, but they may change your code quite a bit.

Lets take your first two “API” functions and turn it into a protocol.

(defprotocol IContactRepo
  (find-contact-by-id [repo id] "a docstring")
  (create-contact! [repo contact]))

So, these now take an extra special first argument, being the thing that implements it.

You can then create implementations using either deftype, defrecord or reify.

(let [fake (reify IContactRepo
             (find-contact-by-id [_ id] {:id 1 :name "example"})
             (create-contact! [_ _] :ok))]
  
  (find-contact-by-id fake 1))

The component would create such an implementation, and the caller side would need to supply that thing to call it. This will likely cause some rather big changes in your code, but what you get is easily swappable implementations.

Mutating vars is bad and is not something I’d recommend doing.

1 Like