clean-architecture-golang
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCustom Clean Architecture Implementation Guide
自定义Clean架构实现指南
Expert guidance for implementing features using this project's custom Clean Architecture pattern with Golang. This is NOT Uncle Bob's standard Clean Architecture - it's a specialized adaptation.
在Golang项目中使用本项目自定义Clean架构模式实现功能的专业指导。注意:这并非Uncle Bob的标准Clean Architecture,而是经过专门适配的版本。
Architecture Overview
架构概述
Four layers with strict dependency rules:
Integration → Application → Domain ← InfrastructureDependency Rule: Inner layers NEVER depend on outer layers.
具有严格依赖规则的四层架构:
Integration → Application → Domain ← Infrastructure依赖规则:内层绝不能依赖外层。
🚨 Critical Rules
🚨 核心规则
MUST DO
必须遵守
- START with BDD feature file - Never skip test-first development
- Integration adapters MUST implement usecase interfaces - Enable type casting
- Use context.Context as first parameter - Always
- Convert at boundaries - DTO↔Entity↔Model
- Follow error code format - PREFIX-XXYYYY
- Type cast repositories to usecases - In dependency injection
- 从BDD特性文件开始 - 绝不能跳过测试优先开发
- 集成适配器必须实现用例接口 - 启用类型转换
- 始终将context.Context作为第一个参数
- 在边界处进行转换 - DTO↔Entity↔Model
- 遵循错误代码格式 - PREFIX-XXYYYY
- 在依赖注入中将存储库类型转换为用例
NEVER DO
绝对禁止
- Skip BDD test creation - Tests come first
- Create adapters without usecase interfaces - Will break dependency injection
- Put business logic in controllers/repositories - Only in services
- Use DTOs in domain/application - Only in integration layer
- Access database from services - Only through usecases
- Create circular dependencies - Dependencies flow inward only
- 跳过BDD测试创建 - 测试先行
- 不基于用例接口创建适配器 - 会破坏依赖注入
- 将业务逻辑放在控制器/存储库中 - 只能放在服务层
- 在领域层/应用层使用DTO - 仅在集成层使用
- 从服务层直接访问数据库 - 只能通过用例
- 创建循环依赖 - 依赖只能向内流动
Implementation Workflow
实现流程
Step 1: Create BDD Test (MANDATORY)
步骤1:创建BDD测试(必填)
Start here ALWAYS. Location:
/test/integration/features/gherkin
Feature: Create entity functionality
Scenario: Create entity success
When I call "POST" "/v1/entities" with payload
Then status should be 201
And db should contain entity始终从此步骤开始。路径:
/test/integration/features/gherkin
Feature: Create entity functionality
Scenario: Create entity success
When I call "POST" "/v1/entities" with payload
Then status should be 201
And db should contain entityStep 2: Domain Layer
步骤2:领域层
-
Entity ()
/internal/domain/entity/- Simple structs, NO logic
- Audit fields (CreatedAt, UpdatedAt)
-
Errors ()
/internal/domain/error/- Format:
PREFIX-XXYYYY - One error per file
- Format:
-
Enums ()
/internal/domain/enums/- String types
- SCREAMING_SNAKE_CASE values
-
实体()
/internal/domain/entity/- 简单结构体,无逻辑
- 包含审计字段(CreatedAt、UpdatedAt)
-
错误定义()
/internal/domain/error/- 格式:
PREFIX-XXYYYY - 每个错误对应一个文件
- 格式:
-
枚举()
/internal/domain/enums/- 字符串类型
- 值采用SCREAMING_SNAKE_CASE格式
Step 3: Application Layer
步骤3:应用层
-
Adapter Interface ()
/internal/application/adapter/- Service contracts
- Use domain entities
-
UseCase Interfaces ()
/internal/application/usecase/- Atomic operations
- FindX, SaveX, UpdateX, DeleteX
-
Service Implementation ()
/internal/application/service/- Business logic HERE
- Orchestrate usecases
-
适配器接口()
/internal/application/adapter/- 服务契约
- 使用领域实体
-
用例接口()
/internal/application/usecase/- 原子操作
- 命名格式:FindX、SaveX、UpdateX、DeleteX
-
服务实现()
/internal/application/service/- 业务逻辑仅在此处
- 编排用例
Step 4: Integration Layer
步骤4:集成层
-
Adapter Interfaces ()
/internal/integration/adapter/gotype Repository interface { usecase.Find // MUST embed usecase.Save // MUST embed } -
DTOs ()
/internal/integration/entrypoint/dto/- Request/Response structs
- ToEntity() methods
- Validation tags
-
Controller ()
/internal/integration/entrypoint/controller/- Handle HTTP
- DTO↔Entity conversion
-
Model ()
/internal/integration/persistence/model/- GORM annotations
- ToEntity() methods
-
Repository ()
/internal/integration/persistence/- Implements usecase interfaces
- Entity↔Model conversion
-
适配器接口()
/internal/integration/adapter/gotype Repository interface { usecase.Find // 必须嵌入 usecase.Save // 必须嵌入 } -
DTO()
/internal/integration/entrypoint/dto/- 请求/响应结构体
- 包含ToEntity()方法
- 带有验证标签
-
控制器()
/internal/integration/entrypoint/controller/- 处理HTTP请求
- 完成DTO↔Entity的转换
-
模型()
/internal/integration/persistence/model/- 带有GORM注解
- 包含ToEntity()方法
-
存储库()
/internal/integration/persistence/- 实现用例接口
- 完成Entity↔Model的转换
Step 5: Infrastructure Layer
步骤5:基础设施层
-
Dependency Injection ()
/internal/infra/dependency/injector.gogo// Type cast repository to usecase usecase.Find(i.GetRepository()) -
Router ()
/internal/infra/server/router/router.go- Add routes
- Validation middleware
-
依赖注入()
/internal/infra/dependency/injector.gogo// 将存储库类型转换为用例 usecase.Find(i.GetRepository()) -
路由()
/internal/infra/server/router/router.go- 添加路由
- 配置验证中间件
Step 6: Run Tests
步骤6:运行测试
bash
make test-integrationbash
make test-integrationQuick Patterns
快速模式
Integration Adapter Pattern (CRITICAL)
集成适配器模式(核心)
go
// Application defines need
type FindProduct interface {
FindById(ctx, id) (*entity, error)
}
// Integration MUST implement
type ProductRepository interface {
usecase.FindProduct // EMBED!
}
// Type cast in DI
usecase.FindProduct(repository)go
// 应用层定义需求
type FindProduct interface {
FindById(ctx, id) (*entity, error)
}
// 集成层必须实现
type ProductRepository interface {
usecase.FindProduct // 必须嵌入!
}
// 在依赖注入中进行类型转换
usecase.FindProduct(repository)Error Codes
错误代码示例
- = Client conflict (409)
CLI-01409 - = User not found (404)
USR-01404 - = Product server error (500)
PRD-02500
- = 客户端冲突(409)
CLI-01409 - = 用户不存在(404)
USR-01404 - = 产品服务端错误(500)
PRD-02500
Conversion Flow
转换流程
Request → DTO → Entity → Model → DB
Response ← DTO ← Entity ← Model ← DBRequest → DTO → Entity → Model → DB
Response ← DTO ← Entity ← Model ← DBReference Documentation
参考文档
Detailed guides in references/:
- Layer Implementation - Complete layer examples
- Critical Patterns - Must-know patterns
- Implementation Workflow - Step-by-step guide
详细指南位于references/目录下:
- Layer Implementation - 完整的层实现示例
- Critical Patterns - 必须掌握的模式
- Implementation Workflow - 分步指南
Templates
模板
Ready-to-use templates in assets/:
- - Domain entity template
entity-template.go - - Application service template
service-template.go - - Repository template
repository-template.go
assets/目录下提供可直接使用的模板:
- - 领域实体模板
entity-template.go - - 应用服务模板
service-template.go - - 存储库模板
repository-template.go
Implementation Checklist
实现检查清单
Before starting any feature:
- BDD feature file exists
- Domain entity defined
- Domain errors created
- Application adapter interface defined
- Application usecases created
- Application service implemented
- Integration adapters created WITH usecase interfaces
- DTOs with ToEntity() methods
- Controller handling HTTP
- Model with ToEntity() method
- Repository implementing usecases
- Dependencies wired in injector
- Routes added to router
- Tests passing
开始任何功能开发前,请确认:
- BDD特性文件已存在
- 领域实体已定义
- 领域错误已创建
- 应用层适配器接口已定义
- 应用层用例已创建
- 应用层服务已实现
- 已创建包含用例接口的集成适配器
- DTO带有ToEntity()方法
- 控制器已处理HTTP请求
- Model带有ToEntity()方法
- 存储库已实现用例
- 依赖已在注入器中配置
- 路由已添加到路由器
- 测试已通过
Common Mistakes to Avoid
需避免的常见错误
- Forgetting usecase interfaces on adapters - Breaks type casting
- Business logic in wrong layer - Only in services
- Wrong dependency direction - Check imports
- Missing BDD test - Always start with test
- Wrong error code format - Use PREFIX-XXYYYY
- Not converting at boundaries - DTO↔Entity↔Model
- 适配器上遗漏用例接口 - 会破坏类型转换
- 业务逻辑放错层级 - 只能放在服务层
- 依赖方向错误 - 检查导入关系
- 缺少BDD测试 - 始终从测试开始
- 错误代码格式不正确 - 使用PREFIX-XXYYYY格式
- 未在边界处进行转换 - 必须完成DTO↔Entity↔Model的转换
Example Implementations
示例实现
Study these existing implementations:
- Client:
/internal/{domain,application,integration}/*/client*.go - User:
/internal/{domain,application,integration}/*/user*.go - Forest:
/internal/{domain,application,integration}/*/forest*.go
可参考以下现有实现:
- Client:
/internal/{domain,application,integration}/*/client*.go - User:
/internal/{domain,application,integration}/*/user*.go - Forest:
/internal/{domain,application,integration}/*/forest*.go