Any recommended resources for large-scale system design in clojure? Been using clojure for ~3 years, done mostly “small” web apps, but want to improve my design/organization skills.
Could also be resources around large-scale FP design in general, would understand Haskell examples (for the most part)
Have you seen Stuart Sierra' "Clojure in the Large" talk? That's a good "first step" in code organization.
Yes, although I’m probably due for a rewatch. Also seen “component, just enough structure”, and have used component in my projects.
My main concern is that I’ve never been exposed (personally, in a mentorship sense) to a more experienced clojure developer, and I am now in a position where I am the “experienced” clojure dev in a group of developers. Want to ensure I’m developing high quality clojure code so I don’t lead down an incorrect path.
We have about 75,000 lines of Clojure. We've settled on a mono-repo approach with lots of subprojects for "libraries" and "servers" within that. We use Boot to manage that (with dependencies in deps.edn
files -- that predate tools.deps
) so we can build uberjars for any combination of subprojects.
I think there are a lot of different ways of writing "good" Clojure but there's not much out there about namespace organization and general architecture "at scale" unfortunately...
@dadair Generally I can recommend making your call stack as shallow as possible and having side effects like writing to db as close to the edges and up the call stack as possible (e.g at the end of a request handler not hidden in some deep function sandwiched between other side effects). It's not easy though.
@yonatanel Yeah, I wrote a library (called Engine) that was meant to help with writing more "pure" code but we abandoned it after trying to use it for a while. It made for some odd-looking code. The idea was that you provided a hash map of data "sources" (things that are "queryable") and the library had update/insert functions that produced data structures describing the changes you wanted made, and then at the end you would "commit" them and the data structures would be walked and stuff written to "sinks" (things that are "committable").
It was nice for testability -- no functions under test would do anything side-effect-y and you could easily supply mocked queryable sources, and then just assert the correct shape of the "change" data structures.
But it was all a bit monadic in order to carry the sources and changes through all your code and that made things rather opaque at times.
I still like the concept of it and if I can figure out a better implementation, I may well rewrite it...
@seancorfield Don't you want to just use commands and events, maybe event sourcing?
@yonatanel That's also an option to separate pure logic and side effects but it also has its pros and cons. Everything's a trade off 🙂