Fork me on GitHub
#clojure
<
2019-03-06
>
schmidt7301:03:56

I'm torn between using plain functions for grabbing users from a database for my website or a protocol. I'm using component to manage dependencies and I saw this:

At this point you may be thinking, “API functions where the first argument determines a lot of the behavior… that sounds a lot like a protocol.” That’s an excellent point. For many common components, particularly ones that can be swapped out with different implementations like database connections, it can be valuable to define their API as a protocol. This can also enhance testability, since it gives us a flexible way to inject different mock components in our tests.

schmidt7301:03:37

I don't understand what a protocol offers vs functions such as get-user : db * username -> user_row

lilactown01:03:11

you can pass in a "mock" db that just returns pure data

schmidt7301:03:47

I've been thinking this whole time about only mocking with a test database but if I use a protocol I can mock everything.

schmidt7301:03:22

Maybe though not at the user level.

rymndhng01:03:27

@henri.schmidt depends on your use case: if you're building a http service, then the interface of your system is your HTTP api, and not the functions/protocols inside of it if you're building a library, then you may consider using a protocol With functions, if I want to mock the database call for testing, we use with-redefs to make it explicit that we're monkey patching a particular function for testing

schmidt7301:03:08

I'm building a website, so neither.

schmidt7301:03:29

Would it be better to mock jdbc/sql commands though?

schmidt7301:03:36

rather than the individual user calls

lilactown01:03:42

yep. you can just have a

(deftype FakeDB
  IUserInfo
  (get-user [this username]
   {:posts [] :name "Foo Bar"}))
and use that in your component system

schmidt7301:03:57

I feel like IUserInfo will be really large

lilactown01:03:59

eh, usually you want to operate at a higher level of abstraction in most of your code

schmidt7301:03:01

have defprotocol SqlDB with query do_command etc I feel like that offers a more powerful way to swap in certain behaviours.

schmidt7301:03:08

If I were to have:

lilactown01:03:08

depends on how coupled you want to be to your SQL

schmidt7301:03:20

But I guess both could work

schmidt7301:03:33

AS they are not mutually exclusive

lilactown01:03:53

IMO you usually want to use abstractions to model your domain

schmidt7301:03:07

@lilactown I really appreciate your help btw, now I see the value in the defrecord crap.

schmidt7301:03:38

I'll take your advice, I can always add the SqlDB later.

schmidt7301:03:41

If necessary