# Sharing code

People often wonder what Polylith brings to the table and if it's worth looking into.

To see if Polylith might be right for you, ask yourself whether these statements are true or not for the systems you work with:

* I can easily split up a service into two.
* I can easily share code between services without creating libraries.
* I have no unwanted code duplication in my entire system.
* I can easily change, find, refactor, debug, and reason about all my code, even across services.

There aren’t many developers who can do all the above, but if you can, congratulations! Even so, Polylith can still help you be more productive and enjoy your work, so keep reading!

## The difficulties of sharing code

Let's say we have two nicely structured services, where each box represents some source code that lives in its own namespace with a single responsibility:

<div align="left"><figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2FvfX9fb8FpXR5sYwRgnsc%2Fservice.png?alt=media&#x26;token=4a9c4afd-3805-4f4c-a03b-31458f89bde1" alt=""><figcaption></figcaption></figure></div>

If we want to use the code that lives in the red box in both service A and B…

<div align="left"><figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2FM3JeA5TZwWwJ3mh9wq3O%2Fservice.png?alt=media&#x26;token=c757b5e9-ed89-4e1b-9d7d-8c600d0c9a75" alt=""><figcaption></figcaption></figure></div>

...we have four alternatives:

* Duplicate the code
* Create a library
* Create a service
* Use a monorepo

### Duplicating the code

If we take a closer look at service A, we realise that the red box depends on the green box that depends on the purple box:

<div align="left"><figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2FzLhrpWZA6Fgyn3X9GYu8%2Fservice.png?alt=media&#x26;token=bcfdf2ec-a027-48c3-be27-23c65d46950e" alt=""><figcaption></figcaption></figure></div>

Now we not only need to copy the red box, but all three of them, and paste them to service B:

<div align="left"><figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2FSnnZDaVUZrdnKQVfTHlF%2Fservice.png?alt=media&#x26;token=665cca8c-d4d1-42bd-ad0b-d2a8333af99b" alt=""><figcaption></figcaption></figure></div>

