Fork me on GitHub
#architecture
<
2023-09-21
>
tengstrand05:09:17

If you have missed the post in https://clojurians.slack.com/archives/C06MAR553/p1694925153126529, please take a few minutes of your time and read the updated https://polylith.gitbook.io/polylith/introduction/polylith-in-a-nutshell page!

🙌 1
Rupert (All Street)08:09:28

TBH, I'm not sure I understand Polylith yet. • is Polylith an architecture? • is it a pattern? • a set of best practices? • is it something new or is it documenting something old? • can you be doing polylith without knowing you are doing polylith? • is it a suite of tools? How do I know that I am looking at a Polylith repo? What's the rule of thumb? On the homepage it says: > Polylith is a software architecture that decouples the backend code into reusable ”LEGO bricks” that can be reused and shared (mainly) across services while we can still work with all our code as if it was a single codebase. This describes a lot of software - for example two decades ago - I was making reusable Java components and then wiring them together at runtime with Spring Framework XML. Does that mean I was doing Polylith? Creating modular code is purpose of many dependency injection frameworks (e.g. Integrant, Spring Framework, Google Guice etc). Is using Dependency Injection mean you are doing Polylith? The descriptions of Polylith seem quite broad/unspecific, I'm wondering if Polylith is this the following? > Polylith is the combination of two things: > > (A) All the features, benefits and mindset of a monorepo - but using multiple repos instead of just a single repo. (Note: This means that you must always use the same (i.e. latest) version of a module everywhere). > (B) The requirement to write code as modules/components and be able to wire them together flexibly (e.g. using dependency injection like integrant). > > If you are doing (A) and (B) you are Polylith if you are only doing one of them you are not doing Polylith. Or perhaps its something much narrower and much more specific?

imre08:09:57

My take has always been that is's a collection of patterns, best practices and suite of tools that help enforce the patterns/practices and help carry out development tasks (like running tests) in a monorepo. I think that it's orthogonal to architecture; by providing the above it promotes a way it considers easy towards code reuse and aims to help you deliver the architecture of your choice.

👍 2
👌 1
jasonjckn23:09:05

I think part of the issue is polylith itself could be simplified, maybe could be be broken apart into 2 or 3 pieces, if deps CLI at execution time only operates on 1 constructed classpath — just go up one level up in abstraction from there: a deps CLI-like tool, that is aware and constructs multiple classpaths at runtime, that's 1/4 chunk of polylith that could be standalone tool that composes with other tools to deliver the full feature set. I do like interfaces, but slf4j-api is another take on that pattern, that also works just fine with a long track record. So some people may want to take that or leave it. Not everyone desires that kind of compositional simplicity, can also make things harder to use. but you know i'm grateful for what was released either way, and kind of nit picking here, also am probably naive.

tengstrand03:09:06

I both agree, while also disagreeing with you @U08BJGV6E. Let's take an example. Slightly simplified, Microservices consists of two main ideas (as I understand it): - You want to divide the code into smaller parts (services) to be able to change and reason about it more easily. - You want to be able to deploy each service individually. If we take the Hexagonal architecture (Ports & Adapters) as an example, it has two main ideas that I know of: - Split the code in such a way that we separate the business code (domain) from other code, such as connections to the UI, databases, and message queues. - Abstract away how things are implemented, e.g. direct database calls, so we can change how we persist our data, without having to change the calling code. With Polylith, we essentially do this: - Divide the code into smaller parts, where each part is responsible for a specific area, to be able to change and reason about it more easily. - Split the code in a way so that we can freely share it between the services and tools we build. - Abstract away the implementation (e.g. how we persist the code) by introducing "interfaces at compile time". - Be able to work with all code from one place for increased efficiency. We can argue that all three architectures are a collection of patterns, best practices, and tooling support. All three attempt to address identified problems, like trying to reduce complexity or increasing changeability. Sometimes in similar ways, and sometimes in different ways. The important thing is that if someone talks about Microservices, Hexagonal, or Polylith, we should know which architectural pattern they mean. You can choose Polylith and at the same time try to ensure that you can deploy your services independently of each other. You will most certainly separate your components into pure domain components in Polylith, just as you would with Hexagonal (but without using components). So my tip is to use Polylith and at the same time use the best practices you find work well from other architectures.

