Skip to content

Instantly share code, notes, and snippets.

@dazld
Last active July 20, 2018 13:18
Show Gist options
  • Save dazld/97f54437a06e51a07fb4d83a7339fb69 to your computer and use it in GitHub Desktop.
Save dazld/97f54437a06e51a07fb4d83a7339fb69 to your computer and use it in GitHub Desktop.

Sure, let's say you're writing a web app that at some point needs to look up users by id and password. You could implement this as a function:

(defn get-user [db id pw]
  ...query the db...)

But the problem as you've noticed is that it's hard to test this function, because you have to somehow either actually hit a database during a test, or you have to redef the function. Instead I say we should make formal contracts in our applications. So we'd implement a protocol:

(defprotocol IDb
  (get-user [this id pw]))

(deftype MainDBInterface [db-conn]
  IDb
  (get-user [this id pw]
   ...))

Now it's trivial to stub out the database with something that provides a mock DB:

(defn mock-db [ids-and-pw]
  (reify IDb
    (get-user [this id pw]
      (= pw (get ids-and-pw id)))))

So what we've done here is taken a implicit contract "get-user" and made it explicit "IDb". Now if we need to go and implement a new database, or port this project to run on a different platform we know exactly where we need to go to do our porting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment