1. 16
  1. 3
    Let's compare for example
    (defn lookup-users-i []
      (query (get-db-conn)
             '[:find [?user ...] :in $ :where [?user :user/name _]]))
    (defn lookup-users-ii [db-conn]
      (query db-conn
             '[:find [?user ...] :in $ :where [?user :user/name _]]))
    The first version is easier to invoke via the REPL because you offload any db connection setup logic to the get-db-conn function. You don't need to worry about building a connection and passing it in. On the flip-side, at the lookup-user-i call-sites you don't have arguments going in, which provides folks reading the code with less context regarding the function's behavior.

    One could make two different arities of the function:

    (defn lookup-users-iii
      ([] (lookup-users-iii (get-db-conn)))
       (query db-conn
              '[:find [?user ...] :in $ :where [?user :user/name _]])))

    This way, one gets the best of both worlds, at the cost of a little extra typing upfront.

    1. 2

      My current pattern is a map of override functions. I can give them defaults using :or, and overwrite side effecting functions, or define a function in my scope. This works for me so far, and enables tests easily (since part of a side effecting function is the contract by which you call the side effects) and allows you to call a different function for repl side work.