ЧАСТЬ II: ФУНДАМЕНТ МАСТЕРСТВА

Навык #2: Архитектурное мышление

Глава 5. Навык #2: Архитектурное мышление

"AI может написать функцию за секунды. Но спроектировать всю систему — ваша задача."


5.1. AI пишет код, вы — архитектор

Новая роль программиста

Представьте стройку небоскрёба:

Рабочие — кладут кирпичи, варят сваи, красят стены. Архитектор — проектирует здание, решает, где что будет, как всё соединится.

С AI:

  • AI — это рабочие (пишут код)
  • Вы — архитектор (проектируете систему)

Что может AI

AI отлично справляется с:

  • ✅ Написать функцию по описанию
  • ✅ Создать CRUD API
  • ✅ Настроить базу данных
  • ✅ Написать тесты
  • ✅ Исправить баг

Что НЕ может AI (пока)

AI плохо справляется с:

  • ❌ Спроектировать архитектуру всей системы
  • ❌ Понять бизнес-контекст и долгосрочные цели
  • ❌ Предвидеть, как система будет масштабироваться
  • ❌ Решить, какие компромиссы приемлемы
  • ❌ Увидеть "большую картину"

Это ваша зона ответственности.

Пример

Плохо (без архитектурного мышления):

Вы: "AI, создай систему для онлайн-магазина"
AI: [генерирует монолитное приложение со всем в одном файле]

Через месяц:

  • Код превратился в спагетти
  • Невозможно добавить новую функцию без багов
  • Тормозит при 100+ пользователях
  • Невозможно разделить работу в команде

Хорошо (с архитектурным мышлением):

Вы: "AI, создай систему для онлайн-магазина.
Используй следующую архитектуру:
- Frontend: React
- Backend API: Node.js/Express
- База данных: PostgreSQL
- Разбей на модули: users, products, orders, payments
- Каждый модуль — отдельный сервис (микросервисы)
- Используй REST API для коммуникации"

AI: [генерирует структурированную систему]

Через месяц:

  • Чистая архитектура
  • Легко добавлять функции
  • Каждый сервис масштабируется независимо
  • Команда может работать параллельно над разными модулями

Разница: Вы спроектировали систему, AI реализовал.


5.2. Как разбить большую задачу на модули

Принцип: Divide and Conquer

Большую задачу невозможно решить за один раз.

Нужно разбить на части:

  1. Выделить модули (независимые части системы)
  2. Определить ответственность каждого модуля
  3. Определить интерфейсы между модулями

Пример: Система для блога

Большая задача: "Создать платформу для блогов, где пользователи могут писать статьи, комментировать, подписываться друг на друга"

Без разбиения (монолит):

blog_system.py  (3000 строк кода — всё в одном файле)

С разбиением (модули):

users/           # Модуль пользователей
  - models.py    # User модель
  - auth.py      # Аутентификация
  - profile.py   # Профили

articles/        # Модуль статей
  - models.py    # Article модель
  - crud.py      # Создание, редактирование, удаление
  - search.py    # Поиск статей

comments/        # Модуль комментариев
  - models.py    # Comment модель
  - moderation.py# Модерация

subscriptions/   # Модуль подписок
  - models.py    # Subscription модель
  - feed.py      # Лента подписок

Как определить модули

Задайте вопросы:

  1. Какие основные сущности (entities) в системе?

    • Пользователи (Users)
    • Статьи (Articles)
    • Комментарии (Comments)
    • Подписки (Subscriptions)
  2. Какие операции выполняются над каждой сущностью?

    • Users: регистрация, логин, профиль
    • Articles: создание, редактирование, удаление, поиск
    • Comments: добавление, удаление, модерация
    • Subscriptions: подписка, отписка, лента
  3. Можно ли эти операции выделить в отдельный модуль?

    • Да! Каждая сущность → отдельный модуль

С AI

Промпт:

Проанализируй требования к платформе блогов:
- Пользователи могут писать статьи
- Комментировать статьи
- Подписываться друг на друга
- Видеть ленту подписок

Предложи модульную архитектуру.
Опиши каждый модуль и его ответственность.

AI даст вам предложение.

Ваша задача: Проверить, осмыслить, скорректировать.


5.3. Separation of Concerns

Принцип: Каждый модуль — одна ответственность

Separation of Concerns (Разделение ответственности):

Каждая часть системы должна заниматься одной вещью и делать её хорошо.

Плохой пример

