Bedrock Pattern : A better way of sharing code ?
You want to create a new java microservice `
hello-world-api,` you have done this 20 time before , so you go and copy the last `hello-neighbour` project you did and start modifying it. You dont like this approach, you have always thought about writing a maven archetype project but never got to it, writing code generators are never fun or easy. Read on then….
Lets examine the components of a typical hello-world-spring boot app to get it production ready:
Removing boilerplate code from project has always been a challenge in large scale software teams. With the popularity of microservices, this has become a even more critical as in microservices a major portion of the code is typically structural code. When you have 100s of microservices, you want to put some `Standardisation` across them. You want everyone follow the same logging pattern, same REST error standards, same docker base image etc..
Traditionally we solved it via Shared library / Generated Code / Monolith Project with feature flags:
You build some framework with the cross cutting concerns and share them via zip , jar , dll etc.
There are a few major issues with this from experience:
- Shared code are for solving a specific problem, but our project mostly consist of gluing code like log4j patterns or maven pom file with groovy compilers, custom jenkinsfile etc
- Once you put stuff in library and apply it via a framework like AOP / Maven Hook , it becomes magic to people. No one really understand how it works.
- Changing stuff in the shared code becomes a issue because you dont know which project you are going to break, you start versioning then you are maintaining 10 version of the same code
There are some great code-generators out there like: https://www.jhipster.tech. But the code-generators stops just at that, Generating code! How do you maintain the code from that. If you want to change something, you would have to go and change it across 100s of microservice project.
Monolith Project with feature flags:
Looks ingenious in the beginning, becomes a nightmare in a few years , definitely a big NO..
Solution (?): `The Bedrock Pattern`
Inspired by linux kernel module development process : https://www.youtube.com/watch?v=4XpnKHJAok8 , we thought why can’t we use / abuse git to achieve the `Template Design Pattern / Inheritance model` for sharing code.
- No framework development required , easy to build a template project
- You dont need to get the template project right on the first day, it will evolve over time and the child can pull the improvements
- Just like you extract super-class from a java implementation class, you can extract a bedrock from a well structured project and turn it into a standard
- If you do it right, you can revamp you code module usage (for example logging) just in the bedrock and get it pulled by the subprojects without a single line of code change. You just magically inherit new capabilities.
- You can assign the team/tech leads as the owner of the bedrock project and they can review / accept the changes as global change candidate (The famous Dictator/lieutenant workflow: https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows )
- Its easy to pull improvements / bug fixes from the bedrock project
- The child projects has the full control over their own source code, no magic! They can change as they see fit without impacting the rest of the team (unlike shared libraries)
- The child project owners can share improvement items via PR , the bedrock project becomes your companies internal open source module
- Child projects can pull the improvements at their own pace when they are ready
- Shared standards , easy rollout bug-fixes etc etc
- Not suitable for teams which don’t have mastery on GIT (its amazing how many people just use it for just git pull / push) , need to be very fluent on working with multi upstream project, conflict resolve, PR etc.
- Need to be very disciplined and not give into the temptation of creating BEDROCK a god project and introduce a lot of if/else
- Multiple level of bedrock hierarchy can be hard to maintain, just like java inheritance best practice, if its beyond 3 level deep, its bad.
- Need strong lieutenants to oversee the code changes , sub-projects unnecessarily not following standards (open code give people freedom to break standards)
- Need to ensure the code coming from bedrock are left untouched / minimum change otherwise
- Same bug can propagate to every project
- The benefit will be truly seen when you have many many template project, I wouldnt do this for a small team maintaining 1–2 projects.
We started bedrock pattern to easily share our complex boilerplate code/configs (kubernetes / docker) that we didn’t want to diff from project to project. However, I can see this pattern being used for any code project, ie. cloudformation stack, nodejs , common-UI / workflow projects etc.