Some checks failed
Build and Push Docker / build (push) Failing after 2m33s
- Add CLEANDDD-WORKFLOW.md - CleanDDD development workflow guide - Keep GATEWAY_ADMIN_README.md and DATABASE_SCHEMA_FIX.md - Remove all .planning/ GSD workflow documents - Remove old EF migrations (using EnsureCreated for test env)
184 lines
5.8 KiB
Markdown
184 lines
5.8 KiB
Markdown
# CleanDDD 开发工作流
|
||
|
||
本文档描述 Fengling 微服务项目的标准开发流程,基于 Clean Architecture 和 Domain-Driven Design 原则。
|
||
|
||
## 开发技能栈
|
||
|
||
| 技能 | 用途 | 位置 |
|
||
|------|------|------|
|
||
| `cleanddd-requirements-analysis` | 需求澄清与拆解 | `~/.agents/skills/` |
|
||
| `cleanddd-modeling` | 领域模型设计(聚合/命令/事件/查询) | `~/.agents/skills/` |
|
||
| `cleanddd-dotnet-coding` | 代码实现(实体/命令/端点/事件) | `~/.agents/skills/` |
|
||
| `cleanddd-dotnet-init` | 新项目初始化 | `~/.agents/skills/` |
|
||
|
||
## 标准开发流程
|
||
|
||
### 阶段 1:需求分析
|
||
```
|
||
业务需求描述
|
||
↓
|
||
cleanddd-requirements-analysis
|
||
↓
|
||
结构化需求文档(标注业务实体、干系人)
|
||
```
|
||
|
||
### 阶段 2:领域建模
|
||
```
|
||
结构化需求
|
||
↓
|
||
cleanddd-modeling
|
||
↓
|
||
领域蓝图:
|
||
- 聚合根定义(含强类型ID)
|
||
- 领域事件列表
|
||
- 命令与查询分离
|
||
- API 端点设计
|
||
- 仓储接口
|
||
```
|
||
|
||
### 阶段 3:代码实现
|
||
```
|
||
领域蓝图
|
||
↓
|
||
cleanddd-dotnet-coding
|
||
↓
|
||
项目结构:
|
||
├── Domain/
|
||
│ ├── AggregatesModel/{Aggregate}/
|
||
│ │ ├── {Aggregate}.cs # 聚合根
|
||
│ │ ├── {Aggregate}Id.cs # 强类型ID
|
||
│ │ └── Events/ # 领域事件
|
||
│ └── DomainEvents/
|
||
├── Infrastructure/
|
||
│ ├── EntityConfigurations/ # EF 配置
|
||
│ └── Repositories/ # 仓储实现
|
||
└── Web/
|
||
├── Application/
|
||
│ ├── Commands/ # CQRS 命令
|
||
│ ├── Queries/ # CQRS 查询
|
||
│ └── DomainEventHandlers/ # 领域事件处理器
|
||
└── Endpoints/ # API 端点
|
||
```
|
||
|
||
## 项目结构规范
|
||
|
||
### CleanDDD 标准结构
|
||
|
||
```
|
||
{ServiceName}/
|
||
├── src/
|
||
│ ├── {ServiceName}.Domain/ # 领域层(无依赖)
|
||
│ │ ├── AggregatesModel/
|
||
│ │ │ └── {Aggregate}/
|
||
│ │ │ ├── {Aggregate}.cs
|
||
│ │ │ ├── {Aggregate}Id.cs
|
||
│ │ │ └── Events/
|
||
│ │ └── DomainEvents/
|
||
│ │
|
||
│ ├── {ServiceName}.Infrastructure/ # 基础设施层
|
||
│ │ ├── EntityConfigurations/
|
||
│ │ ├── Repositories/
|
||
│ │ └── {ServiceName}DbContext.cs
|
||
│ │
|
||
│ └── {ServiceName}.Web/ # 表现层
|
||
│ ├── Application/
|
||
│ │ ├── Commands/
|
||
│ │ │ └── {Feature}/
|
||
│ │ │ ├── {Command}.cs
|
||
│ │ │ └── {Command}Handler.cs
|
||
│ │ ├── Queries/
|
||
│ │ └── DomainEventHandlers/
|
||
│ └── Endpoints/
|
||
│ └── {Feature}Endpoints.cs
|
||
│
|
||
└── tests/ # 测试项目
|
||
├── {ServiceName}.Domain.UnitTests/
|
||
├── {ServiceName}.Infrastructure.UnitTests/
|
||
└── {ServiceName}.Web.UnitTests/
|
||
```
|
||
|
||
### 命名约定
|
||
|
||
| 类型 | 命名格式 | 示例 |
|
||
|------|----------|------|
|
||
| 聚合根 | `{名词}` | `Campaign`, `Order` |
|
||
| 强类型ID | `{名词}Id` | `CampaignId`, `OrderId` |
|
||
| 领域事件 | `{名词}{动词}edEvent` | `CampaignCreatedEvent` |
|
||
| 命令 | `{动词}{名词}Command` | `CreateCampaignCommand` |
|
||
| 查询 | `Get{名词}Query` | `GetCampaignQuery` |
|
||
| 端点 | `{名词}Endpoints` | `CampaignEndpoints` |
|
||
| 仓储 | `I{名词}Repository` | `ICampaignRepository` |
|
||
|
||
## 代码规范
|
||
|
||
### 必须遵守
|
||
|
||
1. **强类型 ID**:所有实体使用 `IInt64StronglyTypedId` 或 `IGuidStronglyTypedId`
|
||
2. **聚合根**:继承 `Entity<TId>`,实现 `IAggregateRoot`
|
||
3. **领域事件**:在状态变更时发布 `this.AddDomainEvent()`
|
||
4. **仓储**:使用异步方法(`GetAsync`, `AddAsync`),禁止在 Handler 中调用 `SaveChanges`
|
||
5. **命令验证**:每个命令必须有对应的 `AbstractValidator<T>`
|
||
6. **端点配置**:使用属性配置 `[HttpPost]`, `[Tags]`,不使用 `Configure()` 方法
|
||
|
||
### 禁止事项
|
||
|
||
- ❌ 手动赋值实体 ID(使用 EF 值生成器)
|
||
- ❌ 在领域层引用基础设施层
|
||
- ❌ 在非聚合/实体中发布领域事件
|
||
- ❌ 仓储同步方法
|
||
- ❌ 命令 Handler 中调用 `SaveChanges`
|
||
|
||
## 网关架构说明
|
||
|
||
### 配置流向
|
||
|
||
```
|
||
K8s Service (app-router-* label)
|
||
↓
|
||
Console (K8sServiceWatchService)
|
||
↓
|
||
PendingConfigCache (内存缓存)
|
||
↓
|
||
PendingConfigController (用户确认)
|
||
↓
|
||
PostgreSQL (GwRoutes, ServiceInstances)
|
||
↓
|
||
PostgreSQL NOTIFY (gateway_config_changed)
|
||
↓
|
||
Gateway (PgSqlConfigChangeListener)
|
||
↓
|
||
YARP DynamicProxyConfigProvider
|
||
↓
|
||
TenantRoutingTransform (按 TenantCode 路由)
|
||
↓
|
||
后端服务
|
||
```
|
||
|
||
### 多租户路由
|
||
|
||
| 路由类型 | URL 模式 | 说明 |
|
||
|----------|----------|------|
|
||
| 全局路由 | `/{ServicePrefix}/{Version}/{Resource}` | 所有租户共享 |
|
||
| 租户路由 | `/tenant/{tenantCode}/{ServicePrefix}/{Version}/{Resource}` | 租户专属目标 |
|
||
|
||
### 关键实体
|
||
|
||
- **GwRoute**:全局路由配置(Path → Cluster)
|
||
- **GwCluster**:服务集群(含 Destinations 列表)
|
||
- **GwDestination**:目标端点(含 TenantCode 用于租户路由)
|
||
|
||
## 故障排除
|
||
|
||
| 问题 | 原因 | 解决 |
|
||
|------|------|------|
|
||
| `bigint = character varying` | 表结构过时 | 见 `DATABASE_SCHEMA_FIX.md` |
|
||
| `libgssapi_krb5.so.2` 警告 | Alpine 缺少 Kerberos 库 | 可忽略,或设 `Logging__LogLevel__Npgsql=Error` |
|
||
| Watch 连接断开不恢复 | HTTP/2 连接超时 | 已修复:onClosed 回调触发重连 |
|
||
| Config 未生效 | NOTIFY 未触发 | 检查 `LISTEN config_changes;` |
|
||
|
||
## 相关文档
|
||
|
||
- `DATABASE_SCHEMA_FIX.md` - 数据库表结构修复步骤
|
||
- `GATEWAY_ADMIN_README.md` - Gateway Admin UI 开发指南
|
||
- `../../AGENTS.md` - 项目级架构概览
|