polylith

Andrew Leverette 2025-01-16T02:05:38.827519Z

I'm new to Polylith and I think I understand the overall goals and pattern, but I've run into something that I'm not 100% sure about. So let's say I have three components - config, logger, and database. Both the logger and database use the config component, and the database also uses the logger component. Am I breaking the pattern here or is this okay?

seancorfield 2025-01-16T02:23:27.308219Z

No circular references, right? Why do you think this breaks any patterns?

seancorfield 2025-01-16T02:23:55.881389Z

There are no explicit dependencies in components, only in projects

Andrew Leverette 2025-01-16T02:25:49.175459Z

No circular references or anything. I was just looking at and thinking this seemed off, but I've read through your example and the RealWorld one and it seemed fine.

Andrew Leverette 2025-01-16T02:27:11.289579Z

So, any component can depend on any other component?

Andrew Leverette 2025-01-16T02:27:34.511979Z

As long as there are no circular references

seancorfield 2025-01-16T02:27:56.682489Z

We have ~170 components and some of those low-level ones are used (transitively) by "everything".

Andrew Leverette 2025-01-16T02:28:21.050759Z

Okay, that makes sense.

Andrew Leverette 2025-01-16T02:29:30.722009Z

I'm still feeling my way around this structure, but I do like how it forces you to think about component interfaces.

seancorfield 2025-01-16T02:30:38.783999Z

Yup. You think about naming, and you think about dependencies, because everything is done through interfaces.

Andrew Leverette 2025-01-16T02:34:40.843769Z

I'm also learning about component systems, ie. the stuartsierra/component library. I'm still a little fuzzy on that. But if I understand it correctly, they are for stateful components like database connections. Is that right?

seancorfield 2025-01-16T02:51:23.372679Z

Yes, mostly

tvaisanen 2025-01-16T14:24:18.996009Z

Quick Q! Is there a way to fetch dependant bricks for a brick programmatically from Clojure for custom tooling. For example

(poly/deps :brick/foo)

✋ 1
tvaisanen 2025-01-17T08:02:03.691179Z

I'm working on a Polylith project that has a lot of components and project. I'm looking into creating a component to collect functionalities for a feature. I'd like to programmatically traverse all the dependant projects/components where this feature is used to build documentation and release notes for this particular feature, since it's dispersed across all the projects. Therefore I'm looking into if Polylith has baked in functionality to collect this information for me from the whole project. I see that the Poly CLI lists the dependants by running deps brick:.... -> Can I use this somehow from Clojure code. I'm also interested on other suggestions on how to go about documentation. Thanks!

seancorfield 2025-01-17T17:16:28.348159Z

Well, you can use Polylith as a library but there's nothing in the CLI API specifically for what you need so you'd have to dig around in the source a bit... Who is the consumer of this documentation and info? For our public API, we've documented the REST-ish API separately, and our build process generates HTML from Markdown and adds it to the uberjar for our API service so it's available through the same URL as the API itself. If we were starting over, we'd probably use Swagger and provide a more automated/standard documentation approach.

tvaisanen 2025-01-20T07:19:24.705739Z

Thanks, I'll keep digging. I'm hacking the first pass of this PoC by parsing the EDN files. I'll take another look at the CLJ API if we decide to take this further. The consumers are technical people who are not familiar with this side of the project. I want to create docs that gives a high overview of how this feature is spread over different projects and components. So when new developers take a look they can get the big picture with a quick look instead of tracing manually where the code is used etc.

Mark Sto 2025-01-23T20:40:32.913629Z

@vaisanen.toni howdy! How about creating a separate project with manually picking the bricks you need for this + using https://github.com/dundalek/dinodoc/ with this classpath? Too much of a handwork?

tvaisanen 2025-01-24T06:56:20.283509Z

I need to look into this, thanks Mark!

🤝 1
❤️ 1
seancorfield 2025-01-16T16:01:10.376169Z

Can you explain your use case? I suspect you can just use the Clojure CLI but if need to understand better what actual problem you're trying to solve.

Mark Sto 2025-01-24T16:04:48.664849Z

BTW, @vaisanen.toni. Dinodoc supports compiling docs for a whole Polylith workspace OOTB. Just in case if this feature simplifies your task.

ikitommi 2025-01-16T17:02:08.215219Z

Is it a ok for a component to depend on other component(s)? e.g. have a direct dependency in deps.edn like:

