architecture-patterns:把后端分层架构讲成可执行的样板

前言

后端代码写久了最常见的问题不是性能,而是分层退化:domain 里直接 import 了 ORM,use case 里塞满了 HTTP 状态码,测试必须连数据库才能跑。架构规则写在文档里没人看,写在代码里又没人维护。下面介绍的 architecture-patterns 是一个提示词型 Skill,作用是把这些规则带进对话流程,让模型在设计或重构时按同一套分层约束产出代码。

这是什么

architecture-patterns 是一个通用 SKILL.md 格式的后端架构模式 Skill,坐标 @clawhub_wpank/architecture-patterns,版本 1.0.0,发布者 wpank,来源 clawhub,分类 dev-programming。它覆盖清洁架构(Clean Architecture)、六边形架构(Hexagonal / Ports & Adapters)与领域驱动设计(DDD),用于构建可维护、可测试、可扩展的系统,并给出清晰的分层结构和依赖方向约束。

在 SkillHub 上的页面标注为「Architecture Patterns」,属于 dev-programming 分类。

核心功能

下面介绍的都是 SKILL.md 中实际写明的能力。

1、一个选型决策表,按场景推荐模式。简单 CRUD 应用建议不加架构(避免过度设计),中等复杂度且需要团队统一标准时用清洁架构,外部集成多且变化频繁时用六边形架构,业务规则复杂的领域用 DDD,多团队的大规模系统用 DDD + 限界上下文。

2、清洁架构的分层图与依赖规则。四层分别是 Entities、Use Cases、Interface Adapters、Frameworks & Drivers,依赖只能由外向内,内层不得 import 外层。

3、六边形架构的 Port 与 Adapter 图示,端口定义领域需要什么,适配器是可替换的实现,测试时可换掉。

4、一套目录结构约定,app/domain 放实体与业务规则(内层),use_cases 放应用逻辑,adapters 放接口实现(仓储、控制器),infrastructure 放框架与外部关注点。

5、可直接参考的代码骨架,包括实体定义、抽象端口(IUserRepository)、用例编排(CreateUserUseCase)、Postgres 适配器、领域服务与适配器替换示例、不可变值对象(Email、Money)、聚合根与不变量校验。

6、要点标注:实体内不写框架依赖,业务规则放在实体和聚合里,端口定义契约而不给实现,适配器可互换以便测试。

安装与启用

安装命令来自官方页面:

$ openclaw skills install @wpank/architecture-patterns

页面同时给出另一种途径,用 npx 通过 skills CLI:

npx skills

安装后在对话中触发即可,触发条件写得很明确:从零设计后端系统、为可维护性重构单体、为团队建立架构标准、创建可测试可 mock 的代码库、规划微服务拆分。

当前资料里没有列出 Cursor / Codex CLI / Claude Code 的差异化安装方式,这里不做推测。

典型用法

下面的例子都来自 SKILL.md,可直接对照。

先看目录结构,把分层落到文件上:

app/
├── domain/            # 实体与业务规则(最内层)
│   ├── entities/
│   │   └── user.py
│   ├── value_objects/
│   │   └── email.py
│   └── interfaces/    # 端口
│       └── user_repository.py
├── use_cases/         # 应用业务规则
│   └── create_user.py
├── adapters/          # 接口实现
│   ├── repositories/
│   │   └── postgres_user_repository.py
│   └── controllers/
│       └── user_controller.py
└── infrastructure/    # 框架与外部关注点
    ├── database.py
    └── config.py

实体层不引入框架,业务规则写在实体方法里:

from dataclasses import dataclass
from datetime import datetime

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

    def deactivate(self):
        """Business rule in entity."""
        self.is_active = False

    def can_place_order(self) -> bool:
        return self.is_active

端口只定义契约,不给实现:

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

用例负责编排,依赖通过构造函数注入:

@dataclass
class CreateUserRequest:
    email: str
    name: str

