mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 14:46:36 +08:00
refactor(plugins): restructure admin and message_gateway into standard layered sub-packages
This commit is contained in:
@@ -610,8 +610,8 @@ Wavelet/
|
||||
3. **`plugins/`**:
|
||||
- **职责**:所有业务逻辑和驱动实现的归宿。遵循标准分层架构(Layered Architecture / MVC 变体)。
|
||||
- **分层模式选型**:
|
||||
- **模式 1(扁平自包含分层,简单业务推荐)**:单 package 内部通过文件划分职责(`plugin.go`, `handlers.go`, `service.go`, `repository.go`, `models.go`, `errs.go`, `migrations/`)。适用于代码量 < 3000 行、单聚合根的插件。
|
||||
- **模式 2(严格子包物理分层,复杂业务推荐)**:多 package 目录级物理隔离(`plugin.go`, `controller/`, `service/`, `repository/`, `model/`, `errs/`, `migrations/`)。编译器级约束 `controller -> service -> repository -> model` 单向依赖。适用于代码量 ≥ 3000 行、多聚合根的大型复杂插件。
|
||||
- **模式 1(极简单文件分层,极简微型插件专用)**:单 package 内部仅各保留 1 个对应文件(`plugin.go`, `handlers.go`, `service.go`, `repository.go`, `models.go`, `errs.go`, `migrations/`)。仅适用于单一实体、极小代码量 (<500行) 的微型插件。
|
||||
- **模式 2(标准独立子包分层架构,官方推荐标准)**:按职责严格物理分包(`plugin.go`, `handler/`, `service/`, `repository/`, `model/`, `errs/`, `migrations/`)。**子包内文件以纯业务实体命名(如 `user.go`、`config.go`),严禁在根包平铺 `handlers_*`、`service_*`、`repository_*` 等前缀文件**。编译器级强约束 `handler -> service -> repository -> model` 单向依赖。
|
||||
- **严禁**:插件之间严禁跨包 import 内部私有代码,跨插件调用一律走 `contracts` 接口或 `EventBus`。
|
||||
|
||||
---
|
||||
@@ -657,36 +657,39 @@ Wavelet/
|
||||
│
|
||||
┌───────────────────────┴───────────────────────┐
|
||||
▼ ▼
|
||||
【模式 1:扁平自包含分层】 【模式 2:严格子包分层】
|
||||
适合:简单/单一聚合/轻量插件 (<3000行) 适合:复杂业务/多聚合/高协同插件 (≥3000行)
|
||||
结构:单 Package,文件级职责划分 结构:多 Package,目录物理隔离与单向依赖
|
||||
【模式 1:极简单文件分层】 【模式 2:标准独立子包分层】
|
||||
适合:极简微型/Demo插件 (<500行) 适合:标准/中大型业务插件 (推荐标准)
|
||||
结构:单 Package,每层仅对应 1 个同名文件 结构:严格分包 handler/, service/, repository/, model/
|
||||
禁令:严禁根目录平铺 handlers_* 等前缀文件 规范:子包内以业务实体命名 (如 user.go, order.go)
|
||||
```
|
||||
|
||||
| 维度 | 模式 1:扁平自包含分层 (Flat Self-Contained) | 模式 2:严格子包物理分层 (Strict Sub-packages) |
|
||||
| 维度 | 模式 1:极简单文件分层 (Single-File Flat) | 模式 2:标准独立子包分层 (Standard Sub-packages) |
|
||||
| :--- | :--- | :--- |
|
||||
| **适用场景** | 简单业务、单一聚合根、中小型插件(推荐默认) | 复杂业务、多聚合根、状态流转复杂的大型插件 |
|
||||
| **代码量规模** | 通常 < 3000 行(如 `upload`, `cap`, `system`) | 通常 ≥ 3000 行(如大型 `auth`, `order/billing`, `admin`) |
|
||||
| **Go 包形态** | 单一 Go Package,按文件名语义拆分各层 | 多个 Go Package 物理子目录隔离,编译级约束依赖 |
|
||||
| **核心优势** | 彻底杜绝 Go 循环导入;开发摩擦极小;直观扁平 | 强约束调用方向(Controller → Service → Repo → Model) |
|
||||
| **适用场景** | 极简微型插件、单一实体(仅用于小型工具/示例) | 标准业务插件、包含多实体/多接口(**官方推荐标准**) |
|
||||
| **代码量规模** | 通常 < 500 行 | 通常 ≥ 500 行(如 `upload`, `auth`, `admin`, `order`) |
|
||||
| **Go 包形态** | 单一 Go Package,各层级仅各 1 个同名文件 | 按职责严格物理子目录分包,编译级强约束单向依赖 |
|
||||
| **命名禁令** | **严禁在根目录平铺 `handlers_*`、`service_*` 文件** | **子包内文件直接以业务命名(如 `user.go`),禁止带 `handler_*` 前缀** |
|
||||
|
||||
---
|
||||
|
||||
## 2. 模式 1:扁平自包含分层规范与完整代码模板
|
||||
## 2. 模式 1:极简单文件分层规范与完整代码模板
|
||||
|
||||
### 2.1 目录结构
|
||||
```text
|
||||
backend/plugins/domain/order/
|
||||
├── plugin.go # [Cordis 接入层] 实现 core.Plugin,负责 Apply 组装、依赖注入与扩展点注册
|
||||
├── handlers.go # [Controller 层] HTTP 控制器:参数校验、上下文提取、信封响应 (response.OK/Abort)
|
||||
├── service.go # [Service 层] 核心业务用例、事务编排、事件触发 (ctx.Events().Emit),仅接收 context.Context
|
||||
├── repository.go # [Repository 层] 数据持久化层:GORM / DB 操作、SQL 防注入与 EscapeLike 转义
|
||||
├── models.go # [Model 层] GORM 表映射实体 (带插件前缀)、入参/出参 DTO、请求响应结构体
|
||||
├── errs.go # [Error 层] 模块内专用错误常量 (camelCase 字符串)
|
||||
backend/plugins/domain/<plugin_name>/
|
||||
├── plugin.go # [Cordis 接入层] 实现 core.Plugin,负责 Apply 组装与扩展点注册
|
||||
├── handlers.go # [Handler 层] 单一文件:Gin API Handler
|
||||
├── service.go # [Service 层] 单一文件:核心业务用例
|
||||
├── repository.go # [Repository 层] 单一文件:GORM / DB 操作
|
||||
├── models.go # [Model 层] 单一文件:实体与 DTO
|
||||
├── errs.go # [Error 层] 单一文件:错误常量
|
||||
├── plugin_test.go # 插件级单元与集成测试
|
||||
└── migrations/ # [Migration 层] 专属 Goose SQL 嵌入文件 (//go:embed)
|
||||
└── 20260828000001_init_order.sql
|
||||
└── migrations/ # Goose SQL 嵌入文件 (//go:embed)
|
||||
└── 20260828000001_init_<plugin_name>.sql
|
||||
```
|
||||
|
||||
> ⚠️ **严禁规则**:当单一文件膨胀或需要拆分多个业务实体时,**严禁在根目录创建 `handlers_user.go`, `handlers_admin.go`, `service_user.go` 等前缀文件**,必须立即重构并迁移为 **模式 2(标准独立子包分层架构)**!
|
||||
|
||||
### 2.2 核心代码模板 (模式 1)
|
||||
|
||||
#### (1) `plugin.go` (插件入口与装配)
|
||||
@@ -928,29 +931,36 @@ const (
|
||||
|
||||
---
|
||||
|
||||
## 3. 模式 2:严格子包物理分层规范与完整代码模板
|
||||
## 3. 模式 2:标准独立子包物理分层规范与完整代码模板 (推荐标准)
|
||||
|
||||
用于大型复杂插件,各层使用独立的 Go package 物理隔离。
|
||||
用于标准与中大型业务插件,各层使用独立的 Go package 物理隔离。
|
||||
|
||||
### 3.1 目录结构
|
||||
### 3.1 目录结构与文件命名规约
|
||||
```text
|
||||
backend/plugins/domain/order/
|
||||
├── plugin.go # [插件根入口] 实现 core.Plugin,装配各子包并向 Cordis 注册
|
||||
├── controller/ # package controller:HTTP API Handler
|
||||
│ ├── http.go # 参数校验、上下文提取、调用 service、信封响应与 Swagger 注解
|
||||
│ └── router.go # 路由组挂载
|
||||
├── service/ # package service:核心业务逻辑
|
||||
│
|
||||
├── handler/ # package handler:HTTP API 接入层(或 controller/)
|
||||
│ ├── router.go # 路由组挂载与中间件绑定
|
||||
│ └── order.go # 订单相关 Handler(以业务直接命名,禁止 handlers_order.go)
|
||||
│
|
||||
├── service/ # package service:核心业务逻辑层
|
||||
│ ├── service.go # 业务用例接口定义 (Service Interface)
|
||||
│ └── service_impl.go # 业务接口实现 (ServiceImpl)
|
||||
│ └── order.go # 订单业务用例实现(以业务直接命名,禁止 service_order.go)
|
||||
│
|
||||
├── repository/ # package repository:数据访问持久化层 (DAL)
|
||||
│ ├── repository.go # 仓储接口定义 (Repository Interface)
|
||||
│ └── repository_impl.go # GORM 数据持久化实现与安全转义
|
||||
├── model/ # package model:纯领域实体与传输对象(零外部框架依赖)
|
||||
│ ├── repository.go # 仓储通用方法与工厂
|
||||
│ └── order.go # 订单仓储持久化实现(以业务直接命名,禁止 repository_order.go)
|
||||
│
|
||||
├── model/ # package model (或 models/):纯领域实体与传输对象(零外部框架依赖)
|
||||
│ ├── entity.go # 数据库映射实体 (TableName() 必须带 w_<plugin>_ 前缀)
|
||||
│ └── dto.go # 请求与响应 DTO
|
||||
├── errs/ # package errs:错误常量与错误码定义
|
||||
│ ├── dto.go # 请求与响应 DTO
|
||||
│ └── events.go # 领域事件结构体
|
||||
│
|
||||
├── errs/ # package errs:错误常量与错误码定义 (或根目录 errs.go)
|
||||
│ └── errs.go
|
||||
└── migrations/ # Goose SQL 独立迁移嵌入文件
|
||||
│
|
||||
└── migrations/ # Goose SQL 独立迁移嵌入文件 (//go:embed)
|
||||
└── 20260828000001_init_order.sql
|
||||
```
|
||||
|
||||
@@ -963,7 +973,7 @@ import (
|
||||
|
||||
"github.com/Rain-kl/Wavelet/core"
|
||||
"github.com/Rain-kl/Wavelet/core/contracts"
|
||||
"github.com/Rain-kl/Wavelet/plugins/domain/order/controller"
|
||||
"github.com/Rain-kl/Wavelet/plugins/domain/order/handler"
|
||||
"github.com/Rain-kl/Wavelet/plugins/domain/order/repository"
|
||||
"github.com/Rain-kl/Wavelet/plugins/domain/order/service"
|
||||
)
|
||||
@@ -985,10 +995,10 @@ func (p *Plugin) Apply(ctx *core.Context) error {
|
||||
repo := repository.NewOrderRepository(ctx)
|
||||
svc := service.NewOrderService(ctx, repo)
|
||||
|
||||
// 3. 构造控制器并挂载路由
|
||||
ctrl := controller.NewOrderController(svc)
|
||||
// 3. 构造 Handler 并挂载路由
|
||||
h := handler.NewOrderHandler(svc)
|
||||
authSvc, _ := core.Inject[contracts.AuthService](ctx)
|
||||
controller.RegisterRoutes(ctx.Router(), ctrl, authSvc)
|
||||
handler.RegisterRoutes(ctx.Router(), h, authSvc)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -565,8 +565,8 @@ Wavelet/
|
||||
3. **`plugins/`**:
|
||||
- **职责**:所有业务逻辑和驱动实现的归宿。遵循标准分层架构(Layered Architecture / MVC 变体)。
|
||||
- **分层模式选型**:
|
||||
- **模式 1(扁平自包含分层,简单业务推荐)**:单 package 内部通过文件划分职责(`plugin.go`, `handlers.go`, `service.go`, `repository.go`, `models.go`, `errs.go`, `migrations/`)。适用于代码量 < 3000 行、单聚合根的插件。
|
||||
- **模式 2(严格子包物理分层,复杂业务推荐)**:多 package 目录级物理隔离(`plugin.go`, `controller/`, `service/`, `repository/`, `model/`, `errs/`, `migrations/`)。编译器级约束 `controller -> service -> repository -> model` 单向依赖。适用于代码量 ≥ 3000 行、多聚合根的大型复杂插件。
|
||||
- **模式 1(极简单文件分层,微型插件专用)**:单 package 极简结构(仅单文件 `plugin.go`, `handlers.go`, `service.go`, `repository.go`, `models.go`, `errs.go`, `migrations/`)。适用于单一实体、极小代码量 (<500行) 的微型插件。
|
||||
- **模式 2(标准独立子包分层架构,官方推荐标准)**:按职责严格物理分包(`plugin.go`, `handler/`, `service/`, `repository/`, `model/`, `errs/`, `migrations/`)。**子包内文件以纯业务实体命名(如 `user.go`、`config.go`),严禁在根包平铺 `handlers_*`、`service_*`、`repository_*` 等前缀文件**。编译器级强约束 `handler -> service -> repository -> model` 单向依赖。
|
||||
- **严禁**:插件之间严禁跨包 import 内部私有代码,跨插件调用一律走 `contracts` 接口或 `EventBus`。
|
||||
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Cordis 架构插件标准分层设计规范 (Plugin Layered Architecture Spec)
|
||||
|
||||
- **文档状态**: 已敲定 (Approved)
|
||||
- **版本**: v1.0.0 (2026-08-28)
|
||||
- **版本**: v1.1.0 (2026-08-28)
|
||||
- **适用范围**: Wavelet 官方插件 (`backend/plugins/`)、下游定制插件 (`downstream/custom_plugins/`)
|
||||
|
||||
---
|
||||
@@ -11,85 +11,101 @@
|
||||
在 Wavelet 的 Cordis 微内核架构中,系统通过 **微内核 (`core/`) + 服务契约 (`core/contracts/`) + 自包含插件 (`plugins/`)** 实现高度解耦与单向依赖。
|
||||
为了规范插件内部代码组织,插件遵循 **标准分层架构(Layered Architecture / MVC 变体)**,并根据业务复杂度提供两套标准物理包结构:
|
||||
|
||||
| 模式 | 适用场景 | 复杂度特征 | 物理结构形式 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **模式 1:扁平自包含分层**<br>(Flat Self-Contained) | 简单逻辑插件(推荐默认) | 代码量 < 3000 行、单聚合根、单一职责(如 `upload`, `cap`, `system`) | 单 Go package,文件级划分职责 |
|
||||
| **模式 2:严格子包分层**<br>(Strict Sub-packages) | 复杂业务插件 | 代码量 ≥ 3000 行、多聚合根、状态机流转复杂(如大型 `auth`, `order/billing`, `admin`) | 多 Go package,目录级物理隔离 |
|
||||
| 模式 | 适用场景 | 复杂度特征 | 物理结构形式 | 命名规范核心禁令 |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| **模式 1:极简单文件自包含**<br>(Single-File Flat) | 极简微型插件 | 仅有 1 个单一实体、代码量 < 500 行(如极简工具、Demo) | 单 Package,每个层级仅对应 1 个同名文件 (`handlers.go`, `service.go`, `models.go`, `repository.go`) | **严禁在根目录平铺 `handlers_*`、`service_*` 等前缀文件** |
|
||||
| **模式 2:独立子包分层架构**<br>(Strict Sub-packages) | 标准/中大型业务插件(**官方推荐标准**) | 包含多实体/多接口、代码量 ≥ 500 行(如 `upload`, `auth`, `admin`, `order` 等) | 严格按层独立子包 (`handler/`, `service/`, `repository/`, `model/`, `errs/`) | **子包内文件直接以业务命名(如 `user.go`, `config.go`),禁止带 `handler_*` / `service_*` 前缀** |
|
||||
|
||||
---
|
||||
|
||||
## 2. 模式 1:扁平自包含分层规范 (Flat Self-Contained Package)
|
||||
## 2. 模式 1:极简单文件自包含规范 (Single-File Flat Package)
|
||||
|
||||
适合中小型或单一功能插件。所有代码位于同个 package(如 `package order`),彻底避免 Go 子包循环导入。
|
||||
仅适用于极简小型插件(整个插件代码极少且各层只有一个文件)。
|
||||
|
||||
### 2.1 目录结构
|
||||
```text
|
||||
backend/plugins/domain/<plugin_name>/
|
||||
├── plugin.go # [Cordis 接入层] 实现 core.Plugin,负责 Apply 组装、依赖注入与扩展点注册
|
||||
├── handlers.go # [Controller 层] Gin API Handler:参数校验、认证上下文提取、信封响应 (response.OK/Abort)
|
||||
├── service.go # [Service 层] 核心业务用例、事务编排、事件触发 (ctx.Events().Emit),入参仅为 context.Context
|
||||
├── repository.go # [Repository 层] 数据持久化层:GORM / DB 操作、SQL 防注入与转义
|
||||
├── models.go # [Model 层] 数据表映射模型 (GORM)、入参/出参 DTO、请求响应结构体
|
||||
├── errs.go # [Error 层] 模块内专用错误常量 (camelCase 字符串)
|
||||
├── plugin_test.go # 插件单元与集成测试
|
||||
└── migrations/ # [Migration 层] 专属 Goose SQL 嵌入文件 (//go:embed)
|
||||
├── plugin.go # [Cordis 接入层] 实现 core.Plugin,负责 Apply 组装与扩展点注册
|
||||
├── handlers.go # [Handler 层] 单一文件:Gin API Handler
|
||||
├── service.go # [Service 层] 单一文件:核心业务用例
|
||||
├── repository.go # [Repository 层] 单一文件:GORM / DB 操作
|
||||
├── models.go # [Model 层] 单一文件:实体与 DTO
|
||||
├── errs.go # [Error 层] 单一文件:错误常量
|
||||
├── plugin_test.go # 插件测试
|
||||
└── migrations/ # Goose SQL 嵌入文件
|
||||
└── 20260828000001_init_<plugin_name>.sql
|
||||
```
|
||||
|
||||
### 2.2 横向文件扩展
|
||||
当某一职责文件变大时,按语义横向拆分(仍在同一 package 内):
|
||||
- `handlers_admin.go`, `handlers_user.go`
|
||||
- `models_dto.go`, `models_entity.go`
|
||||
> ⚠️ **严禁规则**:当单一文件膨胀或需要拆分多个业务实体时,**严禁在根目录创建 `handlers_user.go`, `handlers_admin.go`, `service_user.go` 等前缀文件**,必须立即重构并迁移为 **模式 2(独立子包分层架构)**!
|
||||
|
||||
---
|
||||
|
||||
## 3. 模式 2:严格子包分层规范 (Strict Sub-package Architecture)
|
||||
## 3. 模式 2:标准独立子包分层架构 (Standard Sub-package Architecture - 推荐规范)
|
||||
|
||||
适合重型业务插件,通过 Go package 物理隔离强制依赖方向(`controller -> service -> repository -> model`)。
|
||||
适用于绝大多数业务插件。各层使用独立的 Go package 物理隔离,**在子包内以纯业务实体命名文件**。
|
||||
|
||||
### 3.1 目录结构
|
||||
### 3.1 目录结构与文件命名规约
|
||||
```text
|
||||
backend/plugins/domain/<plugin_name>/
|
||||
├── plugin.go # [插件根入口] 实现 core.Plugin,装配各子包并向 Cordis 注册
|
||||
├── controller/ # package controller:HTTP API Handler
|
||||
│ ├── http.go # Gin 请求参数校验与信封响应
|
||||
│ └── router.go # 路由映射与中间件挂载函数
|
||||
├── service/ # package service:核心业务逻辑
|
||||
│ ├── service.go # 业务接口定义 (Service Interface)
|
||||
│ └── service_impl.go # 业务接口实现 (ServiceImpl)
|
||||
├── repository/ # package repository:数据持久化访问层
|
||||
│ ├── repository.go # 仓储接口定义 (Repository Interface)
|
||||
│ └── repository_impl.go # GORM 数据持久化实现
|
||||
├── model/ # package model:纯实体与 DTO(无外部依赖)
|
||||
│ ├── entity.go # 数据库映射实体 (TableName 带插件前缀)
|
||||
│ └── dto.go # 请求与响应 DTO
|
||||
├── errs/ # package errs:错误常量与错误码定义
|
||||
│
|
||||
├── handler/ # package handler:HTTP API 接入层(或 controller/)
|
||||
│ ├── router.go # 路由组挂载与中间件绑定
|
||||
│ ├── auth.go # 认证相关 Handler(直接命名为 auth.go,禁止 handlers_auth.go)
|
||||
│ ├── user.go # 用户相关 Handler(直接命名为 user.go,禁止 handlers_user.go)
|
||||
│ ├── config.go # 配置相关 Handler(直接命名为 config.go,禁止 handlers_config.go)
|
||||
│ └── logs.go # 日志相关 Handler(直接命名为 logs.go,禁止 handlers_logs.go)
|
||||
│
|
||||
├── service/ # package service:核心领域业务逻辑层
|
||||
│ ├── service.go # 顶层 Service 组合与构造工厂
|
||||
│ ├── auth.go # 认证业务逻辑(直接命名为 auth.go,禁止 service_auth.go)
|
||||
│ ├── user.go # 用户业务逻辑(直接命名为 user.go,禁止 service_user.go)
|
||||
│ ├── config.go # 配置业务逻辑(直接命名为 config.go,禁止 service_config.go)
|
||||
│ └── logs.go # 日志业务逻辑(直接命名为 logs.go,禁止 service_logs.go)
|
||||
│
|
||||
├── repository/ # package repository:数据访问持久化层 (DAL)
|
||||
│ ├── repository.go # 仓储通用方法与工厂
|
||||
│ ├── user.go # 用户仓储实现(直接命名为 user.go,禁止 repository_user.go)
|
||||
│ ├── config.go # 配置仓储实现(直接命名为 config.go,禁止 repository_config.go)
|
||||
│ └── log.go # 日志仓储实现(直接命名为 log.go,禁止 repository_log.go)
|
||||
│
|
||||
├── model/ # package model (或 models/):纯领域实体与传输对象
|
||||
│ ├── entity.go # 数据库映射实体 (TableName() 必须带 w_<plugin>_ 前缀)
|
||||
│ ├── dto.go # 请求入参与响应出参 DTO
|
||||
│ └── events.go # 插件内部/广播事件结构体定义
|
||||
│
|
||||
├── errs/ # package errs:错误常量与错误码定义 (或根目录 errs.go)
|
||||
│ └── errs.go
|
||||
└── migrations/ # Goose SQL 独立迁移嵌入文件
|
||||
│
|
||||
└── migrations/ # Goose SQL 独立迁移嵌入文件 (//go:embed)
|
||||
└── 20260828000001_init_<plugin_name>.sql
|
||||
```
|
||||
|
||||
### 3.2 依赖方向约束 (Strict Dependency Flow)
|
||||
```mermaid
|
||||
graph TD
|
||||
Plugin[plugin.go 入口] --> Controller[controller/]
|
||||
Plugin --> Service[service/]
|
||||
Plugin --> Repository[repository/]
|
||||
Controller --> Service
|
||||
Controller --> Model[model/]
|
||||
Controller --> Errs[errs/]
|
||||
Plugin[plugin.go 入口] --> Handler[handler/ 接入层]
|
||||
Plugin --> Service[service/ 业务层]
|
||||
Plugin --> Repository[repository/ 仓储层]
|
||||
Handler --> Service
|
||||
Handler --> Model[model/ 实体与DTO]
|
||||
Handler --> Errs[errs/ 错误常量]
|
||||
Service --> Repository
|
||||
Service --> Model
|
||||
Service --> Errs
|
||||
Repository --> Model
|
||||
```
|
||||
* **禁止反向依赖**:`repository` 严禁依赖 `service` 或 `controller`;`service` 严禁依赖 `controller`;`model` 严禁依赖任何上层包。
|
||||
* **单向依赖铁律**:
|
||||
1. `handler/` 依赖 `service/`、`model/`、`errs/`;
|
||||
2. `service/` 依赖 `repository/`、`model/`、`errs/`,**严禁 import gin**;
|
||||
3. `repository/` 依赖 `model/` 和数据库底层,**严禁反向依赖 service 或 handler**;
|
||||
4. `model/` 纯粹由 Go 结构体组成,**严禁依赖上层 handler/service/repository**。
|
||||
|
||||
---
|
||||
|
||||
## 4. 各层职责边界与编码守则 (Layer Responsibilities & Guardrails)
|
||||
|
||||
### 4.1 Controller / Handler 层 (接入层)
|
||||
### 4.1 Handler 层 (`handler/`)
|
||||
1. **参数绑定**:使用 `c.ShouldBindJSON` 或 `c.ShouldBindQuery`。
|
||||
2. **上下文提取**:从 `*gin.Context` 提取登录态(如 `oauth.GetCurrentUser(c)`)。
|
||||
3. **调用下游**:调用 Service 方法,禁止直接调用 Repository 或编写 SQL。
|
||||
@@ -98,23 +114,23 @@ graph TD
|
||||
- 失败:使用 `backend/pkg/response` 的 `Abort*` 系列函数(如 `AbortBadRequest`、`AbortUnauthorized`、`AbortNotFound`、`AbortInternal`)。
|
||||
5. **Swagger 注释**:每个导出 Handler 必须编写完整的 OpenAPI/Swagger 注解。
|
||||
|
||||
### 4.2 Service 层 (业务用例层)
|
||||
### 4.2 Service 层 (`service/`)
|
||||
1. **纯 Go 逻辑**:第一参数必须为 `ctx context.Context`,返回 `(result, error)`。
|
||||
2. **禁止依赖 Web 框架**:严禁 import `github.com/gin-gonic/gin`,严禁接收 `*gin.Context`,严禁调用 `c.JSON`/`Abort*`。
|
||||
3. **事务编排**:涉及插件内多表原子操作时,通过 `ctx.DB().Transaction(...)` 编排。
|
||||
4. **事件驱动解耦**:跨插件业务通知与状态联动统一通过 `ctx.Events().Emit(...)` 广播领域事件,杜绝直接跨插件调用私有方法。
|
||||
|
||||
### 4.3 Repository 层 (持久化访问层)
|
||||
### 4.3 Repository 层 (`repository/`)
|
||||
1. **GORM / SQL 操作**:统一接收 `context.Context`,通过 `db.WithContext(ctx)` 操作数据。
|
||||
2. **SQL LIKE 防注入**:所有含用户输入的模糊查询必须调用 `backend/pkg/util.EscapeLike` 并显式声明 `ESCAPE '\\'`。
|
||||
3. **表单一所有者原则**:仅操作本插件所属表(前缀 `w_<plugin>_*`),严禁越权 DML/DDL 其他插件所有表。
|
||||
|
||||
### 4.4 Model 层 (实体与 DTO 层)
|
||||
### 4.4 Model 层 (`model/` 或 `models/`)
|
||||
1. **GORM 映射**:显式实现 `TableName() string` 返回带前缀表名。
|
||||
2. **零值对齐**:Go 结构体字段零值必须与数据库默认值匹配。
|
||||
3. **无物理外键**:禁止物理外键约束,显式建立单列/复合索引。
|
||||
|
||||
### 4.5 Plugin 入口 (Cordis 生命周期与装配)
|
||||
### 4.5 Plugin 入口 (`plugin.go`)
|
||||
1. 实现 `core.Plugin` 接口(`Name() string` 与 `Apply(ctx *core.Context) error`)。
|
||||
2. 在 `Apply` 中完成:
|
||||
- 依赖注入与解析(`core.Provide` / `core.Inject` / `ctx.Using`)
|
||||
|
||||
Reference in New Issue
Block a user