mcpField
A
architecture-patterns

architecture-patterns

github.com/secondsky开发240503 次安装5 周前更新
代码仓库

关于 architecture-patterns

面向后端开发者的架构指导技能,涵盖整洁架构、六边形架构和领域驱动设计,并介绍设计原则、实现模式与常见问题。

主要功能

  1. 01整洁架构指导
  2. 02六边形架构模式
  3. 03领域驱动设计概念
  4. 04依赖与接口原则
  5. 05架构常见问题

适用场景

  1. 01从头设计后端系统
  2. 02重构单体应用
  3. 03规划微服务边界
  4. 04提升代码可测试性

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/secondsky/claude-skills --skill architecture-patterns

安装后在 Claude Code 中输入/architecture-patterns确认已加载。

详细介绍

架构模式

掌握经过验证的后端架构模式,包括 Clean Architecture、Hexagonal Architecture 和 Domain-Driven Design,以构建易于维护、可测试且可扩展的系统。

何时使用此技能

  • 从头开始设计新的后端系统
  • 重构单体应用以提升可维护性
  • 为团队制定架构标准
  • 从紧耦合架构迁移到松耦合架构
  • 实施领域驱动设计原则
  • 创建可测试且易于模拟的代码库
  • 规划微服务拆分

核心概念

1. Clean Architecture(Uncle Bob)

分层(依赖关系向内流动):

  • 实体:核心业务模型
  • 用例:应用业务规则
  • 接口适配器:控制器、展示器、网关
  • 框架与驱动:UI、数据库、外部服务

关键原则:

  • 依赖关系指向内层
  • 内层不了解外层
  • 业务逻辑独立于框架
  • 无需 UI、数据库或外部服务即可进行测试
2. Hexagonal Architecture(端口与适配器)

组成部分:

  • 领域核心:业务逻辑
  • 端口:定义交互的接口
  • 适配器:端口的实现(数据库、REST、消息队列)

优点:

  • 可轻松替换实现(用模拟对象进行测试)
  • 核心不依赖特定技术
  • 职责划分清晰
3. Domain-Driven Design(DDD)

战略模式:

  • 限界上下文:为不同领域划分独立模型
  • 上下文映射:上下文之间的关系
  • 通用语言:共享的术语

战术模式:

  • 实体:具有标识的对象
  • 值对象:由属性定义的不可变对象
  • 聚合:一致性边界
  • 仓储:数据访问抽象
  • 领域事件:已发生的事情

Clean Architecture 模式

目录结构
app/
├── domain/           # Entities & business rules
│   ├── entities/
│   ├── value_objects/
│   └── interfaces/   # Abstract interfaces
├── use_cases/        # Application business rules
├── adapters/         # Interface implementations
│   ├── repositories/
│   ├── controllers/
│   └── gateways/
└── infrastructure/   # Framework & external concerns
实现示例
# domain/entities/user.py
from dataclasses import dataclass
from datetime import datetime

@dataclass
class User:
    """Core user entity - no framework dependencies."""
    id: str
    email: str
    name: str
    created_at: datetime
    is_active: bool = True

    def deactivate(self):
        """Business rule: deactivating user."""
        self.is_active = False

    def can_place_order(self) -> bool:
        """Business rule: active users can order."""
        return self.is_active

# domain/interfaces/user_repository.py
from abc import ABC, abstractmethod
from typing import Optional

class IUserRepository(ABC):
    """Port: defines contract, no implementation."""

    @abstractmethod
    async def find_by_id(self, user_id: str) -> Optional[User]:
        pass

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

# use_cases/create_user.py
from dataclasses import dataclass
import uuid
from datetime import datetime

@dataclass
class CreateUserRequest:
    email: str
    name: str

class CreateUserUseCase:
    """Use case: orchestrates business logic."""

    def __init__(self, user_repository: IUserRepository):
        self.user_repository = user_repository

    async def execute(self, request: CreateUserRequest) -> CreateUserResponse:
        # Business validation
        existing = await self.user_repository.find_by_email(request.email)
        if existing:
            return CreateUserResponse(user=None, success=False, error="Email already exists")

        # Create entity
        user = User(
            id=str(uuid.uuid4()),
            email=request.email,
            name=request.name,
            created_at=datetime.now(),
            is_active=True
        )

        # Persist
        saved_user = await self.user_repository.save(user)
        return CreateUserResponse(user=saved_user, success=True)

