Skip to content

KISS - Keep It Simple, Stupid


Definition

KISS Definition


Over-Engineering Examples

// BAD: Over-engineered for a simple need
// "We might need to support multiple formats later"

public interface DataSerializer<T> {
    byte[] serialize(T data);
    T deserialize(byte[] bytes);
}

public abstract class AbstractSerializerFactory<T> {
    protected abstract DataSerializer<T> createSerializer();
    protected abstract void configure(SerializerConfig config);
}

public class JsonSerializerFactory<T> extends AbstractSerializerFactory<T> {
    private ObjectMapper mapper;
    private SerializerConfig config;
    private List<SerializerPlugin> plugins;
    // ... 100 more lines
}

// GOOD: Simple solution for current need
public class UserSerializer {

    private final ObjectMapper mapper = new ObjectMapper();

    public String toJson(User user) {
        return mapper.writeValueAsString(user);
    }

    public User fromJson(String json) {
        return mapper.readValue(json, User.class);
    }
}
// When you actually need multiple formats, refactor then.

Simplicity in Code

// BAD: Clever but hard to understand
public int findMax(int[] arr) {
    return Arrays.stream(arr)
        .boxed()
        .reduce(Integer.MIN_VALUE, (a, b) ->
            a ^ ((a ^ b) & -((a - b) >>> 31)));
}

// GOOD: Clear and obvious
public int findMax(int[] arr) {
    if (arr.length == 0) {
        throw new IllegalArgumentException("Array is empty");
    }

    int max = arr[0];
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    return max;
}

// Or even simpler:
public int findMax(int[] arr) {
    return Arrays.stream(arr).max()
        .orElseThrow(() -> new IllegalArgumentException("Array is empty"));
}

Architecture Simplicity

Architecture Complexity


Signs of Over-Complexity

Signs of Over-Complexity


Simplicity Techniques

// Technique 1: Use clear naming instead of comments
// BAD
int d; // elapsed time in days

// GOOD
int elapsedTimeInDays;


// Technique 2: Prefer composition over complex inheritance
// BAD: Complex inheritance hierarchy
class Animal { }
class Mammal extends Animal { }
class Canine extends Mammal { }
class Dog extends Canine { }
class ServiceDog extends Dog { }

// GOOD: Flat composition
class Dog {
    private final Breed breed;
    private final Training training;
    private final boolean isServiceAnimal;
}


// Technique 3: Early returns over nested conditions
// BAD
public String getLabel(User user) {
    if (user != null) {
        if (user.isActive()) {
            if (user.isPremium()) {
                return "Premium";
            } else {
                return "Standard";
            }
        } else {
            return "Inactive";
        }
    } else {
        return "Unknown";
    }
}

// GOOD
public String getLabel(User user) {
    if (user == null) return "Unknown";
    if (!user.isActive()) return "Inactive";
    if (user.isPremium()) return "Premium";
    return "Standard";
}


// Technique 4: Extract when it clarifies, not just to reduce lines
// BAD: Extraction makes it harder to follow
public void process(Order order) {
    doStep1(order);
    doStep2(order);
    doStep3(order);
    // Have to jump to 3 methods to understand
}

// GOOD: Keep simple logic inline
public void process(Order order) {
    validateOrder(order);

    // Calculate totals
    Money subtotal = order.getItems().stream()
        .map(item -> item.getPrice().multiply(item.getQuantity()))
        .reduce(Money.ZERO, Money::add);
    Money tax = subtotal.multiply(TAX_RATE);
    order.setTotal(subtotal.add(tax));

    orderRepository.save(order);
}

KISS vs Premature Optimization

KISS vs Premature Optimization


Tips & Tricks

KISS Tips