A very popular habit among us developers is creating reusable components to avoid inconsistency (and stay DRY).
Which is, of course, a good thing: If a developer has been digging deep into a technical problem, came up with a good solution and managed to get it into production there is no point in having another developer doing exactly the same.
Or is it?
Especially in the domain where I work, which is microservice architectures you have to be very careful with “common” components and libraries, because they affect the independence of the microservices and the teams that are responsible for them.
Also creating re-usable components as a default behavior is over-engineering. It will greatly affect your productivity in a negative way if you do it too often.
On the other hand if you wait too long with extracting re-usable things the work of your teams will differ in how they approach things and lead to inconsistency.
While these inconsistencies will sort them selves out in a single team usually (because developers will talk to each other about it), they will make it hard to be flexible between teams:
A developer from one team can not easily switch to another team, because the approaches for the same problems differ!
The Rule of Three
A good rule of thumb for creating re-usable components is the Rule of Three.
You do something once and let it be like this.
Keep it simple, don’t extract any “possibly common behavior” yet.
If you need to do the same thing a second time do it a second time. You might do copy & paste programming then, but also don’t extract anything yet.
If you need to do it a third time you have a good indicator that something can be extracted.
You can’t make a reusable framework until you first make a usable framework. Reusable frameworks require that you build them in concert with several reusing applications.
Robert C. Martin (“Uncle Bob”) – Clean Code 2018
Creating re-usable stuff is not the only option to avoid inconsistency
This is something important we sometimes forget: There are other ways to ensure consistency in your projects.
Swarm knowlegde
The easiest and simplest thing to have your ways of doing things “in line” is to create swarm knowledge.
Like “Ask Hannah or Paul when it comes to integrating dependency checking into your build pipeline”. After one of these told the questioner how to do it, you will have one more person that knows about it.
It doesn’t involve much effort. However since it doesn’t scale well obviously it’s only suited for small senior teams.
Write things down
The next thing that is still simple is to write things down. For example in a wiki.
This scales well: Anyone, new or senior, can read it up once it’s written down.
But here you have to be careful already:
- No developer wants to read 200 wiki pages before being able to start something.
- You have to keep it up to date!
These two points may seem obvious at a first glance, but I didn’t work at a single company so far where I didn’t take a look at some documentation for a specific thing, only to be told: “This is outdated. We do it like this…”
Not cool!
I usually tell junior developers: “If you find outdated documentation try to update it. And if you can’t just delete it”. (Of course trying to update it involves asking around people who might know about it)
It’s better to have no documentation than to have wrong documentation!
(And just in case it is still needed version control will still have it)
Creating reusable components
Creating re-usable templates, libraries, components, etc. is the third and most expensive option.
Don’t get me wrong: It’s fine when it suits. But don’t ever try to have it as the default behavior or your productivity will plunge and developers will have to bend their code to fit all the frameworks you create for them.
The more generic the general component is, the more the code “around it” needs to be fitted or generalized for matching it.
Of these three, swarm knowledge, written documentation and re-usable stuff, choose the one that fits best.
E.g write down testing guidelines instead of creating a framework that needs to include every specific shit that you can imagine so far (and doesn’t work until your next service needs to do something new). Let the build pipeline-specific things be swarm knowledge (if you can’t automate them away) but definitely extract that logging library you need for each and every one of your microservices…
YMMV, these are just simple examples!
So what should we do to avoid inconsistency?
In my opinion the best thing to do is to create a habit of consistency in the teams as long as they are small. Let the people talk to each other, look at each others code in the code reviews and do pair programming so that everyone has an idea how things are done.
Write the things down that need to be written down. Before there are more teams and they the number of people involved grows too much.
And finally have some good developers discuss and extract the re-usable components you really need. These experienced developers don’t need to be architects or seniors IMO.
They just need to be developers which embrace consistency and have an eye for the necessary things.
How can we get rid of inconsistencies and duplication?
If you already have some inconsistencies in your environment consider dedicating a developer team for re-gaining consistency. A specialized team that focuses only on internal guidelines, general documentation and tooling.
But make sure this team understands agile/iterative development and actively seeks feedback from all the other teams!
As the specialized team won’t work on business problems they need this input for discovering inconsistencies and duplication.
I believe a nice approach for setting this up is having an internal “open-source” model for your general components and guidelines:
All developers in a company can contribute, but the members of the specialized team are the maintainers which have the oversight.
What do you think about it?