Logo Craft Homelab Docs Контакты Telegram
KISS, YAGNI, DRY — принципы простой разработки
Sat Nov 29 2025

KISS, YAGNI, DRY: практическое применение

Три важнейших принципа разработки, которые помогают избежать переусложнения кода.

Эти принципы дополняют друг друга и формируют философию прагматичной разработки. Следование им экономит время и нервы как вам, так и коллегам, которые будут поддерживать код после вас.

KISS — Keep It Simple, Stupid

Простота — признак мастерства. Сложный код сложнее поддерживать и легче сломать.

Пример

# Сложно
def get_status(user):
    if user is not None:
        if user.is_active:
            if user.has_subscription:
                if user.subscription.is_valid:
                    return "active_subscriber"
                else:
                    return "expired_subscriber"
            else:
                return "free_user"
        else:
            return "inactive_user"
    else:
        return "guest"

# Просто (KISS)
def get_status(user):
    if user is None:
        return "guest"
    if not user.is_active:
        return "inactive_user"
    if not user.has_subscription:
        return "free_user"
    return "active_subscriber" if user.subscription.is_valid else "expired_subscriber"

Когда усложнение оправдано

  • Решение реальной проблемы производительности
  • Улучшение читаемости для команды
  • Решение известной задачи более эффективно

YAGNI — You Aren’t Gonna Need It

Не добавляй функциональность, которая может понадобиться в будущем. Это приводит к:

  • Неиспользуемому коду
  • Усложнению рефакторинга
  • Путанице для новых разработчиков

Антипаттерн YAGNI

# Плохо: добавление "на будущее"
class UserService:
    def __init__(self):
        self.db = Database()
        self.cache = RedisCache()  # Пока не используется
        self.notification_service = NotificationService()  # Не нужен
        self.analytics = Analytics()  # Запланировано на v2
    
    def create_user(self, email, password):
        # Просто создаём пользователя
        user = self.db.create(email, password)
        return user

Правильный подход

# Хорошо: добавляем только когда нужно
class UserService:
    def __init__(self):
        self.db = Database()
    
    def create_user(self, email, password):
        user = self.db.create(email, password)
        return user

# Позже, когда понадобится кеширование:
class UserService:
    def __init__(self, cache: Cache = None):
        self.db = Database()
        self.cache = cache
    
    def get_user(self, user_id):
        if self.cache:
            cached = self.cache.get(f"user:{user_id}")
            if cached:
                return cached
        user = self.db.get(user_id)
        if self.cache and user:
            self.cache.set(f"user:{user_id}", user)
        return user

DRY — Don’t Repeat Yourself

Избегай дублирования кода. Выноси общую логику в функции, классы, модули.

Антипаттерн DRY

# Плохо: дублирование
def create_user_form(request):
    name = request.POST.get("name")
    email = request.POST.get("email")
    # Валидация
    if not name:
        return {"error": "Name required"}
    if len(name) < 2:
        return {"error": "Name too short"}
    if not email or "@" not in email:
        return {"error": "Invalid email"}
    # ... сохранение

def update_user_form(request):
    name = request.POST.get("name")
    email = request.POST.get("email")
    # Та же валидация!
    if not name:
        return {"error": "Name required"}
    if len(name) < 2:
        return {"error": "Name too short"}
    if not email or "@" not in email:
        return {"error": "Invalid email"}
    # ... обновление

Правильный подход

# Хорошо: вынос общей логики
def validate_user_data(data: dict) -> dict | None:
    errors = {}
    name = data.get("name")
    email = data.get("email")
    
    if not name:
        errors["name"] = "Name required"
    elif len(name) < 2:
        errors["name"] = "Name too short"
    
    if not email or "@" not in email:
        errors["email"] = "Invalid email"
    
    return errors if errors else None

def create_user_form(request):
    errors = validate_user_data(request.POST)
    if errors:
        return {"error": errors}
    # ... сохранение

def update_user_form(request):
    errors = validate_user_data(request.POST)
    if errors:
        return {"error": errors}
    # ... обновление

Баланс между принципами

Когда DRY может навредить

# Излишнее обобщение
class EntityValidator:
    @staticmethod
    def validate_user(data): ...
    @staticmethod
    def validate_product(data): ...
    @staticmethod
    def validate_order(data): ...
    # 50 методов для разных сущностей

# Лучше: отдельные классы с общим базовым
class BaseValidator:
    def validate_required(self, data, fields): ...
    def validate_email(self, email): ...

class UserValidator(BaseValidator):
    pass

class ProductValidator(BaseValidator):
    pass

Практические рекомендации

  1. Сначала просто — начни с простого решения
  2. Рефакторинг потом — заметил дублирование — вынеси
  3. Не переусердствуй — абстракция ради абстракции — зло
  4. Думай о команде — код должен быть понятен другим

Заключение

Эти принципы работают вместе:

  • KISS — пиши проще
  • YAGNI — не добавляй лишнего
  • DRY — не повторяйся

Следование этим принципам делает код чище, проще в поддержке и экономит время.