@lvh I've heard from Cognitect team members that they use spec for the pure side of things, and not IO-bits and bobs. I suppose in this case that would mean specifying what happens inside the deferred operation and not the delayed (maybe IO?) side of things. I think https://clojure.org/guides/spec#_combining_code_check_code_and_code_instrument_code may be a good example of how to split the specification and deferred/side of things?
HTH.
@jcf Yep; thanks 🙂 I guess I can just write my assertions on the first pure fn 🙂
I find spec to still be quite useful for the deferred side because stubbing
@lvh that makes sense. I've struggled with specifying Datomic in the past and ended up only annotating the pure transaction building bits etc.
wait; are they hard because they’re impure, or hard because some things are wrapped in a deferred
I thought it was strictly the latter; it may be wrapped in a deferred but I still have Strong Opinions(TM) about what the value inside that deferred will get to look like
@lvh I don't know about things being hard, but if you're dealing with executors and thread pools specs may not be appropriate?
the stubbing affects the var itself so executors and thread pools get sidestepped entirely
of course, that enables plenty of cases where e.g. you’d have a livelock in prod that doesnt’ show up in testing
If you're cutting out the threads you can cut out the deferreds too I suppose. You're right though. Effectively ignoring what is a big part of the production code path isn't going to necessarily end well.
Maybe happy-path integration tests and/or some simulation testing would fill that gap if budgets/constraints allow.