If i were to choose a principle that summarizes what’s behind a good design, that would absolutely be KISS : as the wise once said nobody is really up to the challenge of being a programmer. Simplicity often means humbleness, which in turn shows that the author has already learned his lesson.
That said, complexity is unavoidable. Code itself is complexity: no lines of code is always the most elegant solution but, zen value put aside, it accomplishes little. We have to deal with some amount of complexity no matter what, so i think it is better to know who your enemy is than to bury your head in the sand ( even if that’s really agile 😉 ).
Let’s take a look at the following snippet :
Now the car must be modified: it shouldn’t be able to move if the engine is not ignited. What should we do to implement this change in behavior?
if in the right place and voilà, the job is done. It’s the kind of change that TDD (and, by proxy, YAGNI) often brings to: the simplest thing that can possibly work, which is also very often the best thing you can do. It’s horizontal because it doesn’t add layers to your design: an atomic change is most likely to involve just one method or, at most, one class. It’s almost harmless when taken in small quantities but, when misused, can turn really, really bad.
I believe that the real problem about
ifs (and conditional statements as a whole) is that they’re too easy. Providing such an easy way to fork the world in two at the language level is like putting RPGs for sale at the grocery store – no matter what’s your level of trust in people’s reasoning, somebody’s gonna get hurt… heck, there’s a whole movement out there trying to put them down.
Two new classes and constructor logic: that’s the price you pay so you don’t have to put one of that nasty
ifs into your pristine method. It also hides some of the code away from sight: looking at the method only is no longer sufficient to understand its behavior. It’s vertical because the change in your code will be likely to be small in each single part but distributed in various layers.
If you write one
if too much you ‘re shooting yourself in the foot; if you do this the wrong way you ‘re blowing your whole leg off.
Overengineering is cheap and often mistaken as quality. The damage done, which often presents itself in the form of Yet Another Crappy Framework destined for internal use, is massive if measures are not taken early so i think it’s a really good idea to stop coding if you don’t know what you’re doing, like when:
- You just finished reading a certain book which was totally sweet and you can’t wait to see memento in action. On the invoices module.
- You had a genius idea and you absolutely must put it in your code so everybody knows how freakin’ smart you are.
- You start to wonder how cool would that be to have all that nasty business logic in a XML file so the customer can edit it himself
In the end…
Which one is better? That depends on you and on the situation: if the code you’re writing will be not be seen by human eyes after it is deployed then i think design and quality are not that important. If you know from the start your code will be mantained (which is pretty much always) it might be a good idea to add some structure (just some) even if the task to accomplish is simple. But if you have no clue please be a good boy, stop coding that CommonMethods class and ask for guidance 🙂