# 📋 OCDP 开发规范 本文档定义了 OCDP 项目的开发规范和架构要求。 ## 🎯 整体架构 (Full Stack) ### 1. OpenAPI 驱动开发 采用 OpenAPI 规范来驱动前后端开发,确保 API 契约的一致性。 **优势**: - API 设计优先,前后端并行开发 - 自动生成类型安全的代码 - 文档和代码永远同步 - 减少沟通成本 **实践**: ```bash # 1. 设计 API (编辑 backend/docs/openapi.yaml) # 2. 验证规范 make openapi-validate # 3. 生成代码 make openapi-gen # 4. 实现功能 ``` ### 2. Docker Compose 部署 使用 Docker Compose 进行整个应用的部署。新版的 Docker 已经将 Compose 集成到 Docker 里面了,所以使用 `docker compose`(带空格)而非旧版的 `docker-compose`(带连字符)。 **部署服务**: - PostgreSQL - 数据持久化 - Redis - 缓存和会话 - Backend - Go 后端服务 - Frontend - React 前端应用 - Nginx - 反向代理(生产环境) ## 🎨 前端规范 (Frontend) ### 1. 纯函数渲染 **要求**:使用纯函数进行组件渲染,避免不必要的副作用。 **原则**: - 组件应该是可预测的(相同输入→相同输出) - 避免在渲染过程中修改外部状态 - 使用 `useEffect` 等 Hook 处理副作用 - 保持组件的可测试性 **示例**: ```typescript // ✅ 好的实践 - 纯函数组件 interface Props { name: string; count: number; } const UserCard = ({ name, count }: Props) => { // 纯函数:只依赖 props,不修改外部状态 return (

{name}

