###《》 | 类别 | 编号 | 规则内容 | 备注 | | ----- | --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | | OOP规约 | 1 | 避免通过对象引用访问静态变量或方法,应直接使用类名 | | | | 2 | 所有覆写方法必须加@Override注解 | instinctive | | | 3 | 可变参数应为相同参数类型、相同业务含义,避免使用Object | | | | 4 | 不允许修改正在使用的接口方法签名,过时接口必须加@Deprecated注解 | | | | 5 | 不能使用过时的类或方法 | | | | 6 | 使用常量或确定有值的对象来调用equals方法 | | | | 7 | 所有整型包装类对象之间值的比较,使用equals方法 | | | | 8 | 货币金额以最小单位的整型进行存储 | | | | 9 | 浮点数之间的等值判断,不能使用==或equals | | | | 10 | BigDecimal的等值比较应使用compareTo()方法 | instinctive | | | 11 | DO类的属性类型要与数据库字段类型匹配 | | | | 12 | 禁止使用BigDecimal(double)构造方法 | | | | 13 | POJO类属性必须使用包装数据类型;RPC方法的返回值和参数必须使用包装数据类型 | | | | 14 | 定义POJO类时,不要设定任何属性默认值 | 与 item61 思想不同 | | | 15 | 序列化类新增属性时,不要修改serialVersionUID字段 | | | | 16 | 构造方法中禁止加入业务逻辑 | WrapperInfo 那个需求我不是坑人么 | | | 17 | POJO类必须写toString方法 | lombok 省事 | | | 18 | POJO类中,禁止同时存在isXxx()和getXxx()方法 | | | | | | | | 代码格式 | 1 | 大括号使用约定:空代码块写成{};非空代码块左大括号不换行,右大括号前换行 | | | | 2 | 小括号和相邻字符间不需要空格;左大括号前需要空格 | | | | 3 | if/for/while/switch/do等保留字与括号之间必须加空格 | | | | 4 | 任何二目、三目运算符的左右两边都需要加空格 | instinctive | | | 5 | 采用4个空格缩进,禁止使用Tab字符 | instinctive | | | 6 | 注释的双斜线与注释内容之间有且仅有一个空格 | instinctive | | | 7 | 类型强制转换时,右括号与强制转换值之间不需要空格 | | | | 8 | 单行字符数限制不超过120个,超出需要换行 | instinctive | | | 9 | 方法参数在定义和传入时,多个参数逗号后面必须加空格 | instinctive | | | 10 | IDE的text file encoding设置为UTF-8;文件换行符使用Unix格式 | | | | | | | | 常量定义 | 1 | 不允许任何魔法值直接出现在代码中 | instinctive | | | 2 | long或Long赋值时,数值后使用大写L,不能是小写l | | | | 3 | 浮点数类型的数值后缀统一为大写的D或F | | | | | | | | 日期时间 | 1 | 日期格式化时,传入pattern中表示年份统一使用小写的y | | | | 2 | 在日期格式中分清楚大写的M和小写的m,大写的H和小写的h | | | | 3 | 获取当前毫秒数使用System.currentTimeMillis(),而不是new Date().getTime() | | | | 4 | 不允许使用java.sql.Date、java.sql.Time、java.sql.Timestamp | | | | 5 | 禁止在程序中写死一年为365天 | instinctive | | | | | | | 集合处理 | 1 | 覆写equals必须覆写hashCode,Set的对象必须覆写这两个方法,Map的键必须覆写这两个方法 | | | | 2 | 判断集合是否为空使用isEmpty(),而不是size() == 0 | instinctive | | | 3 | 使用Collectors.toMap()时,处理重复key需使用含mergeFunction参数的方法 | | | | 4 | 使用Collectors.toMap()时,注意value为null会抛NPE | | | | 5 | ArrayList的subList结果不可强转成ArrayList | | | | 6 | Map的keySet()/values()/entrySet()返回集合不可进行添加元素操作 | | | | 7 | Collections类返回的对象,如emptyList()等是不可变的,不能进行添加或删除元素的操作 | | | | 8 | 在subList场景中,注意对原集合元素的增删操作会导致子列表操作出现异常 | | | | 9 | 使用集合转数组的方法,必须使用toArray(T[]array),传入类型一致、长度为0的空数组 | | | | 10 | 使用Collection的addAll()方法时,要对输入的集合参数进行NPE判断 | | | | 11 | Arrays.asList()返回的List不支持添加、删除、清空操作 | | | | 12 | 泛型通配符`<? extends T`>不能使用add方法,`<? super T>`不能使用get方法 | | | | 13 | 无泛型限制集合赋值给有泛型限制集合时,使用元素需要进行instanceof判断 | | | | 14 | 不要在foreach循环里进行元素的remove/add操作,remove操作请使用Iterator方式 | | | | 15 | Comparator实现类需满足三个条件:x.compareTo(y) == -y.compareTo(x),x.compareTo(y) > 0 && y.compareTo(z) > 0 时 x.compareTo(z) > 0,x.compareTo(y) == 0 时 x.compareTo(z) == y.compareTo(z) | | | | | | | | 并发处理 | 1 | 获取单例对象需要保证线程安全,其中的方法也要保证线程安全 | | | | 2 | 创建线程或线程池时请指定有意义的线程名称 | | | | 3 | 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程 | | | | 4 | 线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式 | | | | 5 | SimpleDateFormat是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类 | | | | 6 | 必须回收自定义的ThreadLocal变量,尤其在线程池场景下 | | | | 7 | 高并发时,同步调用应该去考量锁的性能损耗 | | | | 8 | 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁 | | | | 9 | 使用阻塞等待获取锁的方式时,必须在try代码块之外,并且在加锁方法与try代码块之间没有任何可能抛出异常的方法调用 | | | | 10 | 使用尝试机制来获取锁的方式中,进入业务代码块之前,必须先判断当前线程是否持有锁 | | | | 11 | 并发修改同一记录时,避免更新丢失,需要加锁 | | | | 12 | 多线程并行处理定时任务时,使用ScheduledExecutorService而不是Timer | | | | | | | | 控制语句 | 1 | switch语句要么通过break等终止,要么注释说明程序将继续执行到哪一个case为止;必须包含default语句并放在最后 | | | | 2 | 当switch括号内的变量类型为String并且此变量为外部参数时,必须先进行null判断 | | | | 3 | 在if/else/for/while/do语句中必须使用大括号 | instinctive | | | 4 | 三目运算符使用时注意NPE异常 | 需要注意 | | | 5 | 在高并发场景中,避免使用"等于"判断作为中断或退出的条件 | | | | | | | | 注释规约 | 1 | 类、类属性、类方法的注释必须使用Javadoc规范,使用`/** 内容 */`格式 | instinctive | | | 2 | 所有的抽象方法必须要用Javadoc注释,说明方法用途、功能、返回值、参数、异常等 | instinctive | | | 3 | 所有的类都必须添加创建者和创建日期 | instinctive | | | 4 | 方法内部单行注释使用//,多行注释使用/* */,注意与代码对齐 | instinctive | | | 5 | 所有的枚举类型字段必须要有注释,说明每个数据项的用途 | | | 前后端规约 | 1 | API需明确协议、域名、路径、请求方法、请求内容、状态码、响应体 | | | | 2 | 空列表返回空数组[]或空集合{} | 需要注意 | | | 3 | 错误响应必须包含HTTP状态码、errorCode、errorMessage、用户提示信息 | 大差不差 | | | 4 | JSON数据中的key必须为小写字母开始的lowerCamelCase风格 | sirius 有的用的是蛇形 | | | 5 | errorMessage用于错误追踪,可输出到前端隐藏控件或日志 | | | | 6 | 超大整数场景使用String类型返回,禁止使用Long类型 | String 是万金油和兜底 | | | 7 | URL传递参数不能超过2048字节 | | | | 8 | HTTP请求body传递内容必须控制长度 | | | | 9 | 翻页场景中,参数小于1返回第一页,大于总页数返回最后一页 | 那次还和曾老师争论 | | | 10 | 内部重定向使用forward,外部重定向地址使用URL统一代理模块生成 | | | 其他 | 1 | 正则表达式应利用预编译功能提高匹配速度 | | | | 2 | 避免使用ApacheBeanutils进行属性复制,考虑使用其他方案 | protobuf | | | 3 | Velocity调用POJO类属性时直接使用属性名 | | | | 4 | 后台输送给页面的变量必须加$!{var} | | | | 5 | 获取随机数时注意Math.random()的范围,整数随机数使用Random对象的方法 | | | | 6 | 枚举的属性字段必须是私有且不可变 | private final,枚举是静态常量表格,必须有 final | | 错误码 | 1 | 错误码制定原则:快速溯源、沟通标准化 | | | | 2 | 错误码不体现版本号和错误等级信息 | | | | 3 | 全部正常时返回00000 | | | | 4 | 错误码为5位字符串,分为错误来源和四位数字编号 | sirius 目前是三位,可以看下 spa 那里的 | | | 5 | 编号不与业务架构和组织架构挂钩,遵循先到先得原则 | | | | 6 | 避免随意定义新的错误码 | | | | 7 | 错误码不能直接作为用户提示信息使用 | | | | | | | | 异常处理 | 1 | 可通过预检查方式规避的RuntimeException不应该通过catch处理 | | | | 2 | 异常捕获后不要用来做流程控制,条件控制 | 性能问题 | | | 3 | catch时区分稳定代码和非稳定代码,对非稳定代码尽可能区分异常类型 | | | | 4 | 捕获异常是为了处理它,不要捕获后什么都不做;最外层必须处理异常 | spring 中切面兜底包装异常 | | | 5 | 事务场景中,catch异常后如需回滚,要手动回滚事务 | | | | 6 | finally块必须对资源对象、流对象进行关闭,有异常也要做try-catch | | | | 7 | 不要在finally块中使用return | | | | 8 | 捕获异常与抛异常必须完全匹配,或捕获异常是抛异常的父类 | | | | 9 | 调用RPC、二方包或动态生成类的方法时,用Throwable类捕获异常 | | | | | | | | 日志规约 | 1 | 使用日志框架API,不直接使用日志系统API | 推荐SLF4J | | | 2 | 日志文件至少保存15天,当天日志和历史日志命名规范 | | | | 3 | 特定日志需保存不少于6个月,并进行网络多机备份 | 法律要求 | | | 4 | 扩展日志命名规范:appName_logType_logName.log | | | | 5 | 日志输出中字符串拼接使用占位符方式 | 提高性能 | | | 6 | trace/debug/info级别日志输出前进行日志级别判断 | 避免性能损耗 | | | 7 | 避免重复打印日志,设置additivity=false | | | | 8 | 生产环境禁止使用System.out或System.err输出 | instinctive | | | 9 | 异常日志应包含案发现场信息和异常堆栈信息 | 打 e | | | 10 | 日志打印时禁止直接用JSON工具将对象转换成String | 但是这样很方便啊 | | | | | | | 单元测试 | 1 | 单元测试必须遵守AIR原则(自动化、独立性、可重复)| 自动化工程做的很棒 | | | 2 | 单元测试应全自动执行,非交互式,使用assert验证 | 自动化工程做的很棒 | | | 3 | 保持单元测试的独立性,测试用例间不能互相调用或依赖执行顺序 | 自动化工程做的很棒 | | | 4 | 单元测试可重复执行,不受外界环境影响 | 自动化工程做的很棒 | | | 5 | 单元测试粒度要小,最多是类级别,一般是方法级别 | 自动化工程做的很棒 | | | 6 | 核心业务、应用、模块的增量代码要确保单元测试通过 | 自动化工程做的很棒 | | | 7 | 单元测试代码必须写在src/test/java目录下 | | | | | | | | 安全规约 | 1 | 用户个人页面或功能必须进行权限控制校验 | | | | 2 | 用户敏感数据必须脱敏后才能展示 | 手机号加密 | | | 3 | SQL参数必须使用参数绑定或METADATA字段值限定,防止SQL注入 | | | | 4 | 用户请求的任何参数必须做有效性验证 | | | | 5 | 禁止向HTML页面输出未经安全过滤或未正确转义的用户数据 | 防XSS攻击 | | | 6 | 表单、AJAX提交必须执行CSRF安全验证 | | | | 7 | URL外部重定向的目标地址必须执行白名单过滤 | | | | 8 | 使用平台资源时必须实现正确的防重放机制 | | | | 9 | 文件上传功能需要对文件大小、类型进行严格检查和控制 | 北极星传 excel | | | 10 | 配置文件中的密码需要加密 | 那次配的那个 token?| | | | | | | 二方库依赖 | 1 | GAV定义规则:GroupId、ArtifactId、Version的格式规范 | | | | 2 | 版本号命名方式:主版本号.次版本号.修订号 | | | | 3 | 线上应用不依赖SNAPSHOT版本,正式发布的类库使用RELEASE版本 | instinctive | | | 4 | 二方库新增或升级时,保持其他jar包仲裁结果不变 | | | | 5 | 二方库接口返回值不允许使用枚举类型或包含枚举类型的POJO对象 | | | | 6 | 二方库定制包的命名方式规范 | | | | 7 | 依赖二方库群时,必须定义统一的版本变量 | instinctive | | | 8 | 禁止在子项目的pom依赖中出现相同GroupId和ArtifactId但不同Version | | | | | | | | 服务器 | 1 | 调用远程操作必须有超时设置。| 转正答辩说的 | | | | | | | 设计规约 | 1 | 存储方案和底层数据结构设计需评审并形成文档 | | | | 2 | 复杂需求分析使用用例图表达,User>1类且UseCase>5个 | | | | 3 | 业务对象状态超过3个时使用状态图表达 | | | | 4 | 功能调用链涉及对象超过3个时使用时序图表达 | | | | 5 | 模型类超过5个且依赖关系复杂时使用类图表达 | | | | 6 | 多对象协作的复杂处理流程使用活动图表示,超过2个对象存在协作关系 | 泳道图 | | | 7 | 识别弱依赖并设计降级和应急预案 | 强弱依赖 |