← Назад к вопросам

Что такое YAGNI?

1.0 Junior🔥 121 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI20 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# YAGNI — You Aren't Gonna Need It

YAGNI (You Aren't Gonna Need It) — это принцип проектирования и разработки, который гласит: «Вы это не понадобится». Он подчёркивает, что разработчики не должны добавлять функциональность, которая не требуется в текущих требованиях, даже если есть предположение, что она может быть полезна в будущем.

Суть принципа

Этот принцип является частью методологии экстремального программирования (XP) и близок к принципу KISS (Keep It Simple, Stupid). YAGNI предостерегает от оверинжиниринга и преждевременной оптимизации, которые могут привести к:

  • Излишней сложности кода
  • Увеличению времени разработки
  • Усложнению тестирования и отладки
  • Требованиям к поддержке ненужного функционала
  • Потере гибкости при изменении требований

Примеры нарушения YAGNI

Пример 1: Переинженерные компоненты React

// ❌ ПЛОХО - нарушает YAGNI
interface ButtonProps {
  variant?: 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'danger';
  size?: 'sm' | 'md' | 'lg' | 'xl';
  color?: string;
  disabled?: boolean;
  loading?: boolean;
  icon?: React.ReactNode;
  rightIcon?: React.ReactNode;
  tooltip?: string;
  analytics?: {
    event?: string;
    properties?: Record<string, any>;
  };
  animation?: 'scale' | 'pulse' | 'bounce' | 'none';
  customTheme?: {
    bgColor?: string;
    textColor?: string;
    borderColor?: string;
  };
  // ... ещё 20 пропсов
}

export function Button(props: ButtonProps) {
  // Огромная реализация с поддержкой всех возможных вариантов
}

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

Пример 2: Абстрактные слои

// ❌ ПЛОХО - лишние абстракции
// Repository pattern когда нужен только один источник данных
interface IUserRepository {
  getUser(id: string): Promise<User>;
  saveUser(user: User): Promise<void>;
}

class DatabaseUserRepository implements IUserRepository { }
class CacheUserRepository implements IUserRepository { }
class MockUserRepository implements IUserRepository { }

class UserService {
  constructor(private repo: IUserRepository) { }
  // ...
}

// На самом деле нужно было просто:
class UserService {
  async getUser(id: string) {
    return await db.users.findById(id);
  }
}

Корректное применение YAGNI

Пример 1: Простой компонент Button

// ✅ ХОРОШО - начинаем с простого
interface ButtonProps {
  children: React.ReactNode;
  onClick?: () => void;
  disabled?: boolean;
  className?: string;
}

export function Button({ children, onClick, disabled, className }: ButtonProps) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      className={`px-4 py-2 bg-blue-500 text-white rounded ${className || ''}`}
    >
      {children}
    </button>
  );
}

// Если позже понадобится variant - добавим тогда:
interface ButtonProps {
  children: React.ReactNode;
  onClick?: () => void;
  disabled?: boolean;
  className?: string;
  variant?: 'primary' | 'secondary';  // Добавили когда нужно было
}

Пример 2: Правильное использование паттернов

// ✅ ХОРОШО - простой сервис
class UserService {
  async getUser(id: string) {
    return await db.users.findById(id);
  }

  async updateUser(id: string, updates: Partial<User>) {
    return await db.users.update(id, updates);
  }
}

// Когда действительно нужны разные источники данных - рефакторим:
interface IUserDataSource {
  getUser(id: string): Promise<User>;
}

class UserService {
  constructor(private dataSource: IUserDataSource) { }
  async getUser(id: string) {
    return await this.dataSource.getUser(id);
  }
}

YAGNI в контексте Frontend разработки

1. Управление состоянием

// ❌ Избегайте сложных store если нужно просто передать данные
import { createStore } from 'redux';
// ... код Redux с actions, reducers, selectors

// ✅ Начните с простого
function Parent() {
  const [data, setData] = useState(null);
  return <Child data={data} />;  // Просто props
}

2. Архитектура папок

// ❌ Избегайте
src/
  components/
    Button/
      Button.tsx
      Button.test.tsx
      Button.styles.ts
      Button.types.ts
      Button.stories.tsx
      Button.utils.ts
      index.ts

// ✅ Начните с простого
src/
  components/
    Button.tsx
    Button.test.tsx

3. Типизация

// ❌ Избегайте излишней типизации
interface Config {
  theme?: {
    colors?: {
      primary?: {
        light?: string;
        dark?: string;
      };
    };
  };
}

// ✅ Типизируйте только что используется
interface Config {
  primaryColor: string;
}

Когда НЕ следует применять YAGNI

  1. Архитектурные фундаменты — правильная базовая архитектура экономит время
  2. Безопасность и производительность — эти требования должны быть в начале
  3. Очень вероятные расширения — если расширение действительно очень вероятно, лучше учесть его
  4. Устоявшиеся паттерны — использование проверенных паттернов часто эффективнее

Баланс между YAGNI и гибкостью

YAGNI не означает писать код, который нельзя расширить. Вместо этого:

  1. Пишите расширяемый код — правильная архитектура позволяет добавлять функции легко
  2. Избегайте специфических реализаций — общие решения часто расширяются проще
  3. Тестируйте — хорошее покрытие тестами облегчает рефакторинг
  4. Рефакторьте без страха — если код хорошо протестирован, его легко менять

Практические выводы

  1. Начните с простого — реализуйте минимум для текущих требований
  2. Добавляйте по мере необходимости — новую функциональность добавляйте, когда она действительно нужна
  3. Избегайте оверинжиниринга — не создавайте абстракции "на будущее"
  4. Оценивайте затраты — цена текущей сложности часто больше, чем будущих преимуществ
  5. Поддерживайте баланс — используйте проверенные подходы, но не усложняйте без причины

YAGNI — это не призыв к написанию плохого кода, а напоминание о том, что простота и прагматизм часто лучше, чем предвосхищение будущих потребностей.

Что такое YAGNI? | PrepBro