【开发规范】持续更新中......

目录

一、编码规范

接口规范

命名规范

并发处理

常量定义

集合处理

控制语句

事务规范

其他规范

二、异常日志

日志规范

异常规范

三、工程规约

服务器规约

二方库规约

四、MySQL数据库规范

建表规范

索引规范

SQL语句

五、安全规约


XT开发规范

一、编码规范

接口规范

1、RPC‘接口返回值’以及‘接口入参值’,禁止使用枚举;枚举在你的系统内部使用即可。推荐在这个字段上注释一个枚举类型。【强制】

正例:

 /**  * 类型 {@link com.atta.infra.workorder.api.constrants.WorkOrderType}  */ 
private String type;

2、非查询接口,必须是幂等的。【强制】(幂等定义说明)(幂等返回值方式:告知单号、告知重复,都是成功)幂等ID由上游提供,保证不同业务不同幂等ID。

不考虑并发情况,update本来技术幂等的。根据业务场景,如果是对status的修改,那么修改之前是需要对数据库status进行判断校验的。

3、大数据量查询必须提供分页操作,每页size不超过200条(dba强制:in语句在100条以内)。【强制】(框架解决)

4、浮点数(金额)必须使用BigDecimal,必须使用String构造方法。【强制】(增加案例)

说明:

1)防止精度丢失

5、日元、韩元、台币不允许有小数点。【强制】(补充其他币种:越南币...)

说明:

1)日元、韩元、台币最小单位是元,人民币、美元最小单位是分。

2)日元、韩元、台币,银行系统不支持小数点,会报错。

6、webapp接口,必须做水平权限检查。【强制】

说明:

1)例如:接口是根据id查询业务信息,必须校验id是当前用户的id,否则会出现水平权限漏洞。

正例:
@GetMapping("bankcard/detail")
public bankcardModel getBankcardDetail(@RequestParam String bankcardId){
  BankcardVO bankcardVO = bankcardClient.queryBankcardProfile(bankcardId);
  if(!UserUtils.getFirmId().equals(bankcardVO.getFirmId()){
    //throw 403 异常
  }
  if(UserUtils.getFirmId().equals(bankcardVO.getFirmId())
  return convertVO2Model(bankcardVO);
}
反例:
@GetMapping("bankcard/detail")
public bankcardModel getBankcardDetail(@RequestParam String bankcardId){
  BankcardVO bankcardVO = bankcardClient.queryBankcardProfile(bankcardId);
  return convertVO2Model(bankcardVO);
}

7、敏感数据(手机号、邮箱、企业名称、身份证号、地址等)必须脱敏返回 【强制】(增加安全规范连接)日志里面不能打印用户的信息。打印id即可,然后自己去数据库里面查。手机号、邮箱这种定位到人的,属于敏感;你可以加*来脱敏打印。

说明:可以使用脱敏注解。

8、增删改查,可以提供批量接口的,尽量提供批量接口(批量的size也得有限制)。【推荐】

9、禁止在接口实现中修改接口的入参。【强制】

命名规范

1、数据库表名,必须加数据库缩写前缀。【强制】

说明:可以避免数仓同步数据,表重名问题。

正例:ul_audit_request boss_audit_request 反例:audit_request

2、【强制】抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以 它要测试的类的名称开始,以Test结尾。

3、【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。

正例:应用工具类包名为com.alibaba.open.util、类名为MessageUtils(此规则参考spring的框架结构)

4、【推荐】子程序的名字尽可能的表达出所实现的功能,建议是单子程序只实现单功能(单一原则); 而接口的名字需要站在更高的位置,表达出高度的抽象,其名称只需要表达出主业务功能即可。

  • 子程序实现单一功能时,其名称需要具体到所实现的某种功能:如果子程序只是参数组装(填充):子程序名字可以是assem、fill甚至modify这些动词开头;
  • 子程序实现多个功能时/定义接口时,其名称需要抽象表达主业务功能:如果子程序/接口既需要调用api接口,又需要插入数据库,又需要调用第三方接口:子程序名字可以是handle、process等动词开头,以表达更高的抽象。

5、【参考】各层命名规约:

  1. Service/DAO 层方法命名规约
    1. 获取单个对象的方法用 get 做前缀。
    2. 获取多个对象的方法用 list 做前缀。
    3. 获取统计值的方法用 count 做前缀。
    4. 插入的方法用 save(推荐)或 insert 做前缀。
    5. 删除的方法用 remove(推荐)或 delete 做前缀。
    6. 修改的方法用 update 做前缀。
  2. 领域模型命名规约
    1. 数据对象: xxxDOxxx 即为数据表名。与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
    2. 数据传输对象: xxxDTOxxx 为业务领域相关的名称。数据传输对象,Service 和 Manager 向外传输的对象。
    3. 展示对象: xxxVOxxx 一般为网页名称。显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
    4. BO:业务对象。可以由 Service 层输出的封装业务逻辑的对象。
    5. POJODO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO

并发处理

1、线程池队列如果使用LinkedBlockingQueue,必须设置队列大小。【强制】

2、数据库单条更新操作,必须使用version做乐观锁,modified_time也必须更新;批量更新用status做乐观锁,modified_time也必须更新。【强制】

3、日期格式化必须使用XT自己的DateFormatter工具类。SimpleDateFormat是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁。【强制】

4、【强制】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的 处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

说明:Executors返回的线程池对象的弊端如下:

1)FixedThreadPool和SingleThreadPool: 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。

2)CachedThreadPool和ScheduledThreadPool: 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