@dataclass
class CreateUserResponse:
    user: Optional[User]
    success: bool
    error: Optional[str] = None

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

    def __init__(self, user_repository: IUserRepository):
        self.user_repository = user_repository  # Injected dependency

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

        user = User(
            id=str(uuid.uuid4()),
            email=request.email,
            name=request.name,
            created_at=datetime.now()
        )

        saved = await self.user_repository.save(user)
        return CreateUserResponse(user=saved, success=True)

适配器实现端口,可以换成 Postgres、内存实现或其他:

class PostgresUserRepository(IUserRepository):
    """Adapter: PostgreSQL implementation of the port."""

    def __init__(self, pool: asyncpg.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

六边形架构的用法是给领域服务注入多个端口,测试时替换为 mock 适配器:

class OrderService:
    def __init__(
        self,
        order_repo: OrderRepositoryPort,   # Port
        payment: PaymentGatewayPort,      # Port
        notifications: NotificationPort   # Port
    ):
        self.orders = order_repo
        self.payments = payment
        self.notifications = notifications

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

        payment = await self.payments.charge(order.total, order.customer_id)
        if not payment.success:
            return OrderResult(success=False, error="Payment failed")

        order.mark_as_paid()
        saved = await self.orders.save(order)
        await self.notifications.send(order.customer_email, "Order confirmed")

        return OrderResult(success=True, order=saved)

class StripePaymentAdapter(PaymentGatewayPort):
    async def charge(self, amount: Money, customer: str) -> PaymentResult:
        # Real Stripe implementation
        ...

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

DDD 部分给出不可变值对象与聚合根。值对象用 frozen=True 保证不可变,在 __post_init__ 里校验:

@dataclass(frozen=True)
class Email:
    """Value object: validated, immutable."""
    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)

聚合根承担一致性边界,在方法里强制不变量:

class Order:
    """Aggregate root: enforces invariants."""

    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):
        """Business logic in aggregate."""
        if quantity > product.max_quantity:
            raise ValueError(f"Max {product.max_quantity} allowed")

        item = OrderItem(product, quantity)
        self.items.append(item)
        self._events.append(ItemAddedEvent(self.id, item))

    def submit(self):
        """State transition with invariant enforcement."""
        if not self.items:
            raise ValueError("Cannot submit empty order")
        if self.status != OrderStatus.PENDING:
            raise ValueError("Order already submitted")

        self.status = OrderStatus.SUBMITTED
        self._events.append(OrderSubmittedEvent(self.id))

单元测试部分,资料中的要点是:领域层与用例层只依赖端口,测试时注入内存适配器(in-memory adapter)即可,不需要真实数据库。上面 MockPaymentAdapter 的写法就是同一思路。

适用场景与注意

适合这些情况:新后端服务要定分层标准,单体要按限界上下文拆,外部集成多且可能更换供应商,业务规则复杂需要落在聚合与值对象里,或者正在排查应用层之间的循环依赖。

要注意几点。第一,SKILL.md 明确写了简单 CRUD 应用不需要上这些模式,强行套用属于过度设计,选型表里这是第一行。第二,这套内容是架构约束与代码骨架,不包含运行时框架,落地时需要自己选语言对应的 ORM、HTTP 库和测试框架,示例代码是 Python 风格(async、asyncpg、dataclass),直接抄到别的语言需要改写。第三,示例中的 find_by_email 只出现在 CreateUserUseCase 里,端口定义中并没有声明,按示例跑之前先确认端口补全,否则会运行期报错。第四,资料中未给出运行时的调用示例或配置项,接入方式只有安装命令和触发条件。

结尾

architecture-patterns 的价值在于把「分层」和「依赖方向」从口头约定变成对话里可执行的约束,同时给出目录结构、端口写法和测试替换方式,适合在设计期和重构期使用。它不做框架集成,也不生成项目脚手架,需要与具体技术栈配合。

官方地址:https://api.skillhub.cn/user_692c63a9/architecture-patterns
上游仓库:https://clawhub.ai/wpank/architecture-patterns
SkillHub 页面:https://www.skillhub.cn/skills/clawhub_wpank/architecture-patterns

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye