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

Читал ли литературу по Clean Architecture

2.2 Middle🔥 142 комментариев
#JavaScript Core

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Обзор и применение принципов Clean Architecture в Frontend разработке

Да, я глубоко изучал литературу по Clean Architecture, в первую очередь работы Роберта Мартина ("Uncle Bob"), и активно применяю ее принципы в разработке фронтенд-приложений. Хотя книга Мартина "Clean Architecture: A Craftsman's Guide to Software Structure and Design" ориентирована на общие концепции разработки ПО, ее идеи оказали существенное влияние на современный frontend, особенно с распространением сложных SPA и фреймворков. Для фронтенда ключевой идеей стало разделение ответственностей и создание устойчивых к изменениям систем.

Как Clean Architecture трансформируется для Frontend

Основная задача — адаптировать классические слои (Entities, Use Cases, Interface Adapters, Frameworks & Drivers) к специфике клиентской стороны. Я интерпретирую это следующим образом:

1. Domain Layer (Entities и бизнес-правила)
В frontend это часто модели данных и бизнес-логика, не зависящая от UI или внешних API. Например, валидация форм, расчеты, правила состояния приложения.

// Пример сущности (Entity) и бизнес-правила в TypeScript
class ShoppingCartItem {
  constructor(
    public readonly id: string,
    public readonly productId: string,
    private quantity: number,
    public readonly maxQuantity: number
  ) {}

  // Бизнес-правило: количество не может превышать максимум
  increaseQuantity(amount: number): void {
    const newQuantity = this.quantity + amount;
    if (newQuantity > this.maxQuantity) {
      throw new Error('Quantity exceeds maximum limit');
    }
    this.quantity = newQuantity;
  }

  getQuantity(): number {
    return this.quantity;
  }
}

2. Application Layer (Use Cases)
Это сервисы или контроллеры, которые координируют работу домена и внешних взаимодействий (API, состояние UI). Они не содержат деталей реализации, только "что" нужно сделать.

// Use Case: добавление товара в корзину
class AddItemToCartUseCase {
  constructor(
    private cartRepository: ICartRepository,
    private productService: IProductService
  ) {}

  async execute(productId: string, quantity: number): Promise<void> {
    // 1. Получаем данные продукта (может быть из API)
    const product = await this.productService.getProductDetails(productId);
    
    // 2. Создаем сущность с бизнес-правилами
    const cartItem = new ShoppingCartItem(
      generateId(),
      productId,
      quantity,
      product.maxOrderQuantity
    );
    
    // 3. Сохраняем через абстракцию репозитория
    await this.cartRepository.save(cartItem);
  }
}

3. Interface Adapters Layer
В frontend это включает:

  • Presenters/Controllers для преобразования данных в формат, удобный для UI.
  • Repository implementations для связи с API.
  • State management адаптеры (например, связь Redux/Vuex с доменом).
// Адаптер для преобразования данных домена в формат для UI (Presenter)
class CartPresenter {
  presentCartItems(items: ShoppingCartItem[]): CartItemViewModel[] {
    return items.map(item => ({
      id: item.id,
      quantity: item.getQuantity(),
      // Преобразование для отображения в компоненте
      formattedQuantity: `${item.getQuantity()} units`,
    }));
  }
}

// Реализация репозитория (адаптер к внешнему API)
class ApiCartRepository implements ICartRepository {
  async save(item: ShoppingCartItem): Promise<void> {
    // Преобразование сущности в DTO для API
    const dto = {
      productId: item.productId,
      quantity: item.getQuantity(),
    };
    await fetch('/api/cart', { method: 'POST', body: JSON.stringify(dto) });
  }
}

4. Frameworks & Drivers Layer
Это конкретные UI фреймворки (React, Vue, Angular), библиотеки (axios для HTTP), и сами UI компоненты. Они зависят от всех вышестоящих слоев, но не влияют на них.

// React компонент (Frameworks layer) использует Use Case и Presenter
const CartComponent: React.FC = () => {
  const addItemUseCase = useAddItemToCartUseCase();
  const cartPresenter = useCartPresenter();

  const handleAddItem = async (productId: string) => {
    // Компонент вызывает Use Case, не зная деталей реализации
    await addItemUseCase.execute(productId, 1);
  };

  return (
    <div>
      <button onClick={() => handleAddItem('PROD_123')}>Add Item</button>
    </div>
  );
};

Практические преимущества для Frontend проектов

  • Тестируемость: Доменная логика и use cases легко тестируются без UI.
  • Замена фреймворков: UI фреймворк можно заменить без переписывания бизнес-логики.
  • Устойчивость к изменениям API: изменения в backend API затрагивают только адаптеры в слое репозиториев.
  • Чистые компоненты: UI компоненты становятся "глупыми", только отображают данные и вызывают команды.
  • Масштабирование: новые функции добавляются как новые use cases и сущности, не нарушая существующий код.

Ключевые адаптации для Frontend

В отличие от backend, в frontend я дополнительно уделяю внимание:

  • Слою состояния UI: управление состоянием интерфейса (загрузка, ошибки) как часть адаптеров.
  • Инфраструктуре: сборка, роутинг, инъекция зависимостей (например, через контексты React или Vue provide/inject).
  • Паттернам: часто использую Dependency Injection для связывания слоев и Repository pattern для абстрагирования API.

Пример структуры проекта

src/
├── domain/              # Сущности и бизнес-правила
│   ├── models/
│   └── rules/
├── application/         # Use Cases, сервисы
│   ├── use-cases/
│   └── services/
├── adapters/            # Presenters, репозитории, преобразователи
│   ├── presenters/
│   ├── repositories/
│   └── state/
└── frameworks/          # Компоненты, хуки, конфигурация фреймворка
    ├── components/
    ├── hooks/
    └── utils/

Я считаю, что Clean Architecture не является "серебряной пулей", но для сложных долгосрочных frontend проектов она дает структурную дисциплину, которая значительно снижает стоимость поддержки и расширения. В меньших проектах можно применять ее принципы частично, особенно разделение доменной логики и UI. Главный вывод из литературы: архитектура должна защищать самое важное — бизнес-правила — от изменений в деталях реализации, и в frontend это актуально как никогда.