5、【强制】创建线程或线程池时请指定有意义的线程名称,方便监控和出错时回溯。

正例:
public class TimerTaskThread extends Thread {
	public TimerTaskThread(){
	super.setName("TimerTaskThread"); ...
}

常量定义

1、禁止用内部类初始化对象。【强制】

反例:
user.setAddress(new Address(){{
  setStreet("荆州路");
  setCity("上海");
  setProvince("上海");
}})

2、【推荐】不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护。如: 缓存相关的常量放在类: CacheConsts 下;系统配置相关的常量放在类: ConfigConsts 下。
说明 : 大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。

集合处理

1、不允许for循环查询数据库,使用批量查询。【强制】

2、【强制】关于hashCode和equals的处理,遵循如下规则:

  • 只要重写equals,就必须重写hashCode。
  • 因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。
  • 如果自定义对象做为Map的键,那么必须重写hashCode和equals。

3、【推荐】List 优于数组, 优先使用 list 而不是数组

4、【推荐】要多使用 Collections 集合工具类

  1. 使用空集合是使用 Collections.emptyList() Collections.emptyMap() 

  2. 当集合里面只有一个参数的时候,使用  Collections.singletonList();  Collections.singletonMap();

  3. 使用静态集合变量,使用 Collections.unmodifiableList(), Collections.unmodifiableMap()

控制语句

1、在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有。【强制】

2、复杂表达式,要抽象为一个方法,并增加注释。【推荐】

  1. 复杂表达式:5个以上。

  2. 不允许超过20个,超过说明设计方案有问题。

3、推荐尽量少用else, if-else的方式可以改写成:【推荐】

if(condition){
	...
	return obj;
}
//接着写else的业务逻辑代码;

说明:如果非得使用if()...else if()...else...方式表达逻辑,请勿超过 3层,超过请使用状态设计模式。

事务规范

1、本地事务一律使用编程式事务 【强制】声明式事务不容易引起开发人员的关注;

说明:

    1.注解事务只能应用到public可见度的方法上,如果应用在protected、private可见度的方法上事务设置不起作用,且不会报错

   2.注解事务对checked异常(IOException、TimeoutException)不会回滚

