Java开发规范(五)

三、单元测试

1. 【强制】好的单元测试必须遵守AIR原则。

说明:单元测试在线上运行时,感觉像空气(AIR)一样并不存在,但在测试质量的保障上,却是非常关键的。好的单元测试宏观上来说,具有自动化、独立性、可重复执行的特点。 l AAutomatic(自动化) l

IIndependent(独立性)

RRepeatable (可重复)

2. 【强制】单元测试应该是全自动执行的,并且非交互式的。测试用例通常是被定期执行的,执行过程必须完全自动化才有意义。输出结果需要人工检查的测试不是一个好的单元测试。单元测试中不准使用System.out来进行人肉验证,必须使用assert来验证。

3. 【强制】保持单元测试的独立性。为了保证单元测试稳定可靠且便于维护,单元测试用例之间决不能互相调用,也不能依赖执行的先后次序。

反例:method2需要依赖method1的执行,将执行结果作为method2的输入。

4. 【强制】单元测试是可以重复执行的,不能受到外界环境的影响。

说明:单元测试通常会被放到持续集成中,每次有代码check in时单元测试都会被执行。如果单元测试对外部环境(网络、服务、中间件等)有依赖,容易导致持续集成机制的不可用。 正例:为了不受外界环境影响,要求设计代码时就把SUT的依赖改成注入,在测试时用spring 这样的DI框架注入一个本地(内存)实现或者Mock实现。

5. 【强制】对于单元测试,要保证测试粒度足够小,有助于精确定位问题。单测粒度至多是类级别,一般是方法级别。

说明:只有测试粒度小才能在出错时尽快定位到出错位置。单元测试不负责检查跨类或者跨系统的交互逻辑,那是集成测试的领域。

6. 【强制】核心业务、核心应用、核心模块的增量代码确保单元测试通过。

说明:新增代码及时补充单元测试,如果新增代码影响了原有单元测试,请及时修正。

7. 【强制】单元测试代码必须写在如下工程目录:src/test/java,不允许写在业务代码目录下。

说明:源码构建时会跳过此目录,而单元测试框架默认是扫描此目录。

8. 【推荐】单元测试的基本目标:语句覆盖率达到70%;核心模块的语句覆盖率和分支覆盖率都要达到100%

说明:在工程规约的应用分层中提到的DAO层,Manager层,可重用度高的Service,都应该进行单元测试。

9. 【推荐】编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量。 l

BBorder,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。 l

CCorrect,正确的输入,并得到预期结果。 l

DDesign,与设计文档相结合,来编写单元测试。

EError,强制错误信息输入(如:非法数据、异常流程、非业务允许输入等),并得到预期的结果。

10. 【推荐】对于数据库相关的查询,更新,删除等操作,不能假设数据库里的数据是存在的,或者直接操作数据库把数据插入进去,请使用程序插入或者导入数据的方式来准备数据。 反例:删除某一行数据的单元测试,在数据库中,先直接手动增加一行作为删除目标,但是这一行新增数据并不符合业务插入规则,导致测试结果异常。

11. 【推荐】和数据库相关的单元测试,可以设定自动回滚机制,不给数据库造成脏数据。或者对单元测试产生的数据有明确的前后缀标识。

正例:在RDC内部单元测试中,使用RDC_UNIT_TEST_的前缀标识数据。

12. 【推荐】对于不可测的代码建议做必要的重构,使代码变得可测,避免为了达到测试要求而书写不规范测试代码。

13. 【推荐】在设计评审阶段,开发人员需要和测试人员一起确定单元测试范围,单元测试最好覆盖所有测试用例(UC)。

14. 【推荐】单元测试作为一种质量保障手段,不建议项目发布后补充单元测试用例,建议在项目提测前完成单元测试。

15. 【参考】为了更方便地进行单元测试,业务代码应避免以下情况: l

构造方法中做的事情过多。 l

存在过多的全局变量和静态方法。 l

存在过多的外部依赖。 l

存在过多的条件语句。

说明:多层条件语句建议使用卫、策略模式状态等方重构。

16.【参考】不要对单元测试存在如下误解: l

那是测试同学干的事情。本文开发手册,凡是本文内容都与开发同学强相关的。 l

单元测试代码是多余的。 汽车的整体功能 与各单元部件的测试正常否是强相关。 l

单元测试代码不需要维护。 一年半载后,那么几乎处于废弃状态l

单元测试 与线上故障没有辩证关系。好的单元测试能够最大限度地规避线上故障。

四、安全规约

1. 【强制】隶属于用户个人的页面或者功能必须进行权限控制校验。

说明:防止没有做水平权限校验就可随意访问、修改、删除别人的数据,比如查看他人的私信内容、修改他人的订单。

2. 【强制】用户敏感数据禁止直接展示,必须对展示数据进行脱敏。

