Files
photography/backend-old/internal/CLAUDE.md
xujiang 604b9e59ba fix
2025-07-10 18:09:11 +08:00

8.3 KiB

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/)

  • 职责: 提供跨层共享的工具和常量
  • 依赖: 最小化依赖
  • 原则: 保持稳定,避免频繁变更

🔧 开发规范

包导入规则

标准导入顺序

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. 依赖倒置

// ✅ 正确:在 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. 接口隔离

// ✅ 正确:小而专注的接口
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. 错误传播

// 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

# 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

# 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

# 1. 实现仓储
vim internal/infrastructure/repositories/new_repository.go

# 2. 实现其他基础设施(如需要)

Step 4: API Layer

# 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: 数据库集成测试

测试隔离

// 使用依赖注入便于测试
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 对象配置正确

调试技巧

// 使用结构化日志
logger.Debug("Processing request",
    logger.String("handler", "UserHandler.GetUser"),
    logger.Uint("user_id", userID),
)

这个架构设计确保了代码的可维护性、可测试性和可扩展性。遵循这些指导原则,可以构建出高质量的后端服务。