   3.同一类中的方法调用事务不会生效

2、update方法要检查返回值是否是期望的,也必须放在DAO层检查【强制】

3、如果事务内catch异常处理,必须手动回滚。【强制】

//反例
transactionTemplate.execute(status -> {
    try {
        ...
    } catch (Exception e) {
        log.error(...);
        return ...;
    }
};
//正例
transactionTemplate.execute(status -> {
    try {
        ...
    } catch (Exception e) {
        status.setRollbackOnly();
        log.error(...);
        return ...;
    }
}

4、我们的mysql数据库事务隔离级别设置为read-commited。不要在一个事务里面重复读。【参考】

5、我们目前的事务传播是REQUIRES_NEW,新开启事务,挂起老事务,因此要注意嵌套事务的问题,父事务rollback,子事务不会rollback。【参考】

其他规范

1、禁止使用BeanUtils.copyProperties(A,B)或其他类似工具,手写转换方法就好【强制】

2、定时任务的job接口,必须是异步执行。【强制】

二、异常日志

日志规范

1、日志中禁止打印客户的敏感信息(密码、秘钥、手机号、邮箱、身份证号、企业名称、住址等)。【强制】

  1. 推荐:不要打印完整对象
  2. 推荐:按需打印对象中的信息,如:id。

2、禁止使用e.printStackTrace()。【强制】

说明:直接这么用,线上异常栈打不到日志中。

3、system.out.print禁止使用(增)【强制】

4、【强制】异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么往上抛。

正例:logger.error(各类参数toString + "_" + e.getMessage(), e);

5、【强制】对trace/debug/info级别的日志输出,必须使用条件输出形式或者使用占位符的方 式。

说明:logger.debug(“Processing trade with id: “ + id + “ symbol: “ + symbol);如果日志级别是warn,上述日志不会打印,但是会执行字符串拼接操作,如果symbol是对象,会执行toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。

正例:(条件)
if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
}
正例:(占位符)
logger.debug("Processing trade with id: {} symbol : {} ", id, symbol);

6、日志一定要加入关键输入/输出参数,不要打印大量无关信息。【推荐】

打log导致系统异常故障

异常规范

1、【强制】对大段代码进行try-catch,这是不负责任的表现。catch时请分清稳定代码和非稳定代 码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的catch尽可能进行区分异常类型,再做对应的异常处理。

2、【强制】有try块放到了事务代码中,catch异常后,如果需要回滚事务,一定要注意手动回滚事 务。

3、【强制】不能在finally块中使用return,finally块中的return返回后方法结束执行,不会再执行try块、catch块中的return语句

4、【强制】方法的返回值可以为null,不强制返回空集合,或者空对象等,必须添加注释充分说明什 么情况下会返回null值。调用方需要进行null判断防止NPE问题。 说明:本规约明确防止NPE是调用者的责任。即使被调用方法返回空集合或者空对象,对调用者来说,也并非高枕无忧,必须考虑到远程调用失败,运行时异常等场景返回null的情况。

三、工程规约

服务器规约

  1. 【推荐】高并发服务器建议调小 TCP 协议的 time_wait 超时时间。 说明: 操作系统默认 240 秒后,才会关闭处于 time_wait 状态的连接,在高并发访问下,服 务器端会因为处于 time_wait 的连接数太多,可能无法建立新的连接,所以需要在服务器上 调小此等待值。
    正例 : 在 linux 服务器上请通过变更/etc/sysctl.conf 文件去修改该缺省值(秒): net.ipv4.tcp_fin_timeout = 30

  2. 【推荐】调大服务器所支持的最大文件句柄数(File Descriptor,简写为 fd)。
    说明 : 主流操作系统的设计是将 TCP/UDP 连接采用与文件一样的方式去管理,即一个连接对 应于一个 fd。主流的 linux 服务器默认所支持最大 fd 数量为 1024,当并发连接数很大时很容易因为 fd 不足而出现“open too many files”错误,导致新的连接无法建立。 建议将 linux 服务器所支持的最大句柄数调高数倍(与服务器的内存数量相关)。

  3. 【推荐】给 JVM 设置-XX:+HeapDumpOnOutOfMemoryError 参数,让 JVM 碰到 OOM 场景时输出 dump 信息
    说明 : OOM 的发生是有概率的,甚至有规律地相隔数月才出现一例,出现时的现场信息对查错 非常有价值。

  4. 【参考】服务器内部重定向使用 forward;外部重定向地址使用 URL 拼装工具类来生成,否则 会带来 URL 维护不一致的问题和潜在的安全风险。

  5. webapp服务,禁止连接数据库。【强制】

  6. webapp连接的redis和server连接的redis不能用相同的key。(架构上处理)【强制】。   说明:redis的key只能在一个服务中出现,如果另一个服务需要访问同一个key的redis数据,通过接口提供访问。

二方库规约

  1. 【强制】定义 GAV 遵从以下规则:
  1. GroupID 格式: com.{公司/BU }.业务线.[子业务线],最多 4 级。
    说明 : {公司/BU} 例如: alibaba/taobao/tmall/aliexpress 等 BU 一级;子业务线可选。
    正例 : com.taobao.jstorm 或 com.alibaba.dubbo.register
  2. ArtifactID 格式: 产品线名-模块名。语义不重复不遗漏,先到中央仓库去查证一下。
    正例 : dubbo-client / fastjson-api / jstorm-tool
  3. Version: 详细规定参考下方。
  1. 【强制】二方库版本号命名方式: 主版本号.次版本号.修订号
  1. 主版本号: 当做了不兼容的 API 修改,或者增加了能改变产品方向的新功能
  2. 次版本号: 当做了向下兼容的功能性新增(新增类、接口等)。
  3. 修订号: 修复 bug,没有修改方法签名的功能加强,保持 API 兼容性。
    说明 : 注意: 起始版本号必须为: 1.0.0,而不是 0.0.1 正式发布的类库必须先去中央仓库进行查证,使版本号有延续性,正式版本号不允许覆盖升级。如当前版本: 1.3.3,那么下一个合理的版本号: 1.3.4 或 1.4.0 或 2.0.0
  1. 【强制】线上应用不要依赖 SNAPSHOT 版本(安全包除外)。
    说明 : 不依赖 SNAPSHOT 版本是保证应用发布的幂等性。另外,也可以加快编译时的打包构建。

  2. 【强制】二方库的新增或升级,保持除功能点之外的其它 jar 包仲裁结果不变。如果有改变, 必须明确评估和验证,建议进行 dependency:resolve 前后信息比对,如果仲裁结果完全不一 致,那么通过 dependency:tree 命令,找出差异点,进行<excludes>排除 jar 包。

  3. 【强制】二方库里可以定义枚举类型,参数可以使用枚举类型,但是接口返回值不允许使用枚举类型或者包含枚举类型的 POJO 对象

  4. 【强制】依赖于一个二方库群时,必须定义一个统一的版本变量,避免版本号不一致。 说明: 依赖 springframework-core,-context,-beans,它们都是同一个版本,可以定义一 个变量来保存版本: ${spring.version},定义依赖的时候,引用该版本。

  5. 【强制】禁止在子项目的 pom 依赖中出现相同的 GroupId,相同的 ArtifactId,但是不同的 Version。
    说明 : 在本地调试时会使用各子项目指定的版本号,但是合并成一个 war,只能有一个版本号 出现在最后的 lib 目录中。可能出现线下调试是正确的,发布到线上却出故障的问题。

  6. 【推荐】所有 pom 文件中的依赖声明放在<dependencies>语句块中,所有版本仲裁放在 <dependencyManagement>语句块中

    1.   <dependencyManagement>里只是声明版本,并不实现引入,因此子项目需要显式的声明依赖,而version 和 scope 都读取自父 pom。如果子项目自己也声明了version、scope,那么就用子项目自己的。

    2. <dependencies>所有声明在主 pom 的 <dependencies>里的依赖都会自动引入,并默认被所有的子项目继承。

    3. 声明:同一个pom文件可以同时具备 <dependencyManagement>和<dependencies>。 该pom文件可以自娱自乐,自己在<dependencyManagement>里面定义一个依赖 并指定版本,然后在<dependencies>中声明这个依赖。参考链接

  7. 【推荐】二方库不要有配置项,最低限度不要再增加配置项。

  8. 【参考】为避免应用二方库的依赖冲突问题,二方库发布者应当遵循以下原则:
    1)精简可控原则。移除一切不必要的 API 和依赖,只包含 Service API、必要的领域模型对 象、Utils 类、常量、枚举等。如果依赖其它二方库,尽量是 provided 引入,让二方库使用 者去依赖具体版本号;无 log 具体实现,只依赖日志框架。
    2)稳定可追溯原则。每个版本的变化应该被记录,二方库由谁维护,源码在哪里,都需要能 方便查到。除非用户主动升级版本,否则公共二方库的行为不应该发生变化。

  9. 引入3方包,需要向基础架构组申请,版本号放到atta-infra项目中。【强制】

  10. 【强制】二方库里可以定义枚举类型,参数可以使用枚举类型,但是接口返回值不允许使用枚举类型或者包含枚举类型的POJO对象。

