KISS revisited

Today, I’m going to discuss the KISS principle. I consider it the second most valuable software development principle.

KISS: the principle

The acronym KISS stands for "Keep it simple, stupid" (or "Keep it short and simple", according to other sources). It means that you should keep your system as simple as possible, because the simpler your application is, the easier it is to maintain.

This principle correlates with Yagni, but they are not the same thing. While Yagni states you need to cut off the code you don’t need right now, KISS is about making the remaining code simple. Here’s how it can be visualized:

YAGNI and KISS working together
YAGNI and KISS working together

Simplicity allows us to read and understand the source code more easily, and the ability to reason about the source code is vital for further development.

Here are three characteristics that can be attributed to any software system: Correctness, Performance, Readability. How would you arrange them by their importance?

It’s quite a tricky question, because the answer depends on several things, such as whether or not you will ever need to touch this system. But I believe for every typical enterprise application with a long development and support period the answer would be pretty much the same. So, what is it?

I guess one can think the order of importance is the following: Correctness > Readability > Performance. That is, the correctness is more important than readability which is itself more important than performance.

Now, think about it. Is it better to have an unreadable application that does things correctly than an application with bugs whose source code is simple and straightforward? In the short term, yes, it’s better to have a flawless system. But what if you need to add or change something in it? If you can’t understand the code, how can you implement the change?

It turns out that if you are ever going to enhance or evolve your system (which is true for most of enterprise systems), you are better off having one that is readable than the one that is bugless. The situation with the latter is unstable; most likely, you will introduce new bugs with the very first changes as you can’t fully understand it. On the other hand, with a readable and simple source code, you can find and fix bugs pretty quickly. That is, the order rather looks like this: Readability > Correctness > Performance.

There are two ways of constructing a software design: one way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies.

 — C. A. R. Hoare.

Simplicity vs Easiness

Simplicity shouldn’t be confused with easiness. These two concepts are completely different.

An easy solution is one that doesn’t take you much effort to implement. At the same time, a simple solution is usually far more difficult to achieve. It’s easy to create a complicated system that is hard to understand; it takes a lot of time to boil such system down to several core aspects and remove unnecessary complexity. Here’s a nice talk on that topic: Simple made easy.

This notion strongly correlates with the concept of technical debt. It’s easier to introduce technical debt than it is to remove it. A complicated system often contains a lot of technical debt, so you have to get rid of it in order to make the system simpler.

Accidental vs essential complexity

Not all systems can be made easy to understand. If you develop a CAD system, you can’t make it as simple as a To-Do List software, regardless of your attempts. You just have to understand 2D- and 3D-graphics and underlying math in order to build such application.

That brings us to two different types of complexity: accidental and essential. Essential complexity relates to the problem domain itself - the problem we need to solve in order to create the application. Nothing can decrease the essential complexity of a software system.

Accidental complexity, on the other hand, refers to the issues developers have to address on their way to solve the essential problems. Such things as cache management, optimization practices and other stuff that is not directly related to the application’s domain model is considered accidental complexity.

Most of the software engineering practices are aimed to reduce the accidental complexity, so is the KISS principle. The KISS principle has two main implications:

  • If you need to choose between two solutions, choose the simplest one.

  • Constantly work on simplifying your code base.

The first statement seems obvious, but too often I saw developers choosing a more complicated solution without any good reason. I guess, such decisions were dictated by a feeling that the simpler solution just isn’t solid enough for the problem they were working on.

In reality, the contrary is the case. The simpler your solution is, the better you are as a software developer. Most software developers can write code that works. Creating code that works and is as simple as possible - that is the true challenge.

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.

 — Antoine de Saint-Exupery.

Conclusions

A human’s mind can only handle 5-9 objects in memory. Throwing unnecessary complexity to code reduces your ability to reason about it and thus reduces your productivity. Even more, such reduction is not linear, but rather exponential. Increasing the unnecessary complexity of the code for just a little bit makes you times less productive when you work with it. Simplicity is the thing that is always worth investing in.

Subscribe


I don't post everything on my blog. Don't miss smaller tips and updates. Sign up to my mailing list below.

Comments


comments powered by Disqus