test-frontend/.claude/backend.md

7.8 KiB
Raw Blame History

02 — 后端规则

适用:所有后端 AI 开发任务。


分层不变式

Controller  → 参数校验 + 调 Service + 返回统一格式
              禁止:写业务逻辑、直接调 Mapper、处理事务

Service     → 业务逻辑 + 事务管理
              禁止:处理 HTTP 请求/响应、直接操作 Request/Response

Mapper      → 数据访问MyBatis-Plus BaseMapper
              禁止:写业务逻辑、调用其他 Mapper

Entity      → 数据映射(@TableName 对应表名)
              禁止:写业务方法、放非持久化字段(放 DTO/VO

包结构

com.ghb.base/
├── system/                   # 系统模块(不改)
│   ├── entity/  SysUser, SysRole, SysMenu...
│   ├── controller/
│   └── service/
└── business/                 # 业务模块 ← 你的代码放这里
    ├── entity/               # 继承 JeecgBoot 的 BaseEntity
    ├── controller/           # 继承 JeecgController
    ├── service/              # impl/ 继承 ServiceImpl
    ├── mapper/               # 继承 BaseMapper
    │   └── xml/              # MyBatis XML复杂查询才需要
    └── vo/                   # 请求/响应 DTO (*VO, *Request, *ImportRow)

命名规则

元素 规则 示例(正确 → 错误)
类名 大驼峰,名词 TaskController OrderService UserMapper
方法名 小驼峰,动词开头 getById() saveTask() listByStatus()
变量 小驼峰,有意义 taskList userId list id data
包名 全小写,点分隔 com.xxx.server.controller
Entity 大驼峰,对应表名 task_apply → 类 TaskApply
DTO 大驼峰,后缀 DTO/VO/Request TaskCreateRequest UserListVO
常量 全大写,下划线分隔 MAX_RETRY_COUNT DEFAULT_PAGE_SIZE
SQL 表名 小写,下划线分隔 task_apply user_profile
SQL 字段 小写,下划线分隔 create_time task_id del_flag
URL 路径 小写,短横线或斜杠 /app/task/list /app/Task/GetList
配置文件 kebab-case 或小写 application-prod.yml

长度控制

类名、方法名、表名不要过长。超过 3 个单词或 30 个字符时,用通用缩写。

前缀也要缩:模块前缀用一个单词,别堆多个词。

完整 缩写 JeecgBoot 实际案例
Department Dept SysDepartRolePermissionSysDeptRolePerm
Permission Perm 同上
Announcement Notice SysAnnouncementSendSysNoticeSend
Enterprise Ent WechatEnterpriseWxEnt
Message Msg SysMessageTemplateSysMsgTemplate
// ❌ JeecgBoot 原版 — 太长
SysDepartRolePermissionServiceImpl        // 35 字符
SysAnnouncementSendServiceImpl           // 30 字符
ThirdAppWechatEnterpriseServiceImpl      // 35 字符

// ✅ 缩写后
SysDeptRolePermServiceImpl               // 26 字符
SysNoticeSendServiceImpl                 // 25 字符
ThirdAppWxEntServiceImpl                 // 27 字符

原则:优先用全称,超长再缩写。缩写必须一眼能认出含义,不自造别人看不懂的缩写。


注释规则

位置 要求 示例
类/接口 必须有 Javadoc说明职责 /** 任务管理 Controller处理任务的增删改查 */
公共方法 必须有 Javadoc说明入参/返回/异常 /** @param taskId 任务ID @return 任务详情 @throws 无 */
复杂逻辑 行内注释说明"为什么这么做" // 先查缓存再查库,避免击穿
常量 必须有注释说明含义 /** 最大重试次数 */
TODO/FIXME 必须有负责人和日期 // TODO(yaoshuli 2026-06) 后续改为配置项
禁止 注释写"做了什么"(代码本身已说明) // 查询任务列表 ← 删掉
禁止 注释掉的旧代码 直接删Git 有历史
禁止 无意义注释 // 定义一个变量 // 返回结果
禁止 Controller 方法加 Javadoc 说"这是xxx接口" 写业务含义,不写技术废话

注释示例

/** 任务服务,负责任务的创建、分配、状态流转 */
@Service
public class TaskServiceImpl implements TaskService {

    /** 单次批量操作上限 */
    private static final int BATCH_LIMIT = 100;

    /**
     * 根据状态和截止时间查询待处理任务。
     * 先查 Redis 缓存,未命中再查 MySQL。
     *
     * @param status 任务状态,不能为 null
     * @param deadline 截止时间,只查此时间之前的任务
     * @return 任务列表,可能为空
     */
    @Override
    public List<Task> listPending(String status, LocalDateTime deadline) {
        // 缓存 key: pending:{status}
        String cacheKey = "pending:" + status;
        List<Task> cached = cacheService.get(cacheKey);
        if (cached != null) return cached;

        // 查库(这里用复合索引 idx_status_deadline
        List<Task> tasks = taskMapper.selectByStatusBefore(status, deadline);
        cacheService.set(cacheKey, tasks, 300);
        return tasks;
    }
}

新增功能标准步骤

1. 建表 SQL        → [项目数据库脚本目录]
2. Entity           → 表映射
3. Mapper           → 继承 BaseMapper
4. Service 接口+实现 → 业务逻辑
5. Controller       → 接口暴露
6. 编译验证         → 构建通过

CRUD 模板(填空式)

// ===== 分页列表 =====
@GetMapping("/list")
public Result<IPage<Xxx>> list(@RequestParam(defaultValue = "1") int page,
                                @RequestParam(defaultValue = "10") int size) {
    Page<Xxx> p = new Page<>(page, size);
    // [填空] 构建查询条件
    return Result.ok(service.page(p, wrapper));
}

// ===== 详情 =====
@GetMapping("/{id}")
public Result<Xxx> detail(@PathVariable Long id) {
    Xxx entity = service.getById(id);
    if (entity == null) return Result.error("[资源]不存在");
    return Result.ok(entity);
}

// ===== 新增 =====
@PostMapping
public Result<?> create(@RequestBody @Valid XxxDto dto) {
    // [填空] DTO → Entity 转换
    service.save(entity);
    return Result.ok();
}

// ===== 更新 =====
@PutMapping("/{id}")
public Result<?> update(@PathVariable Long id, @RequestBody @Valid XxxDto dto) {
    Xxx entity = service.getById(id);
    if (entity == null) return Result.error("[资源]不存在");
    // [填空] 字段更新
    service.updateById(entity);
    return Result.ok();
}

禁止清单

类别 禁止
分层 Controller 里写 if/else 业务判断
分层 Controller 直接调 Mapper/Repository
分层 Entity 里写业务方法
数据 SQL/查询条件字符串拼接
数据 查不到不判空,直接返回可能 NPE
数据 selectOne / getOne 不做唯一性约束
输入 入参不校验(该用 @Valid 的地方手撸 if
输出 返回裸对象、裸字符串、自造格式
代码里硬编码魔法数字、魔法字符串
事务 该加事务的地方漏加

检查表

每完成一个后端任务,逐项自检:

  • 编译通过(mvn compile / go build / 对应构建命令)
  • 所有返回值是统一格式,无裸返回
  • 分页接口格式正确(list/total/pages/current/size
  • Controller 方法体不超过 20 行(超过说明写了业务逻辑)
  • 查不到/null 路径有明确的 fail 返回
  • 改了接口 → 已 grep 同步所有前端调用方
  • 新增/改字段 → 已更新数据库脚本
  • 无禁止清单中的违规项