Anyone has tried splitting view defns into pure and impure parts? (systematically, at scale)
For example in https://github.com/jacekschae/conduit/blob/732d56d5bd981bd47fab3cdd1b2d96ea27b1e7ff/src/conduit/views.cljs#L209-L216 , the @(subscribe
part makes the defn impure, which might preclude some techniques.
I figured the splitting could make sense: it would be akin to the controller<->view separation in MVC frameworks. The "C" part would handle state and the "V" part would be a pure fn of app-data -> hiccup
signature
This is how Redux’s connected components work, don’t they? The mapStateToProps and mapDispatchToProps (the impure bits) are injected into the HOC that “wraps” the “pure” React component.
It's a balance. Having impure components does indeed preclude some techniques. But having all components consist of a pure fn + an impure one will make it harder to write and support. So if you need some of those techniques for all or for the majority of the views - sure, it makes sense. But if you need them only for some - I would split only those few view functions.
Basically I'm interested in whether it would work at all (beyond a basic example), perhaps some experience report Supporting it might be less painful than it sounds - if one settles in using a MVC-like project structure, then splitting concerns would come quite naturally and mechanically i.e. many devs appreciate a proliferation of defns, files etc even when they know they could inline everything over one defn
It would work, sure. The whole re-com library is built that way.
To be clear - it has only one layer, the pure functions. It doesn't depend on re-frame at all - that part is up to the user.
There’s also this small library I wrote that provides another flexible way of creating form-1 components: https://github.com/sansarip/peanuts you can play around with it in the https://sansarip.github.io/peanuts/#!/peanuts.cards.main.
That looks neat. It's useful that you point out performance - I suspected there was that possible drawback.
Btw have you tried an API in this style? (defn vanilla-defn)
+ (defc my-component vanilla-defn)
So one sticks to vanilla clojure.core defns, increasing the confidence in whether magic is in fact reduced. Also would mean automatic support for :pre/:post and the other things you point out
If I understand you correctly, that’s actually supported 🙂 That was the original implementation. If you look at an https://github.com/sansarip/peanuts/tree/5499859a2a00d37454256312b1d784c80ddb6587, you’ll see info on defc
and fnc
.
Unfortunately due to how the macro works, you’d need to inline your vanilla defn
e.g.
(defc my-component (fn []))
This is because defc
actually will dissect your vanilla-fn
to get at the parameters it accepts and injects a bit of code into it.
defc
and fc
are still around in the latest version, alongside the newer defnc
and fnc
macrosNice! Will check out
I’m familiar with this idea under the name “container components”. I use the pattern a lot, and it enables testing your views without any wiring in things like storybook (or dev cards etc.)