Fork me on GitHub
#clojure-uk
<
2018-01-31
>
maleghast09:01:35

Morning Everyone.

danm10:01:50

Ahoy hoy

danm10:01:26

Went over a 2" nail on Monday night. Not only trashed the tyre and tube, tore holes in the inside of my rim too

rickmoynihan12:01:21

Ugh that sucks… I drove my car into a huge pothole in the dark and blew out a tyre last week too 😞

danm12:01:01

Potholes around Mancs are absolute rubbish at the moment. And the resurfacing they're doing is crap too. One of the roads I take for my route in got resurfaced back in October, but it was a quick cheap job so the new surface is already peeling back

danm10:01:53

Had to sand all the rough gouges down and then fit new rim tape before I could even put the tyre back on

mccraigmccraig11:01:39

was that a nail sticking up through a plank or something @carr0t?

danm12:01:04

Just lying in the road. It must have been exactly facing down my direction of travel so as I rode over it I forced it up into the wheel or something

otfrom14:01:40

@rickmoynihan goes with the old drafty rooms 🙂

rickmoynihan14:01:41

Drafty == Georgian Damp Proofing

otfrom14:01:54

don't want to die of miasma

chrjs16:01:43

Morning folks! Here’s a little puzzler for anyone who likes thinking about namespaces and testing 🙂 I have a namespace with some stuff in it.

(ns uk-clj-rocks.core
  (:require [dependency :as d]))

(defn thing [x] (d/function x))
I want to test it. But, for reasons (cough datomic peer vs client), I want to test it with dependency swapped out for another library providing all the same functions as dependency. Essentially I’d like to do something like this:
(ns uk-clj-rocks.core-test
  (:require [core.test :refer :all]
            [uk-clj-rocks.core :as core]
            [different-dependency :as dd]))

(deftest thing-test
  (with-ns-redefs [d dd]
    (stuff-from-core-but-with-dd-not-d ...)))
where with-ns-redef is not an actual function AFAIK. There are the with-redefs and with-redefs-fn functions, so one option is to not redef the whole namespace, but just explicitly define vars in uk-clj-rocks.core for the functionality from dependency that I want, then use with-redefs to overwrite those. An overall “namespace injection” seems cleaner though. Thoughts? Is this just nuts?

chrjs16:01:47

Oooh, hold the phone, I can replace the namespace function at a time without defining them in core. That may have solved my problem.

chrjs16:01:07

Thanks, rubber ducks 🦆 🦆 🦆

rickmoynihan16:01:38

@chrjs: You’re probably much better using something like integrant/component… or just defining a boundary with a protocol/interface, or doing

(defn thing [function x] ,,,)

rickmoynihan16:01:47

and injecting a different function in to thing depending on context. Patterns like (thing (constantly {:test :data}) :x) are your friend 🙂

chrjs17:01:17

Hmm, I did consider function injection, but I’ve not looked at integrant or component properly. I will do, thanks @rickmoynihan!

rickmoynihan17:01:21

you can also define two namespaces with the same name, and toggle which gets put on the :source-path, by e.g. having a namespace in env/dev/src/different/dependency.clj and env/prod/src/different/dependency.clj, and then toggle them with a lein (or boot) profile… but this I’d consider this more a packaging concern though. So wouldn’t recommend for your usecase; that trick is more for having extra tooling available in dev and prod… or perhaps loading different middlewares in different envs.

chrjs18:01:00

I think that might be the wrong thing for my particular use case, as you say (I will still want access to both dependencies in test actually: the point of the mocking is for unit tests - end to end tests should be on the real thing). Nonetheless, I had not thought about toggling namespaces using the build tool - very cool.

rickmoynihan23:01:23

well it’s a bit of a hack really… but it can work well when you want to provide different code in different environments. e.g. you may want to switch off authentication entirely in a dev profile but hardcode it in production (so assuming the build is ok; there’s no way to misconfigure it in production to run without auth)

rickmoynihan23:01:25

but would only use it in very limited contexts. Also regarding protocols, you probably only want them if you have java object implementations you want to dispatch on (or if you’re using component). Integrant is my personal favourite dependency injector.

chrjs10:02:51

Yeah, with great power …

mccraigmccraig18:01:22

@chrjs we generally define protocols for all our integration points and pass around an app-context, which is just a map of those protocol implementations (built with our own integrant-like lib) - pretty much hexagonal architecture. it works very nicely

chrjs18:01:38

@mccraigmccraig I’m going to have to look at integrant. Protocols could be exactly the right thing. Ta!

mccraigmccraig18:01:54

@chrjs here's our own lib which is aimed at async systems - it works happily with factory-fns which return promises of things - https://github.com/employeerepublic/deferst

xlevus20:01:24

Is there a clojure idiomatic way to do human-readable input validation? clojure.spec/Schema both do a good job at ensuring the data structure is legit, but aren't that great at saying "Please enter a number between 1 and 5" or "That is not a valid email address" or "that email address is in use"

madstap21:01:38

@xlevus There's this one, if you're talking about humans as in end users https://github.com/alexanderkiel/phrase

xlevus21:01:19

looks legit. 👍

madstap21:01:24

Not sure about idiomatic, the spec stuff's not really settled down in general

xlevus21:01:00

it's certainly more idiomatic than what I'd produce :D

xlevus21:01:08

and yeah, I've noticed spec seems a bit, wobbly. Have to either use Schema, or upgrade compojure-api to 2.0.0-alphaX