beginners

2025-12-28T09:39:54.523009Z

hi! i'm quite used to leiningen uberjars and i wonder why is it seemingly more complex / not idiomatic (?) to produce and use them in tools.cli? i know there's tonsky/uberdeps, but getting to being able to just run java -jar foo.jar is a separate section of additional steps and there's https://clojure.org/guides/tools_build#_compiled_uberjar_application_build which explains how to build it, my question is why isn't it a builtin functionality?

respatialized 2025-12-29T14:42:14.167369Z

Off the top of my head, I can only think of one language ecosystem where there's mostly one "official" way to do everything: golang (gofmt, go get, etc). Many languages have even more fragmentation for tools that cover some of the same ground: • Python: pip, conda, uv • Java: maven, gradle, bazel • JavaScript: node, deno, bun, webpack, vite, etc... • R: renv, remotes, packrat Clojure (excluding cljs) has two tools for project management and building. I bring this up mostly to question the premise that having multiple ways of doing similar things is a hindrance to language adoption: it doesn't seem to have impeded these other languages.

👍 1
p-himik 2025-12-28T09:50:50.614309Z

There are pretty much as many uberjar'ing approaches as there are people who are really interested in the topic. And there are as many differences in specific steps as there are more or less complex apps. So it's easier, simpler, and more flexible to provide an API where its users can create whatever they need themselves.

2025-12-28T10:04:45.994729Z

easier, simpler and more flexible - yes, for library builders, but probably not for users, especially beginners.

p-himik 2025-12-28T10:08:42.960049Z

For users as well, when you need something specifically for your app. But yeah, a hard sell for beginners. But at the same time, it's all very well documented and the bare minimum example that you can just copy-paste is right there on the docs page.

p-himik 2025-12-28T10:13:09.155599Z

It was years and years ago so I don't remember the specifics, but at some point I decided that I'd be better of packaging and deploying an app that I was making as an uberjar. So I learned about all the available options, tried them out and... nothing worked properly, the way I wanted. Some tools straight up didn't work at all with my dependencies. Some did but some resources were missing or name clashes were resolved in a wrong order. And so on and so forth. I completely gave up and continued deploying the app as a collection of sources inside a Docker image with all the dependencies already downloaded. My guess is that I could implement what I need perfectly with tools.build. But I got burned so bad by previous tech that I just don't see the point. :) That's not to say that tools.build is not worth it, but to say that all that was there before was not enough.

2025-12-28T10:47:05.955709Z

> I learned about all the available options, tried them out and... nothing worked properly, the way I wanted that kind of illustrates my point 😃 if there was a well documented built-in functionality that also detects possible misconfigurations in your project - you would not have spent any time at all that's what i don't understand - why can it work (to a sufficient level of satisfaction) in leiningen but can't be provided with tools deps? 🤷

p-himik 2025-12-28T11:05:20.302629Z

What is "misconfiguration" though? The tools were reasonably well documented. But due to the nature of uberjars (there's more than meets the eye!), the tools inherently have quirks and my own requirements did not align well with any of the tools. > to a sufficient level of satisfaction Of some (probably large) fraction of users. Lein uberjars also did not work properly in that project.

2025-12-28T11:10:21.409209Z

It is very, very nice to have a "batteries included" option - "lein test" etc - and that option is Leiningen and why not use it? Maven (Shade plugin) presents lots more options to control the uberjar than Leiningen does. In a nutshell, that's a red flag that marks the feature as out-of-scope for the deps.edn thing. On the other hand, Maven is "incrementally accessible" and that's exactly what the part-time hobbyist needs.

respatialized 2025-12-28T16:33:56.825579Z

> my question is why isn't it a builtin functionality? ... why can it work (to a sufficient level of satisfaction) in leiningen but can't be provided with tools deps? My general impression of deps.edn and its derivatives (like tools.build) is that it requires you to do more work up front to explicitly configure things and define the behavior you want. I've come to prefer this approach. I pretty much always end up with a better understanding of what the build is actually doing than if I just use a "magic button" command. Defining things explicitly is the idiom embraced by these tools; I would argue that trying to provide a one-click solution is "not idiomatic" because it hides complexity from the user. If you prefer leiningen, use it! It hasn't gone away - https://www.surveymonkey.com/results/SM-hht04mGydwZ6Nqr7N8vjCA_3D_3D/ (at least some of the time). It's a perfectly valid choice to just decide to use lein uberjar and move on with building your app. I think you just need to change your expectations of how tooling is supposed to work if you want to keep using tools.build - it embraces a different approach than other tools, and that's OK.

2025-12-28T19:41:12.354779Z

there's a lot of reasons one can prefer tools-deps to lein: • it's overkill • it's slower • it's less convenient when working with local libs, etc "just use lein" would be a fair argument if lein was built on top of and integrated with tools-deps - that would reduce fragmentation of ecosystem, fragmentation of knowledge, friction when trying to reuse existing solutions i'm not a beginner in clojure world and i sometimes shudder when i think of what a beginner experience is - all the guides and tutorials describe many different ways to achieve mostly overlapping goals without a clear direction of what is more idiomatic and going to be supported going forward