Files
huachuang/.claude/skills/nl-java-style/references/rules.md

7.4 KiB
Raw Permalink Blame History

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 内部类型。
  • ProviderApi 这类对外暴露接口,参数对象命名为 XXXReq,返回对象命名为 XXXResp
  • 新增和编辑如果是两个接口,请求参数定义为两个对象,可以让 UpdateXXXReq 继承 InsertXXXReq
  • 枚举如果没有特殊要求,默认只有一个字段 code,查询方法叫 getByCodecode 类型根据数据库字段决定,可以是 StringInteger
  • 类上非必要注解不要写,比如 @EqualsAndHashCode@ToString;可以使用 @Data 和 Apifox 相关注解。
  • Apifox 接口上的 example 不要写。
  • Collectors.toMap 时,如果 key 是 idvalue 使用 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@InjectMocksMockito.whenMockito.verify

禁止事项

  • 禁止使用 BeanUtils.copyProperties,改为逐字段赋值,或者直接让 mapper 返回目标对象。
  • 禁止无意义的 trim/null 兜底。
  • 禁止写 normalizeXxxdistinctNonNullgetXxxOrThrow 这类辅助方法。
  • 禁止类似 normalizeSourceType 这种兜底方法;接口层会通过注解限制,如果注解解决不了,就在业务方法里直接校验。
  • 禁止为数据库默认值手动补空值、补更新时间、补 is_deleted
  • 禁止一行代码也抽方法的过度封装。
  • 禁止过度封装“查不到就抛错”的一层薄方法。
  • 禁止无需求说明时省略默认排序。
  • 禁止在 service 分页查询接口中散传基本类型参数。
  • 禁止写列表转分页时的 instanceof Page<?> 兼容分支。
  • 禁止使用 @Select 注解写 SQL。
  • 禁止在业务代码里重复写接口参数判空兜底。
  • 禁止为了一个方法去创建对象承载多个参数;如果某个地方需要返回多个参数,直接在核心业务逻辑里处理即可。
  • 禁止 java8 使用 orElse
  • 禁止直接用从数据库查询出来的对象去更新数据类似productcompareMapper.updateById(existed);
  • 禁止使用trim()这个方法做一些字符串的兜底