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

Как производится проектирование программных решений?

2.0 Middle🔥 181 комментариев
#Soft Skills#Архитектура и паттерны

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

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

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

Как производится проектирование программных решений

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

Фаза 1: Понимание требований

Встречаюсь с заказчиком и задаю вопросы:

Функциональные:

  • Какие основные юзкейсы?
  • Какие ограничения по производительности?
  • Какие объёмы данных?

Нефункциональные:

  • Масштабируемость?
  • Надёжность?
  • Безопасность?
  • Стоимость?

Фаза 2: High-Level Design (архитектура)

Определяю основные компоненты системы.

Пример: система заказов для e-commerce

┌─────────────┐
│  Frontend   │
└──────┬──────┘
       │
┌──────▼──────────┐
│  API Gateway    │
└──────┬──────────┘
       │
┌──────▼──────────────────────┐
│    Microservices             │
├─────────────┬──────────┬──────┤
│ Orders      │ Users    │ Payments
│ Service     │ Service  │ Service
└─────────┬───┴──────────┴──┬───┘
          │                 │
    ┌─────▼────┐      ┌─────▼──────┐
    │   DB     │      │   Cache    │
    │PostgreSQL│      │   Redis    │
    └──────────┘      └────────────┘

Фаза 3: Low-Level Design (компоненты)

Для Order Service определяю структуру:

from dataclasses import dataclass
from enum import Enum
from typing import List
from datetime import datetime

class OrderStatus(Enum):
    PENDING = "pending"
    CONFIRMED = "confirmed"
    SHIPPED = "shipped"
    DELIVERED = "delivered"
    CANCELLED = "cancelled"

@dataclass
class OrderItem:
    product_id: int
    quantity: int
    price: float

@dataclass
class Order:
    id: str
    user_id: int
    items: List[OrderItem]
    status: OrderStatus
    created_at: datetime
    total_amount: float

class OrderService:
    def create_order(self, user_id: int, items: List[OrderItem]) -> Order:
        if not items:
            raise ValueError("Order must have items")
        
        total = sum(item.quantity * item.price for item in items)
        order = Order(
            id=self._generate_id(),
            user_id=user_id,
            items=items,
            status=OrderStatus.PENDING,
            created_at=datetime.utcnow(),
            total_amount=total
        )
        self.db.add(order)
        self.db.commit()
        return order
    
    def update_order_status(self, order_id: str, new_status: OrderStatus):
        order = self.db.get(Order, order_id)
        if not order:
            raise ValueError(f"Order {order_id} not found")
        
        valid_transitions = {
            OrderStatus.PENDING: [OrderStatus.CONFIRMED, OrderStatus.CANCELLED],
            OrderStatus.CONFIRMED: [OrderStatus.SHIPPED, OrderStatus.CANCELLED],
            OrderStatus.SHIPPED: [OrderStatus.DELIVERED],
        }
        
        if new_status not in valid_transitions.get(order.status, []):
            raise ValueError(f"Invalid transition")
        
        order.status = new_status
        self.db.commit()

Фаза 4: Выбор паттернов

# Repository Pattern — абстракция для БД
class OrderRepository:
    def get_by_id(self, order_id: str) -> Order:
        pass
    
    def get_by_user(self, user_id: int) -> List[Order]:
        pass
    
    def save(self, order: Order) -> Order:
        pass

# Dependency Injection — слабая связанность
class OrderController:
    def __init__(self, order_service: OrderService):
        self.order_service = order_service
    
    def create(self, request):
        order = self.order_service.create_order(
            user_id=request.user_id,
            items=request.items
        )
        return order

Фаза 5: Проектирование БД

# Таблицы:
# orders:
#   id (PK)
#   user_id (FK)
#   status (ENUM)
#   total_amount (DECIMAL)
#   created_at (TIMESTAMP)
#
# order_items:
#   id (PK)
#   order_id (FK)
#   product_id (FK)
#   quantity (INT)
#   price (DECIMAL)

# Миграция Goose
migration_sql = """
CREATE TABLE orders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id INTEGER NOT NULL REFERENCES users(id),
    status VARCHAR(20) NOT NULL,
    total_amount DECIMAL(10, 2) NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_status ON orders(status);

CREATE TABLE order_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    order_id UUID NOT NULL REFERENCES orders(id),
    product_id INTEGER NOT NULL,
    quantity INTEGER NOT NULL,
    price DECIMAL(10, 2) NOT NULL
);

CREATE INDEX idx_order_items_order_id ON order_items(order_id);
"""

Фаза 6: Проектирование API

from fastapi import APIRouter, HTTPException

router = APIRouter(prefix="/api/v1")

@router.post("/orders")
def create_order(request: CreateOrderRequest):
    try:
        order = order_service.create_order(
            user_id=request.user_id,
            items=request.items
        )
        return order
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))

@router.get("/orders/{order_id}")
def get_order(order_id: str):
    order = order_service.get_order(order_id)
    if not order:
        raise HTTPException(status_code=404)
    return order

@router.get("/users/{user_id}/orders")
def get_user_orders(user_id: int):
    return order_service.get_user_orders(user_id)

Фаза 7: Обработка ошибок

# Domain Layer
class OrderNotFound(Exception):
    pass

class OrderService:
    def get_order(self, order_id: str) -> Order:
        order = self.repository.get_by_id(order_id)
        if not order:
            raise OrderNotFound(f"Order not found")
        return order

# Controller Layer
@router.get("/orders/{order_id}")
def get_order(order_id: str):
    try:
        return order_service.get_order(order_id)
    except OrderNotFound:
        raise HTTPException(status_code=404)
    except Exception as e:
        logger.error(f"Error: {e}")
        raise HTTPException(status_code=500)

Фаза 8: Масштабируемость

class Scalability:
    # Кеширование (Redis)
    @cache(ttl=300)
    def get_order(self, order_id: str) -> Order:
        return self.repository.get_by_id(order_id)
    
    # Event Queue для асинхронной обработки
    def create_order_async(self, user_id: int, items: List[OrderItem]):
        self.event_queue.publish('order.created', {
            'user_id': user_id,
            'items': items
        })
    
    # Read Replicas для чтения
    def get_orders_read_only(self, user_id: int):
        return self.read_replica.query(Order).filter_by(user_id=user_id)

Моя методология

  1. Gather Requirements (15%)

    • Встречи с заказчиком
    • Документирование
  2. High-Level Design (20%)

    • Архитектура
    • Компоненты
    • Технологии
  3. Low-Level Design (30%)

    • Классы и функции
    • БД schema
    • API contracts
    • Обработка ошибок
  4. Implementation (25%)

    • Код
    • Тестирование
  5. Review & Refinement (10%)

    • Code review
    • Доработка

Ключевые принципы

  • SOLID — слабая связанность, слабая когезия
  • DDD — domain-driven design
  • Separation of Concerns — каждый слой — своя ответственность
  • Testability — дизайн для тестируемости
  • Scalability — архитектура для роста
  • Documentation — документируй решения
Как производится проектирование программных решений? | PrepBro