def create_article(title, content, user_id):
    # Проверка пользователя
    user = db.query("SELECT * FROM users WHERE id = ?", user_id)
    if not user:
        return "User not found"

    # Проверка прав
    if not user['is_active']:
        return "User not active"

    # Создание статьи
    article_id = db.insert("INSERT INTO articles ...")

    # Отправка email
    send_email(user['email'], "Article created!")

    # Логирование
    log("Article created: " + article_id)

    # Обновление статистики
    update_stats(user_id)

    return article_id

Проблемы:

  • Функция делает слишком много (проверка пользователя, создание статьи, email, лог, статистика)
  • Сложно тестировать
  • Сложно изменить (изменение email затронет всю функцию)

Хороший пример

# users/auth.py
def get_active_user(user_id):
    """Получить активного пользователя"""
    user = db.query("SELECT * FROM users WHERE id = ?", user_id)
    if not user or not user['is_active']:
        return None
    return user

# articles/crud.py
def create_article(title, content, author_id):
    """Создать статью"""
    article_id = db.insert(
        "INSERT INTO articles (title, content, author_id) VALUES (?, ?, ?)",
        title, content, author_id
    )
    return article_id

# notifications/email.py
def notify_article_created(user_email, article_id):
    """Уведомить о создании статьи"""
    send_email(user_email, f"Article {article_id} created!")

# analytics/stats.py
def update_user_stats(user_id):
    """Обновить статистику пользователя"""
    # ...

# Главная функция (orchestrator)
def publish_article(title, content, user_id):
    # Проверка пользователя
    user = get_active_user(user_id)
    if not user:
        return {"error": "User not found or inactive"}

    # Создание статьи
    article_id = create_article(title, content, user_id)

    # Побочные эффекты (асинхронно)
    notify_article_created(user['email'], article_id)
    update_user_stats(user_id)
    log_event("article_created", article_id)

    return {"article_id": article_id}

Преимущества:

  • Каждая функция делает одну вещь
  • Легко тестировать каждую функцию отдельно
  • Легко изменить (изменение email не затронет создание статьи)
  • Можно переиспользовать функции

С AI

Плохо:

AI, создай функцию для публикации статьи

Хорошо:

AI, создай следующие функции:
1. get_active_user(user_id) - проверить пользователя
2. create_article(title, content, author_id) - создать статью в БД
3. notify_article_created(user_email, article_id) - отправить email
4. publish_article(title, content, user_id) - главная функция, которая оркестрирует всё

Каждая функция должна иметь одну ответственность.

AI сгенерирует чистую архитектуру.


5.4. Слоистая архитектура

Принцип: Разделить систему на слои

Слоистая архитектура (Layered Architecture):

Система разделена на горизонтальные слои, каждый слой общается только с соседними.

Типичные слои

┌─────────────────────────┐
│  Presentation Layer     │  ← UI, API endpoints
├─────────────────────────┤
│  Business Logic Layer   │  ← Бизнес-логика, правила
├─────────────────────────┤
│  Data Access Layer      │  ← Работа с БД
├─────────────────────────┤
│  Database               │  ← Хранилище данных
└─────────────────────────┘

Правило: Каждый слой общается только с непосредственно соседним.

Пример

Слой 1: Presentation (API)

# api/articles.py
@app.post("/articles")
def create_article_endpoint(request):
    """API endpoint для создания статьи"""
    data = request.json

    # Валидация входных данных
    if not data.get('title') or not data.get('content'):
        return {"error": "Missing fields"}, 400

    # Вызов бизнес-логики
    result = article_service.create_article(
        title=data['title'],
        content=data['content'],
        user_id=request.user_id
    )

    return {"article_id": result}, 201

Слой 2: Business Logic (Сервис)

# services/article_service.py
def create_article(title, content, user_id):
    """Бизнес-логика создания статьи"""

    # Проверка прав пользователя
    user = user_repository.get_by_id(user_id)
    if not user or not user.is_active:
        raise PermissionError("User not active")

    # Проверка лимитов
    if user.article_count >= user.max_articles:
        raise LimitError("Article limit reached")

    # Создание статьи через Data Access Layer
    article = article_repository.create(
        title=title,
        content=content,
        author_id=user_id
    )

    # Обновление счётчика
    user_repository.increment_article_count(user_id)

    return article.id

Слой 3: Data Access (Repository)

