KISS: Keep it simple, stupid!
Makar M.Введение
KISS придумали не программисты. Аббревиатура фиксируется в английском языке по крайней мере с 1938 года и означала «keep it short and simple» — «держи это коротким и простым». Её использовали в деловом и военном контексте как напоминание: избыточная сложность мешает пониманию и исполнению.
В 1960-е принцип получил совремённое звучание. Конструктор Келли Джонсон из Lockheed Skunk Works формулировал его жёстко: Keep it Simple, Stupid. Идея проста: система должна быть настолько понятной, чтобы её могли обслуживать в поле обычные техники с минимальным набором инструментов.
Как KISS добрался до программирования
После авиации KISS разошёлся по инженерным дисциплинам — механике, электронике, проектированию — и естественно пришёл в софт. В 1960–70-е, на фоне «софтверного кризиса», стало заметно: программы ломаются по той же причине, что и машины, — из-за переусложнения.
UNIX закрепил цифровую форму принципа: Do one thing and do it well — делай одну вещь и делай её хорошо. Малые утилиты, которые легко комбинировать, стали образцом практического минимализма.
В 1980–90-е KISS вошёл в культуру разработки: модульность и сокрытие информации у Дэвида Парнаса, «No Silver Bullet» Фреда Брукса, подходы объектно-ориентированного проектирования. Простота перестала быть эстетикой — это критерий качества.
С приходом Agile и Extreme Programming (1990-е–2000-е) KISS стал свойством процесса: короткие итерации, маленькие поставки, рефакторинг «по факту», отказ от заделов «на потом».
Сегодня, среди фреймворков, микросервисов и оркестраторов, KISS напоминает: чем сложнее система, тем выше ответственность инженера за её простоту.
Суть принципа
KISS — это устранение ненужной сложности. Не призыв к примитивности и не запрет на абстракции. Любая новая сущность, уровень или зависимость должны иметь ясное основание.
Простота — не отсутствие сложности, а управление ею. Разработчик ищет прямое решение, которое закрывает задачу сегодня, не плодит «магии» ради гипотетической гибкости. Система должна быть понятна тому, кто будет её поддерживать через полгода, независимо от автора.
Признаки простой системы в коде:
- минимум уровней абстракции;
- короткие, очевидные функции;
- прозрачные зависимости между модулями;
- отсутствие логики «на будущее» (YAGNI);
- читаемость и предсказуемость поведения.
Паттерны и архитектура уместны, когда упрощают понимание и поддержку. Если усложняют — они против KISS.
Главный вопрос инженера: «Можно ли сделать это проще — без потери смысла и качества?»
Пример рефакторинга
Допустим, у нас есть сервис, который вычисляет итоговую цену заказа с учётом скидки и доставки. Без KISS это может выглядеть вот так:
До KISS
public class OrderService {
public double calculatePrice(Order order, boolean includeDelivery, boolean includeDiscount) {
double price = 0;
if (order != null && order.getItems() != null && !order.getItems().isEmpty()) {
for (Item item : order.getItems()) {
if (item != null && item.getPrice() > 0) {
price += item.getPrice() * item.getQuantity();
}
}
if (includeDiscount) {
if (order.getCustomer() != null && order.getCustomer().getDiscount() > 0) {
price = price - (price * order.getCustomer().getDiscount() / 100);
}
}
if (includeDelivery) {
if (order.getAddress() != null && "remote".equals(order.getAddress().getRegion())) {
price += 10;
} else {
price += 5;
}
}
}
return price;
}
}
На первый взгляд, код «рабочий». Но он нарушает KISS почти в каждом месте:
- слишком много ветвлений и проверок;
- повторение логики и флагов;
- неявная зависимость между условиями;
- трудность в тестировании и расширении.
Сделаем рефакторинг. Уберём лишние флаги, разнесём ответственность и оставим только то, что действительно нужно:
После KISS
public class OrderService {
private final DeliveryService deliveryService;
private final DiscountService discountService;
public OrderService(DeliveryService deliveryService, DiscountService discountService) {
this.deliveryService = deliveryService;
this.discountService = discountService;
}
public double calculatePrice(Order order) {
double itemsTotal = order.getItems().stream()
.mapToDouble(i -> i.getPrice() * i.getQuantity())
.sum();
double discounted = discountService.applyDiscount(order, itemsTotal);
double delivery = deliveryService.calculateDelivery(order);
return discounted + delivery;
}
}
Что изменилось:
- ушли флаги и дублирующие условия;
- ответственность разделена; скидки и доставка тестируются изолированно;
- чтение сверху вниз без «магии»;
- изменение правил скидок не трогает остальной код.
Итог тот же, но система проще и надёжнее — это и есть устранение случайной сложности при сохранении существенной.
Заключение
KISS — это не «писать меньше кода», а делать понятные и поддающиеся изменению системы. Каждая строка и зависимость должны быть оправданы. Нет оправдания — это шум.
Простота — не противоположность мастерству, а его верхняя планка. Простые решения переживают технологии и моды.
Делайте просто. Понятно. Надёжно. Всё остальное — временно.