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.
hrmm...
i wonder if you'd like component more if you weren't learning it adjacent to polylith
i find polylith cool but impenetrable
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.
I .. wish I remembered more clearly the details though.
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.
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?
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).
This makes sense. I was actually going to ask you about that.
Wait... does it make sense? component/using is declaring what will get assoc'd in, yeah? /me goes to read docs
Oh... Ok, so true. component/using can rename them. So yes that makes sense.
Hrmm... Ok. So if you miss a dependency in the base brick (or main function or whatever), Component doesn't catch that.
But you can assert on start.
Right, and we do have some assert calls in some of our Component start functions.
But it's the sort of omission you catch real quick 🙂
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.
Hrmm...
more coffeeee
This is why there are so many DI/lifecycle libraries in Clojure 🙂
You might like https://github.com/potetm/lightweaver which is Component-but-simpler 🙂
came home to my neighbor walking his dog while in shorts
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 :)