Recent submissions

Comment · 4 years ago
Thank you for explaining how you work, and I would never laugh at a developer for copy/pasting code. We've all done it!

I'm still intrigued to understand exactly how you share code across services. Let's say that you've written a piece of code for logging, which you want to use in both service A and service B. Do you package it up in a library? If so, doesn't that mean you have to place that library in a repository, so both services can access it? Doesn't that mean that if you want to make changes to the logging code that you now have to publish a new version of the library, and remember to update both services to depend on the new version?

That's the friction I'm talking about.

With Polylith, the logging code would live in a component that's directly accessible to all the other components in the system. That's because Polylith lets us work with all our components as if they're a monolith (even if we chose to deploy them as multiple services). This means that when we update the logging component, there's zero friction to update any impacted components in the services.

If the change only affects the logging component's implementation (and not its interface) then no other components need to be updated, and we can just redeploy the system. If it's a breaking change to the interface, then we can immediately fix the impacted components within our monolithic development environment. If the change is a refactor of the logging component's interface, then the other components will be automatically updated by our refactoring tool!

Hopefully that explains how Polylith solves this challenge so elegantly.

Comment · 4 years ago
Thank you for your comprehensive and detailed feedback!

I'll leave Joakim to respond to your comments about his presentation, and I'll respond directly to your comments about the nutshell video.

> you've actually never demonstrated your product to me once

That's partially true, although I'd argue that by showing the components and bases from an example system, we are showing "the product". Perhaps you're thinking about showing code or filesystem structure from a complete production Polylith workspace? We do that in other videos, but didn't think it would be a good fit in the 10-minute "why?" introduction.

> The toothpick model isn't a mess, it's a masterpiece. I admire the person who made it, but you're telling me that I shouldn't want to build software with that model.

I agree that the toothpick model is a masterpiece! However, the reason we shouldn't want to build software in the same way comes down to one word: change. The real Whitehouse doesn't change shape very often, but all the software I've ever been involved in building does. That's why building software with LEGO pieces is so much better than building it with toothpicks and glue. Which is exactly why it's a such strong metaphor.

> Secondly, the Lego analogy is overdone. As I said in another post, every architecture has made this claim, even if they are actually toothpicks.

You might be right about this, but most of the other recent architectures we'd come across seemed to steer away from talking about LEGO (onion, hexagon, DDD, microservices, etc.), so we were hoping it wasn't overused.

Comment · 4 years ago
I'm not sure we're understanding each other. When I asked "How does it solve the problem of sharing code across service boundaries?", I meant how does your language or architecture enable you to share code across separately deployed artefacts, for example across two microservices.

There are three approaches that I'm aware of for solving this problem: 1) copy/paste the shared code between the two repositories, 2) freeze the code into a library that both services depend on, 3) keep both services in one repository, extract the shared code into a module or component, both services depend on the shared module, deploy the services as separate artefacts.

1) is bad for obvious reasons, 2) adds unnecessary friction to the development process, and 3) is how Polylith solves it.

I was wondering if you've come across another way to achieve 3), or perhaps a fourth approach?

Comment · 4 years ago
That's useful feedback, thank you. I'll suggest that change to Joakim.
Comment · 4 years ago
Have you read the "Advantages of Polylith" page? https://polylith.gitbook.io/polylith/conclusion/advantages-o... It tries to summarise the benefits from both a development and deployment perspective.
Comment · 4 years ago
Technically, a Polylith interface is a collection of "pass-through" functions, each of which delegate their function call to an "implementation" function within the component.

I agree with you that many languages have syntax to support building interfaces. However, I've yet to come across one that offers all the benefits of Polylith's approach with components.

Comment · 4 years ago
Which ecosystem do you work with? How does it solve the problem of sharing code across service boundaries?
Comment · 4 years ago
That's right, it's a highly opinionated approach to building software, which comes with a host of benefits.

Including my favourite; a complete untangling of your development and production environments. With Polylith you always develop your system as a monolith (because that's the most effective way to build software), but you're able to deploy it as multiple services (because that's sometimes the most effective way to run software). It turns out that separating deployment complexity from development complexity is a game-changer, and something that I haven't come across from other architectures.

It's true that you don't reap all the benefits of Polylith until your entire codebase uses the same structure, which feels a bit like "all or nothing". However, many of the benefits are unlocked "as you go", so even converting one or two existing microservices to Polylith will feel like a nicer codebase to work with.

> so I shall simply wish you good luck with that part

Thanks!

Comment · 4 years ago
I was confused because you were replying to a comment which mentioned the "long video", so I assumed you were both talking about the forty-minute one on the homepage of the documentation. My mistake.

Did my response to `cjg` in this thread help to clarify anything for you?

Comment · 4 years ago
The idea with that part of the video was to couch the new concept (components) within the framework of existing concepts (functions, objects, layers, etc.) to try to help people connect the new concept at the right place in their knowledge graph. Though your feedback makes me think it didn't work as well as I hoped.

Components do have attributes in common with microservices and with stateless objects (e.g. a public interface and encapsulated implementation).

Where components differ from microservices is that a component's interface is simply a collection of functions, rather than network-facing endpoints. This means that multiple components can be deployed into a single artefact, keeping deployment complexity and cost down.

Where components differ from objects is that a component is a higher-level abstraction, closer in scope to a microservice.

However, we think that Polylith's biggest differentiator is the separation it gives between development and production. Let's say you have a Polylith project with 100 components, that you deploy in production across 10 services. You can work with all 100 components in a single development environment, and test them as though they're a monolith, even though they're not deployed that way in production. It's a lot like building systems with LEGO, and we think its just as fun!

Comment · 4 years ago
Exactly! Components are an attempt at scaling-up functions to a system-level building block, whilst maintaining as many of the benefits as possible.
Comment · 4 years ago
Your understanding of Polylith is essentially correct. It is a combination of existing ideas, such as monorepos, convention, components, interfaces, encapsulation, and static code analysis. However, I'd argue that what emerged in Polylith from those ingredients was more than the sum of its parts - due to how those particular concepts resonate with each other.

For example, because of the forced conventions, it's trivial for the Polylith Tool to perform static code analysis on a Polylith codebase. This means that the tool can identify the subset of tests to run, based on the components that have changed since the last run. Which leads to a fast-feedback loop, and encourages both good testing practices and fine-grained component modularity.

Polylith gives you a system-level architectural building block; the component, which encourages a modular design and separation of concerns. However, you're right that it's still possible to create spaghetti code with Polylith. All it would take is poorly designed components, with bad names, multiple reasons to change, and exposing their state everywhere. However, I'd argue that when you give someone a well designed tool (like Polylith), then they're more likely to craft a well designed product with it.

To understand how builds and deployments work with Polylith, I'd recommend reading the "Workflow" section in the Polylith Tool's documentation: https://polylith.gitbook.io/poly/workflow/shell (especially "Build", "Git", "Continuous Integration", and "Testing").

Comment · 4 years ago
Thanks for the feedback, we appreciate it.

It's tricky to pick the right level of detail when explaining an idea like Polylith. If we could precisely identify the level of understanding of the reader, then we could tailor the content to perfectly match their experience level and vocabulary. Unfortunately, we can't do that, so we have to pick a middle ground, where we probably over explain some concepts, and under explain others.

However, we'd be grateful if you could give us some specific examples of sections or pages that you didn't find useful or enlightening.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton