User Tools

Site Tools


principles:keep_it_simple_stupid

This is an old revision of the document!


Keep It Simple Stupid (KISS)

Variations and Alternative Names

  • (Rule of) Simplicity
  • KISS may also mean “Keep it short and simple”, “keep it simple and straightforward”, “keep it smart and simple”, etc. A large amount of variations exists.

Remarks: “Stupid” may be interpreted as an adjective or a noun. Compare the two variants “keep it simple and stupid” vs. “keep it simple, stupid!”. Despite all these alternative names the general idea of the KISS principle is always the same.

Context

Principle Statement

A simple solution is better than a complex one—even if the solution looks stupid.

Description

The KISS principle is about striving for simplicity. Modern programming languages, frameworks and APIs have powerful means to create sophisticated solutions for various kinds of problems. Sometimes developers might feel tempted to write “clever” solutions that use all these complex features. The KISS principle states that a solution is better when is uses less inheritance, less polymorphism, fewer classes, etc.

A solution that follows the KISS principle might look boring or even “stupid” but simple and understandable. The KISS principle states that there is no value in a solution being “clever” but in one being easily understandable.

This does not mean that features like inheritance and polymorphism should not be used at all. Rather they should only be used when they are necessary or there is some substantial advantage in using them.

Rationale

A simpler solution is better than a complex one because simple solutions are easier to maintain. This includes increased readability, understandability, and changeability. Furthermore writing simple code is less error prone.

The advantage of simplicity is even bigger when the person who maintains the software is not the one who once wrote it. The maintainer might also be less familiar with sophisticated programming language features. So simple and stupid programs are easier to maintain because the maintainer needs less time to understand them and is less likely to introduce further defects.

Strategies

This is a very general principle so there is a large variety of possible strategies to adhere more to this principle largely depending on the given design problem:

  • Avoid inheritance, polymorphism, dynamic binding and other complicated OOP concepts. Use delegation and simple if-constructs instead.
  • Avoid low-level optimization of algorithms especially when involving Assembler, bit-operations, and pointers. Slower implementations will work just fine.
  • Use simple brute-force solutions instead of complicated algorithms. Slower algorithms will work in the first place.
  • Avoid numerous classes and methods as well as large code blocks (see More Is More Complex)
  • For slightly unrelated but rather small pieces of functionality use private methods instead of an additional class.
  • Avoid general solutions needing parameterization. A specific solution will suffice.

Caveats

See section contrary principles.

Origin

The principle was coined by the American engineer Kelly Johnson referring to the requirement that a military aircraft should be repairable with a limited set of tools under combat conditions 1).

The principle of striving for simple solutions sometimes is also called “(rule of) simplicity”2) which was also prominently stated by Tony Hoare in his Turing Award lecture: “I conclude that 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. The first method is far more difficult.”3)

Evidence

Accepted: This principle is widely known and accepted in practice. See for example Jargon File: KISS Principle

Examined: While the preference for simple solutions can be considered trivially intuitive, there has been some work relating simplicity or rather complexity and certain quality attributes. But as there is no universally applicable complexity metric and not even a commonly agreed upon clear definition of simplicity, research is bound to examine certain aspects of KISS independently.

The following hypotheses can be stated:

  1. Simpler solutions are faster to implement.
  2. Simpler solutions yield less implementation faults (which reduces testing effort).
  3. Simpler solutions are easier to maintain, i.e. detecting and correcting defects is effective and efficient.
  4. Simpler solutions yield more reliable software, i.e. less defects show up after releasing the software.

All these hypotheses can be examined with respect to different complexity metrics.

Hypothesis 1 can be regarded true by definition. If the solution cannot be implemented fast, it is not simple.

Though hypotheses 2 and 3 are not true by definition but they can be regarded intuitively clear. There is only few scientific research concerning these questions directly. As a specific aspect of complexity, complexity through deep inheritance relations is known to reduce effectiveness and efficiency of maintenance. There are controlled experiments showing this4)5). On the other hand these results are limited as there may be many factors which are neglected by the experiment. Most notably in these experiments maintenance tasks where carried out on systems with artificially constructed inheritance hierarchies. Typically there are good ways and bad ways of using inheritance. And rarely there are several equally good solutions for the same problem only differing in the depth of inheritance. So there is some evidence but no “proof” that deep inheritance hampers maintenance.

Furthermore software cost estimation techniques are partly based on complexity judgments6). So complexity—although this normally relates the complexity of the problem and not to the complexity of the solution—is a known cost factor.

Lastly hypothesis 4 is likely to be false. Several studies relating complexity metrics and post-release reliability show that module size in lines of code predicts reliability at least as good as the McCabe metric (also called cyclomatic complexity) 7). Assuming cyclomatic complexity correctly depicts the complexity of a module, reliability should not the reason for applying KISS.

Relations to Other Principles

Generalizations

Specializations

Contrary Principles

Note that many principles are contrary to KISS. This means that it is worthwhile to consider KISS when considering one of those. Nevertheless this does not mean that this is true the other way around. When considering KISS, one wouldn't want to consider all principles that have complexity as a disadvantage. So here are those needing consideration:

  • Generalization Principle (GP): This is the directly converse principle. A solution that is generally applicable typically is not simple anymore.
  • Murphy's Law (ML): The ultimate reason behind KISS is to increase maintainability and reduce the introduction of defects. But following KISS blindly by always using the simplest solution may also lead to reduced maintainability when Murphy's Law is not considered.
  • Model Principle (MP): There are often simpler ways to build a software system than to model and mirror the real world behavior, which frequently means having more objects and more complicated structures. Nevertheless it is advisable to do so anyway.

Complementary Principles

Principle Collections

OOD Principle Language
General Principles
ML KISS MIMC DRY GP RoE
Modularization Principles
MP HC ECV
Module Communication Principles
TdA/IE LC DIP
Interface Design Principles
EUHM PLS UP
Internal Module Design Principles
IH/E IAP LSP PSU

Examples

Example 1: Fuzzy Simplicity

Simplicity is a blurry, partly subjective measure. Sometimes it is difficult to tell what is simpler. The following example shows that:

public String weekday1(int dayOfWeek)
{
    switch (dayOfWeek)
    {
        case 1: return "Monday";
        case 2: return "Tuesday";
        case 3: return "Wednesday";
        case 4: return "Thursday";
        case 5: return "Friday";
        case 6: return "Saturday";
        case 7: return "Sunday";
        default: throw new IllegalArgumentException("dayOfWeek must be in range 1..7");
    }
}
 
public String weekday2(int dayOfWeek)
{
    if ((dayOfWeek < 1) || (dayOfWeek > 7))
        throw new IllegalArgumentException("dayOfWeek must be in range 1..7");
 
    final String[] weekdays = {
        "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
 
    return weekdays[dayOfWeek-1];
}

Both methods do exactly the same thing. they return a string representing the weekday. Just the implementation is different.

Description Status

Further Reading

4)
John Daly, Andrew Brooks, James Miller, Marc Roper and Murray Wood: An Empirical Study Evaluating Depth of Inheritance on the Maintainability of Object-Oriented Software
5)
Barbara Unger and Lutz Prechelt: The Impact of Inheritance Depth on Maintenance Tasks
6)
Barry W. Boehm: Software Engineering Economics, IEEE
7)
see Albert Endres, Dieter Rombach: A Handbook of Software and Systems Engineering, p. 168pp.
principles/keep_it_simple_stupid.1363945930.txt.gz · Last modified: 2013-05-19 22:10 (external edit)