feat:添加superpower-skill与code style - skill

This commit is contained in:
2026-07-09 08:57:40 +08:00
parent a0ef4b01ad
commit ab079c526b
4 changed files with 126 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
---
name: holdwell-java-style
description: 用于在编写、修改、评审或重构 Java 17 / Spring Boot / MyBatis 后端代码时启用,适用于需要遵循 Holdwell 团队规范的 coding 项目后台服务,包括:使用 ResultPo / PageResult 响应结构、使用 @Resource 注入、基于注解进行参数校验、共享 DTO 放在 product-api 模块、手动字段映射而不是使用 BeanUtils.copyProperties、使用中文注释/日志,以及优先依赖数据库默认值等实践。
---
# NL Java Backend Skill
## 何时使用
- 在编写Java代码的时候
- 新增或调整 `Controller``Service``ServiceImpl``Mapper``Config``Dto``Api`
- 评审或重构 Java / Spring / MyBatis 代码时,需要严格对照团队规范。
## 使用方式
1. 开始改代码前,先阅读 [references/rules.md](references/rules.md)。
3. 实现时优先满足返回值、校验、注入、注释、日志、数据库约束,不要额外写“防御性兜底”代码。
4. 交付前检查命名[rules.md](references/rules.md)、排序、分页入参、字段映射、删除语义、远程调用失败处理是否符合规范。
## 参考
- 详细规则与反例见 [references/rules.md](references/rules.md)。

View File

@@ -0,0 +1 @@
commit

View File

@@ -0,0 +1,4 @@
interface:
display_name: "NL Java"
short_description: "按 NL 规范写 Java 后端代码"
default_prompt: "按 NL 团队规范实现或修改当前 Java/Spring/MyBatis 需求,严格遵守 ResultPo/PageResult、@Resource、注解校验、中文注释和日志、数据库默认值优先、禁止 BeanUtils.copyProperties 等约束。"

View File