# repositories/article_repository.py
def create(title, content, author_id):
    """Создать статью в БД"""
    query = """
        INSERT INTO articles (title, content, author_id, created_at)
        VALUES (?, ?, ?, NOW())
        RETURNING id
    """
    result = db.execute(query, title, content, author_id)
    return result

Преимущества слоистой архитектуры

Разделение ответственности: Каждый слой делает своё ✅ Тестируемость: Можно тестировать каждый слой отдельно ✅ Замена компонентов: Можно заменить БД без изменения бизнес-логики ✅ Читаемость: Ясная структура

С AI

Промпт:

Создай слоистую архитектуру для модуля статей:
1. API layer (endpoints)
2. Service layer (бизнес-логика)
3. Repository layer (работа с БД)

Каждый слой в отдельном файле.

AI создаст чистую структуру.


5.5. API Design — как компоненты общаются

Принцип: Чёткие интерфейсы между модулями

API (Application Programming Interface) — это контракт, как один модуль общается с другим.

Типы API

1. Внутренний API (между модулями вашего приложения)

# users/service.py
def get_user(user_id: int) -> User:
    """Получить пользователя по ID"""
    pass

# articles/service.py
from users.service import get_user

def create_article(title, content, author_id):
    user = get_user(author_id)  # Вызов API другого модуля
    if not user:
        raise ValueError("User not found")
    # ...

2. Внешний API (HTTP/REST)

# API endpoints
GET    /articles          # Список статей
GET    /articles/:id      # Одна статья
POST   /articles          # Создать статью
PUT    /articles/:id      # Обновить статью
DELETE /articles/:id      # Удалить статью

Принципы хорошего API

1. Предсказуемость

Плохо:

def create_article(data):
    # Что в data? Неясно!
    pass

Хорошо:

def create_article(title: str, content: str, author_id: int) -> int:
    """
    Создать статью.

    Args:
        title: Заголовок статьи
        content: Содержимое статьи
        author_id: ID автора

    Returns:
        ID созданной статьи

    Raises:
        ValueError: Если автор не найден
    """
    pass

2. Консистентность

Плохо:

# Одни функции возвращают объект, другие ID
create_article()  # → возвращает ID
create_user()     # → возвращает объект User

Хорошо:

# Все функции возвращают объект
create_article()  # → Article
create_user()     # → User

3. Минимализм

API должен быть простым:

# Плохо: слишком много параметров
def create_article(title, content, author_id, tags, category,
                   published, featured, allow_comments, notify_subscribers):
    pass

# Хорошо: основные параметры, остальное опционально
def create_article(title: str, content: str, author_id: int, **options):
    pass

REST API Design

Принципы REST:

  1. Ресурсы — существительные, не глаголы

    • GET /articles
    • GET /getArticles
  2. HTTP методы определяют действие

    • GET — получить
    • POST — создать
    • PUT/PATCH — обновить
    • DELETE — удалить
  3. Статус-коды информативны

    • 200 — OK
    • 201 — Created
    • 400 — Bad Request
    • 404 — Not Found
    • 500 — Server Error

С AI

Промпт:

Спроектируй REST API для модуля статей.
Включи endpoints для:
- Список статей (с пагинацией)
- Одна статья по ID
- Создание статьи
- Обновление статьи
- Удаление статьи

Используй RESTful принципы.
Опиши каждый endpoint: метод, путь, параметры, ответ.

AI даст вам спроектированный API.

Ваша задача: Проверить консистентность, логичность.


5.6. Масштабируемость

Принцип: Система должна расти с нагрузкой

Масштабируемость — способность системы справляться с ростом:

  • Пользователей
  • Данных
  • Запросов

Два типа масштабирования

1. Вертикальное (Vertical Scaling)

Идея: Купить более мощный сервер.

1 сервер (4 CPU, 8 GB RAM)
    ↓
1 сервер (16 CPU, 64 GB RAM)

Плюсы:

  • Просто
  • Не нужно менять код

Минусы:

  • Дорого
  • Есть предел (нельзя бесконечно улучшать один сервер)

2. Горизонтальное (Horizontal Scaling)

Идея: Добавить больше серверов.

1 сервер
    ↓
10 серверов (за load balancer)

Плюсы:

  • Дешевле (много маленьких серверов)
  • Нет предела (можно добавлять бесконечно)

Минусы:

  • Сложнее
  • Нужна правильная архитектура

Архитектура для масштабирования

Проблема монолита:

[Веб-сервер + Бизнес-логика + БД]  (всё в одном процессе)

Если растёт нагрузка на БД, нужно масштабировать всё.