🙌 1
tengstrand04:09:24

I'm guessing you mean the poly tool and not Polylith (which is just an architectural idea around how to share code, work with code, and reduce complexity) @U0J3J79FE. I have concentrated on building tool support that provides the best possible user experience, including an interactive shell and the ability to visualize the codebase. If any part can also be extracted and used separately, then it is free for everyone to do so as the code is open source.

❤️ 1
Rupert (All Street)11:09:15

> architectural idea around how to share code When I look at a codebase I'm struggling to understand if it is using polylith or not? e.g. I can tell if a codebase is made up of microservices; I can tell if a codebase is a monolith; I can tell if a codebase using dependency injection (or inversion of control); I can tell if a codebase is in a monorepo or multirepo; but I don't currently know how to tell if its polylith or not. How do I tell? Is there a list of things X, Y and Z and if it is doing all of these it is Polylith? e.g. if a codebase is using Java Spring Framework is that Polylith? If not what conditions are met/not met for being polylith?

imre12:09:37

@U1G0HH87L FWIW I don't consider microservices an architecture either, I consider it a deployment strategy. I do consider Hexagonal an architecture. > With Polylith, we essentially do this: > - Divide the code into smaller parts, where each part is responsible for a specific area, to be able to change and reason about it more easily. > - Split the code in a way so that we can freely share it between the services and tools we build. > - Abstract away the implementation (e.g. how we persist the code) by introducing "interfaces at compile time". > - Be able to work with all code from one place for increased efficiency. I read these points as: • usecase or domain driven design • modularity • dependency inversion (compile time but it is still DI) • monorepo And I like all of these and I think Polylith does a great job of supporting them. With polylith one can focus on the architecture they want to follow, whether that's hexagonal or layered or whatever, and then, using polylith projects and bases, choose a deployment strategy that they like, be it a monolith or microservices or something in between.

Rupert (All Street)12:09:05

Thank you. So does that mean that my 10 year old modular Java code that uses Spring Framework (dependency injection) and lives in a monorepo is likely to be polylith? What if I don't use a monorepo? Can I still be doing polylith? I feel like polylith is a collection of best practices - but doesn't make it clear which best practices are essential vs nice to have.

imre12:09:23

I think a monorepo is foundational to polylith but I'm not a team member there so can't really answer these

Rupert (All Street)12:09:07

> I think a monorepo is foundational to polylith but I'm not a team member there so can't really answer these I appreciate your answer and I think that confirms my concern that its not very clear!

imre12:09:11

These are good questions and I'm very interested in the answers to them. Hopefully in the end the true essence of polylith will be distilled

👍 1
tengstrand14:09:06

Before I try to answer @U08BJGV6E, I'm curious about what problem the Hexagonal architecture solves, that Polylith doesn't?

imre15:09:59

> what problem the Hexagonal architecture solves, that Polylith doesn't? Apples to oranges IMO. Hexagonal doesn't talk about how to organize source code, whether to duplicate or create a library, whether to use one or more repos etc. It says your component's business logic should declare its ports and not be source code dependent on the adapters implementing those. While one way to implement something like that is runtime polymorphism, Polylith says well here's an opinionated way to do that at compile time if you prefer that. It also talks a lot about organizing source code to make this possible and to address a lot of the pains associated with monorepos.

tengstrand18:09:59

This requires a proper answer @U08BJGV6E so will come back in a few days (I’m a bit busy right now).

imre18:09:34

Cheers @U1G0HH87L but I think my comments are the least interesting here and could be due only to my perhaps uncommon view on architecture. Feel free to prioritize the ones raised by others.

👍 1
tengstrand04:10:59