This introduces a lot of [code duplication](https://en.wikipedia.org/wiki/Duplicate_code) which is generally considered undesirable.

### Creating a library

The second alternative is to create a library:

<div align="left"><figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2FErzvcSNOPxiY9PFRaZmT%2Fservice.png?alt=media&#x26;token=95aca7fa-a50a-4cc3-9130-52401768ea80" alt=""><figcaption></figcaption></figure></div>

Because the three boxes were connected, we have to include all of them in the library, which violates the [single-responsibility](https://en.wikipedia.org/wiki/Single-responsibility_principle) principle.

Creating a library also harms the development experience, because changes to the code no longer take effect immediately, as we need to build a library every time we make a change.

<div align="left"><figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2FvJOIwjpAHWa0ggcN2a8l%2Fservice.png?alt=media&#x26;token=df1267e8-3ffa-4821-95b3-2ae21cecf935" alt=""><figcaption></figcaption></figure></div>

If we have many services and perhaps many teams, the risk is that we don't get round to updating the version in all the services, which means that we don't use the latest code everywhere.&#x20;

Another option is to create three separate libraries instead of one, however this will make it even harder to keep the code in sync.

The longer we wait to upgrade all libraries to the latest version, the harder it becomes and the higher the risk of introducing bugs.

### Creating a service

The third alternative is to extract the code we want to share into a new service, that lives in its own repository:

<div align="left"><figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2FjlbAAaHd69UvMQ7knvbt%2Fservice.png?alt=media&#x26;token=992fedd5-559c-4d98-9299-a3208074cfc8" alt=""><figcaption></figcaption></figure></div>

Now we add some code to call service C from A and B. This seems to solve our problem, albeit at the price of increased complexity, as we now have one extra service to maintain, and simple function calls have been replaced by network calls.

But let’s see what happens if we add a blue box to service C, which may happen in the future:

<figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2Fi5Iq9Na1g7B3sT3oyuXs%2Fservice.png?alt=media&#x26;token=e6a2f1aa-cd41-451d-a9ef-cc789a8e430c" alt=""><figcaption></figcaption></figure>

Now this piece of code can't easily be shared by the other two services, and we are thus unfortunately back to square one.

### Using a monorepo

The fourth option is to use a [monorepo](https://en.wikipedia.org/wiki/Monorepo), where the code is shared among several src directories instead of just one. Polylith uses this idea but takes composability one stage further, which we’ll soon cover.

This is what a Polylith system looks like; where all boxes (called bricks) can freely access one another ¹ via their exposed *interfaces*:

<div align="left"><figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2FkKEXq3VT1qfnY7UFh733%2Fservice.png?alt=media&#x26;token=18383a5e-88ce-44ca-a212-1dc43ee2aa27" alt=""><figcaption></figcaption></figure></div>

An interface in the Polylith world is just a namespace with the name *interface* ². Since bricks now all have access to each other, we have the freedom to combine them in any way, and they will automatically "connect" ³:

<div align="left"><figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2FlJ2MmGFBnLerUQQxT37k%2Fservice.png?alt=media&#x26;token=f4328c1a-6d95-4df9-b750-0bc3d21c2d2f" alt=""><figcaption></figcaption></figure></div>

Libraries and bricks are used in a similar way so it's sufficient to refer to them by name (here illustrated with dashed lines). But there are also significant differences as libraries are versioned and compressed, while bricks are plain source code which can be easily changed.

If we want to divide service B into two, we can easily do that ⁴:

<div align="left"><figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2F4HhT6Jk2xKsKvdccDCDr%2Fservice.png?alt=media&#x26;token=2544d3ad-efaa-4f2c-9626-2e18e8e9b9a0" alt=""><figcaption></figcaption></figure></div>

Another superpower is the *development* project from which we can work with all our bricks ⁵ and where code changes are immediately reflected in all services:

<figure><img src="https://3095132514-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LAhrWK1psIWk5h5zNLV%2Fuploads%2FHTTW705yBG8DUCXJHhaP%2Fworkspace.png?alt=media&#x26;token=c9932448-802d-42d9-8e90-499825f8ee45" alt=""><figcaption></figcaption></figure>

We have now reached our goal of being able to work with all the code in an efficient way, while also enabling the code to be easily split up and shared ⁶ between services ⁷.

The next great advantage is the ability to test the code incrementally.

### Summary

The whole idea with Polylith is to reduce complexity and make our lives easier, both when developing the code and when changing how things are executed in production.

The introduction of new high-level concepts with well-defined responsibilities in combination with a standardized directory structure also contributes to making the code easier to reason about.

All of this aims to make coding a more joyful experience, while saving both time and money.

In the next section, we will show how the code can be tested incrementally.

### Footnotes

¹ We are only allowed to access interfaces, not the implementing namespace(s). All bricks can access each other, except the green [components](#component) that can't access the blue [bases](#base). These constraints are guaranteed through the use of a Polylith [tool](https://polylith.gitbook.io/polylith/tool).

² The default name is *interface,* but can be changed to any valid namespace name, e.g. *ifc*. Having interface sub namespaces are also allowed, like *interface.mysubns*.

³ The included [bricks](#brick) for a [project](#project) are listed by their name in a config file, which may be implemented differently depending on the chosen programming language and tooling. An interesting detail is that a brick defines which libraries it uses, but not its bricks. They are instead defined in the projects, which makes them loosely coupled and interchangeable ⁵.

⁴ We also need to add some code to B2 to make a service out of it.

⁵ As long as we have just one [component](#component) per interface, which is true 95% of the time, then these components can be directly changed from the [development](#development-project) environment. In the other 5% of cases, they can be edited in other ways, either by switching them into development by using [profiles](https://cljdoc.org/d/polylith/clj-poly/CURRENT/doc/profile), or by directly changing the file (but then we don’t get the refactoring support from the IDE).

⁶ The introduction of interfaces allows us to replace one component for another, as long as they satisfy the same contract/interface (often just a set of functions). The use of [profiles](https://cljdoc.org/d/polylith/clj-poly/CURRENT/doc/profile) makes it possible to switch between components that implement the same interface, from the [development](#development-project) environment. How a service is exposed/called can easily be changed by replacing the [base](#base), from e.g. REST to lambda function.

⁷ Polylith supports any type of artifact, such as services and tools.
