AgentSkillsCN

software-architecture

全面指南:打造面向生产环境的Python后端开发与规模化软件架构。适用于API设计、后端服务构建、微服务开发、Python项目架构规划、数据库模式实现、异步代码编写,以及各类Python后端/服务器端开发任务。内容涵盖整洁架构、领域驱动设计、事件驱动架构、FastAPI/Django开发模式、数据库设计、缓存策略、可观测性、安全性、测试策略,以及高规模生产系统的部署模式。

SKILL.md
--- frontmatter
name: software-architecture
description: Comprehensive guide for production-ready Python backend development and software architecture at scale. Use when designing APIs, building backend services, creating microservices, structuring Python projects, implementing database patterns, writing async code, or any Python backend/server-side development task. Covers Clean Architecture, Domain-Driven Design, Event-Driven Architecture, FastAPI/Django patterns, database design, caching strategies, observability, security, testing strategies, and deployment patterns for high-scale production systems.

Python Backend Architecture

Production-ready patterns for Python backend systems following Clean Architecture, Domain-Driven Design, and modern distributed system patterns.

Quick Reference

Need to...See Reference
Structure a new projectproject-structure.md
Follow code standardscode-style.md
Implement DI, Repository, UoWarchitecture-patterns.md
Design entities and value objectsdomain-driven-design.md
Build FastAPI endpointsapi-design.md
Set up SQLAlchemy and queriesdatabase-patterns.md
Implement cachingcaching.md
Handle events and sagasevent-driven.md
Build microservicesmicroservices.md
Secure the applicationsecurity.md
Add logging, metrics, tracingobservability.md
Write teststesting.md
Deploy to productiondeployment.md

Core Principles

Architecture Layers

code
┌─────────────────────────────────────────────┐
│           Presentation Layer                │  ← API routes, schemas, middleware
├─────────────────────────────────────────────┤
│           Application Layer                 │  ← Use cases, DTOs, interfaces
├─────────────────────────────────────────────┤
│             Domain Layer                    │  ← Entities, value objects, events
├─────────────────────────────────────────────┤
│          Infrastructure Layer               │  ← DB, cache, messaging, external APIs
└─────────────────────────────────────────────┘

Dependency Rule: Dependencies point inward. Domain has no external dependencies.

Key Principles

  1. Dependency Injection - Depend on abstractions, not implementations
  2. Single Responsibility - One reason to change per class/function
  3. Explicit over Implicit - No hidden dependencies or magic
  4. Async by Default - Use async/await for all I/O operations
  5. Type Hints Everywhere - All public APIs fully typed
  6. Immutability - Prefer immutable data structures (especially value objects)
  7. Early Return - Reduce nesting with guard clauses

Architecture Decision Flowchart

mermaid
flowchart TD
    A[New Feature] --> B{Complex domain logic?}
    B -->|Yes| C[Use Domain-Driven Design]
    B -->|No| D{Multiple data sources?}

    C --> E[Define Entities & Value Objects]
    E --> F[Create Repository Interfaces]
    F --> G[Implement Use Cases]

    D -->|Yes| H[Use Repository Pattern]
    D -->|No| I{Transaction across aggregates?}

    H --> G

    I -->|Yes| J[Use Unit of Work]
    I -->|No| K[Direct repository calls]

    J --> G
    K --> G

    G --> L{Cross-service operation?}
    L -->|Yes| M[Use Saga Pattern]
    L -->|No| N[Single transaction]

    M --> O[Publish Domain Events]
    N --> O

    O --> P{Needs real-time updates?}
    P -->|Yes| Q[Event-Driven Architecture]
    P -->|No| R[Request-Response]

Common Patterns Summary

Domain Layer

Application Layer

  • Use Cases: Single operation orchestrators
  • DTOs: Data transfer between layers
  • Interfaces: Abstract ports for infrastructure

Infrastructure Layer

Presentation Layer


Error Handling Strategy

python
# Domain errors (business logic violations)
class DomainError(Exception): pass
class EntityNotFoundError(DomainError): pass
class BusinessRuleViolationError(DomainError): pass

# Infrastructure errors (external system failures)
class InfrastructureError(Exception): pass
class DatabaseConnectionError(InfrastructureError): pass
class ExternalAPIError(InfrastructureError): pass

# Map to HTTP in presentation layer
@router.get("/{id}")
async def get_item(id: UUID, use_case: GetItemUseCase = Depends(...)):
    try:
        return await use_case.execute(id)
    except EntityNotFoundError:
        raise HTTPException(status_code=404, detail="Not found")
    except BusinessRuleViolationError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except InfrastructureError:
        raise HTTPException(status_code=503, detail="Service unavailable")

See code-style.md for full exception hierarchy.


Quick Start Patterns

Basic Repository + Use Case

python
# 1. Define interface (application layer)
class UserRepository(ABC):
    @abstractmethod
    async def get_by_id(self, id: UUID) -> User | None: pass

    @abstractmethod
    async def save(self, user: User) -> User: pass

# 2. Implement (infrastructure layer)
class PostgresUserRepository(UserRepository):
    def __init__(self, session: AsyncSession):
        self._session = session

    async def get_by_id(self, id: UUID) -> User | None:
        result = await self._session.execute(
            select(UserModel).where(UserModel.id == id)
        )
        model = result.scalar_one_or_none()
        return self._to_entity(model) if model else None

# 3. Use case (application layer)
@dataclass
class GetUserUseCase:
    user_repo: UserRepository

    async def execute(self, user_id: UUID) -> UserDTO:
        user = await self.user_repo.get_by_id(user_id)
        if not user:
            raise EntityNotFoundError("User", str(user_id))
        return UserDTO.from_entity(user)

# 4. Route (presentation layer)
@router.get("/{user_id}")
async def get_user(
    user_id: UUID,
    use_case: GetUserUseCase = Depends(get_user_use_case)
):
    return await use_case.execute(user_id)

Adding Caching

python
@dataclass
class GetUserUseCase:
    user_repo: UserRepository
    cache: CacheService

    async def execute(self, user_id: UUID) -> UserDTO:
        # Try cache
        cached = await self.cache.get(f"user:{user_id}")
        if cached:
            return UserDTO.parse_raw(cached)

        # Fetch from DB
        user = await self.user_repo.get_by_id(user_id)
        if not user:
            raise EntityNotFoundError("User", str(user_id))

        # Cache result
        dto = UserDTO.from_entity(user)
        await self.cache.set(f"user:{user_id}", dto.json(), ttl=300)
        return dto

See caching.md for advanced patterns.

Publishing Events

python
@dataclass
class CreateOrderUseCase:
    order_repo: OrderRepository
    event_bus: EventBus

    async def execute(self, command: CreateOrderCommand) -> OrderDTO:
        order = Order.create(user_id=command.user_id, items=command.items)
        saved = await self.order_repo.add(order)

        # Publish event after successful save
        await self.event_bus.publish(OrderCreatedEvent.from_entity(saved))

        return OrderDTO.from_entity(saved)

See event-driven.md for event handlers and saga patterns.


Production Readiness

Before deploying, verify:

  • Observability: Logging, metrics, tracing configured. See observability.md
  • Security: Auth, input validation, rate limiting. See security.md
  • Testing: Unit, integration, E2E tests passing. See testing.md
  • Resilience: Circuit breakers, retries, graceful shutdown. See microservices.md
  • Deployment: Docker, K8s, health checks configured. See deployment.md