9.0 KiB
9.0 KiB
架构规范
状态:已确定
最后更新:2025-01-28
一、后端架构规范
1.1 分层架构
API层 (internal/api/)
↓
Service层 (internal/service/)
↓
Repository层 (internal/storage/repository/)
↓
Infrastructure层 (internal/dbclient/)
1.2 职责划分
API层
- 职责:暴露给前端的接口
- 约束:只负责参数验证和调用Service
- 文件命名:
{功能}_api.go
Service层
- 职责:业务逻辑处理
- 约束:不直接访问数据库,通过Repository
- 文件命名:
{功能}_service.go
Repository层
- 职责:数据访问
- 约束:只负责CRUD操作,不包含业务逻辑
- 文件命名:
{模型}_repo.go
Infrastructure层
- 职责:基础设施(数据库客户端、连接池等)
- 约束:提供统一的接口,隐藏实现细节
二、前端架构规范
2.1 组件结构
Views (views/db-cli/)
↓
Components (components/)
↓
Composables (composables/)
↓
Types (types/)
2.2 职责划分
Views
- 职责:页面级组件,负责布局和状态协调
- 约束:不包含具体业务逻辑
Components
- 职责:可复用组件
- 约束:组件应该是无状态的(通过props接收数据)
Composables
- 职责:状态管理和业务逻辑
- 约束:可复用的逻辑封装
Types
- 职责:TypeScript类型定义
- 约束:所有类型定义集中管理
三、事件系统规范
3.1 事件命名
- 格式:
<组件>-<动作>或<功能>-<动作> - 示例:
connection-select、table-structure
3.2 事件参数
- 格式:对象格式,不使用多个参数
- 类型:所有事件都有TypeScript类型定义
- 位置:
types/events.ts
3.3 事件处理
- 位置:在父组件中处理
- 职责:调用相应的composable方法
四、架构设计美学原则
4.1 参数数量约束(最高优先级)
原则:方法参数不得超过 3 个,超过必须使用结构体/对象封装。
违反示例(不可接受):
// ❌ 9个参数,完全不可接受
func SaveDbConnection(id uint, name, dbType, host string, port int, username, password, database, options string) error
正确示例:
// ✅ 使用结构体封装
type SaveConnectionRequest struct {
ID uint
Name string
Type string
Host string
Port int
Username string
Password string
Database string
Options string
}
func SaveDbConnection(req SaveConnectionRequest) error
前端同理:
// ❌ 参数过多
function saveConnection(id: number, name: string, type: string, host: string, port: number, username: string, password: string, database: string, options: string)
// ✅ 使用对象封装
interface SaveConnectionRequest {
id: number
name: string
type: string
host: string
port: number
username: string
password: string
database: string
options: string
}
function saveConnection(req: SaveConnectionRequest)
4.2 依赖注入美学
原则:减少手动依赖注入,优先使用自动依赖获取。
当前问题:
// 需要手动注入依赖
const { executeSQL } = useSqlExecution(resultState, messageLog)
优化方向:
// 内部自动获取依赖(通过 provide/inject 或全局状态)
const { executeSQL } = useSqlExecution()
4.3 代码简洁性
原则:代码应该简洁、直接、易于理解。
要求:
- 避免过度抽象
- 减少中间层
- 直接表达意图
- 移除不必要的包装
4.4 一致性原则
原则:相同功能在不同实现中保持一致的命名和结构。
要求:
- 统一的错误处理方式
- 统一的命名规范
- 统一的数据结构
- 统一的接口风格
4.5 可组合性
原则:Composables 应该可以独立使用,也可以组合使用。
要求:
- Composables 之间依赖关系清晰
- 支持按需组合
- 避免循环依赖
- 提供清晰的组合模式
五、架构优化建议
5.1 后端 API 层优化(高优先级)
问题:API 方法参数过多,违反设计美学。
优化方案:
- 所有 API 方法参数超过 3 个时,必须使用请求结构体
- 统一请求/响应结构体命名:
{Action}Request/{Action}Response - 结构体定义放在对应的 API 文件中
示例:
// connection_api.go
type SaveConnectionRequest struct {
ID uint `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`
Password string `json:"password"`
Database string `json:"database"`
Options string `json:"options"`
}
func (api *ConnectionAPI) SaveDbConnection(req SaveConnectionRequest) error {
conn := &models.DbConnection{
ID: req.ID,
Name: req.Name,
Type: req.Type,
Host: req.Host,
Port: req.Port,
Username: req.Username,
Password: req.Password,
Database: req.Database,
Options: req.Options,
}
return api.connService.SaveConnection(conn)
}
5.2 前端 Composables 依赖优化(中优先级)
问题:需要手动注入依赖,使用不够优雅。
优化方案:
- 使用
provide/inject或全局状态管理依赖 - Composables 内部自动获取依赖
- 保持向后兼容,支持手动注入
示例:
// 使用 provide/inject
const resultState = useResultState()
const messageLog = useMessageLog()
provide('resultState', resultState)
provide('messageLog', messageLog)
// useSqlExecution 内部自动获取
export function useSqlExecution() {
const resultState = inject<ReturnType<typeof useResultState>>('resultState')
const messageLog = inject<ReturnType<typeof useMessageLog>>('messageLog')
// ...
}
5.3 Service 层验证逻辑提取(中优先级)
问题:验证逻辑分散在 Service 方法中,代码重复。
优化方案:
- 创建独立的验证器(Validator)
- 统一验证错误格式
- 可复用的验证规则
示例:
// validator/connection_validator.go
type ConnectionValidator struct{}
func (v *ConnectionValidator) ValidateSave(conn *models.DbConnection) error {
if conn.Name == "" {
return fmt.Errorf("连接名称不能为空")
}
if conn.Type == "" {
return fmt.Errorf("数据库类型不能为空")
}
if conn.Host == "" {
return fmt.Errorf("主机地址不能为空")
}
return nil
}
5.4 Composables 组合优化(低优先级)
问题:index.vue 中 composables 较多,可以进一步抽象。
优化方案:
- 创建
useDbClicomposable 作为统一入口 - 内部组合所有相关 composables
- 提供简洁的 API
示例:
// composables/useDbCli.ts
export function useDbCli() {
const connection = useDbConnection()
const editor = useEditorState()
const result = useResultState()
const message = useMessageLog()
const sql = useSqlExecution(result, message)
const structure = useStructureState()
const structureEdit = useStructureEdit()
return {
connection,
editor,
result,
message,
sql,
structure,
structureEdit
}
}
六、架构检查清单
开发优先原则检查
- 是否使用了 Vue 的响应式系统管理状态?
- 是否使用了模板引用而非 DOM 查询?
- 是否在正确的时机执行操作(通过
nextTick、requestAnimationFrame等)? - 是否移除了不必要的重试循环?
- 是否移除了过多的条件检查和兜底逻辑?
- 代码是否简洁直接,易于理解?
- 是否避免了防御性编程模式?
后端检查
- API 方法参数不超过 3 个,超过使用结构体封装
- 所有请求/响应结构体命名统一
- Service 层验证逻辑清晰
- 错误处理统一
前端检查
- Composables 依赖关系清晰
- 减少手动依赖注入
- 代码简洁直接
- 类型定义完善
设计美学检查
- 参数数量符合约束(≤3)
- 代码简洁易读
- 命名一致统一
- 结构清晰优雅
四、数据流规范
4.1 数据流向
用户操作
↓
组件事件
↓
Composable方法
↓
API调用
↓
后端Service
↓
Repository
↓
数据库
4.2 状态管理
- 原则:使用Composables管理状态
- 位置:
composables/目录 - 命名:
use{功能}State.ts
五、约束条件
5.1 后端约束
- 方法参数不超过3个
- 不返回
RetResult<Void>类型 - 使用分层架构,职责分离
5.2 前端约束
- 使用Arco基础样式
- 事件参数使用对象格式
- 所有事件有类型定义
六、检查清单
架构检查
- 分层架构清晰
- 职责分离明确
- 依赖方向正确
- 符合架构规范