Count: {count}

); }; // ✅ 副作用在 useEffect 中处理 const UserList = () => { const [users, setUsers] = useState([]); useEffect(() => { // 副作用(API 调用)在这里处理 fetchUsers().then(setUsers); }, []); return users.map(user => ); }; // ❌ 不好的实践 - 在渲染中产生副作用 const BadComponent = () => { // 不要在这里调用 API 或修改外部状态 globalState.count++; // ❌ 副作用 fetchData(); // ❌ 副作用 return
Bad
; }; ``` ### 2. 技术栈 - **框架**: React 18+ (使用 Hooks) - **语言**: TypeScript 5+ - **构建工具**: Vite - **样式**: Tailwind CSS - **路由**: React Router 6+ - **状态管理**: React Context + Hooks - **API 客户端**: 从 OpenAPI 自动生成 ## 🔧 后端规范 (Backend) ### 1. 六边形架构 (Hexagonal Architecture) 后端采用六边形架构(也称为端口和适配器架构),将业务逻辑与技术实现解耦。 **核心目录结构**: ``` backend/internal/ ├── domain/ # 领域层 - 业务逻辑核心 │ ├── entity/ # 领域实体 │ ├── service/ # 领域服务 │ └── repository/ # 仓库接口(端口) ├── application/ # 应用层 - 用例编排 │ └── usecase/ # 用例实现 └── adapter/ # 适配器层 - 技术实现 ├── input/ # 输入适配器 │ └── http/ # HTTP REST API └── output/ # 输出适配器 ├── persistence/ │ ├── mock/ # Mock 实现 │ └── postgres/ # PostgreSQL 实现 ├── oci/ # OCI Registry 客户端 └── helm/ # Helm SDK 封装 ``` **职责划分**: - **Domain 层**:纯业务逻辑,不依赖任何框架或外部库 - **Application 层**:编排 Domain 层的服务,实现具体的用例 - **Adapter 层**:处理所有技术细节(HTTP、数据库、第三方 API) ### 2. Mock Adapter 实现 **要求**:除了实现 ports 的 adapters 外,还要做 mock。Mock 的是 adapter 的行为反应而非假数据。 **Mock 原则**: - ✅ 模拟真实 adapter 的行为 - ✅ 可以注入真实数据 - ✅ 可以通过调用接口自行加入数据 - ✅ 使用内存来模拟 adapter 的交互 - ❌ 不是返回固定的假数据 **示例**: ```go // Mock Repository - 模拟真实的数据库行为 type RegistryRepositoryMock struct { registries map[string]*entity.Registry // 内存存储 mu sync.RWMutex } func (r *RegistryRepositoryMock) Create(ctx context.Context, registry *entity.Registry) error { r.mu.Lock() defer r.mu.Unlock() // 模拟真实行为:检查重复、生成 ID、加密等 if _, exists := r.registries[registry.ID]; exists { return errors.New("registry already exists") } r.registries[registry.ID] = registry return nil } func (r *RegistryRepositoryMock) GetByID(ctx context.Context, id string) (*entity.Registry, error) { r.mu.RLock() defer r.mu.RUnlock() registry, exists := r.registries[id] if !exists { return nil, errors.New("registry not found") } return registry, nil } ``` ### 3. Makefile 支持 **要求**:采用 Makefile 来支持 mock 启动以及 real 启动。 **命令规范**: ```makefile # 开发模式(Mock Adapter) run-mock: @echo "Starting backend with Mock adapters..." MODE=mock go run cmd/api/main.go # 生产模式(Real Adapter) run-real: @echo "Starting backend with Real adapters..." MODE=real go run cmd/api/main.go # 运行测试 test: go test -v ./... # 生成代码 generate: go generate ./... ``` **使用方式**: ```bash # 开发模式(无需数据库) make run-mock # 生产模式(需要 PostgreSQL) make run-real ``` ### 4. 技术栈 - **语言**: Go 1.21+ - **Web 框架**: Gin (轻量、高性能) - **ORM**: GORM (可选,用于 PostgreSQL adapter) - **OCI 客户端**: ORAS Go SDK v2 - **Helm 客户端**: Helm SDK v3 - **K8s 客户端**: client-go ## 📐 架构原则 ### 1. 依赖方向 ``` Adapter → Application → Domain (技术) (编排) (业务) ``` - Domain 层不依赖任何外部库(除了标准库) - Application 层依赖 Domain 层 - Adapter 层依赖 Application 和 Domain 层 ### 2. 端口和适配器 **端口(Port)**:接口定义,在 Domain 层 ```go // domain/repository/registry_repository.go type RegistryRepository interface { Create(ctx context.Context, registry *entity.Registry) error GetByID(ctx context.Context, id string) (*entity.Registry, error) List(ctx context.Context) ([]*entity.Registry, error) } ``` **适配器(Adapter)**:接口实现,在 Adapter 层 ```go // adapter/output/persistence/mock/registry_repository_mock.go type RegistryRepositoryMock struct { // Mock 实现 } // adapter/output/persistence/postgres/registry_repository_postgres.go type RegistryRepositoryPostgres struct { // PostgreSQL 实现 } ``` ### 3. 依赖注入 使用构造函数注入依赖: ```go // 创建 Mock 模式的应用 func NewMockApp() *App { // 创建 Mock Repository registryRepo := mock.NewRegistryRepositoryMock() // 创建 Service(注入 Repository) registryService := service.NewRegistryService(registryRepo) // 创建 Handler(注入 Service) registryHandler := handler.NewRegistryHandler(registryService) return &App{ RegistryHandler: registryHandler, } } // 创建 Production 模式的应用 func NewProductionApp(db *gorm.DB) *App { // 创建 PostgreSQL Repository registryRepo := postgres.NewRegistryRepositoryPostgres(db) // ... 其他相同 } ``` ## 🔄 开发工作流 ### 1. 功能开发流程 ```bash # 1. 设计 API vim backend/docs/openapi.yaml # 2. 生成代码 make openapi-gen # 3. 实现 Domain 层 vim backend/internal/domain/service/xxx_service.go # 4. 实现 Mock Adapter vim backend/internal/adapter/output/persistence/mock/xxx_mock.go # 5. 实现 Handler vim backend/internal/adapter/input/http/handler/xxx_handler.go # 6. 启动测试 make run-mock # 7. 实现前端 vim frontend/src/features/xxx/pages/XxxPage.tsx # 8. 集成测试 make dev # 9. 实现 Production Adapter vim backend/internal/adapter/output/persistence/postgres/xxx_postgres.go # 10. 部署测试 docker compose up ``` ### 2. 测试策略 - **单元测试**:Domain 层和 Service 层(使用 Mock Repository) - **集成测试**:使用 Mock Adapter 测试完整流程 - **E2E 测试**:使用真实 Adapter 测试生产环境 ## 📚 参考文档 - [后端六边形架构详解](../../backend/HEXAGONAL_ARCHITECTURE.md) - [OpenAPI 规范](../../backend/docs/openapi.yaml) - [Docker 部署指南](../deployment/docker-guide.md) - [安全实现方案](../security/security-implementation.md) --- **版本**: 1.0 **最后更新**: 2025-11-07