Решение: разделить на сервисы

[Веб-сервер] ← → [API сервер] ← → [БД сервер]

Теперь можно масштабировать каждую часть независимо:

  • 10 веб-серверов
  • 5 API серверов
  • 3 БД реплики

Пример: кэширование

Проблема: База данных тормозит при 1000 запросах/сек.

Решение: добавить кэш (Redis, Memcached)

# Без кэша (медленно)
def get_article(article_id):
    return db.query("SELECT * FROM articles WHERE id = ?", article_id)

# С кэшем (быстро)
def get_article(article_id):
    # Проверяем кэш
    cached = cache.get(f"article:{article_id}")
    if cached:
        return cached  # Возвращаем из кэша (быстро!)

    # Запрос к БД
    article = db.query("SELECT * FROM articles WHERE id = ?", article_id)

    # Сохраняем в кэш на 10 минут
    cache.set(f"article:{article_id}", article, ttl=600)

    return article

Результат: 90%+ запросов обслуживаются из кэша (в миллисекунды вместо секунд).

С AI

Плохо:

AI, сделай систему быстрее

Хорошо:

AI, добавь кэширование для функции get_article.
Используй Redis.
Кэшируй результаты на 10 минут.
Инвалидируй кэш при обновлении статьи.

5.7. Практика: проектируем архитектуру с AI

Упражнение: TODO-приложение

Задача: Спроектировать архитектуру для TODO-приложения.

Требования:

  • Пользователи могут регистрироваться и логиниться
  • Создавать задачи (TODO items)
  • Отмечать задачи как выполненные
  • Фильтровать: все / активные / выполненные
  • Каждый пользователь видит только свои задачи

Шаг 1: Определите модули

Подсказка

Модули:

  • users — регистрация, аутентификация
  • todos — CRUD операции с задачами

Шаг 2: Определите слои

Подсказка

Слои:

  • API layer — HTTP endpoints
  • Service layer — бизнес-логика
  • Repository layer — работа с БД

Шаг 3: Спроектируйте API

Подсказка
POST   /auth/register       # Регистрация
POST   /auth/login          # Логин

GET    /todos               # Список задач (?filter=all|active|completed)
POST   /todos               # Создать задачу
PUT    /todos/:id           # Обновить задачу
DELETE /todos/:id           # Удалить задачу
PATCH  /todos/:id/complete  # Отметить как выполненную

Шаг 4: Используйте AI для генерации

Промпт:

Создай архитектуру для TODO-приложения:

Модули:
- users (регистрация, аутентификация)
- todos (CRUD операции)

Слои:
- API layer (Flask/FastAPI)
- Service layer (бизнес-логика)
- Repository layer (SQLAlchemy)

API endpoints:
[вставьте спроектированные endpoints]

Создай структуру файлов и базовый код для каждого слоя.

Шаг 5: Проверьте результат

Проверьте:

  • ✅ Каждый модуль имеет одну ответственность?
  • ✅ Слои чётко разделены?
  • ✅ API консистентен?
  • ✅ Можно легко добавить новую функцию (например, теги для задач)?

5.8. Упражнения

Задание 1: Анализ архитектуры

Попросите AI сгенерировать простое приложение (например, блог).

Затем проанализируйте:

  1. Какие модули выделены?
  2. Есть ли разделение на слои?
  3. Как модули общаются друг с другом?
  4. Можно ли улучшить архитектуру?

Задание 2: Рефакторинг монолита

Попросите AI создать монолитное приложение (всё в одном файле).

Затем:

  1. Разбейте на модули
  2. Выделите слои
  3. Попросите AI помочь с рефакторингом
  4. Сравните до/после

Задание 3: Проектирование API

Спроектируйте REST API для:

  • Системы бронирования отелей
  • Магазина электронных книг
  • Социальной сети для программистов

Используйте AI для генерации, но сначала спроектируйте сами, потом сравните.


Ключевые выводы главы

Архитектор vs Исполнитель: AI пишет код, вы проектируете систему

Модули: Разбивайте большую задачу на независимые части

Separation of Concerns: Каждый модуль — одна ответственность

Слоистая архитектура: API → Service → Repository → DB

API Design: Чёткие интерфейсы, предсказуемость, консистентность

Масштабируемость: Проектируйте с учётом роста

С AI: Вы проектируете, AI реализует

Проверяйте AI: Архитектура требует человеческого понимания контекста


Следующая глава: Алгоритмическое мышление — понимание сложности и оптимизации