Refactor-able code

I have been thinking lately what is the best way to Stop over-engineering and still not fall victim of duplicate code (or even worse - very similar code).

At first glance, the approach of Test-first programming and refactoring seems to be the perfect remedy to over-engineering. What it basically says is:

This guarantees you that the code will be right-engineered. Not over-engineered (unnecessary complexity), nor under-engineered (duplicate, similar code all over).

The problem with that approach is that it does not work. It does not work because the “at all costs” rule above is frequently overruled by non-engineering reasons. A typical example will be when you decide not to re-factor to fit in the latest feature since you are too close to a release and you don’t want to introduce new bugs or void the testing already done.

Then you fall into the “I will patch it now for the release and re-factor later” down-spiral. So if you are stubborn on the “at all costs” rule, you will not be able to make your releases, and if you are not you will end up with an under-engineered code-base.

The root of the problem is that refactoring takes time and brings instability to the system. And to me there is no reason for that. We should be able to write code that is not complex at that moment, but is refactor-able (or refactor-friendly). Such refactor-able code will be easy and clear to refactor if necessary, but without doing it in advance. We will save time from the development (as compared to over-engineering it), but we will still be able to follow the “at all costs” rule, since refactoring will be easy.

My goal is to come up with a definition and how-to for refactor-able code. I am posting this much more as a basis of discussion and ideas, rather than as something carved in stone.

Definition: refactor-able code - code that is easy and risk-free to refactor
How to do it:
There is just one simple rule - Over-engineer in your head, do it simple. What I mean is to keep in your head a vision of how would you over-engineer it if you had all the time in the world. Then write the code simple, preparing it to match the vision in your head.
Since this is a really vague how-to, I will try to list cases in which you can substitute the urge to over-engineer something with much simpler preparations for that. Following is a list of examples

If I was over-engineering I would… Instead I will…
Split this into two modules and use callbacks to communicate Keep the two modules together, but keep the would-be-callbacks as separate functions.
Make a base class for the generic part and inherit it for this special case Do one class, keeping the “generic” methods together and don’t allow a lot of special-case code to go into the generic methods

Comments

Leave a Reply

You must be logged in to post a comment.