If you have read any other post in this blog you might have noticed an emerging pattern: I like simplicity.
I bet you have read the following quote before, in any of its multiple forms
A junior engineer creates complex solutions to complex problems, an more experienced engineer creates simple solutions to simple problems, and a senior engineer creates simple solutions to complex problems.
I would reduce that to something even simpler (see, the same pattern again)
Some engineers create simple solutions, some engineers create complex solution. The complexity of the problem does not actually matter.
In my experience, there is an inflection point in every developer’s career, right at the spot where said developer first encounters design patterns. Suddenly, the whole world becomes a playground, where everything can and will be modelled as a use case of a design pattern.
Don’t get me wrong. There will be plenty of life-changing moments in a developer’s career, but this one affects each and everyone of us at some point or another.
Design patterns are solutions to problems that you will find again and again. Every developer should know their patterns. They provide a shared language, a lexicon, so to speak, that allows developers to describe a problem in a few words. Phrases like “that’s a command” or “use a factory for that” should provide enough information for any developer to know what to do.
As usual, “the virtue of justice consists in moderation”. If is very easy to turn into a pattern-freak, and start seeing patterns everywhere. That syndrome, if left unattended, can lead to a serious disease: over-engineering.
The problem: over-engineering
This is, sadly, an unrecoverable disease. Some symptoms are using interfaces that extend tag interfaces to type method parameters, trying to turn everything around you into a UML diagram, using the term “business domain” more than once in a single week, and generally speaking, writing code that solves problems that you don’t have.
The solution: keeping it simple
Here is where all the fancy acronyms in the post title come into play. KISS (Keep it Single Stupid) and YAGNI (You Ain’t Gonna Need It) are two terms easy to remember and understand. But in a way, both can be reduced to a very simple principle
Occam’s Razor is a problem-solving principle devised by a ￼William Ockham￼. There are a thousand variations of the principle’s formulation, but I am extremely fond of this one:
Frustra fit per plura quod potest fieri per pauciora (It is futile to do with more things that which can be done with fewer)
In other words: less is more.
There are many benefits in not over-designing or over-abstracting at an early stage.
It is very difficult to see deficiencies in overly complicated code
Well, sometimes the trees don’t let you see the forest and so on and so forth. Complicated code is difficult to read. Too many abstractions make difficult to follow the flow, to understand what is happening.
However, when dealing with simpler code, all the deficiencies will be extremely easy to identify.
Allowing some duplication at early stages simplifies the design
DRY FTW! Sure, but sometimes, a little bit of D is precisely what you need in order to identify what you should abstract and generalise.
You can not foresee the future.
If you could, you would have probably won the lotto by now, and you would live a happy life. However, here you are, reading this.
Adding layers upon layers of abstraction to accommodate future changes in the system is fun, and makes you feel smart, but it is very likely that many of those layer will not be actually necessary.
In a month’s time, you will have to read the code you write today.
Right before extracting that interface that declares just one method that receives something typed as another interface as parameter, ask yourself: “will I still understand what I did here in a month’s time?” If the answer is no, well, you know what not to do.
Life as a software engineer is complicated enough as it is. Adding to many abstractions too early might make things too complicated.
Object Oriented Design is all about trade-offs. Often times, the simplest possible solution is the best one in the long term, even if it is only because it makes your mistakes and bad decisions popup immediately at you.
Keep it simple!