Write less not worse

I’m fascinated by refactoring techniques and everything you can do to write less code.

less is more

That’s efficiency. However, it is not always the best approach, and I want to explain why.

Stay DRY, don’t DIE

DIE means “Duplication Is Evil”. DRY is quite the same idea, and it means “do not repeat yourself”.

With this principle in mind, you drastically reduce repetition and redundancy. Instead, you abstract logic in, let’s say, functions or helpers, and you apply it where you need.

These are excellent patterns, but I’ve seen so many counterexamples involving both experienced developers and beginners. They may have read those principles at face value.

Don’t add useless wrappers

Whether it’s with a framework or the language itself, I’ve seen some developers wrapping built-in functions. For example, in PHP:

function getArrayParts($array, $start = 0, $end = 1)
{
    return array_slice($array, $start, $end);
}

This alias makes you write more code than necessary.

At this time, the developer told me that it was a starter, and he planned to add more treatments in the future.

Even with that in mind, it did not feel right. Any change in the code could introduce nasty bugs (which happened one week later).

The main reason is that there are different use contexts, and even with small applications, it’s hard to remember everything.

Modifications added in the getArrayParts() function had terrible side effects. It was pretty hard to fix, as there were neither fatal errors nor warnings.

Don’t try to look like a ninja

Writing fewer lines of code is pretty cool. However, it’s sometimes a lot worse for readability.

Look at the following examples in PHP and JavaScript:

$result = ( CONDITION ) ? CONDITION2 ? 'value1' : 'value2' : 'value3';
let num = 7, str = num + "", num = +s;

There are undeniably fewer lines, but it’s not readable at all. This point is super tricky because it might seem bright, so the developer may think that’s the way to look like a code ninja.

I can ensure you that it’s not a professional code and that recruiters don’t look for that, simply because it’s not maintainable.

Don’t overthink your app

Overengineering happens when you start overthinking potential evolutions and usages for your code.

I’ve heard that a lot since the beginning of my career:

for now, it’s useless, but what if we need that change in the future. We won’t even have to code it.

While it might look brilliant, most of the time, it’s not.

If you follow the right patterns, you are probably right, and there’s a good chance that doing maintenance and evolutions will be more comfortable.

However, if you take twice more time to prepare your code like it’s an open-source project that must cover all parallel universes, you will probably do it wrong.

There is a chance you do extra work for nothing, and it’s unlikely you won’t have to add anything, even if your code is ready for evolutions.

The cost of too much abstraction

Sometimes, the cost of abstraction is high, and undoing it is even more painful. Don’t be over satisfied with your refactoring. You’d be surprised.

Not all code needs to be in one place. Again, you can have two functions that look the same, but their use context could be very different.

It often leads to functions and helper classes with an extensive range of parameters. All your code might be in one place, but to reuse it, you have to repeat a lot things:

static function renderTemplate($template, $is_debug = false, $is_single = true, $theme = "default", $has_sidebar = true) {
    // some code
} 

Here, the function multiplies parameters to match all cases, and you have to write many true and false only to render a simple template. It’s less readable, and your code is not easy to handle.

If you have to modify the code for some reason, the risk of side effects is higher. It is harder to maintain.

The abstraction paradox

Don’t get me wrong with all those thoughts. I love abstraction, clean code, and refactoring. My point is we code for the business, our teammates, and our “future self”.

The problem with abstraction is that the better it is, the higher is the risk of failure.

Why? Because when abstraction is valuable, we want to use it everywhere, so we extend the range of situations where it might fail.

Besides, any later change in the abstract code might break a lot of code built upon it.

So what can we do?

Abstract and refactor code sparingly. Even if “Duplication Is Evil”, the wrong abstraction too. Don’t try to use the same interface for wildly different situations.

Don’t overuse nesting blocks in your functions to try to cover all cases.

Discuss codes and approaches with your teammates. It’s best if you do code reviews and pair programming regularly.

Occam’s razor in code

The most straightforward solution to a problem is often the right approach. In that perspective, I like to apply a famous philosophical principle called Occam’s razor.

It’s a problem-solving principle that says that the simplest explanation is usually the right one.

Instead of making the code as extensible as possible, I try to keep the codebase readable and straightforward for my coworkers and me.

KISS or YAGNI are related approaches.

Photo by Damir Spanic on Unsplash