I’ve started a few new projects recently, and faced a lot of bootstrap effort. Tricks of the trade, like efficiently loading environment variables into the runtime, or pulling together common setups for tests, take a lot of effort.
Developing microservices, or even things smaller than that, for serverless computing, you end up with lots of small separate codebases. There’s a dilemma:
- Write the same code over and over again
- Bloat the code with some huge monolithic libraries relating to all of them
That’s the dilemma you can see… there’s a hidden problem, though.
Libraries are Great Until They’re Not
Two separate services are NOT meant to share code. You enter all manner of dependency hell if you cannot guarantee the interface between libraries in a way that’s stronger than well, they were built from the same version of the code.
So when considering sharing a library across services, you have to look at some down sides we didn’t expect:
- What’s the coupling between unrelated services?
- What’s the build process for keeping services in sync with the shared concern?
- What’s the code bloat effect of this shared library?
- Will the maintainers of the library care about the services that consume it?
- Is this general purpose code even better than simpler, more specific code on a per-use-case basis?
- Will this library end up becoming a dumping ground for unrelated features – a feature magnet?
So Don’t Have ANY Libraries?
That seems a ridiculous prospect. If you have well-thought out components that solve common problems, coding increasingly becomes like attaching lego bricks. We want that effect. When it’s relevant.
What are the Success Criteria for a Library?
If you have a big monolothic build, then have libraries – they’re easy to manage and you can DRY everything out with them. It’s a good pattern.
If you are going to create a fantastic self-contained, maintained, reusable library. Doing it in the style of an open-source project. Then great. You’ll compose a solid set of interfaces and processes for keeping it working. You’ll have a splendid library and you can maintain and control it.
If you want to share a few local tricks between related modules, then:
- Modularise – make the library single purpose
- Ensure that the consumers are local
- Document it well, as though it’s a larger library
- Stop before it gets too diverse/entangled
- Avoid putting service business logic into the library
When To Paste/Fork
The way we did this in that other project was great!
If you feel like you’ve got the library you want, but it was used in another project, then unless you can promote it to an organisational global library, you’re better forking it, or copying/pasting the code you need.
That sounds wrong.
But libraries have their own trajectory, and if you cannot guarantee the relationship between all consumers, then you should not build a link on the basis of some coincidentally similar code.