vertical-slice-architecture

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Vertical Slice Architecture

垂直切片架构(Vertical Slice Architecture)

Quick Reference: The 5 Rules

快速参考:五大规则

  1. One feature = one directory containing handler, request/response types, validation, and tests
  2. One entry point per feature — a setup/registration function that receives the router and dependencies. Name varies by convention (
    Setup
    ,
    RegisterRoute
    ,
    Map
    ); the role is the invariant, not the name.
  3. Minimize coupling between slices, maximize coupling within a slice
  4. No premature abstractions — no shared repository/service layers until genuine duplication emerges across multiple slices
  5. Test each feature primarily through its entry point, verifying outcomes (DB state, API calls, response). Platform/adapter tests are also encouraged.
  1. 一个功能对应一个目录,包含处理器、请求/响应类型、校验逻辑及测试代码
  2. 每个功能对应一个入口点——一个接收路由器和依赖项的设置/注册函数。函数名称遵循各语言约定(如
    Setup
    RegisterRoute
    Map
    );核心是其作用,而非具体名称。
  3. 最小化切片间耦合,最大化切片内耦合
  4. 避免过早抽象——只有当多个切片出现真正的代码重复时,才创建共享的仓储/服务层
  5. 主要通过入口点测试每个功能,验证执行结果(如数据库状态、API调用、响应内容)。同时推荐进行平台/适配器测试。

Project Structure

项目结构

{project}/
  features/              # or internal/features/ (Go), Features/ (.NET)
    {domain}/            # orders/, users/, kvs/
      {operation}/       # create/, list/, delete/
        handler          # Single entry point + orchestration
        request/response # DTOs
        validator        # Input validation (optional)
        test             # Co-located integration test
        internal/        # Feature-private helpers (optional)
  platform/              # or Infrastructure/ — shared cross-cutting concerns
    middleware/           # Auth, error handling, idempotency
    database/            # Connection pooling, circuit breakers
    observability/       # Metrics, tracing, structured logging
    opqueue/             # Operation queues, outbox patterns (if needed)
  main                   # Composition root wires features + infrastructure
{project}/
  features/              # 或 internal/features/(Go语言)、Features/(.NET)
    {domain}/            # 如orders/、users/、kvs/
      {operation}/       # 如create/、list/、delete/
        handler          # 单一入口点 + 编排逻辑
        request/response # 数据传输对象(DTO)
        validator        # 输入校验(可选)
        test             # 同目录集成测试
        internal/        # 功能私有辅助工具(可选)
  platform/              # 或 Infrastructure/ — 共享横切关注点
    middleware/           # 身份认证、错误处理、幂等性
    database/            # 连接池、断路器
    observability/       # 指标监控、链路追踪、结构化日志
    opqueue/             # 操作队列、发件箱模式(按需使用)
  main                   # 组合根,连接功能模块与基础设施

Workflow: Adding a New Feature

工作流:新增功能

  1. Create directory:
    features/{domain}/{operation}/
  2. Define the handler with a single exported setup function
  3. Define request/response types (inline for simple cases)
  4. Add validation logic
  5. Register in the composition root (
    main
    )
  6. Write integration test that calls the setup function, sends request, verifies outcomes
  1. 创建目录:
    features/{domain}/{operation}/
  2. 定义处理器,并对外暴露一个设置函数
  3. 定义请求/响应类型(简单场景可内联定义)
  4. 添加校验逻辑
  5. 在组合根(
    main
    )中注册
  6. 编写集成测试,调用设置函数、发送请求并验证结果

Workflow: Adding Cross-Cutting Concerns

工作流:新增横切关注点

Place in
platform/
(not inside a feature). Examples:
  • Auth middleware, error handling, request logging
  • Database connection pooling, circuit breakers
  • Idempotency middleware, operation queues, event notifications
  • Observability (metrics, tracing, structured logging)
