13 KiB
13 KiB
name, description
| name | description |
|---|---|
| likei-dev | Likei Services 项目开发 Skill。接到任何功能需求、Bug 修复、重构任务时触发。执行完整的「需求分析 → 读文件 → 编码 → 提交 → Review → 修复循环 → 汇总」工作流,直到代码无问题为止。适用于 rc-service-other、rc-service-wallet、rc-service-order、rc-auth、rc-inner-api 等模块的开发工作。 |
Likei Services 开发 Skill
核心工作流(每次接到需求必须严格按此顺序执行)
1. 读文件 → 理解现有结构和上下文
2. 设计方案 → 列出改动文件、核心思路,询问用户是否同意,等待确认后再继续
3. 编码 → 按规范写代码
4. git add → 暂存变更(指定文件,禁止 git add .)
5. git commit → 提交(默认不 push,除非用户明确要求)
6. git show → diff review,逐文件检查
7. 发现问题? → 修复 → 追加 commit → 再次 review
8. 无问题 → 输出汇总,询问是否 push
循环终止条件:git diff review 所有文件均无逻辑漏洞、无原逻辑改动、无字段错误、无 NPE 风险。
数据库变更规则:设计方案中若涉及 MySQL 表结构变更(新增字段、修改索引等)或 MongoDB 索引变更,必须在方案里直接给出可执行的 SQL / MongoDB Shell 语句,不能只描述变更内容。
第一步:读文件(禁止跳过)
接到需求后,先读,不要直接写代码。
必读文件
- 需求涉及的所有现有业务文件(Controller / ServiceImpl / Cmd / CO 等)
- 同模块至少一个 peer 文件,用于对齐命名和代码风格
- 涉及对接文档时,仔细比对每个字段
按需读取的规范文档
| 场景 | 文档 |
|---|---|
| 工具类、Redis key、MongoDB 操作 | D:\workspace\likei-services\项目工具类说明.md |
| DDD 分层、模块结构 | D:\workspace\likei-services\OTHER模块DDD架构说明.md |
| 排行榜 season/cycle 相关 | D:\workspace\likei-services\ranking-season-cycle.md |
读完后先说明:要改哪些文件、改什么,再动手编码。
第二步:编码规范
分层架构(严格遵守,禁止跨层调用)
Controller(other-adapter)
↓ 只调用 Service 接口
ServiceImpl(other-application)
↓ 只调用 CmdExe / Gateway / DatabaseService
CmdExe / Gateway(other-application / other-infrastructure)
↓
DAO / MongoTemplate / Redis(other-infrastructure)
文件路径速查(other 模块)
| 类型 | 路径模板 |
|---|---|
| Controller | other-adapter/src/main/java/com/red/circle/other/adapter/app/{模块}/ |
| Service 接口 | other-client/src/main/java/com/red/circle/other/app/service/{模块}/ |
| Cmd | other-client/src/main/java/com/red/circle/other/app/dto/cmd/{模块}/ |
| CO | other-client/src/main/java/com/red/circle/other/app/dto/clientobject/{模块}/ |
| CmdExe | other-application/src/main/java/com/red/circle/other/app/command/{模块}/ |
| QryExe | other-application/src/main/java/com/red/circle/other/app/command/{模块}/query/ |
| ServiceImpl | other-application/src/main/java/com/red/circle/other/app/service/{模块}/ |
| DatabaseService | other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/ |
| DAO | other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/ |
| Entity | other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/ |
| Redis Key 枚举 | other-infrastructure/src/main/java/com/red/circle/other/infra/database/cache/key/{模块}/ |
| Inner API 接口 | rc-inner-api/other-inner/other-inner-api/endpoint/{模块}/ |
| Inner Endpoint 实现 | other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/{模块}/ |
命名规范
| 类型 | 命名规则 |
|---|---|
| Controller | {功能}RestController |
| Service 接口 | {功能}Service |
| ServiceImpl | {功能}ServiceImpl |
| CmdExe | {功能}CmdExe 或 {功能}Exe |
| QryExe | {功能}QryExe |
| Cmd(写操作入参) | {功能}Cmd |
| CO(读操作返回) | {功能}CO |
| DAO | {实体名}DAO,继承 BaseDAO<T> |
注解规范
// Cmd / CO / DTO:@Data,需要时加 @Builder @NoArgsConstructor @AllArgsConstructor
// 校验注解:jakarta.validation.constraints.*(禁止用 javax.validation)
// 注入方式:@RequiredArgsConstructor(构造器注入,禁止 @Autowired 字段注入)
// 日志:@Slf4j,查询接口不加 log.info,只在关键业务节点记录
// 事务:@Transactional 只加在 public 方法,不加在 private 方法(Spring AOP 限制)
// API 文档:@eo.name / @eo.url / @eo.method(不使用 Swagger 注解)
// 作者:@author tf
// 分页查询 Cmd:继承 PageQueryCmd,不手写分页参数
// 写操作 Cmd:需要时继承 AppExtCommand(含 reqUserId 等公共字段)
常用外部工具类(外部 jar,禁止在项目中搜索源码)
| 类名 | 包路径 | 用途 |
|---|---|---|
RedisService |
com.red.circle.component.redis.service.RedisService |
Redis,含 setIfAbsent/increment/expire |
IdWorkerUtils |
com.red.circle.tool.core.sequence.IdWorkerUtils |
雪花 ID,getId()/getIdStr() |
ZonedDateTimeUtils |
com.red.circle.other.infra.utils.ZonedDateTimeUtils |
Riyadh 时区工具 |
ZonedId |
com.red.circle.tool.core.date.ZonedId |
时区枚举,ASIA_RIYADH / ASIA_SHANGHAI |
ArithmeticUtils |
com.red.circle.tool.core.num.ArithmeticUtils |
金额计算 |
AppExtCommand |
com.red.circle.common.business.dto.cmd.AppExtCommand |
Cmd 基类 |
PageQueryCmd |
com.red.circle.common.business.dto.PageQueryCmd |
分页查询基类 |
PageResult |
com.red.circle.framework.dto.PageResult |
分页结果封装 |
关键业务规则
- 时区:所有时间统计和调度使用 Asia/Riyadh
- AR 分区判断:使用
RegionConstants.AR_REGION_IDS,分区值为"AR"或"OTHER" - Integer 比较:用
Objects.equals()或Integer.valueOf(x).equals(y),禁止== - MQ createTime:发送时设为
new Date(),不用业务时间戳 - RocketMQ 幂等 key:在业务执行成功后写入 Redis,不能在执行前
- 金额:使用
PennyAmount(以分为单位),展示时用getDollarAmount() - Response 空检查:调用外部服务(walletGoldClient / authClient 等)后必须判断
isSuccess()和getBody() != null
编码完成后自检清单
- 命名清晰,无 a、b、tmp 等无意义变量
- 无跨层调用
- 所有外部服务返回值有空检查
- Integer / Long 比较未使用
== - 金额操作有幂等保护(bizNo / requestId / orderId)
- 幂等标记在业务成功后写入
- 关键业务有
@Transactional(public 方法) - 异常信息有意义,不直接
new RuntimeException("error") - 新代码未破坏原有逻辑
第三步:git 操作
环境信息
git 可执行文件:D:\datasource\git\bin\git.exe
项目根目录: D:\workspace\likei-services
工作范围: D:\workspace\likei-services 及其子目录(禁止操作父目录)
标准命令模板
# add(指定文件路径,禁止 git add .)
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services add {相对路径1} {相对路径2}
# 查看状态
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services status
# 查看最近提交
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services log --oneline -5
# diff review(必须用 git show,不用 git diff HEAD)
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services show {hash}
# push
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services push origin {branch}
commit 命令(必须用 PowerShell,避免中文解析失败)
& 'D:\datasource\git\bin\git.exe' -C 'D:\workspace\likei-services' commit -m 'message in english'
commit 后 PowerShell 输出不稳定,不能直接从 commit 输出中读取 hash。commit 完成后立即用以下命令确认:
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services log --oneline -1
commit message 规范(英文,禁止中文)
| 类型 | 格式 |
|---|---|
| 新功能 | feat: add xxx |
| Bug 修复 | fix: xxx null check |
| 重构 | refactor: extract xxx |
| 配置变更 | chore: update xxx config |
第四步:Review 检查项(git show 后必须逐文件核对)
字段映射
- Cmd 字段与对接文档/需求是否完全一致,无遗漏
- CO / 响应字段与文档是否一致
@JsonProperty是否正确处理下划线命名(如game_infos)- 类型是否正确(
IntegervsLong,intvslong)
原逻辑保护
- 原有业务流程(广播、排行榜、任务、日志等)是否完整保留
- 重构时条件判断位置移动是否导致行为变化(如 type 判断从方法内移到方法外)
- 注释掉的代码是否被意外删除
- 原有 error log 是否被移除
空指针防御
- 外部服务返回值是否有
isSuccess()+getBody() != null双重检查 Integer/Long类型是否用了==比较(必须用Objects.equals)Optional链是否有.orElse()兜底- 外部接口返回的集合类型为
Collection时,调用subList/sort/indexOf等List专有方法前必须先转为new ArrayList<>(collection)
幂等与并发
changeBalance/ 余额变动类接口是否有幂等保护(RedissetIfAbsent或 requestId 标记)- 幂等标记是否在钱包调用成功后写入(不是之前)
- 幂等 TTL 是否合理(建议 ≥ 600s)
- 重复请求命中幂等时的返回值是否正确
架构合规
- 业务逻辑是否在正确的层(Controller 不写逻辑,Infrastructure 不写业务)
- 是否有跨层调用
- 公共逻辑是否抽到合适的位置(如
GameEventService)
发现问题时的处理流程
- 明确说明:哪个文件、哪行、什么问题、为什么
- 直接修复代码,不只是建议
git add修改的文件- 追加 commit(message 说明修复内容)
- 再次
git showreview,确认问题消失 - 重复直到所有问题清零
第五步:汇总输出(Review 无问题后输出)
## 本次变更汇总
### 涉及文件
| 文件 | 操作 | 变更内容 |
|------|------|----------|
| XxxController.java | 修改 | 错误码对齐 v4 协议 |
| XxxCmd.java | 新增 | v4 请求字段定义 |
### 关键逻辑说明
- ...
### Commits
- {hash} {message}
- {hash} {message}
### Review 结论
✅ 字段映射完整,与文档一致
✅ 原有业务逻辑完整保留
✅ 外部服务返回值均有空检查
✅ Integer 比较已用 Objects.equals
✅ 幂等保护正常,TTL 合理
✅ 架构分层合规,无跨层调用
然后询问用户:是否需要 push 到远端?
附:常见问题处理
新建文件 vs 编辑文件
- 新建文件:必须用
Filesystem:write_file,edit_file只能操作已存在的文件,对新路径会报 ENOENT。 - 编辑已有文件:优先用
Filesystem:edit_file;遇到编码匹配失败时改用Desktop Commander:write_file(rewrite 模式,超过 30 行分块写入)。
git commit 报错(cmd 下 -m 后内容被拆分为多个参数)
根本原因:在 cmd 下直接执行 git commit -m "message with spaces" 时,cmd 会将双引号内的空格当作参数分隔符,导致 message 被拆成多个 pathspec 参数报错。无论是否含中文,只要 message 含空格就会出错。
正确做法(必须严格遵守):
- add 用 cmd + 完整 git 路径 +
-C指定仓库:
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services add {相对路径}
- commit 必须切换到 PowerShell,用单引号包裹 message,且只用英文:
& 'D:\datasource\git\bin\git.exe' -C 'D:\workspace\likei-services' commit -m 'feat: add xxx'
- commit 完成后用 cmd 确认 hash:
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services log --oneline -1
禁止行为:
- ❌ 禁止在 cmd 下执行
git commit -m "有空格的message" - ❌ 禁止用
cd /d xxx && git commit(PATH 中的 git 不保证可用) - ❌ 禁止省略
-C D:\workspace\likei-services(依赖 cwd 不可靠) - ✅ commit message 必须用中文,PowerShell 单引号包裹中文没有问题
git show 无输出(exit 0)
说明 hash 是最新提交,HEAD 和它相同,改用:
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services show {完整hash}
搜索 Java 文件
使用 Filesystem:search_files,必须加 excludePatterns: ["target"] 排除构建产物。
批量读文件
优先用 Filesystem:read_multiple_files 一次读多个,减少工具调用轮次。
新目录下创建文件
先用 Filesystem:create_directory 建目录,再写文件;impl 子目录不会自动创建。
文件超长(>100 行)需要写入
用 Desktop Commander:write_file 分块写:首块 mode: rewrite,后续块 mode: append,每块不超过 30 行。