Aller au contenu

KISS - Keep It Simple, Stupid

Ce contenu n’est pas encore disponible dans votre langue.

“Simplicity is the ultimate sophistication.” — Leonardo da Vinci


KISS is one of the most important principles in software development. It encourages us to prefer simple solutions over complex ones. Simple code is easier to:

  • Understand — For you and your colleagues
  • Maintain — Fewer bugs, easier modifications
  • Test — Fewer complex test cases
  • Debug — Problems are easier to locate

// Complex version — Avoid!
function processUserDataWithAdvancedValidationAndTransformation(userData) {
const validationRules = {
name: (val) => val && val.length > 0 && val.length < 50 && /^[a-zA-Z\s]*$/.test(val),
email: (val) => val && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),
age: (val) => val && !isNaN(val) && val > 0 && val < 150
};
const transformationRules = {
name: (val) => val.trim().toLowerCase().split(' ').map(word =>
word.charAt(0).toUpperCase() + word.slice(1)).join(' '),
email: (val) => val.trim().toLowerCase(),
age: (val) => parseInt(val, 10)
};
const errors = [];
const processedData = {};
Object.keys(userData).forEach(key => {
if (validationRules[key]) {
if (!validationRules[key](userData[key])) {
errors.push(`Invalid ${key}`);
} else {
processedData[key] = transformationRules[key] ?
transformationRules[key](userData[key]) : userData[key];
}
}
});
return errors.length > 0 ? { errors } : { data: processedData };
}

// Simple version — Much better!
function validateUser(userData) {
const errors = [];
if (!isValidName(userData.name)) {
errors.push('Invalid name');
}
if (!isValidEmail(userData.email)) {
errors.push('Invalid email');
}
if (!isValidAge(userData.age)) {
errors.push('Invalid age');
}
return errors;
}
function formatUser(userData) {
return {
name: formatName(userData.name),
email: formatEmail(userData.email),
age: parseInt(userData.age, 10)
};
}
function isValidName(name) {
return name && name.length > 0 && name.length < 50;
}
function isValidEmail(email) {
return email && email.includes('@');
}
function isValidAge(age) {
return age && age > 0 && age < 150;
}
function formatName(name) {
return name.trim();
}
function formatEmail(email) {
return email.trim().toLowerCase();
}

Each function has a specific role and an explicit name.

You can test each function independently:

// Simple and clear tests
test('isValidEmail should return true for valid email', () => {
expect(isValidEmail('user@example.com')).toBe(true);
});
test('formatName should trim spaces', () => {
expect(formatName(' John Doe ')).toBe('John Doe');
});

Need to change email validation? Only modify isValidEmail().


// ❌ Function that does everything
function processOrder(order) {
// validation + calculation + saving + email
}
// ✅ Specialized functions
function validateOrder(order) { /* ... */ }
function calculateTotal(order) { /* ... */ }
function saveOrder(order) { /* ... */ }
function sendConfirmationEmail(order) { /* ... */ }
// ❌ Too abstract for a simple case
class DataProcessor {
constructor(strategy) {
this.strategy = strategy;
}
process(data) {
return this.strategy.execute(data);
}
}
// ✅ Simple and direct
function processUserData(data) {
return data.filter(user => user.active)
.map(user => user.name);
}
// ❌ Code that requires comments
function calc(u, r) { // calculates price with discount
return u * r * 0.9; // applies 10% discount
}
// ✅ Self-documenting code
function calculatePriceWithDiscount(unitPrice, quantity) {
const DISCOUNT_RATE = 0.9;
return unitPrice * quantity * DISCOUNT_RATE;
}

// ❌ Complex store for a todo list
const store = new Vuex.Store({
modules: {
todos: {
namespaced: true,
state: { /* ... */ },
mutations: { /* ... */ },
actions: { /* ... */ },
getters: { /* ... */ }
}
}
});
// ✅ Simple local state
const todos = ref([]);
const addTodo = (text) => todos.value.push({ id: Date.now(), text, done: false });
const toggleTodo = (id) => {
const todo = todos.value.find(t => t.id === id);
if (todo) todo.done = !todo.done;
};

KISS does not mean:

// Acceptable repetition at first
function getUserById(id) { return fetch(`/users/${id}`); }
function getPostById(id) { return fetch(`/posts/${id}`); }
// But when the pattern repeats, abstraction becomes simple
function getResourceById(resource, id) {
return fetch(`/${resource}/${id}`);
}
// ❌ Too simple = dangerous
let user = JSON.parse(response); // Can crash
// ✅ Simple but safe
let user;
try {
user = JSON.parse(response);
} catch {
user = null;
}

  • Writing code you’ll understand in 6 months
  • Preferring multiple small functions over one big function
  • Choosing explicit variable names
  • Avoiding “clever” solutions in favor of clarity
  • Avoiding all abstraction
  • Ignoring useful patterns
  • Writing insecure code

Simplicity requires more work upfront but saves a tremendous amount of time in the long run!