# adapters/repositories/postgres_user_repository.py
class PostgresUserRepository(IUserRepository):
    """Adapter: PostgreSQL implementation."""

    def __init__(self, pool):
        self.pool = pool

    async def find_by_id(self, user_id: str) -> Optional[User]:
        async with self.pool.acquire() as conn:
            row = await conn.fetchrow("SELECT * FROM users WHERE id = $1", user_id)
            return self._to_entity(row) if row else None

    async def save(self, user: User) -> User:
        async with self.pool.acquire() as conn:
            await conn.execute(
                """INSERT INTO users (id, email, name, created_at, is_active)
                VALUES ($1, $2, $3, $4, $5)
                ON CONFLICT (id) DO UPDATE SET email = $2, name = $3, is_active = $5""",
                user.id, user.email, user.name, user.created_at, user.is_active
            )
            return user

Hexagonal Architecture 模式

# Core domain (hexagon center)
class OrderService:
    """Domain service - no infrastructure dependencies."""

    def __init__(
        self,
        order_repository: OrderRepositoryPort,
        payment_gateway: PaymentGatewayPort,
        notification_service: NotificationPort
    ):
        self.orders = order_repository
        self.payments = payment_gateway
        self.notifications = notification_service

    async def place_order(self, order: Order) -> OrderResult:
        # Business logic
        if not order.is_valid():
            return OrderResult(success=False, error="Invalid order")

        # Use ports (interfaces)
        payment = await self.payments.charge(amount=order.total, customer=order.customer_id)

        if not payment.success:
            return OrderResult(success=False, error="Payment failed")

        order.mark_as_paid()
        saved_order = await self.orders.save(order)

        await self.notifications.send(
            to=order.customer_email,
            subject="Order confirmed",
            body=f"Order {order.id} confirmed"
        )

        return OrderResult(success=True, order=saved_order)

# Adapters
class StripePaymentAdapter(PaymentGatewayPort):
    """Primary adapter: connects to Stripe API."""
    async def charge(self, amount: Money, customer: str) -> PaymentResult:
        # Implementation

class MockPaymentAdapter(PaymentGatewayPort):
    """Test adapter: no external dependencies."""
    async def charge(self, amount: Money, customer: str) -> PaymentResult:
        return PaymentResult(success=True, transaction_id="mock-123")

Domain-Driven Design 模式

# Value Objects (immutable)
@dataclass(frozen=True)
class Email:
    value: str

    def __post_init__(self):
        if "@" not in self.value:
            raise ValueError("Invalid email")

@dataclass(frozen=True)
class Money:
    amount: int  # cents
    currency: str

    def add(self, other: "Money") -> "Money":
        if self.currency != other.currency:
            raise ValueError("Currency mismatch")
        return Money(self.amount + other.amount, self.currency)

# Entities (with identity)
class Order:
    def __init__(self, id: str, customer: Customer):
        self.id = id
        self.customer = customer
        self.items: List[OrderItem] = []
        self.status = OrderStatus.PENDING
        self._events: List[DomainEvent] = []

    def add_item(self, product: Product, quantity: int):
        item = OrderItem(product, quantity)
        self.items.append(item)
        self._events.append(ItemAddedEvent(self.id, item))

    def submit(self):
        if not self.items:
            raise ValueError("Cannot submit empty order")
        self.status = OrderStatus.SUBMITTED
        self._events.append(OrderSubmittedEvent(self.id))

# Aggregates (consistency boundary)
class Customer:
    def __init__(self, id: str, email: Email):
        self.id = id
        self.email = email
        self._addresses: List[Address] = []

    def add_address(self, address: Address):
        if len(self._addresses) >= 5:
            raise ValueError("Maximum 5 addresses allowed")
        self._addresses.append(address)

最佳实践

  1. 依赖规则:依赖关系始终指向内层
  2. 接口隔离:接口小而专注
  3. 业务逻辑位于领域层:核心代码中不引入框架
  4. 测试独立性:核心代码无需基础设施即可测试
  5. 限界上下文:明确领域边界
  6. 通用语言:术语保持一致
  7. 精简控制器:将工作委托给用例
  8. 丰富的领域模型:数据与行为并存

常见陷阱

  • 贫血领域模型:实体只有数据,没有行为
  • 框架耦合:业务逻辑依赖框架
  • 臃肿的控制器:业务逻辑写在控制器中
  • 仓储泄漏:暴露 ORM 对象
  • 缺少抽象:核心代码依赖具体实现
  • 过度设计:简单的 CRUD 也使用 Clean Architecture

评论

支持 Markdown