When I look at a codebase I'm struggling to understand if it is using polylith or not?I think this is a really interesting question. But I realised that if you look at an arbitrary system/codebase, how do you know if it's Hexagonal, Union, DCI, Clean architecture, Monolith, Polylith, Microservices, or something else? What all have in common is that they separate different concerns as a way to improve changeability, but they say very little about how this can be achieved in practice (Polylith is an exception here). As an example, you could put ten services/applications in ten different source files in a single src directory, and still say that you do Hexagonal, as long as the "arrows" point in the right direction, suggested by the architecture. If you look at a codebase like that, would you be able to recognize that to be a Hexagonal architecture?

Rupert (All Street)09:10:09

> how do you know if it’s Hexagonal I’m assuming plenty of time to look at the code and also have access to the configuration and deployment scripts etc too. As you read the code/configuration - if you draw a diagram that can help answer the question. > If you look at a codebase like that, would you be able to recognize that to be a Hexagonal architecture? Yes - given time I could see that the rules of hexagonal architecture have been met or not. They key thing about architectures (and also algorithmic patterns and data structures) is that they are well defined - so people in the team know if they have a Monolith/Microservices/Hexagonal architecture. Polylith doesn’t seem to have these simple set of requirements set out anywhere. It’s also not clear if Polylith is an architecture or a “collection of best practices”, it’s also not clear which elements are recommended and which ones are required (e.g. mono repo, dev project etc). As someone that has a codebase in a monorepo and highly modular components (over 200 separate clojure projects), I have no idea whether I am already doing Polylith or what changes I would need to be doing to make the codebase Polylith. In the current situation it is possible for someone to be a huge fan of Polylith (e.g. to write blog posts and give talks on Polylith) then find out 5 years later than none of the code they have written is actually Polylith because the rules are currently not written down.

tengstrand10:10:53

If you read the https://polylith.gitbook.io/polylith/conclusion/faq we answer the question "What parts of Polylith are important and what are just “cermony”?" like this: Answer: The short answer is that all parts are needed: • interface: Enables encapsulation and functionality to be replaced in projects/artifacts. • component: The way we package reusable functionality. • base: Enables a public API to be replaced in projects/artifacts. • library: Enables global reuse of functionality. • project: Enables us to pick and choose what functionality to include in the final artifact. • development: Enables us to work with all our code from one place. • workspace: Keeps the whole codebase in sync. The standardized naming and directory structure is an example of https://en.wikipedia.org/wiki/Convention_over_configuration which enables incremental testing/builds and tooling to be built around Polylith. On the https://polylith.gitbook.io/polylith/architecture/simplicity page, I also try to explain why all parts are needed. But maybe we should be more clear or add something @UJVEQPAKS?

tengstrand10:10:02

A Polylith codebase consists of one or several https://polylith.gitbook.io/polylith/architecture/2.1.-workspace which have four directories. Two of the directories, bases and components store the building blocks (called bricks) where each brick has its own directory in these two directories, with a unique names, e.g. "invoicer". These bricks can be put together into projects which is the third directory. A project is a directory, living in projects with the name of that project, which contains the bricks to include in each deployable artifact (e.g. service or tool). The fourth directory is the development directory that contains a configuration file that specifies all our bricks (sometimes not true, but always a big majority of them) so that we can work with the code from a single place. The directory structure with these four directories, reflects the architecture, and actually is the architecture, together with the constraint that you are only allowed to access components via their interfaces from bricks (bases can access bases, but components can't). So if you want to know if a codebase is a Polylith codebase, then looking out for these four directories @UJVEQPAKS is a good start.

Rupert (All Street)11:10:36

Excellent, thanks for the follow ups, I feel like this has helped me to understand it better. > What parts of Polylith are important and what are just “cermony”? This uses several terms that have existing/common meanings outside of Polylith (“interface”, “component”, “library”, “workspace”, “development”) - I misunderstood and thought you were referring to the general/common meaning for these terms, but you are actually referring to the specific/narrow Polylith meaning of these terms. It might be worth clarifying that in the FAQ text. Agree that your folder structure clearly indicates a codebase as Polylith or not. This means that non-Polylith codeabases can have many/all of the benefits of Polylith - but just a different folder structure. From this description it seems like Polylith is more of a Code Structure/Layout Convention rather than an architecture (e.g. Layered, Microservices, Event Driven, Service Oriented etc). It sounds like most Architectures are compatible with Polylith Code Structure Convention (ie Polylith doesn’t compete with them).