放置在
platform/
目录下(而非某个功能目录内)。示例:
  • 身份认证中间件、错误处理、请求日志
  • 数据库连接池、断路器
  • 幂等性中间件、操作队列、事件通知
  • 可观测性(指标监控、链路追踪、结构化日志)

Workflow: Extracting Shared Logic

工作流:提取共享逻辑

Only extract when genuine duplication emerges across multiple slices (use judgment — the "3+ slices" heuristic is guidance, not a hard rule):
  • Duplicate business rule: extract to a domain entity/value object
  • Duplicate data access pattern: extract to a shared repository (only for that specific pattern)
  • Duplicate HTTP helper: extract to
    platform/httpx/
仅当多个切片出现真正的代码重复时才进行提取(需灵活判断——“3个及以上切片重复”是参考准则,而非硬性规定):
  • 重复业务规则:提取到领域实体/值对象
  • 重复数据访问模式:提取到共享仓储(仅针对该特定模式)
  • 重复HTTP辅助工具:提取到
    platform/httpx/
    目录

Key Decisions by Language

各语言核心决策

Detect the project's language/framework and consult the appropriate reference:
  • Patterns per language: See references/patterns-by-language.md for Go, .NET, Java, TypeScript, Python
  • Testing per language: See references/testing.md for testcontainers, mock verification, integration test patterns
  • Core principles: See references/principles.md for detailed rules, anti-patterns, and shared domain model guidance
根据项目使用的语言/框架,参考对应指南:
  • 各语言实现模式:Go、.NET、Java、TypeScript、Python相关内容请查看references/patterns-by-language.md
  • 各语言测试方案:Testcontainers、Mock验证、集成测试模式相关内容请查看references/testing.md
  • 核心原则:详细规则、反模式及共享领域模型指南请查看references/principles.md

Single Entry Point Contract

单一入口点约定

Every feature exposes one primary setup/registration function. Internal types stay private. The entry point name is conventional — the invariant is: one public function per feature that wires the slice to the framework.
LanguageConventionSignatureDI mechanism
Go
Setup
or
RegisterRoute
func Setup(r gin.IRoutes, repo Repository)
Explicit params
.NET
Map
(static)
static void Map(IEndpointRouteBuilder app)
DI container resolves deps in handler
Java/Kotlin
@RestController
class
Controller discovered by component scanSpring DI (constructor injection)
TypeScript
setup
function setup(router: Router, db: Database): void
Explicit params
Python
setup
def setup(router: APIRouter, db: Database) -> None
Explicit params or
Depends()
Exceptions: Versioned APIs may have
SetupV1
/
SetupV2
wrappers sharing internal handler wiring. Frameworks with auto-discovery (Spring, NestJS) use the controller/module class itself as the entry point.
每个功能对外暴露一个主设置/注册函数,内部类型保持私有。入口点名称遵循约定——核心准则是:每个功能对应一个公开函数,用于将切片与框架关联
语言约定函数签名依赖注入机制
Go
Setup
RegisterRoute
func Setup(r gin.IRoutes, repo Repository)
显式参数注入
.NET
Map
(静态)
static void Map(IEndpointRouteBuilder app)
依赖注入容器在处理器中解析依赖
Java/Kotlin
@RestController
组件扫描自动发现控制器Spring DI(构造函数注入)
TypeScript
setup
function setup(router: Router, db: Database): void
显式参数注入
Python
setup
def setup(router: APIRouter, db: Database) -> None
显式参数注入或
Depends()
例外情况:版本化API可能会有
SetupV1
/
SetupV2
包装函数,共享内部处理器逻辑。支持自动发现的框架(如Spring、NestJS)直接将控制器/模块类作为入口点。

Testing

测试

See references/testing.md for full testing strategy per language, including feature integration tests, platform/adapter tests, mock verification patterns, and test naming conventions.
各语言完整测试策略(包括功能集成测试、平台/适配器测试、Mock验证模式及测试命名规范)请查看references/testing.md