PaxLee
PaxLee学无止境
Назад к списку
Проектирование систем для небольших команд: сначала границы, потом абстракции
技术软件工程系统设计软件架构工程决策小团队实践

Проектирование систем для небольших команд: сначала границы, потом абстракции

Опубликовано 31 июля 2026 г.5 min read

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

Проектирование систем для небольших команд: сначала границы, потом абстракции

На прошлой неделе друг рассказал о своём AI-инструменте для письма. Сначала они использовали одну LLM (GPT-4), потом захотели добавить Claude и локальную модель. Команда спроектировала «универсальный адаптер моделей» — фабрика, стратегия, интерфейсы, нормализация параметров… Код писали три недели. В итоге три модели отличались только в двух местах: формат запроса и парсинг ответа. Три недели на абстракцию, которая не понадобилась.

Это не единичный случай. Самая распространённая ошибка небольших команд — слишком ранняя абстракция. Мы боимся «а вдруг потом придётся расширять» и вводим паттерны, слои, промежуточные middleware. Код становится тяжелее, каждое изменение затрагивает много файлов, онбординг замедляется.

Почему маленькие команды склонны к переусложнению?

Три причины:

  1. Ловушка опыта — Кто-то из большой компании приносит сложные паттерны (микросервисы, событийно-ориентированное, DDD) и применяет их к маленькому проекту без контекста.
  2. Страх будущего — Босс говорит «мы будем поддерживать десять моделей», и вы проектируете под десять, хотя в реальности за год используете только две.
  3. Инженерная гордость — Код, который не «элегантен», кажется неправильным. Лучше потратить лишнее время, чтобы диаграмма классов выглядела идеально.

Цена реальна: увеличивается когнитивная нагрузка, удлиняется отладка, растёт стоимость изменений. В маленькой команде один слой абстракции может превратить задачу на полдня в два дня.

Мой фреймворк: сначала границы, потом отношения

После нескольких продуктов я выработал простой метод — «карта границ и отношений». Суть: сначала определить, что действительно должно меняться независимо, а потом решить, как они связаны.

Шаги:

1. Перечислите кандидатов на изменения

Запишите, что может измениться:

  • Формат запроса для разных AI-моделей
  • Разные базы данных (MySQL vs PostgreSQL)
  • Разные платёжные каналы (WeChat, Alipay)
  • Разные темы UI

Включайте только те изменения, которые вы реально пережили или точно ожидаете в ближайшее время. Не включайте фантазии «а вдруг когда-нибудь…».

2. Оцените каждый кандидат по двум шкалам:

  • Вероятность: Насколько вероятно изменение в ближайшие 6 месяцев. 0-10.
  • Влияние: Сколько файлов/модулей придётся изменить, если это произойдёт? 0-10.

Пример: формат запроса AI-модели → Вероятность 8 (уже планируется вторая модель), Влияние 5 (затрагивает отправку, парсинг, обработку ошибок). Смена БД → Вероятность 1 (не планируется), Влияние 8.

3. Решите, нужна ли абстракция:

  • Если вероятность низкая (<4), пишите жёстко, рефакторите, когда изменение реально произойдёт.
  • Если вероятность высокая и влияние большое (>5), стоит построить слой абстракции.
  • Если вероятность высокая, но влияние маленькое (например, меняется только одна функция), используйте простую обёртку — не нужен паттерн «фабрика».

Вернёмся к примеру с AI-моделями: Вероятность 8, но Влияние 5. Достаточно простого конфигурационного файла и switch-case (или словаря функций). Никакого адаптера.

4. Нарисуйте границы: определите, какой код меняется вместе

Используйте концепцию ограниченных контекстов (без полного DDD). Отметьте области, где код склонен меняться синхронно:

  • Слой вызова моделей: конструирование запроса, парсинг ответа, повторные попытки
  • Слой бизнес-логики: сборка промптов, обработка результатов, взаимодействие с пользователем
  • Слой данных: сохранение, кэширование

Принцип: высокая связность внутри, низкая связанность снаружи. Если изменения в слое вызова моделей не затрагивают бизнес-логику, граница верна.

5. Нарисуйте отношения: определите направление зависимостей между границами

Ещё одна распространённая ошибка — хаотичное направление зависимостей. Например, бизнес-логика напрямую зависит от конкретных классов вызова моделей, и при смене модели её приходится менять. Правильный подход: бизнес-логика зависит только от простого интерфейса слоя вызова моделей, а не от конкретных реализаций. Но этот интерфейс должен предоставлять только те методы, которые реально нужны бизнес-логике, а не все возможные возможности модели.

Пример:

# Бизнес-логике нужно:
def generate_text(prompt: str, model_config: dict) -> str:
    pass

А не:

# Переусложнено
class ModelInterface:
    def generate(self, prompt: str, temperature: float, max_tokens: int, stop_sequences: list, ...):
        pass
    def stream_generate(self, ...):
        pass
    def count_tokens(self, ...):
        pass

Абстрагируйте только то, что реально нужно бизнесу. Игнорируйте то, что может понадобиться потом.

Практический чек-лист

Перед каждым решением о проектировании пройдитесь по пунктам:

  1. Произойдёт ли это изменение в ближайшие 6 месяцев? (Если нет — не абстрагируйте сейчас)
  2. Если не абстрагировать, будет ли стоимость будущего рефакторинга приемлемой? (Если да — не абстрагируйте)
  3. Уменьшает ли абстракция общее количество строк кода? (Если увеличивает — пересмотрите)
  4. Вводит ли абстракция новые зависимости или сторонние библиотеки? (Если да — взвесьте затраты)
  5. Сможет ли каждый член команды понять эту абстракцию? (Если только один — это риск)
  6. Упрощает ли абстракция тестирование? (Если усложняет — откажитесь)

Когда это может не сработать

Этот фреймворк не идеален. Иногда ранняя абстракция может быть полезна:

  • Команда опытна и может точно предсказать будущие изменения, экономя время на рефакторинг.
  • Проекту нужен быстрый демо-показ с поддержкой нескольких моделей, и ранняя абстракция уменьшает авральные правки.
  • Проектирование абстракции само по себе является обучением, помогающим команде лучше понять проблемную область.

Но для большинства небольших команд, особенно когда направление рынка неопределённо, простота — самый безопасный выбор. Когда я делал AI-продукты для письма в Chengdu Past Time, мы сначала поддерживали только одну модель. Когда пользователи попросили другие, мы внесли изменения — и объём работы оказался гораздо меньше ожидаемого.

Итог

Проектирование систем — это не нагромождение паттернов. Это управление неопределённостью. У маленьких команд ограниченные ресурсы, и их стоит тратить на основную бизнес-логику, а не на прокладывание путей для изменений, которые могут никогда не произойти. Сначала нарисуйте границы, чтобы понять, что меняется вместе, затем определите чистые направления зависимостей, и наконец введите минимальную абстракцию для решения реальной проблемы.

В следующий раз, когда будете проектировать новую фичу, спросите себя: «Если я не сделаю абстракцию сейчас, а изменение придёт позже, смогу ли я позволить себе рефакторинг?» Если ответ «да» — не абстрагируйте пока.

PaxLee