tengstrand13:10:28

Different architectures use different terms/lingo. port in Hexagonal has the same role as an interface in Polylith, and the incoming adapter has the same role as the base in Polylith. Just because we choose to use words that have been used before, and that we e.g. use components and bases to compose the deployable artifacts (called applications in Hexagon) instead of e.g. ports , adapters and core/domain doesn't automatically disqualify it from being an architecture. > It might be worth clarifying that in the FAQ text. Good point, will clarify that. > This means that non-Polylith codeabases can have many/all of the benefits of Polylith - but just a different folder structure. Yes, any given architecture X can have many/all of the benefits of any other architecture Y, but it doesn't automatically disqualify Y from being an architecture. For example, we can make sure that all our services can be deployed in isolation (Microservices) and/or that each service is structured as a Hexagon and is event driven. > From this description it seems like Polylith is more of a Code Structure/Layout Convention rather than an architecture (e.g. Layered, Microservices, Event Driven, Service Oriented etc). The way Polylith structure the code doesn't disqualify it from being an architecture. The structure reflects the architecture, which is really helpful when working with the code, and an active design choice, that makes it easier to reason about the code and to add tooling support around it. Polylith lives in its own category, Component based architectures, and you don't care much about layers when using it, just focus on the bricks, and how to deploy things in production (projects). Polylith has constraints on what can access what, just like Hexagon or Clean Architecture. It just has fewer types of building blocks, but it solves the same problem as they do. Polylith may seem like a code convention thing, but that is just a design choice among many. It is an architecture just as much as the Hexagonal architecture is. > It sounds like most Architectures are compatible with Polylith Code Structure Convention (ie Polylith doesn’t compete with them). Polylith let you share functionality across your services. This is possible to achieve with other architectures too, but is built into Polylith out of the box. Code duplication and the difficulty of changing how code runs in production are common problems that Polylith addresses, which I write about https://polylith.gitbook.io/polylith/introduction/polylith-in-a-nutshell.

Rupert (All Street)13:10:04

I guess some architectures are more abstract and some are less abstract. I can now see that Polylith can be considered an architecture that is less abstract. It may just be confusing if people are used to very abstract architectures (e.g. monolith/microservices/event sourcing/mvc etc) - I think this is what happened for me. > Polylith lives in its own category, Perhaps in some ways Polylith is in the same category of thing as Ruby on Rails? • Ruby on Rails is not an architecture. It strongly promotes MVC (an architecture) but allows you to follow other architecture as you wish (e.g. monolith, microservice, SOA, Event Driven etc). • Ruby on Rails code folder structure allows an ecosystem of tools to work with it (e.g. for testing/deploying/schema migrations). • The standardised code structure means that Ruby on Rails developers can quickly learn/navigate/understand new Ruby on Rails codebases (because the structure is always familiar). • The Ruby on Rails code structure convention saves time at the start of the project because the structure is already decided for you.

tengstrand14:10:29

It's true that Polylith addresses more problems than other architectures. In my opinion, the most important thing an architecture should address, is to slow down the exponential growth of complexity that is built into writing software, which cannot be avoided, just kept to a manageable level. I will try to explain my ideas in a blog post that I'm working on (that you already know about). Wikipedia says that https://en.wikipedia.org/wiki/Active_record_pattern, that Ruby on Rails implements, is an architectural pattern. For me it feels like Microservices is just a deployment pattern. We could also argue that decoupling things by using events also is just a architectural pattern, that can be used in combination with Clean Architecture, Hexagona, Polylith, or Microservices. This industry is quite obsessed with definitions, but the most important thing for me is that we design our systems in a way that solve real problems, and on top of that list is often how to fight complexity.

Rupert (All Street)17:10:22

I would mention that Active Record is just a small part of Ruby on Rails. Thanks very much for the discussion and for answering my questions in this thread. I look forward to reading the finalised blog post.

👍 1
tengstrand18:11:59

FYI. I just https://clojurians.slack.com/archives/C8NUSGWG6/p1698864153152019 the blog post in the news-and-articles channel.