Fork me on GitHub

Hi all, I’ve been reading a lot about Polylith recently, and I very much like the concept. We decided to try and migrate our monorepo to Polylith. We’ve made the first steps, and things are working nicely. Basically, besides the Polylith folders, we have created a folder “libraries” that contain a few (quite large) libraries that we use in our apps. As per, I have migrated the smallest library to a component just now; it has a very small interface surface area, so that was quite easy. Two other libraries have very large interface surface areas however. So now I find myself confused on how to proceed with the migration. The logical migration path seems to be: library -> one single huge component -> lots of small components. But then, like @emccue, I run into the issue that everything MUST always go through the interface, and for those huge components that doesn’t seem feasible. And I cannot set aside a couple of weeks just for refactoring this all at once. Don’t get me wrong, I absolutely like to get to the end state eventually, but I also like to find a path towards it that allows me to chip away at it one piece at the time. Is there an alternative migration path that I’m missing? It doesn’t feel good to have a dependency from polylith component “foo” to library “common” back to polylith component “bar” (and potentially indirectly “foo” as well), if that is even possible. Thanks for your thoughts!!


You could also place all of your code in the interface.clj without splitting it into interface + implementation. You can eventually refactor into proper components. However, this could be bad if that code lays there for a long while an people start to think its the final state. Another option (the one suggested in the documentation) could be placing all the legacy code into a base and extract components out of it gradually. This way, you’ll always have proper components and the base with the legacy code can refer to those components. Over the time, you will have many components and the legacy base will disappear slowly.


Interesting, I didn’t think of making the libraries into bases. But then a component “my-special-new-shiny-component” would have to depend on the base “legacy-common”. Would that work?


I don't think components can refer to bases? What we've done at work is move applications to bases and then slowly refactored code out of those to components. For our "libraries", we mostly kept them in the legacy subprojects and had the migrated code -- in both bases and components -- depend on the legacy subprojects via :local/root deps. Then over time we've extracted components from those in a bottom-up process, ensuring each new component depends only on existing components that we've already refactored out (to avoid potential circular dependencies).


That said, we have a couple of components that still depend on legacy "library" subprojects but those are fairly "big" components that only bases depend on. Teasing legacy code apart so components are small and relatively self-contained is definitely tricky and takes time.


The renaming to .interface is definitely the most painful thing about migrating to Polylith @UGNFXV1FA


But we're basically in the "large library" situation like you.


Yes, that’s pretty much the direction I was taking. I was hoping for a quicker method to get as much of the code under Polylith sooner, but ah well, this way will work too. Yes that interface thing, but that’s also what appeals to me so much, I feel “normally” the distinction between public and private is not enough. Hence also people are using the “impl” pattern I believe, which is a different way of differentiating between interface and “the rest”.


Thanks for your feedback @U2BDZ9JG3 and @U04V70XH6!


Cool that you are migrating to Polylith @UGNFXV1FA. No, components can’t refer to bases, at least not via direct function calls. You need to be patient, and begin by putting your code into bases if they are not directly accessed by other code, and the rest as :local/root imports if they are, in the same way @U04V70XH6 suggests, and then try to tease out one component at a time (and maybe also perform the step suggested in the documentation, by teasing out one huge component from each base).