clojure-ohio

eraserhd 2026-02-11T16:36:00.676309Z

I think I mostly like polylith, and still find component frustrating. So, the thing that still bugs me is that in my sample polylith app, the base goes and gets a db from the db module, which it needs to pass back to make queries (this part is fine), but it also needs to know it is a component, know what it depends on, put those things into a system map with dependencies, and start it. What it seems to do is make an implicit call graph. I think I would just start the DB in new-db in the db module -- or I could make a "start" fn if I really need to have unstarted databases lying about. Then I would pass the db to the router for it to close over, just as a function "make-handler" or whatever. So then, now I pass the db (which is a necessary dependency) as a parameter to the constructor-like fn. I get that this is basically dependency injection, but it still feels off? Because when I used Google Guice I still had constructors that took dependencies, I think.

eraserhd 2026-02-11T16:38:55.089859Z

hrmm...

2026-02-11T16:39:54.227709Z

i wonder if you'd like component more if you weren't learning it adjacent to polylith

2026-02-11T16:39:59.928309Z

i find polylith cool but impenetrable

eraserhd 2026-02-11T16:59:09.093419Z

I used component in a large project back 2016-2020 - in fact, the project was started by two Cognitect contractors, one of them being Sierra. I remember debugging system maps, but I also remember being unhappy with the resulting structure of the app.

eraserhd 2026-02-11T16:59:22.916299Z

I .. wish I remembered more clearly the details though.

eraserhd 2026-02-11T17:06:46.162119Z

Ok, let me see if I can remember... one point was that consuming a component requires being a component, so much like Singleton, it was "contagious." We had a Datomic db, Datomic migrations, a Pedestal server, a Clara Rules session, and a Kinesis bus consumer, and I remember writing a "config" component to read a config file, so that the other components can depend on it.

eraserhd 2026-02-11T17:07:32.763509Z

It seems not strictly true that consuming a component requires being a component, as we can pass things to component constructors... but if we were to do that, we wouldn't end up using component?

seancorfield 2026-02-11T18:17:44.157069Z

I remembered today why we don't use component/using "inside" the component constructor function! It forces the dependency name to match in the top-level code that builds the system-map. In a lot of our code, we wire up differently named components at the top-level, so the names we use are determined by the "app" rather than whatever the individual component depends on, and that mapping exists explicitly at the top-level. Pro: not tied to the obvious, internal name of a dependency for a low-level dependency. Con: the top-level code still needs to know that internal name so it can map it (but that's true however you use Component when there are dependencies).

eraserhd 2026-02-11T18:19:04.401979Z

This makes sense. I was actually going to ask you about that.

eraserhd 2026-02-11T18:20:29.093449Z

Wait... does it make sense? component/using is declaring what will get assoc'd in, yeah? /me goes to read docs

eraserhd 2026-02-11T18:22:42.565649Z

Oh... Ok, so true. component/using can rename them. So yes that makes sense.

eraserhd 2026-02-11T18:29:46.802879Z

Hrmm... Ok. So if you miss a dependency in the base brick (or main function or whatever), Component doesn't catch that.

eraserhd 2026-02-11T18:31:16.491249Z

But you can assert on start.

seancorfield 2026-02-11T18:51:36.836639Z

Right, and we do have some assert calls in some of our Component start functions.

seancorfield 2026-02-11T18:52:03.610649Z

But it's the sort of omission you catch real quick 🙂

eraserhd 2026-02-11T19:13:58.280279Z

So it's entirely possible that I'm missing something, but I keep thinking this is just a topological sort of function calls where function calls depend on arguments (plus the ability to stop the result), and plain, eager functions literally just do that syntactically. I'm trying to find the benefit over passing dependencies via function application, reusing/renaming dependencies via let, and stopping by implementing a protocol on the result. The last bit is sort of the only thing I don't have complete confidence in.

eraserhd 2026-02-11T19:19:10.764629Z

Hrmm...

eraserhd 2026-02-11T19:19:16.627449Z

more coffeeee

seancorfield 2026-02-11T22:32:22.406939Z

This is why there are so many DI/lifecycle libraries in Clojure 🙂

😂 1
seancorfield 2026-02-11T22:39:29.530059Z

You might like https://github.com/potetm/lightweaver which is Component-but-simpler 🙂

2026-02-11T00:07:07.019339Z

came home to my neighbor walking his dog while in shorts

👍🏻 1
seancorfield 2026-02-11T03:27:14.813479Z

Great session tonight! Thanks to Jason, Jeff, and Noah. We got to learn about https://kakoune.org/ and had a good discussion about editors and REPLs and workflows, plus we talked about Component and Polylith as well. And a little tangent about the 6502, and some home ownership woes :)