poly/metrics {:local/root "../metrics"}

mitchelkuijpers 2025-01-17T08:50:08.451389Z

Thanks a lot for this explanation this was not completely clear to me either

Mark Sto 2025-01-23T20:44:58.742639Z

@ikitommi hey Tommi! This is the trick that differs a Poly workspace from a regular multi-module Clojure Deps project. The approach/tool introduce this idea of separating the static/codebase architecture from the deployment-time architecture. So your classpath only gets combined into a whole in a particular project.

seancorfield 2025-01-16T17:46:51.096129Z

Components do not have dependencies on components, only on libraries. Only the project specifies the concrete dependencies.

seancorfield 2025-01-16T17:47:38.010989Z

A component's code may reference other components' interface namespaces, but the deps.edn does not include any dependencies.

ikitommi 2025-01-16T18:17:43.481039Z

thanks, and that’s how I read this, but… how would you do the following with polylith: 1. a mini-framework, component Ato define how to create and run tasks - protocols needed to implement, helpers etc 2. component B a that uses the A defining concrete tasks for certain subdomain. a. no dependencies to A? so won’t compile on itself as it would like to point to namespaces in A 🤔 3. component C that is like B but for a different domain / purpose 4. base D that uses A to run tasks for B and C 5. project E to bundle everything together a. depends on all of A, B, C and D

ikitommi 2025-01-16T18:19:18.169469Z

Am I using components or even whole polylith in a wrong way in that example?

ikitommi 2025-01-16T18:21:55.019049Z

or should A be outside of polylith as a non-polylith thing, just code in a local root in the same repo, e.g. used in B and C with:

library/a {:local/root "../../libraries/a"}

seancorfield 2025-01-16T19:19:38.812099Z

The deps.edn file in components (and in bases) should never contain dependencies for other components -- even if the source code in that brick references other components via interface nses. Only projects deps.edn files contain those local dependencies -- and that includes the :dev alias which is the "development" project.

seancorfield 2025-01-16T19:20:25.182739Z

If you have a component A that has one or more interface nses, those can be referenced by any other bricks' code.

seancorfield 2025-01-16T19:21:41.488049Z

In your example, none of A, B, C, or D would list other bricks in deps.edn; only project E (and development) would list local dependencies.

seancorfield 2025-01-16T19:22:37.681169Z

For point 2a, you would not "compile on itself". You only compile/build/test via projects (including development).

seancorfield 2025-01-16T19:23:19.919509Z

B, C, D source code would all refer to interface nses in A, B, and C as needed.

seancorfield 2025-01-16T19:23:36.659049Z

Does that answer your question(s)?

ikitommi 2025-01-16T19:33:35.988089Z

yes, thanks. It answers. Only projects are concrete, everything else is just abstract building blocks. 🙇

👍 1
👍🏻 1
💯 1
seancorfield 2025-01-16T22:18:06.238889Z

I've been using the latest SHA of the cljs-support PR to test the updates as they're made... however, when changes are force-pushed to a branch, that kills the SHA I was using and I have to keep updating my deps.edn. This is a) really annoying and b) bad practice anyway, as far as I'm concerned: force pushing should almost never be necessary if you're using git correctly. Maybe @tengstrand can speak to why he keeps force-pushes changes? @furkan3ayraktar You've also done this on that branch. The alternative is that I just ignore work-in-progress pull requests and only test changes after you've merged them and then open new issues for bugs you've introduced. Would you prefer that?

Mark Sto 2025-01-23T20:50:12.468759Z

Using force-pushing is totally fine while you work in an isolated, non-public branch. In OSS community this isn’t usually the case after the first “feedback welcome” proposal.

seancorfield 2025-01-23T21:06:24.946489Z

@mstoyukhin I think you mean "while" not "until" there, right?

😅 1
tengstrand 2025-01-16T22:48:43.647179Z

You are right, we need to stop force pushing, so you can continue using your sha. I forgot that it could make life hard for other people. I rebased and force pushed, to keep the commits clean, but I don't need to do that any more. Good that you pointed this out.

👍🏻 1
jussi 2025-01-17T06:58:08.379059Z

I have had to learn to use git merge while working in a branch and avoiding conflicts on the PR for the aforementioned reason of breaking SHA's

Mark Sto 2025-01-24T16:08:30.977259Z

Sure, sure. I’m not a native speaker, mille pardons.