Fork me on GitHub
#polylith
<
2023-05-09
>
furkan3ayraktar10:05:26

Yes, this is how Polylith works. This gives the flexibility to swap implementations at the project level. The dependencies (requires in the base) are dependencies to the interfaces, not to concrete implementation. They are picked at the project level.

tengstrand10:05:39

Okay, Furkan was faster than me, but here comes my answer also! The base depends on the component's interface (e.g. usermanager.schema.interface) and the base doesn't know which component that will "implement" this interface in the end. We could for example create another component special-schema that implements the same interface usermanager.schema.interface and replace the schema component with special-schema . If the base depended on a concrete component, then the possibility to switch between implementations would be lost, and also the support of having different implementations of an interface in different projects wouldn't work either.

pavlosmelissinos13:05:56

Oh, so a base brings components together but in an abstract way. Hmm, that's quite interesting but I'm not sure how I feel about that to be honest! E.g. I understand the concept now but it's still kinda weird that bases are "half-baked" Clojure projects (you can't start a REPL in a base unless you manually specify the implementations) :thinking_face: . That might be a good thing but I haven't grokked it yet. I'll have to think about it a bit! 1. The metaphors are confusing me a bit because something abstract (base) is referred to as something quite concrete (brick). Have you considered "reference" implementations for bricks? 2. Can polylith distinguish between a missing dependency that is a component (in which case it's ok to be missing) or a library (in which case it should probably throw an error I suppose)? Or does this not matter either? 3. On a different note, now that add-lib3 is part of Clojure 1.12, have you considered introducing dev tooling that will cycle through swappable implementations? E.g. it would be nice to be able to hot-swap an S3 component with a localstack S3 component from within a REPL session when working on a project.

seancorfield14:05:16

@UEQPKG7HQ You'd normally run a "dev" REPL using the workspace-level deps.edn which has all bricks specified -- but you could also start a project-specific REPL using the projects/<foo>/deps.edn file if you want (why you'd want that, I don't know).

seancorfield14:05:59

The "brick" refers to Lego:tm: concepts: they're physical things that you assemble to make stuff.

seancorfield14:05:58

Not sure what you mean by Q2 but poly check will highlight missing brick dependencies at the project level.

seancorfield14:05:40

Q3: since the interface ns is the same across swappable implementations, add-lib stuff does not help you here.

seancorfield14:05:31

You can eval the alternate implementations and then the alternate interfaces -- I do that occasionally to test things -- but you're better off using profiles and starting different REPLs.

seancorfield14:05:06

The swappable implementations are intended to be swappable at build time, not runtime.

👍 4
pavlosmelissinos14:05:56

> all bricks specified Sure, it will contain all interfaces but if you use swappable implementations you'll still have blind spots. > Not sure what you mean by Q2 but poly check will highlight missing brick dependencies at the project level. I'm talking about this: https://github.com/seancorfield/usermanager-example/blob/0ad809eab955b88082fb11a428fdd82b3a2cda59/bases/web/src/usermanager/web/main.clj#L31-L36 If these third-party dependencies (component, compojure, ring) don't exist in the base's deps.edn, will/should polylith complain? > The "brick" refers to Lego:tm: concepts: they're physical things that you assemble to make stuff. Even Lego bricks are concrete (physical). I'm not saying the analogy doesn't stand, I just wanted to communicate how I felt after the explanation that bases are abstract, compared to my previous understanding 🙂 > you're better off using profiles and starting different REPLs I wish there was a better way. Having to change REPLs in order to switch from one swappable implementation to another doesn't sound very ergonomic. edit: Thanks for Polylith and for taking the time to humour me! I don't mean to sound defensive, I'm just on the fence about Polylith and getting these answers helps!

seancorfield14:05:36

Since projects are (typically) apps and building a project usually means building an uberjar and therefore probably means compiling code, missing libraries would be caught at build time. If you don't AOT, you'd need to use some other tool to check all libs are present. At work, several of our library dependencies are supplied in the projects deps.edn files (and our :dev alias may in fact have a different library -- or a different version).

seancorfield14:05:08

I don't consider bases to be abstract. They themselves have all of their own code. But in Polylith, dependencies are supplied at build time.

seancorfield14:05:05

We have 140+ components at work. Only three of those have swappable implementations so it's not a problem to work with profiles since you're not constantly swapping components around. You use a specific profile when you develop the alternate implementation and for day-to-day work, you just pick a primary one.

👍 3
seancorfield15:05:45

@UEQPKG7HQ I'm happy to answer as many Qs as you have and chat in great depth about Polylith -- feel free to DM me if you want. We have migrated a pretty large codebase to Polylith so we've had to think about and tackle all sorts of use cases -- and I know our code base is a compromise because our bases are mostly "large apps" that we migrated, rather than a "shell" with all the pieces written as components (which is what Polylith's docs recommend). Our "new" apps get written that way tho'...

🙂 4