November 20th 2020
By Samir Hodžić, Software Engineer
For the last couple of years, I’ve heard repeatedly about monolithic architecture vs. microservices, why we should adopt microservices, how to make your application microservice-based, multiple opinions which suggest starting from the monolith first, and others which recommend not to start with monolith when your goal is a microservices architecture and so on and so forth.
But the main question which bothered me actually, why is it that hard to choose and why? Where both approaches have multiple pros and cons, what makes us hate both of them in a specific way after some time?
Architecture > everything
We can start with both approaches in parallel, where they become a nightmare when it eventually turns into a large bowl of spaghetti. Changing one tiny thing at point A will break something at point Z, and when you try to fix that, you soon have the whole spaghetti on your fork even if you don’t want it.
The interesting question is, why does this happen at all?
Is it a problem with the pattern? Will another pattern approach fix the problem?
The short answer is NO. It is not a problem of the pattern, and a new pattern won’t fix your problems if you don’t fix the cause. If you keep the same root cause, any new endeavor will fail too.
Do you really expect that with the same team mindset and another pattern, you will succeed?
Humans are complex, and besides that, a team is a complex organism, where dev teams are no different.
So, why does this happen?
It’s not a single cause, it is a combination of multiple, and here are the most common I’ve made and encountered in the wild.
One of the worst things that can happen is that a team of fresh junior devs who are developing some kind of serious product and there is no one around to guide them.
Inexperience is typical and not bad per se, but if the whole team is, it means all of them are learning on the project how to build it. And they will make mistakes, many, many, many mistakes. Which is normal in a learning process but a nightmare for the final product. Results I’ve seen and experienced are missed deadlines, un-maintainable codebase and of course, the business side was never happy “for some reason”.
You got a couple of devs on your team who know what they do and the project is split that everyone gets its puzzle piece with minimal interference or overlaps. Now every dev is coding and working in his or her style, good or bad doesn’t matter, all they see is their shiny piece and that is what they care for.
I oversimplify things now because the dynamic at work is quite complex, and part of the negative behavior is covered later. The results are multiple implementations of the same logic, logic in places where it does not belong, broken interfaces (they are never as defined earlier), complaining and moaning, whos’ fault is the error and who should fix it – which will also later result in many unnecessary meetings about on which plate issues should be toss on.
Understand the complexity
Complexity is everywhere, and as a dev, you need to handle a lot of it honestly. This skill is even more important than knowing the syntax of your language of choice.
Before making changes or implementing new features, think about what is affected by that change. What implication might it have? Where is the data flowing along? Does it make sense to place my customer edit logic into the Loans Controller? What are the consequences if I use that method/service/X? <– That one is overlooked A LOT. Look for data loading, side effects it might have, etc.
Let's try something new?
Learning something new is always great and fun, but not on a real project with a tight deadline and no one on the team has ever worked with the new tech stack before. Oh, that framework looks nice, let’s do our next client project with it or we should re-write our stable application into this definitely.
Client or mission-critical projects are not a place to toy with new technologies. A team should use proven techniques they have experience with. And if a new tech might actually help, make it clear to everyone involved that this is new and there will be mistakes.
I can do it quickly
The general problem with the “I do it quickly” “approach is that the dev will overlook the consequences of his doing. He/she will not think much about them, but will only care about fixing the thing as soon as possible. Like loading additional data from another micro-service which is just needed in a specific single case and it could be implemented pretty fast. And, dev just overlooked that it was intentionally left out from the service and his change broke performance on another part.
Well, it is your job as a dev to keep that maintainable. The only exception is throw-away-software or some funny side-project you are doing for your own soul.
Devs are coding, not business guys
If you listen to the complaining of devs, it is always the business guys, project managers, or whoever who is the culprit for that the software is so bad. Never them. The others are.
Sounds familiar, right? You were, myself multiple times too, in that position for sure.
But know what, let’s be honest, the project manager does not write the code. You as a dev do. So, it is your job to do it right. The project manager did not add that spaghetti code. Nope, a dev did.
Yeah, sometimes you don’t have the time and need to hack it in. So be it; you still did write the code. Time is a constraint, make the best out of it but don’t complain about how others do it.
Ignoring rules, being sloppy and lazy
You have rules in your team, ranging from code formatting rules to handling change requests, etc. Yet, there will be a bunch of devs who will right out ignore those.
Was on a team with code formatting rules which had to be checked in a code review. Yet, the same devs always had the code formatted wrong. If a rule is stupid and should be adapted, you should change it.
Being sloppy and any kind of laziness go hand in hand with the “I can do it quickly” fraction. Same effect, different cause.
If the business guy says, “Jump,” many devs ask “how high?” or they just do it. It is the same with requirements or workloads.
If the requirements are rubbish, have logical flaws, missing aspects, or just don’t make sense at all, talk with the business guys. But don’t speak dev gibberish with them, speak in their language about the problem.
Same with the workload. Don’t switch tasks on a whim because one project manager told you it needs to be done. This is notorious for a single team handling multiple projects with different project managers. It is especially bad, when you have “Yes, Sir” types of devs on the team. The results are additional felt pressure on those devs, which tend to quick and sloppy work. Resulting in an unmaintainable codebase in most cases, or making others feel worthless in edge cases.
Making the wrong decisions, not standing behind them, overplaying, or just denying them.
A random example makes that more clear. Take a dev team, who build a new app from scratch. They chose a document store but modeled their domain objects in a relational way. Now X features and iterations later, the performance went downhill… Yet, no one admits the wrong architectural decision. But everybody complains about it - even the devs. The bad platform, bad architecture, etc.
Yep, they definitely made a wrong decision, and in this particular case it was a combination with “New Tech on Client Project.”
Through my experience and many years as a dev, I’ve seen most of those causes and the consequences. I’ve done plenty of them myself, and I can tell you one thing. If you don’t change yourself and your approaches to different problems and situations, you’ll make the same mistakes again and again. And they will result in the same problems, no matter if you are building monoliths or microservices.
It is not always the tech, it’s the devs!