What do beginners struggle with?

I don’t think I’m a beginner, I’ve been playing with Clojure on and off for about 8 years, but I’ve started a new project recently with clojure cli / deps.edn. The biggest problems I’ve had are:

  • Identifying Clojure application architecture best practices
  • Tooling ergonomics
  • Library discovery and selection

For application architecture, Eric Normand’s question “Organizing Clojure code - A real problem?” has been a great help. Turns out I was bringing some C# habits to Clojure.

For deps.edn, examples have been really useful, if a little overwhelming:

I find deps.edn to be a pretty nice way to encode build related stuff as data, and I find it easier to understand than Leiningen, but the ergonomics are just ghastly. I know we should favour simple over easy, but I don’t think it’s unreasonable to want to have both. Tools like Git or Homebrew have a relatively friendly and discoverable interface that helps you learn more about how to use the tooling. I understand that clojure cli is supposed to be simple, and that these kinds of ergonomics aren’t part of what it does. Unfortunately, as a byproduct, I spend far too long trawling through examples and guides to try and curate my own set of aliases.

I found the post “[Idea] A tool for helping developers get started using Clojure CLI tools and deps.edn - Community Center / Community Building - ClojureVerse” which led to the creation of “lilactown/plum”, but at a glance that doesn’t seem to have gone anywhere.

I found an example of a makefile wrapping deps.edn in antq and ended up learning how to debug make so that I could have one too. A couple of days later borkdude announced Babashka task runner, which is rather nice, and I converted my project to using that.

My project is a small thing, and it’s an attempt to port an overly complicated project that I built with Leiningen over to deps.edn. Part of that complexity was too much state in too many places so I decided to find some libraries to handle sql queries, connections, and migrations. There are quite a lot of libraries out there, many of them abandoned (though that doesn’t always matter). Finding them and choosing between them is a time consuming nightmare. Not to mention library gotchas like logging and handling of date and times.

I’m now at the point where I’ve got a bug relating to how migrations are running, which is fine, and I thought I’ve quickly whip up test project so I can try an isolate the problem. I couldn’t remember the semantics for calling seancorfield/clj-new, so had to open up my .clojure/deps.edn to check. I thought about wrapping my global deps.edn in Babashka tasks to try and provide some executable documentation, but it feels like I’m just pushing deps up hill at this point.

So, here I am, frustrated, having poured time into a hobby project where the only real headway I’ve made is setting up tooling, and I’m still haunted by the thought that the next time I set up a project it’s not going to be much easier.

I don’t think the clojure community is deliberately making things hard for beginners, but it is hard. Simple is wonderful, I love simple, but I don’t think it’s unreasonable to want to have at least some of that simple within reach, for it to be easy.

If I’d done this project at work, in C#, I’d already be done. That’s because it’s my day job, but that’s also because all the pieces I need to make it work are within easy reach.

Don’t get me wrong, when I’m dealing with the internals of the application, when all the libraries are in place and I don’t have to think about how to get a repl running, Clojure is wonderful, and I often solve C# problems first in Clojure and try and convert the solution. But getting to that point seems a lot more painful than it has to be.

4 Likes