四、MySQL数据库规范

建表规范

  1. 建表统一增加创建时间(created_time)、修改时间(modified_time)、版本号(version),  并且都为非空字段 【强制】

  2. 必填字段都需要定义成非空【强制】

  3. 约定表名和所有的字段名全部为小写,表名和字段名全部为英文,并带有具体的含义,建表语句的comment需要填写, 要描述清楚表和字段的含义, comment可以为中文。【强制】

  4. 【推荐】如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释

  5. 【强制】表名、字段名、索引名应由小写字母、数字和下划线组成,且以小写字母开头。禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑
    正例 : getter_admin,task_config,level3_name
    反例 : GetterAdmin,taskConfig,level_3_name

  6. 表名、字段名应采用能表达业务含义的抽象名词,禁止出现渠道名、合作商等具体名词【强制】

  7. 表名不使用复数名词【强制】

  8. 表名、字段名不能使用Mysql的保留字,如 desc、range、match、delayed 等。【强制】

  9. 【强制】表达是和否概念的字段,命名规则为:is_xxx。数据类型是 unsigned tinyint( 1 表示是,0 表示否)。
    说明 : 任何字段如果为非负数,必须是 unsigned。
    正例 : 表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。

  10. 主键索引的命名规则为:pk_xxx;唯一索引的命名规则:uk_xxx;普通索引的命名规则为:idx_xxx【强制】

  11. 表的必备字段:id、created_time、modified_time、version【强制】

  12. 【强制】推荐表设计时冗余适当的字段以提高查询性能。字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:
    1)不是频繁修改的字段。
    2)不是 varchar 超长字段,更不能是 text 字段。
    正例 : 商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存储类目名称,避免关联查询。

  13. 【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。
    说明 : 如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。

  14. 小数类型采用decimal,禁止使用float或double【强制】
  15. 非负数字段,采用unsigned,避免存入负数【强制】
  16. DAO方法参数,必须做判空检查或用Lombok的@NonNull,禁止传入空值。【强制】
  17. DO的成员变量,不要用基础类型int,boolean等,基础类型的默认值会导致数据被修改。【推荐】
  18. 不要去写一个大而全的数据更新方法,然后传入POJO类,这样非常容易出错,而且更新无谓的字段,加大消耗【强制】

