I’ve had a slightly different approach to this… Typically, I will start with a dev.clj
namespace, outside of src
, which is a sort of (mostly) append-only scratch pad. I use this to interact with the REPL, and iterate over my code. Stuff that has been “finished”, I archive inside a Rich comment form (so it’s not eval
'ed if I reload the namespace). Once I’m happy with that, I will send it off to its own namespace. For one-off stuff, this could be a single file, but in general, I will split the functions and spec definitions over several namespaces that carry some semantic meaning. For example, I’m currently developing an API with several endpoints grouped by functionality (say, projects
, analysis
, and diagnostics
).
Each one of those groups gets its own little namespace (com.blah.api.projects
, etc) with route definitions and handlers, and I compose those into a single api.core
ns that builds the actual Reitit routes table from the separate components. I have a similar approach to my Malli specs (which is arguably more useful than for the API components, since they can get fairly verbose, and I prefer working on smaller files).
For the data layer, I have a com.blah.db
namespace that deals with all DB matters, and there’s also the com.blah.util
ns, with general helpers, a db-specific com.blah.db-utils
with small DB-specific helpers. I find that working with several smaller namespaces makes my code feel less cluttered. In this particular project, I have 17 separate namespaces (plus the dev
scratchpad). It may sound like quite a lot, but it is actually quite easy to navigate them, and more importantly, they make sense to me.
This last point is probably a caveat, since I’m currently the only person doing Clojure in my team, so if there were more hands in the pot, some sort of formalization on how to group code might be necessary.
Regarding the “append-only” nature of the scratch pad, I sometimes trim stuff that’s become obsolete, to make it easier to navigate the file, but I tend to keep a good amount of “history” there, as well as small helpers I keep coming to when working on the REPL.
I think I should also have a look at Polylith, it looks like it may be a good way to enforce a bit more structure on my approach.