This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-05-07
Channels
- # announcements (16)
- # asami (15)
- # babashka (12)
- # beginners (38)
- # calva (32)
- # cider (1)
- # clj-commons (9)
- # clj-otel (4)
- # clojure (57)
- # clojure-europe (43)
- # clojure-korea (1)
- # clojure-nl (1)
- # clojure-norway (13)
- # clojure-uk (4)
- # clojuredesign-podcast (9)
- # clojurescript (10)
- # cursive (5)
- # datahike (9)
- # deps-new (2)
- # events (1)
- # fulcro (8)
- # hyperfiddle (7)
- # kaocha (1)
- # lsp (2)
- # malli (3)
- # nrepl (2)
- # off-topic (19)
- # releases (3)
- # ring (10)
- # shadow-cljs (4)
- # sql (14)
- # xtdb (57)
- # yamlscript (2)
@neumann @nate Have either of you looked into Polylith? It's used heavily by Sean Corfield at world singles. It gives you an opinionated folder structure (which helps orientation) and then has a CLI tool to enforce that you are only ever calling code via an interface file (part of the opinionated folder structure). You can enforce the check as part of your CI process, so that you know it's being done. This lets you have a familiar structure between projects. And allows all your projects for work, to live in a single monorepo where you can have a repl connected to all of them without having to dip in and out of different projects.
@U04A1LVBBPU I have not had a chance to try it out yet, but I would like to. All of the project I've worked on since it was announced were entrenched prior to Polylith or have been small. I'd love to hear more experience reports. Have you used it?
We use it at work, and I like it the structure that it brings. Because the entire code base is available via a dev repl, it makes it really nice to work with as well as avoids libraries used in one code base from getting out of sync with others and requiring the coordination that entails. But I like that I just have to look at the interface.clj for a component to see it's "API" and don't have to sort through the implementation. It's nice that you get programmatic support for checking that's the case (if a call to something that is not in an interface happens in the code base the Poly CLI check command will find it)
I think the thing it took me a while to realize is that Polylith is completely a source code organization project/tool. It's independent of the artifacts it produces. The constraints it places on you are just on code organization, and doesn't take away anything you would want to do at runtime. And the constraints in code organization, end up being helpful in that they make you think of proper names for things early in the process, and think about their bounds/scope so that the whole project doesn't devolve into an interconnected mess (which is what happened to each of my previous non polylith projects)
@U04A1LVBBPU Thanks so much for writing about your experience with Polylith! I read up on it. It's really neat that (as you mention) you don't need the tool to get started. You can achieve it with just local deps. That feels very simple! It seems like a great system! @nate and I had a big project where we needed to factor out common functionality that was used in different services. What Polylith defines as a "component" really reminds me of what we had. Each was independently testable. We simply included them as local dependencies. It wasn't as formal as Polylith, but we had similar goals. I'll have to experiment with it more. Thanks for bringing it up!
@U04A1LVBBPU Thanks for opening up such an interesting topic. I've been curious about Polylith and have been wondering specifically about two aspects of it that I tried to, somehow cumbersomely, express a few months ago here: https://clojurians.slack.com/archives/C03RZGPG3/p1702906360659049?thread_ts=1701934327.512569&cid=C03RZGPG3 I would love to learn more on this topic.
It took awhile for me to realize that architecture (microservices vs monolith vs other) is orthogonal to polylith. Polylith organizes your code so that it's in a monolith, where you can a REPL that has access to all of it at once. However, you can have (in the case of world singles) 22 projects. Each of which builds a separate Uberjar, and could be deployed as a microservice if you like. Or you could have 1 uberjar that has everything in it. That is up to you. So to answer your question, how is breakage approached? You have a couple options. 1. Break the API and update it (you have all the code in one repo) 2. Make a new component (with a different name) and use that where you would have used the new one, and leave the old one alone (what Rich says to do in his talks) 3. Do number 2, then slowly pay down tech debt at your own pace Polylith makes both easy. For #1, you have the tool to tell you all the callsites for that interface you are about to break. For #2, you can support multiple projects that use different components
@U04A1LVBBPU Thanks a lot for taking the time to reply, it solidified my view on the problem. Also because of your input, I've experimented briefly with polylith and it enriched my view on how code can be organized. I like the component-per-dir approach of polylith, and also the explicit interface; it feels it gives namespaces the structure in which I can orient myself better. I'm experimenting with this new structure now in my current project.
@U0609QE83SS I'm starting to experiment with it myself. Let's trade some experience reports after using it for a while.