索引规范

  1. 【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。 说明: 不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。

  2. 【推荐】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。
    正例 : where a=? and b=? order by c; 索引: a_b_c
    反例 : 索引中有范围查找,那么索引有序性无法利用,如: WHERE a>10 ORDER BY b; 索引 a_b 无法排序。

  3. 【推荐】利用覆盖索引来进行查询操作,避免回表。
    说明 : 如果一本书需要知道第 11 章是什么标题,会翻开第 11 章对应的那一页吗? 目录浏览一下就好,这个目录就是起到覆盖索引的作用。
    正例 : 能够建立索引的种类: 主键索引、唯一索引、普通索引,而覆盖索引是一种查询的一种 效果,用 explain 的结果,extra 列会出现: using index。

  4. 【推荐】利用延迟关联或者子查询优化超多分页场景
    说明 : MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。
    正例 : 先快速定位需要获取的 id 段,然后再关联: SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id

  5. 【推荐】SQL 性能优化的目标: 至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好。
    说明 :
    1) consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。
    2) ref 指的是使用普通的索引(normal index)。
    3) range 对索引进行范围检索。
    反例 : explain 表的结果,type=index,索引物理文件全扫描,速度非常慢,这个 index 级别比较 range 还低,与全表扫描是小巫见大巫。

  6. 【推荐】建组合索引的时候,区分度最高的在最左边
    正例 : 如果 where a=? and b=? ,a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即可。
    说明 : 存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。如: where a>? and b=? 那么即使 a 的区分度更高,也必须把 b 放在索引的最前列。

  7. 【推荐】防止因字段类型不同造成的隐式转换,导致索引失效

  8. 【参考】创建索引时避免有如下极端误解:
    1)宁滥勿缺。误认为一个查询就需要建一个索引。
    2)宁缺勿滥。误认为索引会消耗空间、严重拖慢更新和新增速度。
    3)抵制惟一索引。误认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。

  9. 限制每张表上的索引数量,建议单张表索引不超过5个【推荐】

  10. 索引长度不能超过767,注意计算联合索引的长度【强制】

  11. 在varchar字段上建索引时,必须指定索引长度【强制】

  12. 常用查询的条件要有索引, 注意顺序是否正确【强制】

  13. 删除不再使用或者很少使用的索引【强制】

  14. 最左前缀匹配原则,非常重要的原则【强制】

  15. 比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可【强制】
  16. 索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引【强制】

SQL语句

  1. 【强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
    说明 : count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。

  2. 【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。

  3. 【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为 NULL,因此使用 sum()时需注意 NPE 问题。
    正例 : 可以使用如下方式来避免 sum 的 NPE 问题: SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM table;

  4. 【强制】数据订正时,删除和修改记录时,要先 select,避免出现误删除,确认无误才能执行更新语句。

  5. 【推荐】in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控制在 1000 个之内。

  6. 禁止物理删除,用逻辑删除0为非删除态。【强制】

  7. 禁止代码中使用select * from进行查询,给出明确的待查询字段。【强制】

  8. update操作的where字段要有index。【强制】

  9. 严禁没有where的update操作。【强制】

  10. alter 表必须支持提前执行。【强制】

  11. 重试job必须增加时间间隔,避免并发,如:查询5分钟前的数据。【强制】

  12. 使用#设置参数,like、正则参数判断,必须进行转义。【强制】

  13. 禁止join操作。【强制】

