A component is an independently compilable project directory, with a build file, tests, and a source folder containing separate packages for its public interface and its private implementation.
Components are service-level building blocks, which remove the need for layers (horizontal, vertical slice, or onion) in your architecture.
A component can represent a part of your domain (e.g. cart, invoice, order, user, etc.), or be part of your infrastructure (e.g. authentication, database, log, etc.), or be an integration point to a third-party system (e.g. crm, payment, sms, etc.)
A component's interface is a single package that exposes a collection of functions for other components to call. Each function in a component’s interface “passes-through” to an equivalent function in its private implementation. This “pass-through” approach enables full code navigation and refactoring, whilst maintaining encapsulation.
A component's implementation is one or more packages that implement all of the component’s exposed functionality. A component’s implementation packages are made inaccessible to all other components by the Polylith build tool.
Component-A depends on Component-B by importing Component-B’s interface package into one of its implementation packages. This enables Component-A to call any of the functions that Component-B has exposed in its interface.
A service is an independently compilable project directory, which contains a set of components and a single base. The components and base source code are linked into the service, but are stored independently. This allows for optimal code reuse of components across multiple services.
Service-A depends on Service-B by calling Service-B’s API from one (or more) of its components. This enables Service-A to call any of the end-points that Service-B has exposed in its API.
A base is a special type of component that only exposes its functionality via a public API (e.g. REST, GraphQL, gRPC, command-line, etc.).
A base is an independently compilable project directory, with a build file, tests, and a source directory containing a public API and a private implementation.
A base exposes a collection of endpoints via its API, and delegates the implementation of each endpoint to an appropriate component.
An independently compilable project directory, which contains all of your components and bases. The components and bases source code are linked into the development environment, but are stored independently.
This gives a “monolithic development experience” with full code navigation, debugging, and refactoring across your entire code base, and the possibility to work with your entire system in a single REPL.
Components simplify the design of our services by giving us building blocks at right level of abstraction, which are understandable, composable, reusable, and replaceable.
Components are inherently simple and easy to reason about; they are just code, have a clear interface, and hide their implementation.
Components maximise code reuse to the point of having zero code duplication across our entire code base.
Polylith’s single development environment gives us a delightful development experience; we get all the benefits of coding with a monolith (code navigation, debugging, refactoring, and a single REPL) but maintain the flexibility of deploying our components into any combination of services.
Let's delve deeper into why a new software architecture might be needed.