# Internal 包 - CLAUDE.md 此文件为 Claude Code 在 internal 包中工作时提供指导。internal 包包含了应用程序的核心业务逻辑,不对外暴露。 ## 🎯 模块概览 internal 包采用分层架构设计,包含以下核心层次: - **API Layer** (`api/`): HTTP 接口层,处理请求和响应 - **Domain Layer** (`domain/`): 领域模型层,定义业务实体和规则 - **Application Layer** (`application/`): 应用服务层,编排业务逻辑 - **Infrastructure Layer** (`infrastructure/`): 基础设施层,外部依赖 - **Shared Layer** (`shared/`): 共享工具和常量 ## 📁 目录结构 ``` internal/ ├── CLAUDE.md # 🔍 当前文件 - Internal 包指南 ├── api/ # 🌐 API 接口层 │ ├── CLAUDE.md # API 层开发指南 │ ├── handlers/ # HTTP 处理器 │ ├── middleware/ # 中间件 │ ├── routes/ # 路由配置 │ └── validators/ # 输入验证 ├── domain/ # 🏗️ 领域模型层 │ ├── CLAUDE.md # 领域层开发指南 │ ├── entities/ # 业务实体 │ ├── repositories/ # 仓储接口 │ └── services/ # 领域服务接口 ├── application/ # 🔧 应用服务层 │ ├── CLAUDE.md # 应用层开发指南 │ ├── dto/ # 数据传输对象 │ └── services/ # 应用服务实现 ├── infrastructure/ # 🏭 基础设施层 │ ├── CLAUDE.md # 基础设施指南 │ ├── config/ # 配置管理 │ ├── database/ # 数据库操作 │ ├── cache/ # 缓存服务 │ ├── storage/ # 文件存储 │ └── repositories/ # 仓储实现 └── shared/ # 🔗 共享组件 ├── CLAUDE.md # 共享组件指南 ├── constants/ # 常量定义 ├── errors/ # 错误处理 └── utils/ # 工具函数 ``` ## 🏗️ 分层架构原则 ### 依赖方向 ``` API Layer ──→ Application Layer ──→ Domain Layer ↓ ↓ ↑ Infrastructure Layer ──────────────────┘ ``` ### 层次职责 #### 1. API Layer (api/) - **职责**: 处理 HTTP 请求和响应 - **依赖**: Application Layer - **不允许**: 直接调用 Infrastructure Layer 或包含业务逻辑 #### 2. Application Layer (application/) - **职责**: 编排业务逻辑,协调 Domain Services - **依赖**: Domain Layer - **不允许**: 包含具体的基础设施实现 #### 3. Domain Layer (domain/) - **职责**: 定义业务实体、规则和接口 - **依赖**: 无(最核心层) - **不允许**: 依赖外部框架或基础设施 #### 4. Infrastructure Layer (infrastructure/) - **职责**: 实现外部依赖,如数据库、缓存、文件存储 - **依赖**: Domain Layer (实现接口) - **不允许**: 包含业务逻辑 #### 5. Shared Layer (shared/) - **职责**: 提供跨层共享的工具和常量 - **依赖**: 最小化依赖 - **原则**: 保持稳定,避免频繁变更 ## 🔧 开发规范 ### 包导入规则 #### 标准导入顺序 ```go import ( // 1. 标准库 "context" "fmt" "time" // 2. 第三方库 "github.com/gin-gonic/gin" "gorm.io/gorm" // 3. 项目内部包 - 按依赖层次 "photography-backend/internal/domain/entities" "photography-backend/internal/application/dto" "photography-backend/internal/shared/errors" ) ``` #### 禁止的依赖 - Domain Layer 不能导入 Infrastructure Layer - Application Layer 不能导入 API Layer - 下层不能导入上层 ### 接口设计原则 #### 1. 依赖倒置 ```go // ✅ 正确:在 domain/repositories 定义接口 type UserRepository interface { FindByID(id uint) (*entities.User, error) Save(user *entities.User) error } // ✅ 在 infrastructure/repositories 实现接口 type userRepository struct { db *gorm.DB } func (r *userRepository) FindByID(id uint) (*entities.User, error) { // 实现细节 } ``` #### 2. 接口隔离 ```go // ✅ 正确:小而专注的接口 type UserReader interface { FindByID(id uint) (*entities.User, error) FindByEmail(email string) (*entities.User, error) } type UserWriter interface { Save(user *entities.User) error Delete(id uint) error } // ❌ 错误:过大的接口 type UserRepository interface { // 包含太多方法... } ``` ### 错误处理规范 #### 1. 错误传播 ```go // Domain Layer: 定义业务错误 var ErrUserNotFound = errors.New("user not found") // Application Layer: 处理和转换错误 func (s *UserService) GetUser(id uint) (*dto.UserResponse, error) { user, err := s.repo.FindByID(id) if err != nil { if errors.Is(err, domain.ErrUserNotFound) { return nil, shared.ErrUserNotFound } return nil, fmt.Errorf("failed to get user: %w", err) } return s.toDTO(user), nil } // API Layer: 转换为 HTTP 响应 func (h *UserHandler) GetUser(c *gin.Context) { user, err := h.service.GetUser(id) if err != nil { response.HandleError(c, err) return } response.Success(c, user) } ``` ## 🚀 开发工作流 ### 1. 新功能开发流程 #### Step 1: Domain Layer ```bash # 1. 定义实体 vim internal/domain/entities/new_entity.go # 2. 定义仓储接口 vim internal/domain/repositories/new_repository.go # 3. 定义领域服务接口(如需要) vim internal/domain/services/new_service.go ``` #### Step 2: Application Layer ```bash # 1. 定义 DTO vim internal/application/dto/request/new_request.go vim internal/application/dto/response/new_response.go # 2. 实现应用服务 vim internal/application/services/new_service.go ``` #### Step 3: Infrastructure Layer ```bash # 1. 实现仓储 vim internal/infrastructure/repositories/new_repository.go # 2. 实现其他基础设施(如需要) ``` #### Step 4: API Layer ```bash # 1. 实现处理器 vim internal/api/handlers/new_handler.go # 2. 添加路由 vim internal/api/routes/api_v1.go # 3. 添加验证器(如需要) vim internal/api/validators/new_validator.go ``` ### 2. 测试策略 #### 单元测试 - Domain Layer: 测试业务逻辑 - Application Layer: 测试服务编排 - Infrastructure Layer: 测试数据访问 #### 集成测试 - API Layer: 端到端测试 - Repository Layer: 数据库集成测试 #### 测试隔离 ```go // 使用依赖注入便于测试 type UserService struct { repo domain.UserRepository } // 测试时注入 Mock func TestUserService_GetUser(t *testing.T) { mockRepo := &MockUserRepository{} service := NewUserService(mockRepo) // 测试逻辑 } ``` ## 📋 代码审查清单 ### 架构合规性 - [ ] 是否遵循分层架构原则 - [ ] 是否违反依赖方向 - [ ] 接口设计是否合理 - [ ] 错误处理是否完善 ### 代码质量 - [ ] 命名是否清晰明确 - [ ] 函数是否单一职责 - [ ] 是否有适当的注释 - [ ] 是否有相应的测试 ### 性能考虑 - [ ] 是否有 N+1 查询问题 - [ ] 是否需要添加缓存 - [ ] 数据库操作是否高效 ## 🎯 最佳实践 ### 1. 保持层次清晰 - 每层只关注自己的职责 - 避免跨层直接调用 - 使用接口解耦 ### 2. 依赖注入 - 使用构造函数注入 - 避免全局变量 - 便于测试和替换 ### 3. 错误处理 - 使用带类型的错误 - 适当包装错误信息 - 保持错误处理一致性 ### 4. 性能优化 - 合理使用缓存 - 数据库查询优化 - 避免过度设计 ## 🔍 故障排查 ### 常见问题 1. **循环依赖**: 检查包导入关系 2. **接口未实现**: 确认所有方法都已实现 3. **依赖注入失败**: 检查构造函数和依赖配置 4. **测试失败**: 确认 Mock 对象配置正确 ### 调试技巧 ```go // 使用结构化日志 logger.Debug("Processing request", logger.String("handler", "UserHandler.GetUser"), logger.Uint("user_id", userID), ) ``` 这个架构设计确保了代码的可维护性、可测试性和可扩展性。遵循这些指导原则,可以构建出高质量的后端服务。