基于《阿里巴巴 Java 开发手册》扩展的cursor编程约束
【强制】禁止魔法值直接出现在代码中。【强制】longLong赋值数字后加大写L,禁止小写l(易与 1 混淆)。【推荐】常量按功能归类,避免一个常量类容纳一切。【推荐】常量复用层次:跨应用 → 二方库constant;应用内 → 一方模块constant;子工程、包内、类内各层明确,避免两处定义同义不同值。【推荐】固定范围内取值用enum。【推荐】(tc-fms)枚举优先于零散静态常量:有限、封闭取
cursor中使用效果:
阿牛规范(Java 后端)
规则文件:.cursor/rules/drin.rule.mdc(别名 drin.rule)。本规范以《阿里巴巴 Java 开发手册》v1.4.0 为基底并叠加 tc-fms 项目条款;原手册 PDF 可参考 docs/阿里巴巴Java开发...1528268103.pdf。
对 AI 的约束(代码生成须遵守)
- 在本项目中编写、修改或生成任何 Java 代码,以及与之配套的 SQL、MyBatis XML、日志与异常处理时,必须遵守本文件中的规约。
- 全文应用:当用户或任务明确要求遵循 阿牛规范 / drin.rule 时,须将本文件全部章节(含【强制】/【推荐】/【参考】及「附:与 tc-fms 项目对齐」)一并执行,不得只摘取部分条文。
- 优先级:
AGENTS.md/framework.mdc中的 tc-fms 专规(分层、模块、Java 8、BeanUtils 等)优先;本规约作为阿牛规范通用补充;二者冲突时以项目专规为准。 - 执行尺度:【强制】级别必须满足;【推荐】级别在无充分理由时不应忽略;【参考】级别按场景采纳。
条文分级:规约分 【强制】/【推荐】/【参考】 三级。
与本项目关系:tc-fms 的分层、模块依赖、Java 8 语法、BeanUtils、ResponseDTO 等以 AGENTS.md / framework.mdc 为准;本文件用于对齐工程与编码习惯并收录 tc-fms 专项补充。
一、编程规约
(一)命名风格
- 【强制】 命名不得以下划线或美元符号开始或结束(反例:
_name、$name、name_)。 - 【强制】 禁止拼音英文混用、禁止中文命名;国际通用词(如 alibaba、taobao)可视同英文。
- 【强制】 类名
UpperCamelCase;例外后缀:DO/BO/DTO/VO/AO/PO/UID等(正例:UserDO、XmlService)。 - 【强制】 方法名、参数名、成员变量、局部变量一律
lowerCamelCase。 - 【强制】 常量全大写,单词间下划线,语义完整(正例:
MAX_STOCK_COUNT;反例:MAX_COUNT)。 - 【强制】 抽象类以
Abstract或Base开头;异常类以Exception结尾;测试类以被测类名开头、Test结尾。 - 【强制】 数组:
int[] arrayDemo,禁止String args[]。 - 【强制】 POJO 中布尔类型不要加
is前缀(避免序列化/RPC 解析异常);基本类型Boolean isDeleted与isDeleted()组合尤其要避免。 - 【强制】 包名全小写,点分隔符间仅一个英文单词;包名单数;类名可有复数含义。
- 【强制】 禁止不规范缩写(反例:
AbsClass、condi)。 - 【推荐】 命名用完整单词组合;自定义元素能自解释。
- 【推荐】 使用设计模式时,类名体现模式(正例:
OrderFactory、LoginProxy)。 - 【推荐】 接口方法、属性不加多余修饰符(含 public);接口内变量若必须,应为与接口方法相关的基础常量。
- 【强制】
Service/DAO:对外暴露接口,实现类后缀Impl(正例:CacheServiceImpl实现CacheService)。 - 【推荐】 表能力接口可用形容词形式(如
-able),AbstractTranslator实现Translatable。 - 【参考】 枚举类名建议
XxxEnum,成员全大写下划线。 - 【参考】各层方法命名
- 单个对象:
get前缀;多个:list前缀且表复数,如listObjects;统计:count;插入:save/insert;删除:remove/delete;修改:update。 - 领域模型:
xxxDO(表)、xxxDTO、xxxVO;统称 POJO,禁止命名为xxxPOJO。
- 单个对象:
- 【推荐】(tc-fms)
Map变量命名:建议采用{键语义}K{值语义}Pair形式(中间的K为固定分隔,读作「键到值」,不是泛型尖括号),整体以Pair结尾,一眼可辨「键—值」映射,避免与List、单个实体变量混淆。正例:Map<Long, User> userIdEntityPair(键为用户 ID,值为用户实体);Map<String, Integer> codeCountPair。键或值语义较长时可适度缩写,须保持 lowerCamelCase 可读;避免主名使用无含义的map、data、temp等。若存量代码已采用团队共识且表意清晰的xxxByYyy、xxxToYyy等命名,可延续,新增代码优先本约定。
(二)常量定义
- 【强制】 禁止魔法值直接出现在代码中。
- 【强制】
long/Long赋值数字后加大写L,禁止小写l(易与 1 混淆)。 - 【推荐】 常量按功能归类,避免一个常量类容纳一切。
- 【推荐】 常量复用层次:跨应用 → 二方库
constant;应用内 → 一方模块constant;子工程、包内、类内各层明确,避免两处定义同义不同值。 - 【推荐】 固定范围内取值用
enum。 - 【推荐】(tc-fms)枚举优先于零散静态常量:有限、封闭取值优先用
enum表达,扩展性、可读性、与 switch/映射配合通常优于分散的public static final;优先复用系统或模块内已有枚举,禁止重复新建同义枚举造成多处维护。
(三)代码格式
- 【强制】 空块写
{};非空块:左大括号前不换行、后换行;右大括号前换行;与else连写时右大括号后不换行;终止的右大括号后换行。 - 【强制】 小括号与字符间无空格;左大括号前须空格;
if/for/while/switch/do与括号间须空格。 - 【强制】 二目、三目运算符左右各一空格。
- 【强制】 4 空格缩进,禁止 Tab(若用 Tab 须设为 4 空格且勿勾选“使用 Tab 字符”类选项)。
- 【强制】 注释
//后空一格再写内容。 - 【强制】 单行不超过 120 字符;换行时次行相对首行缩进 4 空格,第三行起不再额外缩进;运算符、方法调用的点与下文一起换行;多参数在逗号后换行;勿在括号前换行。
- 【强制】 方法参数定义与调用:逗号后必须空格。
- 【强制】 文件编码 UTF-8;换行符 Unix(LF)。
- 【推荐】 单方法总行数(含签名、注释、空行)不超过 80;共性逻辑抽取方法。
- 【推荐】 勿用空格对齐多行赋值;不同逻辑间一空行分隔。
- 【推荐】(tc-fms)静态导入:对纯工具类的静态方法(如
com.tc.fms.common.utils.collection.CollectionUtils、org.springframework.util.StringUtils、org.apache.commons.lang3.StringUtils等),优先使用import static 包.类.方法名或import static 包.类.*,在代码中省略类名前缀以缩短调用;若与当前类/父类方法或其它静态导入同名冲突,或静态导入过多导致来源不清,则保留类名.限定。
(四)OOP 规约
-
【强制】 静态成员用类名访问,勿用实例引用。
-
【强制】 覆写方法必须
@Override。 -
【强制】 可变参数:相同类型、相同业务含义才可用;参数放最后;尽量不用可变参数。
-
【强制】 外部已调用的接口不得改方法签名;过时须
@Deprecated并说明替代接口/服务。 -
【推荐】(tc-fms)废弃公共 API:对仍有调用方的公共类/方法/接口,勿直接删除;须先标注
@Deprecated,在 Javadoc 中写明替代方式与预计移除时间,经若干版本观察后再删除,避免破坏依赖方构建。 -
【强制】 禁止使用过时的类/方法;调用方有义务确认新实现。
-
【强制】
equals:用常量或确定非空对象调用,或Objects.equals(JDK7+)。 -
【强制】 包装类型比较一律
equals(注意Integer缓存区间与堆对象区别)。 -
【强制】 POJO 属性用包装类型;RPC 入参/返回值用包装类型;局部变量推荐基本类型。
-
【强制】 DO/DTO/VO 等 POJO 不要设属性默认值。
-
【强制】 序列化类增属性慎改
serialVersionUID;不兼容升级再改并知会。 -
【强制】 构造方法内禁止业务逻辑;初始化放
init等。 -
【强制】 POJO 须
toString;继承时注意super.toString。 -
【强制】 禁止同一属性同时存在
isXxx()与getXxx()。 -
【推荐】
String.split后数组访问注意尾部分隔符与IndexOutOfBoundsException。 -
【推荐】 重载构造/同名方法按序放在一起;类内方法顺序:公有/保护 → 私有 → getter/setter。
-
【推荐】 工具类须以 JDK 为主实现**:纯工具类(如
final类、私有构造、仅提供静态方法的辅助类)在编写其方法体时,须使用 JDK 标准库(java.lang、java.util、java.time、java.nio等)实现可由 JDK 直接完成的等价能力,禁止在无正当理由时为图省事而直接调用 Hutool、Apache Commons、Guava 等第三方工具库替代上述能力,以保障可移植性并控制传递依赖与版本冲突面。例外(须在类或方法 Javadoc 中说明理由):JDK 无等价 API;或经评审确认采用 JDK 手写后在正确性、性能或可维护性上明显劣于某第三方 API。与业务层专规的关系:本条仅约束工具类自身源码;业务代码(Domain、API 等)仍遵循「集合处理」等对项目CollectionUtils、Hutool 等的约定,二者分层适用、不互相替代。 -
【推荐】(tc-fms)抽取方法时的入参:将重复逻辑拆成私有方法或包内辅助方法时,优先传入聚合对象(如入参
XxxDTO、领域实体、或专责承载多字段的「命令/参数」小对象),在方法体内再访问属性;避免把同一来源对象的多个obj.getFoo()、obj.getBar()拆成一长串基本类型或零散形参。尽量减少参数个数,避免同源、同批次的 5 个以上字段平铺成参表;若字段本就属于同一 DTO/实体,直接传该对象即可。例外:跨层纯工具、与类型解耦的算法、或确无合适载体时,可保留少量标量;若新增字段,优先扩展被传对象而非加长参数列表。 -
【推荐】(tc-fms)对外方法形参个数:一般以不超过 3 个为宜;若继续增长,宜封装为 Query/Command/Context 等聚合对象,与上条「优先传聚合对象」一致,避免「参数表」过长难以阅读与演进。
-
【推荐】(tc-fms)可复用的公共能力:对同一语义、多种入参组合的场景,优先通过方法重载、接口抽象或统一参数对象(如配置类、选项类)表达,避免大量仅参数不同的平行方法名。
-
【推荐】(tc-fms)对象装配与转换:在符合分层与
BeanUtils专规的前提下,链式get/set过长时,优先使用构造方法、静态工厂或 Builder,缩短主流程中的样板代码;禁止在 Controller 等上层堆叠大量手写映射。 -
【推荐】 循环内字符串拼接用
StringBuilder#append。 -
【推荐】
final:不可继承类、不可变引用、不可重写方法、POJO setter 可 final、循环内复用变量等场景。 -
【推荐】 慎用
Object#clone(默认浅拷贝)。 -
【推荐】 访问控制从严:工具类无 public 构造、成员尽量 private、按需 protected。
-
【强制】(tc-fms)泛型(Java 8):禁止无正当理由使用原始类型(raw type),变量、参数、返回值、字段及面向对象协作处须写出完整、必要的泛型实参或通配符(如
List<String>、List<?>),不得写成裸List;在赋值右侧、new构造、方法调用链中凡编译器已能推断类型参数时,须使用 diamond<>(如List<String> list = new ArrayList<>();、Map<String, Object> m = new HashMap<>();),避免在<>内重复书写可由左侧或上下文推断的冗余类型实参。与 JDK/第三方遗留 API 交互且无法改写签名时,原始类型仅在局部、加注释前提下可例外。
(五)集合处理
- 【强制】 重写
equals必须重写hashCode;Set元素、Map的 key 为自定义对象时须正确实现二者。 - 【强制】
ArrayList#subList结果不可强转为ArrayList;勿在 subList 场景下对原集合结构增删导致子列表遍历异常。 - 【强制】
Collection#toArray(T[])传入类型一致、大小为list.size();避免无参toArray()再强转。 - 【强制】
Arrays.asList转出的列表不可add/remove/clear;注意底层仍是数组,改数组会影响视图。 - 【强制】 泛型
<? extends T>不可随意add;<? super T>使用注意 PECS(Producer Extends Consumer Super)。 - 【强制】
foreach中不要remove/add;用Iterator.remove,并发时对迭代器加锁。 - 【强制】
Comparator须满足自反、传递、与相等一致,否则Arrays.sort/Collections.sort可能IllegalArgumentException。 - 【推荐】 JDK7+ 使用 diamond;集合初始化指定容量(如
HashMap按元素数/负载因子估算)。 - 【推荐】
Map遍历用entrySet,少用keySet二次查找;JDK8 可用Map.forEach。 - 【推荐】 注意各
Map实现是否允许null键值(如ConcurrentHashMap不可 null)。 - 【参考】 利用
Set去重,避免List+contains暴力去重。 - 【强制】(tc-fms)业务代码(Domain、API、ORM Service 实现等)禁止对
Collection/List/Set等直接编写stream()、parallelStream()及流式链(如map/filter/collect/groupingBy)完成映射、过滤、分组、去重等;须优先在com.tc.fms.common.utils.collection.CollectionUtils中选用已有方法(如convertList、convertMap、filterList、convertMultiMap等)。若无合适方法,应在该工具类中新增静态方法统一封装,实现可采用Stream或普通循环,但入口必须集中;新方法须对 集合为 null、空集合、元素为 null 等边界与空指针风险做一致约定与防护(与现有工具方法风格对齐),避免在业务类中散落 NPE 隐患。 - 【推荐】(tc-fms)将 MyBatis-Plus
IPage<实体>转为IPage<VO/DTO>时,统一使用com.tc.fms.common.utils.collection.CollectionUtils#convertPage,在转换函数中完成单条Entity → VO映射;由工具方法统一拷贝current、size、total、pages与records,避免手写new Page或仅convert导致分页元数据遗漏、空页total丢失或与源页不一致。 - 【推荐】(tc-fms)将
Map<K, V>的 value 统一映射为另一类型得到Map<K, R>(key 不变)时,优先使用CollectionUtils#convertMapValue;若value为List且需对列表元素批量转换,可查convertMapValues等同类方法,避免在业务类中手写循环逐个put。须注意:convertMapValue在单次映射结果为null时会跳过该键;若业务必须保留「值为 null」的条目,应显式处理或扩展工具方法。 - 【推荐】(tc-fms)集合是否为空/非空、字符串是否为空/空白以及列表构造、合并、切片等常用操作,优先使用 Hutool:
cn.hutool.core.collection.CollUtil(及按需ListUtil、SetUtil等)与cn.hutool.core.util.StrUtil,统一空安全与习惯用法,避免散落手写== null、裸length() == 0、重复trim()等易错写法。若语义已由本项目CollectionUtils或专规要求的封装覆盖,优先项目工具,避免同一业务混用多种风格。 - 【推荐】(tc-fms)单次遍历合并逻辑:对同一集合,优先在一次循环内完成多项相关处理(如过滤 + 分组键计算 + 累计),避免为图省事对同一集合多次遍历;若为此需少用一层「仅做单一映射」的集合工具链、改为显式
for以合并逻辑,可接受,以可读性与性能综合权衡为准;仍须遵守业务代码不直接使用stream()链的专规,复杂转换入口集中到CollectionUtils等(见「集合处理」【强制】tc-fms 条)。
(六)并发处理
- 【强制】 单例及其中方法须线程安全。
- 【强制】 线程、线程池命名有意义。
- 【强制】 线程资源通过线程池提供,禁止随意
new Thread。 - 【强制】 线程池使用
ThreadPoolExecutor显式构造,禁止Executors默认工厂(队列/线程数无界导致 OOM 风险)。 - 【强制】
SimpleDateFormat线程不安全;勿随意 static,若 static 须加锁或ThreadLocal;JDK8 可用LocalDateTime、DateTimeFormatter。 - 【强制】 同步调用评估锁开销:能无锁则无锁;能锁块不锁方法;能对象锁不类锁;锁内不调 RPC。
- 【强制】 多资源加锁顺序一致,避免死锁。
- 【强制】 并发更新同一条记录须防丢失更新(应用锁/缓存锁/DB 乐观锁 version 等)。
- 【强制】
Timer多任务时一处未捕获异常会导致其它任务停,宜用ScheduledExecutorService。 - 【推荐】
CountDownLatch异步转同步时,子线程finally或确保countDown,并 catch 异常。 - 【推荐】 避免多线程共享
Random实例竞争 seed;JDK7+ 可用ThreadLocalRandom。 - 【推荐】 双重检查锁单例须将目标字段声明为
volatile(JDK5+)。 - 【参考】 多写场景
volatile不够;count++用AtomicInteger;JDK8 可用LongAdder。 - 【参考】
HashMap并发 resize 风险;高并发考虑替代结构或同步。 - 【参考】
ThreadLocal无法解决共享对象更新问题;实例建议static。
(七)控制语句
- 【强制】
switch:每case须break/return或注释说明继续执行;必须default(可空)放最后。 - 【强制】
if/else/for/while/do必须使用大括号,禁止单行省略。 - 【强制】 高并发场景避免用「等于某值」作为唯一中断条件,防止击穿,宜用区间判断。
- 【推荐】 异常分支少用冗长
if-else,可用早返回;若必须if-else if-else,勿超过 3 层;可用卫语句、策略模式、状态模式。 - 【推荐】 避免
if/else分支体量严重失衡(一侧大段逻辑、另一侧仅少量语句,俗称「胖分支 / 瘦分支」),以免阅读时重心偏移、后续改动易漏改薄分支。优化思路:卫语句与提前返回把简单条件或异常路径放在前;提前初始化默认值或中性状态,主流程只写与条件相关的增量逻辑;必要时将大块分支提取为私有方法,使if/else两侧在抽象层次上大致对称。 - 【推荐】 条件判断中除简单
get/is外,复杂逻辑先赋给有意义的boolean变量再判断。 - 【推荐】 循环内避免重复创建对象、重复获取连接、不必要 try-catch。
- 【推荐】 少用取反运算符,优先正向比较。
- 【推荐】 批量接口做入参保护(数量上限等)。
- 【参考】 参数校验:低频、高耗时、高稳定、对外接口、敏感入口须校验;极高频内层、已保证入参的 private 可省略并文档说明。
- 【推荐】(tc-fms)卫语句与提前返回:多用卫语句、提前返回、小范围前置条件检查(「钩子」),避免单个
if或try包裹大段主干代码导致缩进过深、难测难改。 - 【推荐】(tc-fms)条件判断顺序:先做本地可完成的校验(非空、格式、正则、日期合法性等),再访问数据库、缓存、远程接口,避免廉价校验失败仍白耗一次 I/O。
- 【推荐】(tc-fms)同线程内结果复用:在同一请求/线程内,对查询结果、分支选择结果、昂贵计算结果,宜赋给局部变量或轻量上下文复用,避免重复查询与重复计算。
- 【推荐】(tc-fms)代码局部性:变量声明与首次使用尽量邻近;避免先声明再穿插大量无关逻辑后再使用;避免数据已查询却长期不使用、隔很远才使用,增加阅读负担与出错面。
- 【推荐】(tc-fms)Web 请求内数据传递:在单次 HTTP 请求链路内传递请求级辅助数据,优先使用
HttpServletRequest#setAttribute(及等价请求作用域机制),慎用线程局部变量替代可放入请求作用域的数据,降低错配与泄漏风险。
(八)注释规约
- 【强制】 类、类属性、类方法的注释用 Javadoc
/** */,不用//代替类/方法说明。 - 【强制】 抽象方法(含接口方法)须有 Javadoc:功能、参数、返回值、异常、调用注意。
- 【强制】 类须有创建者与创建日期(团队统一格式即可)。
- 【强制】 方法内单行注释写在被注释语句上方;多行用
/* */并对齐。 - 【强制】 枚举项每项有注释。
- 【推荐】 能用中文说清的用中文;专有名词保留英文。
- 【推荐】 改代码同步改注释(参数、返回值、异常、核心逻辑)。
- 【参考】 谨慎注释掉代码:说明原因或删除;
TODO/FIXME标注人、时间、预计处理时间,定期清理。
(九)其它
- 【强制】 正则使用预编译:
Pattern定义为static final,勿在方法内反复compile。 - 【强制】 Velocity 访问 POJO 属性名规范;
boolean与Boolean包装调用注意。 - 【强制】 后台输出到页面的变量使用
$!{var}形式,避免 null 原样输出。 - 【强制】
Math.random()为double且含 0、不含 1;注意除零;整数随机用Random#nextInt等。 - 【强制】 当前毫秒用
System.currentTimeMillis();纳秒统计用System.nanoTime();JDK8 统计场景可用Instant。 - 【推荐】 视图模板不写复杂逻辑。
- 【推荐】 数据结构构造指定大小,避免无限增长。
- 【推荐】 及时清理无用代码与配置;临时注释用团队约定(如
///)说明理由。 - 【推荐】(tc-fms)死代码与噪声:经确认不再引用的类、方法、代码块及无保留价值的注释应及时删除,避免干扰阅读与检索。
(十)循环与性能(tc-fms)
- 【强制】(tc-fms)循环体内禁止高开销 I/O:
for/while/do-while/foreach的循环体中禁止执行数据库查询、远程 RPC/HTTP 及其他高开销 I/O;应在循环外批量查询、建映射或聚合,循环内仅做内存侧处理与组装。 - 【推荐】(tc-fms)尽早结束循环:在已命中目标或满足提前结束条件时,使用
break、continue,或带标签跳出嵌套循环,避免无意义遍历剩余元素。 - 【强制】(tc-fms)递归须可终止:递归须有明确的基准情形与规模递减(或等价保证),所有分支须通向出口(
return或改为迭代),禁止遗漏终止路径导致栈溢出或进程不可用。 - 【推荐】(tc-fms)缺省与空容器:优先返回
Collections.emptyList()、new ArrayList<>()、new HashMap<>()等空容器代替裸露的null;Map等使用getOrDefault等,减少 NPE 与冗长判空(与对外契约中「是否允许 null」保持一致)。 - 【推荐】(tc-fms)编译警告:重视编译器与静态检查警告,目标为零警告(或团队白名单);新增代码不得滥用
@SuppressWarnings掩盖应修复的问题。
二、异常日志
(一)异常处理
- 【强制】 可通过预检查避免的
RuntimeException(如 NPE、越界)不要用catch处理;无法预检的例外(如NumberFormatException)才可 catch。 - 【强制】 异常不作流程控制、条件分支。
- 【强制】 区分稳定代码与非稳定代码;catch 粒度适当,勿一大段 try-catch。
- 【强制】 catch 后要处理或向上抛;最外层业务须转化为用户可理解信息。
- 【强制】 事务中 catch 若需回滚须手动回滚。
- 【强制】
finally关闭资源;JDK7+ 用 try-with-resources。 - 【强制】
finally中禁止return。 - 【强制】 捕获类型与抛出类型匹配或为父类。
- 【推荐】 可返回
null时须注释说明场景;调用方防 NPE(返回类型、DB、集合元素、RPC、Session、级联调用等);可用Optional(JDK8)。 - 【推荐】 区分 checked/unchecked;抛有业务含义的自定义异常,避免裸
RuntimeException、一般避免直接抛Exception/Throwable。 - 【参考】 对外 HTTP/API 用错误码;内部可抛异常;跨应用 RPC 可用 Result(
isSuccess、错误码、简短信息)。 - 【参考】 DRY:多处相同校验抽取私有方法。
- 【推荐】(tc-fms)异常与对外文案:异常信息、错误码说明、接口返回中的用户可见/运维可读描述须简明、准确、专业,避免口语化、戏谑或歧义表述,确保可定位问题且不误导调用方。
(二)日志规约
- 【强制】 使用 SLF4J API,不直接依赖 Log4j/Logback 实现类。
- 【强制】 日志文件至少保留 15 天。
- 【强制】 扩展日志命名:
appName_logType_logName.log。 - 【强制】
trace/debug/info须条件输出或占位符,避免无谓拼接与toString。 - 【强制】 避免重复打印;log4j 等配置对重复 logger 设
additivity=false。 - 【强制】 异常日志包含现场信息与堆栈:
logger.error("context {}", obj, e)。 - 【推荐】 生产慎打 debug;info 有选择;warn 观察日志注意磁盘。
- 【推荐】 用户参数错误可用 warn,非必要不打 error 刷屏。
- 【推荐】 日志描述优先英文;说不清可用中文;国际化/海外部署考虑全英文。
三、单元测试
- 【强制】 AIR:Automatic、Independent、Repeatable。
- 【强制】 全自动、非交互;用 assert,禁止
System.out人肉验。 - 【强制】 用例互不依赖、无顺序依赖。
- 【强制】 可重复执行,不依赖外部环境(网络等);依赖通过注入替换为 Mock/内存实现。
- 【强制】 粒度小到方法级为主;核心业务增量代码保证单测通过。
- 【强制】 测试代码仅在
src/test/java。 - 【推荐】 语句覆盖率目标约 70%;核心模块语句与分支覆盖率更高。
- 【推荐】 BCDE:边界、正确输入、结合设计、错误输入。
- 【推荐】 DB 相关不假设数据已存在;用程序准备数据;可自动回滚或测试数据前缀。
- 【推荐】 不可测代码先重构;提测前完成单测,而非上线后补。
- 【参考】 避免构造过重、过多全局静态、过多外部依赖、过多条件(需策略/状态等重构)。
四、安全规约
- 【强制】 个人页面与功能须权限校验(含水平越权)。
- 【强制】 敏感数据展示须脱敏。
- 【强制】 SQL 参数绑定或元数据限定,禁止拼接 SQL。
- 【强制】 所有入参有效性校验(page size、order by、重定向、注入、反序列化、ReDoS 等)。
- 【强制】 禁止向页面输出未过滤/未转义的用户数据。
- 【强制】 表单与 AJAX 提交 CSRF 校验。
- 【强制】 短信、邮件、下单、支付等平台资源须防重放(次数、频率、验证码等)。
- 【推荐】 UGC 场景防刷、违禁词等风控。
五、MySQL 数据库
(一)建表规约
- 【强制】 是/否概念:
is_xxx,类型unsigned tinyint(1/0);非负字段 unsigned。 - 【强制】 POJO 布尔不加
is前缀时,与is_xxx字段在 ORM 中映射。 - 【强制】 表名、字段名小写字母或数字;禁止数字开头;禁止两下划线间仅数字。
- 【强制】 表名不用复数名词。
- 【强制】 禁用保留字(
desc、range、match等)。 - 【强制】 主键索引
pk_字段名;唯一uk_字段名;普通idx_字段名。 - 【强制】 小数用
decimal,不用float/double。 - 【强制】 定长用
char;varchar长度合理,超长文本用text并独立表关联。 - 【强制】 表必备:
id、gmt_create、gmt_modified(类型与自增策略按实际规范;本项目若用create_time/update_time则遵循项目表结构)。 - 【推荐】 表名体现业务与作用;库名与应用名一致;改字段含义须更新注释;可冗余字段须考虑一致性与变更频率。
- 【推荐】 单表行数/容量达一定规模再考虑分库分表,忌过早拆分。
- 【参考】 按业务选合适长度与无符号类型。
(二)索引规约
- 【强制】 业务唯一字段(含组合)建唯一索引。
- 【强制】(tc-fms)登录名/账号类字段:须在数据库层保证业务唯一(唯一索引或等价约束);若用户表采用逻辑删除,须对账号字段做置空、加前后缀打乱等处理,避免与唯一约束冲突及被重复占用。
- 【强制】 超过三个表禁止 join;join 字段类型一致且被关联字段有索引。
- 【强制】
varchar索引须指定索引长度(按区分度)。 - 【强制】 搜索禁止左模糊/全模糊依赖普通索引,应搜索引擎等方案。
- 【推荐】
order by与组合索引顺序配合,减少 file sort。 - 【推荐】 覆盖索引减少回表;深分页用延迟关联或子查询优化。
- 【推荐】
explain目标至少 range,追求 ref/const;组合索引高区分度在左;注意隐式类型转换导致索引失效。 - 【参考】 避免索引滥用或过度抵制唯一索引。
(三)SQL 语句
- 【强制】 统计行数用
count(*),不用count(列名)或count(常量)替代标准语义(注意与 NULL 行为差异)。 - 【强制】 理解
count(distinct col)与多列时 NULL 行为。 - 【强制】 全 NULL 列时
sum为 NULL,注意 NPE,可用IF(ISNULL(SUM(g)),0,SUM(g))等。 - 【强制】 NULL 比较用
ISNULL()等,勿直接= NULL。 - 【强制】 分页若
count为 0 直接返回,不再执行后续分页 SQL。 - 【强制】 不使用外键与级联,应用层解决一致性。
- 【强制】 禁止使用存储过程。
- 【强制】 数据订正前先
select确认。 - 【推荐】
in控制集合大小(如千级内评估)。 - 【强制】(tc-fms)动态
IN与空集合:拼接IN (...)时必须判断入参集合非空;空集合时不得生成IN ()非法 SQL,应改写查询分支(如永假条件、跳过该条件、或短路不查),语义须与业务一致。 - 【推荐】(tc-fms)大字段与富文本:列表、检索、导出等场景尽量避免
SELECT大文本(TEXT/LONGTEXT、富文本、大 JSON 等);仅在详情、编辑、下载等必要场景按需加载,减轻数据库与网络传输压力。 - 【参考】 字符集 utf-8/utf8mb4;
LENGTHvsCHARACTER_LENGTH;慎用TRUNCATE。
(四)ORM 映射
- 【强制】 查询不用
SELECT *,列名写清。 - 【推荐】(tc-fms)按需列:除禁止
SELECT *外,仅查询当前用例所需列;DTO/VO 映射与ResultMap亦避免无谓映射大字段(与「大字段」条款配合)。 - 【强制】 POJO 布尔与
is_xxx字段在resultMap/注解中映射。 - 【强制】 返回类型用明确类,不用模糊
resultClass凑合;表与 DO 一一对应。 - 【强制】 MyBatis 参数用
#{},禁止${}拼接(防注入)。 - 【强制】 禁止大分页式「全量查出再 subList」的 API 用法。
- 【强制】 禁止
HashMap/Hashtable作为查询结果类型滥用。 - 【强制】 更新记录须同步更新修改时间字段(与项目字段名一致)。
- 【推荐】 避免大而全 update,只更新变更字段。
- 【强制】(tc-fms)批量与
foreach长度:使用 MyBatis 批量插入/更新/foreach拼接IN等时,须根据驱动与包大小限制评估入参集合长度;过大时分批执行(如按团队约定的每批条数拆分),避免单条 SQL 过长、参数包过大或超出数据库限制。 - 【参考】
@Transactional慎用,考虑缓存/消息等一致性与回滚。
六、工程结构
(一)应用分层
- 【推荐】 开放接口层、终端显示层、Web 层、Service 层、Manager 层、DAO 层、外部系统依赖关系清晰,上层可依赖下层,忌循环依赖。
- 【参考】 分层异常:DAO 可包装
DAOException;Service 记磁盘日志带参数;Web 顶层勿继续抛未处理异常到用户;开放接口转错误码。 - 【参考】 领域模型:
DO、DTO、BO、AO、VO、Query;超过 2 个参数封装查询对象,禁止 Map 传递。
(二)二方库依赖
- 【强制】 GAV:
GroupId如com.{公司/BU}.业务线;ArtifactId产品线-模块名;版本语义化。 - 【强制】 版本号:主.次.修订;起始
1.0.0;正式版不覆盖升级。 - 【强制】 线上不依赖
SNAPSHOT(安全包等例外说明)。 - 【强制】 二方库升级若传递依赖变化须评估,可用
dependency:tree比对。 - 【强制】 二方库接口返回值不用枚举或含枚举的 POJO(客户端兼容)。
- 【强制】 同批依赖统一版本变量,禁止同
GroupId+ArtifactId不同Version出现在子模块。 - 【推荐】 依赖声明与版本管理分块;二方库少配置项。
(三)服务器(参考)
- 【推荐】 高并发下调小
time_wait;调大 fd;OOM 时-XX:+HeapDumpOnOutOfMemoryError;生产Xms=Xmx;内外部重定向方式区分。
七、设计规约
- 【强制】 存储方案与核心数据结构评审通过并文档化;上线后 double check;变更须评审。
- 【强制】 多类用户且用例 >5:用用例图。
- 【强制】 业务状态 >3:用状态图并标明触发条件。
- 【强制】 调用链路对象 >3:用时序图并标明输入输出。
- 【强制】 模型类 >5 且依赖复杂:用类图。
- 【强制】 多对象协作且流程复杂:用活动图。
- 【推荐】 评估异常流程与边界;单一职责;优先组合优于继承(继承须符合里氏替换);依赖倒置;对扩展开放、对修改关闭;共性抽取避免重复。
- 【推荐】 敏捷仍须在关键点有设计与文档。
- 【推荐】(tc-fms)实现功能时,不宜止步于「当前调用点能跑通」;宜审视调用方是否因重复传参、重复判空、重复拼装而臃肿。若通过对合适层次的适度扩展即可收敛多处逻辑——例如为同一语义提供重载、在通用工具类增补可复用的静态方法、在基础设施提供批量/聚合能力以替代循环单次调用——应优先采用,使调用方更短、更一致。扩展须落在职责与分层匹配的模块,避免在业务类中堆积仅服务单次场景的变通写法;新增或重载的公开方法须符合空安全、命名与模块边界,并评估对现有调用方的影响。
- 【参考】 设计为理清需求与维护服务;识别变化点并隔离;架构明确边界、模块关系、演化原则、非功能需求(安全、可用、扩展等)。
- 【推荐】(tc-fms)避免过度设计:忌「为模式而模式」、不合理的方法抽取、职责涣散的工具类、无必要的深层抽象与层层包装;在可维护性与复杂度之间取平衡,优先简单清晰、可演进的结构。
- 【参考】(tc-fms)统计与聚合位置:适度在应用层做统计、聚合、规则裁剪(易单测、易扩展、行数可控),可辅以缓存或结果表;勿一味将复杂统计塞进单条 SQL;须结合数据量与团队能力在 SQL 与代码之间取舍。
附:与 tc-fms 项目对齐(摘要)
- 分层调用链以项目
AGENTS.md为准;Entity 字段、审计列名可能与手册gmt_*示例不同,以本项目表结构与BaseEntity为准。 Map局部变量/字段命名建议{键语义}K{值语义}Pair(见「命名风格」【推荐】)。- Bean 转换使用项目
BeanUtils;API 统一ResponseDTO/PageDTO。 - 分页:
IPage<实体>转IPage<VO/DTO>使用com.tc.fms.common.utils.collection.CollectionUtils#convertPage(见上文「集合处理」【推荐】);禁止在无充分理由时手写Page拼装分页结果。 - Java 仅使用 8 语法;手册中 JDK8+ 特性按项目允许范围使用。
- 工具类静态方法优先 静态导入(见「代码格式」);泛型须写全、构造与可推断处用 diamond
<>(见「OOP 规约」tc-fms 条)。 - 集合/字符串判空与常用操作优先 Hutool
CollUtil/ListUtil/StrUtil等(见「集合处理」【推荐】),与CollectionUtils优先级关系见该条。 - 抽取私有/辅助方法时优先传 DTO/实体等聚合对象,避免把同一对象的多个
getXxx()拆成一长串参数(见「OOP 规约」【推荐】tc-fms 条)。 - 循环与批量:见「循环与性能(tc-fms)」;动态
IN、大字段、MyBatis 分批见「MySQL」「ORM 映射」中 tc-fms 条;枚举优先与废弃 API 见「常量定义」「OOP 规约」。 - Web 请求内数据优先
request作用域;卫语句、条件顺序、同线程复用、代码局部性见「控制语句」tc-fms 条。
执行优先级:【强制】>【推荐】>【参考】;评审与 CI 以团队约定为准。用户指定 阿牛规范 / drin.rule 时,视为要求完整执行本规则文件。
更多推荐



所有评论(0)