Icon for gfsd IntelliJ IDEA

Programming principle "KISS": Keep it simple, stupid!

An illustration for the KISS principle: Keept it Simple, Stupid!

KISS (aka Keep it Simple, Stupid!) is a handy principle for anyone designing complex systems such as software. This post dives into how you can apply it in your projects!

In our series about programming principles, we’ve already covered Chesterton’s Fence, “YAGNI” (You ain’t gonna need it), and “DRY” (Don’t Repeat Yourself). In this current post, we’ll be focusing on the “KISS” principle, a.k.a. Keep it simple, stupid!

What is the KISS (Keep it simple, stupid) principle in coding?

As is often the case with coding principles, KISS originates from a different field altogether, but can (and, we would argue, should) be applied to software development. While the “KISS” acronym itself is largely attributed to a lead engineer at Lockheed, the term was noted by the U.S. Navy in 1960. The rationale behind this principle is a simple one: things tend to break in combat, and the crew on the ground need to be able to repair them with the limited tooling available, and under the psychological pressure of combat. The KISS principle states that there is no value in a solution being “clever” – there is value in it being easily understandable for all.

While it’s not likely that your code will be interpreted in a combat situation, it is safe to assume that other people will work on the lines of code you are writing. Their skill level, brain capacity, or personal situation may mean that they have a more difficult time understanding your code which, to you, seems perfectly straightforward. Similarly, in the case of complex systems and insufficient documentation, things may not be as clear as we’d expect.

Observing KISS in practice

Simple and easy-to-understand code is easier to maintain and debug. That is a fact. Therefore, the ultimate goal for any software developer should be to strive for simplicity.

That said, coming up with simple solutions can be more challenging than just hacking something that works. When looking at a fleshed-out, simple solution to a problem in hindsight, the way to go always looks so obvious. But finding the most simple solution when you’re just trying to create something often tends to be more difficult.

The easiest way to practice sticking to the KISS principle is by using simple APIs and method implementations. When implementing a single function, it is often tempting to use new cool language features or to find especially “smart” solutions to the problem at hand. That’s all great – but readability and understandability should always be a primary focus when writing code.

This is why we also advise you to use the same patterns to solve similar problems. This way, other programmers on your project will recognize a pattern or problem faster. One small example of this is to prefer Go’s strconv.Itoa over fmt.Sprintf when converting an integer to a string.

KISS in small-scale projects

Some best practices for observing KISS on a small scale:

  • Start small and solve problems in an iterative manner (see more on this later).
  • Use simple and easy to understand names for variables.
  • Use the functions that are intended to do a job rather than a workaround (like strconv.Itoa over fmt.Sprintf in the example above).
  • Spend time designing APIs that are easy to understand and use to save some time and effort for users working with your API.
  • Use the same patterns to solve similar problems.
  • Think about optimization once a problem is solved and when it is actually needed to optimize.

KISS in iterations

Our experience suggests that KISS can also be applied as an afterthought to finished solutions. We’ve had success with first finding a solution to the problem, freezing the intended behavior of that solution, and then trying to find better solutions. It is often easier to improve an existing solution than to come up with the perfect solution right away.

We made it a habit to look through our code again before opening up a merge request to spend some time understanding the solution again and think once more about more streamlined solutions.

Let’s take an example! When coming up with the first draft for a function we might end up with something like:

func foo(input1 string, input2 string) (out string) {
  ...
  switch (input 1) {
    case "a":
      ...
      trim(input3)
    case "b":
      ...
      trim(input3)
    default:
      ...
      trim(input3)
  }

  return out
}

This can quite obviously be simplified to:

func foo(input1 string, input2 string) (out string) {
  ...
  switch (input 1) {
    case "a":
      ...
    case "b":
      ...
    default:
      ...
  }
  trim(input3)

  return out
}

Of course, that is just a tiny change. But making it a habit to look for better solutions after you have the first draft might end up in way more straightforward solutions – even in more complex cases. That helps reduce the time future readers of your code will spend figuring out what your intentions were.

Adopting the KISS principle on a large-scale software project

Let’s face it, legacy code can get messy. Code bases tend to degenerate the longer they exist. New features are added step by step, and sometimes, these new features are just not added in the “right” place. The longer various people keep working on and extending a software system, the harder it becomes to understand. At a certain point, it gets hard enough to make changes that it makes more sense to spend time on a refactoring step to clean up the code and simplify things again.

Simplifying existing solutions that grew over time is a perfect example of applying the KISS principle. When extending an already complicated solution, it is a good idea to first take a step back and get the big picture before you attempt to figure out a better solution to the existing implementation. Clean up your immediate “construction site” so that you can get to work efficiently when adding new functionality.

Not convinced if all of this really makes sense to do in a real-life project? Let us give you a quick example: in the Symflower project, with one such exercise of simplifying code, we managed to get rid of almost 90k lines of code!

Symflower's code repository simplified with the KISS principle
90k lines of code saved using the KISS principle in action

Of course, most of these changes were simplifications to generated test code. Still, the code base got way more simple and easy to understand, which will continue to have long-term benefits.

Don’t forget to subscribe to our newsletter and follow us on Twitter, LinkedIn or Facebook to get notified about new articles on software development and testing!

| 2023-07-25