@@ -0,0 +1,101 @@
# NL Java 编码规范
## 必须遵守
- 回复、代码注释、日志统一使用中文。
- 使用 Java 17、UTF-8、4 空格缩进。
- 提交前使用 IDE 格式化代码,并确保 `mvn clean install` 通过。
- 接口返回值使用 `ResultPo`
- 分页接口返回值使用 `Result<PageResult>`
- 分页查询的 service 入参使用 request 对象,不要用基本类型散传。
- 参数校验使用注解,例如 `@NotNull`,不要在业务代码里重复判空兜底。
- 方法里面如果有校验逻辑,先校验,再做业务。
- 注入统一使用 `@Resource`,不要使用构造器注入。
- 默认按 `id` 倒序,除非需求明确指定其他排序。
- 每个接口方法和每个 `private` 方法上方都写中文注释,说明作用。
- 类里的字段、方法上方要加中文注释。
- 代码里的日志统一使用中文。
- 调用其他服务后必须判断 `isSuccess`,失败时抛出业务异常。
- 文字类提醒异常统一使用 `ServiceException`
- 跨模块共享的数据结构放在 `product-api`,不要泄露 `product-server` 内部类型。
- `Provider``Api` 这类对外暴露接口,参数对象命名为 `XXXReq`,返回对象命名为 `XXXResp`
- 新增和编辑如果是两个接口,请求参数定义为两个对象,可以让 `UpdateXXXReq` 继承 `InsertXXXReq`
- 枚举如果没有特殊要求,默认只有一个字段 `code`,查询方法叫 `getByCode``code` 类型根据数据库字段决定,可以是 `String``Integer`
- 类上非必要注解不要写,比如 `@EqualsAndHashCode``@ToString`;可以使用 `@Data` 和 Apifox 相关注解。
- Apifox 接口上的 `example` 不要写。
- `Collectors.toMap` 时,如果 key 是 `id`value 使用 `Function.identity()`
- 如果数据库查询出来的字段是 `Boolean`,并且数据库保证不为空,直接使用 `if (shop.getIsEnable())`,不要写 `!Boolean.TRUE.equals(shop.getIsEnable())`
- 如果是api层的接口就别用swagger注解了用java自带的注解就可以了
- 判断集合是否为空用CollectionUtils,ObjectUtils.isEmpty()这种工具类,别用集合对象.isEmpty()
- java枚举如果code跟名称一样就别单独写code了
- set的时候用reqDTO.getPrepareHouseType() != null ? reqDTO.getPrepareHouseType().getCode(): null
- 如果需要用productcompareMapper.updateById更新数据库的话那么这个参数需要自己new出来别用数据库查询出来的数据
- 调用第三方接口的时候,如果异常了需要打印请求参数,跟返回值,格式类似 log.error("取消出库失败dtos={}, wms返回信息={}", JSON.toJSONString(dtos), JSON.toJSONString(stringResultVo));
- 尽量不要为了简单工具方法抽工具类对象超过3个或者复杂的工具类才需要抽出对象
- 如果是业务方法,尽量一个接口一个对象,如果有多层对象,尽量用内部类
- service方法注解一定需要的需要把方法的核心简单用简短干练的注释说明
- java中controller层或者feign层的方法名称是驼峰那么请求url也驼峰把跟方法保持一致
- 尽量不要try catch如果是需要异常以后继续运行的才进行try catch
- 如果是接口幂等的逻辑,不要返回正常结果,而是抛出业务异常
- 尽量不要抽方法行数在5行一下的方法
- 业务配置放在nacos里面取值用@Value("${alibaba1688.access_token}"), 尽量不用兜底如果没有就报错系统配置放在application里面
- bean对象的转换用mapStruct模仿MemberConfigConvert
- 如果在类里面定义常量那么常量的key跟value尽量保持一致如果是格式不一样值至少是一样的
- 如果是系统内部的类mapper跟mapper对象的dto先不分包manager层外部的也先不分包都放一个包里面。
- 生成的mapper跟表的结构保持一致比如order_item, OrderItemMapper.xml
- 生成单元测试用Spring那一套@SpringBootTest, 可以模仿ProductCompareServiceLocalSpringTest
- 发钉钉通知的话标题里面要带通知或者告警
- 允许简单 SQL 使用 MyBatis-Plus 自带查询方法,例如 `.selectOne`
## 代码结构规范
controller、service、enum、按照业务分包、manager外部调用包装暂时不分包
如果是方法的参数就放在当前包里面的vo、bo、dto包里面
## 数据库规范
- 不要使用 MyBatis-Plus 自带查询方法,例如 `.selectOne`
- 只要有查询逻辑,都写到 xxxMapper.xml 里。
- 不要使用 `@Select` 这类注解 SQL。
- SQL 统一写在 MyBatis XML 文件里。
- 查询条件直接使用 `is_deleted = 0`,不要额外写默认值兜底。
- 根据 `id` 删除时mapper 方法命名就叫 `deleteById`,不要加 `soft` 一类前缀。
- 操作数据库时,不需要手动指定更新时间,数据库有默认值。
- 数据库默认不为空的字段,从数据库拿到后不要再做兜底逻辑。
- 数据库有默认值的字段,查询出来后不要再判断 `null`,除非是审批时间这类本身允许为空的业务字段。
- 生成 DDL 时,不要追加 `DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`
- 唯一索引只有在明确需要唯一约束时才添加。
- 默认不要使用联合索引,除非需求明确说明。
- 如果是根据XXXid查询的如果是主键或者唯一索引的话返回一个对象是关联的id那么返回List别用limit1兜底
- 数据库字段命名是下划线的
- 建表的时候要贴合业务,别取短而抽象的表明,要取能说明业务的表明,见名知意比名字短更重要
- 联动信息不存快照比如更新人名称只存关联的id
## 测试规范
- 如果没有明确要求生成单元测试,就不要生成测试。
- 如果要求生成测试,只生成 Spring 风格集成测试,不生成 mock 测试。
- 测试默认按本地 Spring 集成测试格式编写:使用 `@SpringBootTest``@ActiveProfiles("local")`
- 测试类命名可参考 `*LocalSpringTest`
- 通过 `@Resource` 注入待测 Bean。
- 测试方法至少包含一个有效断言,例如 `Assertions.assertNotNull(...)`
- 严禁生成 Mockito 风格测试骨架,例如 `@Mock``@InjectMocks``Mockito.when``Mockito.verify`
## 禁止事项
- 禁止使用 `BeanUtils.copyProperties`,改为逐字段赋值,或者直接让 mapper 返回目标对象。
- 禁止无意义的 `trim/null` 兜底。
- 禁止写 `normalizeXxx``distinctNonNull``getXxxOrThrow` 这类辅助方法。
- 禁止类似 `normalizeSourceType` 这种兜底方法;接口层会通过注解限制,如果注解解决不了,就在业务方法里直接校验。
- 禁止为数据库默认值手动补空值、补更新时间、补 `is_deleted`
- 禁止一行代码也抽方法的过度封装。
- 禁止过度封装“查不到就抛错”的一层薄方法。
- 禁止无需求说明时省略默认排序。
- 禁止在 service 分页查询接口中散传基本类型参数。
- 禁止写列表转分页时的 `instanceof Page<?>` 兼容分支。
- 禁止使用 `@Select` 注解写 SQL。
- 禁止在业务代码里重复写接口参数判空兜底。
- 禁止为了一个方法去创建对象承载多个参数;如果某个地方需要返回多个参数,直接在核心业务逻辑里处理即可。
- 禁止 java8 使用 orElse
- 禁止直接用从数据库查询出来的对象去更新数据类似productcompareMapper.updateById(existed);
- 禁止使用trim()这个方法做一些字符串的兜底