This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-11-15
Channels
- # announcements (1)
- # asami (29)
- # babashka (31)
- # beginners (48)
- # calva (39)
- # cljsrn (4)
- # clojure (56)
- # clojure-dev (51)
- # clojure-doc (3)
- # clojure-europe (40)
- # clojure-gamedev (13)
- # clojure-italy (22)
- # clojure-nl (3)
- # clojure-uk (5)
- # cursive (9)
- # datomic (184)
- # events (7)
- # fulcro (8)
- # graalvm (2)
- # jobs (1)
- # malli (6)
- # meander (1)
- # nrepl (5)
- # off-topic (10)
- # pathom (9)
- # polylith (33)
- # portal (2)
- # re-frame (7)
- # reagent (12)
- # releases (3)
- # remote-jobs (3)
- # reveal (27)
- # shadow-cljs (34)
- # sql (1)
- # vim (7)
- # xtdb (62)
A small question about the great example https://github.com/seancorfield/usermanager-example
The app-state
should be a component
or project
? Since it could have different app-state if we have multi project
using the same code. e.g. I have a new schedule job projects/usermanager-email-notification-scheduler
which is a separate deployment artifact, I might not need the same configuration that used in the projects/usermanager
.
You could have multiple components that implement that same interface and each project could choose which to use.
At work, we have multiple http-client
components with the same interface. One is an implementation based on httpkit
, one based on Hato
.
hi, we are evaluating polylith and I have some questions that I decided to ask and maybe get some answers.
Polylith does not do anything around state management, you need to manage it yourself in a way that fits you the best. You can choose component, integrant, mount or any other state management library. I know that @U04V70XH6 is using component together with Polylith and he is happy with that. We are using mount at work.
No worries! I’m happy to answer your questions. Some of our Polylith components requires internal state, which sometimes depends on some other components state, in turn, it needs to be coordinated. Then, what we do is, we define the components state within their implementation and expose functions in the interface, if it’s necessary, to access that state.
@U011NGC5FFY Happy to answer any specific questions you have about Component usage with Polylith. My user-manager
example repo has a Polylith branch with an example of Component for application state. You can see the components
interface here: https://github.com/seancorfield/usermanager-example/blob/polylith/components/app-state/src/usermanager/app_state/interface.clj -- so the actual Component machinery (lifecycle) is hidden in the implementation.
thanks for chipping in, now we are evaluating polilith - working on a large code base that has been developed for over 5 years now
Integrant is new to me (I’ve been using @U0541KMAZ ' mount
for some time now), but Polylith makes it… interesting. I’m probably doing my database
brick correctly: returning a connectable of some sort; and my app-URL brick less correctly: loading a base URL from a config into an atom
used for URL generation.
However, either way, one minor issue is Integrant’s load-namespace
method: because all access goes through my.ns.my-brick.interface
, I have to have configuration keys like :my.ns.my-brick.interface/foo
or :my.ns.my-brick/interface
to make that work. But the core
code can’t require the interface
, so it has to spell out the full qualified keyword, rather than use ::foo
or whatever.
@furkan3ayraktar I don't understand why there are no dependencies between components. Article component depends on the db component but that one is not available in deps.edn of articles. https://github.com/furkan3ayraktar/clojure-polylith-realworld-example-app/blob/master/components/article/src/clojure/realworld/article/store.clj
The reason that components don’t have dependencies between is that they are individual building blocks, like lego bricks, with their own external dependencies. The internal dependencies between components are via their interfaces, not implementations. Defining a specific component dependency would break that principle and take away the ability to replace components. You could have two components that implements the same interface and different projects could choose whichever of those different implementations. The component that consumes the interface doesn’t need to know which implementation is used. @U04V70XH6 explains how they use it https://clojurians.slack.com/archives/C013B7MQHJQ/p1636389094211500?thread_ts=1636379842.209500&cid=C013B7MQHJQ. Internal dependencies are resolved when you put bricks together within a project. A projects configuration defines which components and base go together and if you are using poly CLI, it warns you in case of missing dependencies. If you are not using the CLI, you’ll probably notice the missing components during compile time.
@U011NGC5FFY I also blogged about that -- see the Polylith & Swappable Implementations section of https://corfield.org/blog/2021/10/13/deps-edn-monorepo-7/
@U011NGC5FFY We’re now also in the process of migrating a legacy codebase to polylith. Of course I don’t know where you expect potential resistance to focus, but it’s quite doable to do the migration in “baby steps” over a large period of time. We basically converted three separate clojure projects (“common” library, “service one” and “service two”) into three big components. That immediately gave us the ability to run the two services in one single REPL, which is huge for us in terms of development experience. And now we’re slowly extracting components as we go. It’s going quite well I have to say.
we'll be doing similarly. 35 systems across four service projects and one library project
will start with 1 component and 4 fat bases, and a mega-crap-ton-big interface in the component 😅 and then refactor piece by slow, careful piece from there
I didn’t understand this question. Could you elaborate on when you say “mix of API and implementation”?
I think you shouldn’t think about this from an OO perspective. Polylith interfaces are functional interfaces, they are functions that delegate to the implementation and you do not instantiate any objects. You can think of a Polylith interface in Java as a class with full of static functions that delegates to the interface.
There are some FAQ around the interface topic on this page: https://polylith.gitbook.io/polylith/conclusion/faq
Is it idiomatic for components to have some implementation specific functions that are called from the base, (e.g. different implementations may have different way to initialize themselves), or we should strive to put everything into interfaces?
Componets and bases can only access other componets and bases via their interfaces. Otherwise, poly CLI will present you an error. If there are slight changes between different implementations of an interface, it could be an idea to have overloads of a function or some extra functions in the interface that one implementation could skip implementing and just return nil?