五、安全规约

  1. 【强制】隶属于用户个人的页面或者功能必须进行权限控制校验
    说明 : 防止没有做水平权限校验就可随意访问、修改、删除别人的数据,比如查看他人的私信 内容、修改他人的订单。

  2. 【强制】用户敏感数据禁止直接展示,必须对展示数据进行脱敏
    说明 : 查看个人手机号码会显示成:158****9119,隐藏中间 4 位,防止隐私泄露。

  3. 【强制】用户输入的 SQL 参数严格使用参数绑定或者 METADATA 字段值限定,防止 SQL 注入, 禁止字符串拼接 SQL 访问数据库。

  4. 【强制】用户请求传入的任何参数必须做有效性验证
    说明 : 忽略参数校验可能导致:

    • page size 过大导致内存溢出
    • 恶意 order by 导致数据库慢查询
    • 任意重定向
    • SQL 注入
    • 反序列化注入
    • 正则输入源串拒绝服务 ReDoS

    说明 : Java 代码用正则来验证客户端的输入,有些正则写法验证普通用户输入没有问题, 但是如果攻击人员使用的是特殊构造的字符串来验证,有可能导致死循环的结果。

  5. 【强制】禁止向 HTML 页面输出未经安全过滤或未正确转义的用户数据。

  6. 【强制】表单、AJAX 提交必须执行 CSRF 安全过滤。
    说明 : CSRF(Cross-site request forgery)跨站请求伪造是一类常见编程漏洞。对于存在 CSRF 漏洞的应用/网站,攻击者可以事先构造好 URL,只要受害者用户一访问,后台便在用户 不知情情况下对数据库中用户参数进行相应修改。

  7. 【强制】在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防重放限制, 如数量限制、疲劳度控制、验证码校验,避免被滥刷、资损。 说明: 如注册时发送验证码到手机,如果没有限制次数和频率,那么可以利用此功能骚扰到其 它用户,并造成短信平台资源浪费

  8. 【推荐】发贴、评论、发送即时消息等用户生成内容的场景必须实现防刷、文本内容违禁词过 滤等风控策略。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
本文阐述软件项目开发和管理的流程规范,作为软件项目开发的高级指引,本规范定义了软件开发的各个阶段以及每个阶段的工作活动和工件,但不对活动和工件的细节作过多规定。在项目开发过程,每个项目根据自身的需要确定这些活动和工件的细节。这个阶段的工作目的是决定一个项目是否需要启动。为了达到这个目的,首先要明确项目的总体战略目标,对项目的需要建立认同。即确定到底需要做什么、开发什么产品或提供什么服务,以及需要解决什么样的问题和需要满足客户或市场的什么要求等,同时还要总结项目工作的范围、所需资源、大约开支、各种风险,以及该项目不执行的其他替代选择等。这些代表了对整个项目目标从战略角度和宏观层次所进行的分析,通过项目的意向书总结出来,由此确证客户或项目发起人和赞助者的要求与期望,并帮助他们判定项目是否上马。项目意向总结书的通过及项目被批准上马形成了这个项目的起始点。 前一篇文章《软件开发基本原则》谈论了软件开发原则方面的问题,而本篇文章尝试谈谈软件开发更具体的一些内容 —— 普通软件项目的开发过程规范。本座也知道,如果过程规范讲的太具体对谈论者来说是非常冒险的一件事情,它不像技术,对就对错就错,有一个客观的评判标准,别人想喷你也得自己先好好研究等拿到了足够的论据才能喷,但开发过程和项目管理就不同了,别人仅凭一点点所谓的管理经验甚至是主观推断就能喷得你体无完肤,摇摇欲坠 ~ 因为没有什么所谓的事实标准与放之四海皆有效的软件开发过程和项目管理方法。保守估计,100个人至少有150种想法。本座也深知其的凶险,因此避重就轻,从基本原理谈起,宏观的角度阐述相关问题,尽量减少弹的机会。欢迎大家畅所欲言 ^_*

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@来杯咖啡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值