Base

Last updated 18 days ago

Bases are the foundational building block in Polylith. They are a system's gateway to communicate with the outside world.

Bases achieve their encapsulation by separating their implementation from their interface. The metaphor visualises this by showing the base with two layers:

The light-blue layer is the interface (API) and the dark-blue layer is the implementation

Every base has one responsibility: to expose a system's functionality to the outside world.

Because a base's interface exposes an entire system's functionality, we refer to it as an API (Application Programming Interface).

In Polylith, you're free to use any API technology in your base, for example REST, gRPC, GraphQL or just the plain old command line.

Flipping this base reveals its flat bottom

One difference between bases and components is that a base has a flat bottom. This means that bases aren't composable; they can't be depended on by other building blocks. A base always sit at the bottom (the "base") of a Polylith system.

You can look at the source code of the rest-api base in the RealWorld example app to see how it exposes a REST-API. We'll use the same base to see how its code relates to the metaphor.

API

A base's API exposes all of the system's public functionality.

The light-blue layer represents the API, which contains the base's endpoints

If we examine the source code for this base's API, we see that it actually exposes twenty-one endpoints.

To simplify the metaphor, we pretend that the API only has four endpoints.

This system exposes itself to the outside world as a RESTful API, so the base is called rest-api. The code snippet shows the api namespace within the base. Just as with a component, Polylith asks you to put a base's interface (API) in one namespace, though you can spread the implementation across as many namespaces as you like.

The yellow socket is how the 'login' function is exposed to the outside world

The code snippet shows all the API's endpoints for interacting with the various domain entities that the system manages.

You can imagine other systems (Polylith or otherwise) connecting to a base with cables that mate with its endpoint sockets (representing remote API calls).

Popping the base open reveals its API's "pass-through" dependencies

Similar to a component's interface, a base's API is a thin layer that simply passes through any endpoint calls to the equivalent function in its implementation. Here we've highlighted the yellow stud which represents the dependency on the 'login' function in the base's implementation namespace.

The implementation layer exposes its 'login' function signature

Hopefully you now understand that bases share a very similar structure to components. The way a component's interface connects with its implementation matches how a base's API is connects with its implementation.

Where they differ is that a base's API exposes endpoints to the outside world, whereas a component's interface exposes function signatures for other building blocks.

Implementation

A base has a thin "pass through" implementation layer which calls the appropriate functions in other building blocks.

The yellow stud is the dependency on 'login!' from the 'user' component

Here we see that this base's implementation of 'login' is just a thin wrapper around a dependency on the 'login!' function from the 'user' component. The base's implementation adds some validation which allows it to return the values expected by the API.