说明:个人手机号码显示为:158****9119,隐藏中间4位,防止隐私泄露。

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

4. 【强制】用户请求传入的任何参数必须做有效性验证。

说明:忽略参数校验可能导致:

l page size过大导致内存溢出

l 恶意order by导致数据库慢查询

l 任意重定向

l SQL注入

l 反序列化注入

l 正则输入源串拒绝服务ReDoS

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

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

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

7. 【强制】在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防重发限制,如数量限制、疲劳度控制、验证码校验,避免被滥刷导致资损。

说明:如注册时发送验证码到手机,如果没有限制次数和频率,那么可以利用此功能骚扰到其它用户,并造成短信平台资源浪费。

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

五、MySQL数据库

() 建表规约

1. 【强制】表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint1表示是,0表示否)。

说明:任何字段如果为非负数,必须是unsigned

正例: 表达逻辑删除的字段名 is_deleted1表示删除, 0表示未删除。 表示未删除。

2. 【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。

说明: MySQLWindows下不区分大小写,但在Linux不默认是区分大小写。因此,数据库下默认是区分大小写。因此,数据库 名、表字段,都不允许出现任何大写母避免节外生枝。

正例:aliyun_adminrdc_configlevel3_name

反例:AliyunAdminrdcConfiglevel_3_name

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

说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于DO类名也是单数形式,符合表达习惯。

4. 【强制】禁用保留字,如descrangematchdelayed等,请参考MySQL官方保留字。

5. 【强制】主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。

说明:pk_ primary keyuk_ unique keyidx_ index的简称。

6. 【强制】小数类型为decimal,禁止使用floatdouble

说明:floatdouble在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。如果存储的数据范围超过decimal的范围,建议将数据拆成整数和小数分开存储。

7. 【强制】如果存储的字符串长度几乎相等,使用char定长字符串类型。

8. 【强制】varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,如果存储长度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。

9. 【强制】表必备三字段:id, gmt_create, gmt_modified

说明:其中 id必为主键,类型unsigned bigint、单表时自增、步长为1。gmt_create, gmt_modified的类型均为datetime类型,前者现在时表示主动创建,后者过去分词表示被动更新。

10. 【推荐】表的命名最好是加上“业务名称_表的作用”。

正例:alipay_task / force_project / trade_config

11. 【推荐】库名与应用名称尽量一致。

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

13. 【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循: 1)不是频繁修改的字段。

2)不是varchar超长字段,更不能是text字段。

正例:商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存储类目名称,避免关联查询。

14. 【推荐】单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。

说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。

15. 【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。

正例:如下表,其中无符号值可以避免误存负数,且扩大了表示范围。

对象

年龄区间

类型

字节

表示范围

150岁之内

unsigned tinyint

1

无符号值:0到255

数百岁

unsigned smallint

2

无符号值:0到65535

恐龙化石

数千万年

unsigned int

4

无符号值:0到约42.9亿

太阳

约50亿年

unsigned bigint

8

无符号值:0到约10的19次方

 

 

() 索引规约

1. 【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。

说明:不要以为唯一索引影响了insert速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。

2. 【强制】超过三个表禁止join。需要join的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引。

说明:即使双表join也要注意表索引、SQL性能。

3. 【强制】在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。

说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为20的索引,区分度会高达90%以上,可以使用count(distinct left(列名, 索引长度))/count(*)的区分度来确定。

4. 【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。

说明:索引文件具有B-Tree的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。

5. 【推荐】如果有order by的场景,请注意利用索引的有序性。order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort的情况,影响查询性能。 正例:where a=? and b=? order by c; 索引:a_b_c

反例:索引中有范围查找,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引a_b无法排序。

6. 【推荐】利用覆盖索引来进行查询操作,避免回表。

说明:如果一本书需要知道第11章是什么标题,会翻开第11章对应的那一页吗?目录浏览一下就好,这个目录就是起到覆盖索引的作用。

正例:能够建立索引的种类分为主键索引、唯一索引、普通索引三种,而覆盖索引只是一种查询的一种效果,用explain的结果,extra列会出现:using index

7. 【推荐】利用延迟关联或者子查询优化超多分页场景。

说明: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

8. 【推荐】 SQL性能优化的目标:至少要达到 range 级别,要求是ref级别,如果可以是consts最好。

说明: 1consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。

2)ref 指的是使用普通的索引(normal index)。

3)range 对索引进行范围检索。

反例:explain表的结果,type=index,索引物理文件全扫描,速度非常慢,这个index级别比较range还低,与全表扫描是小巫见大巫。

9. 【推荐】建组合索引的时候,区分度最高的在最左边。

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

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

11. 【参考】创建索引时避免有如下极端误解:

1)宁滥勿缺。认为一个查询就需要建一个索引。

2)宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增速度。

3)抵制惟一索引。认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值