ocdp v1
This commit is contained in:
348
docs/development/specification.md
Normal file
348
docs/development/specification.md
Normal file
@ -0,0 +1,348 @@
|
||||
# 📋 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 (
|
||||
<div>
|
||||
<h3>{name}</h3>
|
||||
<p>Count: {count}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// ✅ 副作用在 useEffect 中处理
|
||||
const UserList = () => {
|
||||
const [users, setUsers] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// 副作用(API 调用)在这里处理
|
||||
fetchUsers().then(setUsers);
|
||||
}, []);
|
||||
|
||||
return users.map(user => <UserCard {...user} />);
|
||||
};
|
||||
|
||||
// ❌ 不好的实践 - 在渲染中产生副作用
|
||||
const BadComponent = () => {
|
||||
// 不要在这里调用 API 或修改外部状态
|
||||
globalState.count++; // ❌ 副作用
|
||||
fetchData(); // ❌ 副作用
|
||||
|
||||
return <div>Bad</div>;
|
||||
};
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
Reference in New Issue
Block a user