142
社区成员




这个作业属于哪个课程 | 2022年福大-软件工程;软件工程实践-W班 |
---|---|
这个作业要求在哪里 | 团队作业——站立式会议+alpha冲刺 |
这个作业的目标 | 明确团队代码规范、冲刺任务和冲刺计划 |
其它参考文献 | 百度JavaScript编码规范 阿里巴巴Java开发手册终极版v1.3.0 华为内部代码规范 |
文件
JavaScript 文件使用无 BOM
的 UTF-8
编码。
在文件结尾处,保留一个空行。
结构
缩进
使用 4
个空格做为一个缩进层级,不允许使用 2
个空格 或 tab
字符。
switch
下的 case
和 default
必须增加一个缩进层级。
空格
二元运算符两侧必须有一个空格,一元运算符与操作对象之间不允许有空格。
用作代码块起始的左花括号 {
前必须有一个空格。
if / else / for / while / function / switch / do / try / catch / finally
关键字后,必须有一个空格。
在对象创建时,属性中的 :
之后必须有空格,:
之前不允许有空格。
函数声明、具名函数表达式、函数调用中,函数名和 (
之间不允许有空格。
,
和 ;
前不允许有空格。如果不位于行尾,,
和 ;
后必须跟一个空格。
在函数调用、函数声明、括号表达式、属性访问、if / for / while / switch / catch
等语句中,()
和 []
内紧贴括号部分不允许有空格。
单行声明的数组与对象,如果包含元素,{}
和 []
内紧贴括号部分不允许包含空格.
行尾不得有多余的空格。
换行
每个独立语句结束后必须换行。
每行不得超过 120
个字符。
运算符处换行时,运算符必须在新行的行首。
在函数声明、函数表达式、函数调用、对象创建、数组创建、for
语句等场景中,不允许在 ,
或 ;
前换行。
不同行为或逻辑的语句集,使用空行隔开,更易阅读。
在语句的行长度超过 120
时,根据逻辑条件合理缩进。
对于 if...else...
、try...catch...finally
等语句,推荐使用在 }
号后添加一个换行 的风格,使代码层次结构更清晰,阅读性更好。
语句
不得省略语句结束的分号。
在 if / else / for / do / while
语句中,即使只有一行,也不得省略块 {...}
。
函数定义结束不允许添加分号。
IIFE
必须在函数表达式外添加 (
,非 IIFE
不得在函数表达式外添加 (
。
命名
变量
使用 Camel命名法
。
常量
使用 全部字母大写,单词间下划线分隔
的命名方式。
函数
使用 Camel命名法
。
函数的 参数
使用 Camel命名法
。
类
使用 Pascal命名法
。
类的 方法
/ 属性
使用 Camel命名法
。
枚举变量
使用 Pascal命名法
,枚举的属性
使用 全部字母大写,单词间下划线分隔
的命名方式。
命名空间
使用 Camel命名法
。
由多个单词组成的缩写词,在命名中,根据当前命名法和出现的位置,所有字母的大小写与首字母的大小写保持一致。
类名
使用 名词
。
函数名
使用 动宾短语
。
boolean
类型的变量使用 is
或 has
开头。
Promise对象
用 动宾短语的进行时
表达。
注释
单行注释
必须独占一行。//
后跟一个空格,缩进与下一行被注释说明的代码一致。
多行注释
避免使用 /*...*/
这样的多行注释。有多行注释内容时,使用多个单行注释。
文档化注释
为了便于代码阅读和自文档化,以下内容必须包含以 /**...*/
形式的块注释中。
文档注释前必须空一行。
自文档化的文档说明 what,而不是 how。
类型定义
类型定义都是以 {
开始, 以 }
结束。
对于基本类型 {string}, {number}, {boolean},首字母必须小写。
文件注释
文件顶部必须包含文件注释,用 @file
标识文件说明。
文件注释中可以用 @author
标识开发者信息。
命名空间注释
命名空间使用 @namespace
标识。
类注释
使用 @class
标记类或构造函数。
使用 @extends
标记类的继承信息。
使用包装方式扩展类成员时, 必须通过 @lends
进行重新指向。
类的属性或方法等成员信息不是 public
的,应使用 @protected
或 @private
标识可访问性。
函数/方法注释
函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识。
参数和返回值注释必须包含类型信息,且不允许省略参数的说明。
当函数是内部函数,外部不可访问时,可以使用 @inner
标识。
对 Object 中各项的描述, 必须使用 @param
标识。
重写父类方法时, 应当添加 @override
标识。如果重写的形参个数、类型、顺序和返回值类型均未发生变化,可省略 @param
、@return
,仅用 @override
标识,否则仍应作完整注释。
事件注释
必须使用 @event
标识事件,事件参数的标识与方法描述的参数标识相同。
在会广播事件的函数前使用 @fires
标识广播的事件,在广播事件代码前使用 @event
标识事件。
对于事件对象的注释,使用 @param
标识,生成文档时可读性更好。
常量注释
常量必须使用 @const
标记,并包含说明和类型信息。
复杂类型注释
对于类型未定义的复杂结构的注释,可以使用 @typedef
标识来定义。
AMD 模块注释
AMD 模块使用 @module
或 @exports
标识。
对于已使用 @module
标识为 AMD模块 的引用,在 namepaths
中必须增加 module:
作前缀。
对于类定义的模块,可以使用 @alias
标识构建函数。
多模块定义时,可以使用 @exports
标识各个模块。
对于 exports 为 Object 的模块,可以使用@namespace
标识。
对于 exports 为类名的模块,使用 @class
和 @exports
标识。
变量
变量、函数在使用前必须先定义。
每个 var
只能声明一个变量。
变量必须 即用即声明
,不得在函数或其它形式的代码块起始位置统一声明所有变量。
条件
在 Equality Expression 中使用类型严格的 ===
。仅当判断 null
或 undefined
时,允许使用 == null
。
尽可能使用简洁的表达式。
按执行频率排列分支的顺序。
如果函数或全局中的 else
块后没有任何语句,可以删除 else
。
循环
不要在循环体中包含函数表达式,事先将函数提取到循环体外。
对循环内多次使用的不变值,在循环外用变量缓存。
类型
类型检测
类型检测优先使用 typeof
。对象类型检测使用 instanceof
。null
或 undefined
的检测使用 == null
。
类型转换
转换成 string
时,使用 + ''
。
转换成 number
时,通常使用 +
。
string
转换成 number
,要转换的字符串结尾包含非数字并期望忽略时,使用 parseInt
。
使用 parseInt
时,必须指定进制。
转换成 boolean
时,使用 !!
。
number
去除小数点,使用 Math.floor
/ Math.round
/ Math.ceil
,不使用 parseInt
。
字符串
字符串开头和结束使用单引号 '
。
使用 数组
或 +
拼接字符串。
使用字符串拼接的方式生成HTML,需要根据语境进行合理的转义。
复杂的数据到视图字符串的转换过程,选用一种模板引擎。
对象
使用对象字面量 {}
创建新 Object
。
对象创建时,如果一个对象的所有 属性
均可以不添加引号,建议所有 属性
不添加引号。
对象创建时,如果任何一个 属性
需要添加引号,则所有 属性
建议添加 '
。
不允许修改和扩展任何原生对象和宿主对象的原型。
属性访问时,尽量使用 .
。
for in
遍历对象时, 使用 hasOwnProperty
过滤掉原型中的属性。
数组
使用数组字面量 []
创建新数组,除非想要创建的是指定长度的数组。
不因为性能的原因自己实现数组排序功能,尽量使用数组的 sort
方法。
清空数组使用 .length = 0
。
函数
函数长度
一个函数的长度控制在 50
行以内。
参数设计
一个函数的参数控制在 6
个以内。
通过 options
参数传递非数据输入型参数。
闭包
在适当的时候将闭包内大对象置为 null
。
使用 IIFE
避免 Lift 效应
。
空函数
空函数不使用 new Function()
的形式。
对于性能有高要求的场合,建议存在一个空函数的常量,供多处使用共享。
9.面向对象
类的继承方案,实现时需要修正 constructor
。
属性在构造函数中声明,方法在原型中声明。
自定义事件的 事件名
必须全小写。
自定义事件只能有一个 event
参数。如果事件需要传递较多信息,应仔细设计事件对象。
设计自定义事件时,应考虑禁止默认行为。
动态特性
eval
避免使用直接 eval
函数。
尽量避免使用 eval
函数。
动态执行代码。
使用 new Function
执行动态代码。
with
尽量不要使用 with
。
对象属性
避免修改外部传入的对象。
模块化
AMD
使用 AMD
作为模块定义。
模块 id
必须符合标准。
define
定义模块时不要指明 id
和 dependencies
。
使用 return
来返回模块定义。
require
全局运行环境中,require
必须以 async require
形式调用。
DOM
元素获取
对于单个元素,尽可能使用 document.getElementById
获取,避免使用document.all
。
对于多个元素的集合,尽可能使用 context.getElementsByTagName
获取。其中 context
可以为 document
或其他元素。指定 tagName
参数为 *
可以获得所有子元素。
遍历元素集合时,尽量缓存集合长度。如需多次操作同一集合,则应将集合转为数组。
样式获取
获取元素实际样式信息时,应使用 getComputedStyle
或 currentStyle
。
样式设置
尽可能通过为元素添加预定义的 className 来改变元素样式,避免直接操作 style 设置。
通过 style 对象设置元素样式时,对于带单位非 0 值的属性,不允许省略单位。
DOM 操作
操作 DOM
时,尽量减少页面 reflow
。
尽量减少 DOM
操作。
DOM 事件
优先使用 addEventListener / attachEvent
绑定事件,避免直接在 HTML 属性中或 DOM 的 expando
属性绑定事件处理。
使用 addEventListener
时第三个参数使用 false
。
在没有事件自动管理的框架支持下,应持有监听器函数的引用,在适当时候(元素释放、页面卸载等)移除添加的监听器。
代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
类名使用 UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外:DO / BO / DTO / VO / AO
方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式。
例:localValue / getHttpMessage() / inputUserId
常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。
中括号是数组类型的一部分,数组定义如下:String[] args;
POJO 类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。
包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。
杜绝完全不规范的缩写,避免望文不知义。
为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达其意。
如果模块、接口、类、方法使用了设计模式,在命名时体现出具体模式。
接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁性,并加上有效的 Javadoc 注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是 与接口方法相关,并且是整个应用的基础常量。
接口和实现类的命名
对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务一定是接口,内部的实现类用 Impl 的后缀与接口区别。
例:CacheServiceImpl 实现 CacheService 接口。
如果是形容能力的接口名称,取对应的形容词做接口名(通常是–able 的形式)。
例:AbstractTranslator 实现 Translatable。
枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。
各层命名规约:
Service/DAO 层方法命名规约
获取单个对象的方法用 get 做前缀。
获取多个对象的方法用 list 做前缀。
获取统计值的方法用 count 做前缀。
插入的方法用 save/insert 做前缀。
删除的方法用 remove/delete 做前缀。
修改的方法用 update 做前缀。
领域模型命名规约
数据对象:xxxDO,xxx 即为数据表名。
数据传输对象:xxxDTO,xxx 为业务领域相关的名称。
展示对象:xxxVO,xxx 一般为网页名称。
POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。
不允许任何魔法值(即未经定义的常量)直接出现在代码中。
long或者Long初始赋值时,使用大写的L,不能是小写的l,小写容易跟数字1混 淆,造成误解。
不要使用一个常量类维护所有常量,按常量功能进行归类,分开维护。
常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包 内共享常量、类内共享常量。
跨应用共享常量:放置在二方库中,通常是client.jar中的constant目录下。
应用内共享常量:放置在一方库中,通常是modules中的constant目录下。
子工程内部共享常量:即在当前子工程的constant目录下。
包内共享常量:即在当前包下单独的constant目录下。
类内共享常量:直接在类内部private static final定义。
如果变量值仅在一个范围内变化,且带有名称之外的延伸属性,定义为枚举类。下面 正例中的数字就是延伸信息,表示星期几。
例:public Enum { M0NDAY(1), TUESDAY(2), WEDNESDAY©), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7);}
大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果 是非空代码块则:
左大括号前不换行。
左大括号后换行。
右大括号前换行。
右大括号后还有else等代码则不换行;表示终止的右大括号后必须换行。
左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格。
if/for/while/switch/do等保留字与括号之间都必须加空格。
任何二目、三目运算符的左右两边都需要加一个空格。 说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。
采用4个空格缩进,禁止使用tab字符。
说明:如果使用tab缩进,必须设置1个tab为4个空格。IDEA设置tab为4个空格时, 请勿勾选 Use tab character;而在 eclipse 中,必须勾选 insert spaces for tabs
例:(涉及1-5点)
public static void main(String[] args) {
//缩进4个空格
String say = "hello";
//运算符的左右必须有一个空格
int flag = 0;
//关键词if与括号之间必须有一个空格,括号内的f与左括号,0与右括号不需要空格
if (flag == 0) (
System.out.println(say);
)
//左大括号前加空格且不换行;左大括号后换行
if (flag == 1) (
System.out.println("world");
//右大括号前换行,右大括号后有else,不用换行
) else ( System.out.println("ok");
//在右大括号后直接结束,则必须换行
)
)
单行字符数限制不超过****120****个,超出需要换行
方法参数在定义和传入时,多个参数逗号后边必须加空格。
IDE的text file encoding设置为UTF-8
方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。相同业务逻辑和语义之间不需要插入空行。
避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。
当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起, 便于阅读。
类内方法定义顺序依次是:公有方法或保护方法 > 私有方法> getter/setter方法。
final可以声明类、成员变量、方法、以及本地变量,下列情况使用final关键字:
不允许被继承的类,如:String类。
不允许修改引用的域对象,如:POJO类的域变量。
不允许被重写的方法,如:POJO类的setter方法。
不允许运行过程中重新赋值的局部变量。
避免上下文重复使用一个变量,使用final描述可以强制重新定义一个变量,方便更好 地进行重构。
慎用Object的clone方法来拷贝对象。
类成员与方法访问控制从严:
如果不允许外部直接通过new来创建对象,那么构造方法必须是private。
工具类不允许有public或default构造方法。
类非static成员变量并且与子类共享,必须是protected。
类非static成员变量并且仅在本类使用,必须是private。
类static成员变量如果仅在本类使用,必须是private。
若是static成员变量,必须考虑是否为final。
类成员方法只供类内部调用,必须是private。
类成员方法只对继承类公开,那么限制为protectedo
在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程 序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且 放在最后,即使它什么代码也没有。
在if/else/for/while/do语句中必须使用大括号。即使只有一行代码,避免采用单行的编码方式:if (condition) statements;
表达异常的分支时,少用if-else方式
除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复 杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。
循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、 获取数据库连接,进行不必要的try-catch操作(这个try-catch是否可以移至循环体外)。
接口入参保护,这种场景常见的是用于做批量操作的接口。
下列情形,需要进行参数校验:
调用频次低的方法。
执行时间开销很大的方法。此情形中,参数校验时间几乎可以忽略不计,但如果因为参 数错误导致中间执行回退,或者错误,那得不偿失。
需要极高稳定性和可用性的方法。
对外提供的开放接口,不管是RPC/API/HTTP接口。
敏感权限入口。
下列情形,不需要进行参数校验:
极有可能被循环调用的方法。但在方法说明里必须注明外部参数检查要求。
底层调用频度比较高的方法。毕竟是像纯净水过滤的最后一道,参数错误不太可能到底 层才会暴露问题。一般DAO层与Service层都在同一个应用中,部署在同一台服务器中,所 以DAO的参数校验,可以省略。
被声明成private只会被自己代码所调用的方法,如果能够确定调用方法的代码传入参 数已经做过检查或者肯定不会有问题,此时可以不校验参数。
类、类属性、类方法的注释必须使用Javadoc规范,不得使用 // xxx方式。
所有的抽象方法(包括接口中的方法)必须要用Javadoc注释、除了返回值、参数、 异常说明外,还必须指出该方法做什么事情,实现什么功能。
所有的类都必须添加创建者和创建日期。
方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释,注意与代码对齐。
所有的枚举类型字段必须要有注释,说明每个数据项的用途。
与其“半吊子”英文来注释,不如用中文注释把问题说清楚。专有名词与关键字保持 英文原文即可。
代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑 等的修改。
谨慎注释掉代码。在上方详细说明,而不是简单地注释掉。如果无用,则删除。 说明:代码被注释掉有两种可能性:1)后续会恢复此段代码逻辑。2)永久不用。前者如果没 有备注信息,难以知晓注释动机。后者建议直接删掉(代码仓库保存了历史代码)。
对于注释的要求:
能够准确反应设计思想和代码逻辑;
能够描述业务含 义,使别的程序员能够迅速了解到代码背后的信息。
好的命名、代码结构是自解释的,注释力求精简准确、表达到位。避免出现注释的 一个极端:过多过滥的注释,代码的逻辑一旦修改,修改注释是相当大的负担。
特殊注释标记,请注明标记人与标记时间。注意及时处理这些标记,通过标记扫描, 经常清理此类标记。线上故障有时候就是来源于这些标记处的代码。
待办事宜(TODO):(标记人,标记时间,[预计处理时间])
表示需要实现,但目前还未实现的功能。这实际上是一个Javadoc的标签,目前的Javadoc 还没有实现,但已经被广泛使用。只能应用于类,接口和方法(因为它是一个Javadoc标签)。
错误,不能工作(FIXME):(标记人,标记时间,[预计处理时间])
在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。
velocity调用POJO类的属性时,建议直接使用属性名取值即可,模板引擎会自动按 规范调用POJO的getXxx(),如果是boolean基本数据类型变量(boolean命名不需要加is 前缀),会自动调用isXxx()方法。
后台输送给页面的变量必须加$!{var}—中间的感叹号。 说明:如果var = null或者不存在,那么${var}会直接显示在页面上。
注意Math . random()这个方法返回是double类型,注意取值的范围0<x<1 (能够 取到零值,注意除零异常),如果想获取整数类型的随机数,不要将x放大10的若干倍然后 取整,直接使用Random对象的nextInt或者nextLong方法。
获取当前毫秒数 System.currentTimeMillis();而不是 new Date() .getTime(); 说明:如果想获取更加精确的纳秒级时间值,使用System.nanoTime()的方式。在JDK8中, 针对统计时间等场景,推荐使用Instant类。
不要在视图模板中加入任何复杂的逻辑。
任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存。
及时清理不再使用的代码段或配置信息。
Java类库中定义的一类RuntimeException可以通过预先检查进行规避,而不应该 通过 catch 来处理。
对大段代码进行try-catch,这是不负责任的表现。catch时请分清稳定代码和非稳 定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的catch尽可能进行区分 异常类型,再做对应的异常处理。
捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请 将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的 内容。
有try块放到了事务代码中,catch异常后,如果需要回滚事务,一定要注意手动回 滚事务。
finally块必须对资源对象、流对象进行关闭,有异常也要做try-catch。
不能在finally块中使用return,finally块中的return返回后方法结束执行,不 会再执行try块中的return语句。
捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类。 说明:如果预期对方抛的是绣球,实际接到的是铅球,就会产生意外情况。
方法的返回值可以为null,不强制返回空集合,或者空对象等,必须添加注释充分 说明什么情况下会返回null值。调用方需要进行null判断防止NPE问题。
防止NPE,是程序员的基本修养,注意NPE产生的场景:
返回类型为基本数据类型,return包装数据类型的对象时,自动拆箱有可能产生NPE。
数据库的查询结果可能为null。
集合里的元素即使isNotEmpty,取出的数据元素也可能为null。
远程调用返回对象时,一律要求进行空指针判断,防止NPE。
对于Session中获取的数据,建议NPE检查,避免空指针。
级联调用obj.getA().getB().getC(); 一连串调用,易产生NPE。
定义时区分unchecked / checked异常,避免直接抛出new RuntimeException(), 更不允许抛出Exception或者Throwable,应使用有业务含义的自定义异常。推荐业界已定义 过的自定义异常,如:DAOException / ServiceException 等。
避免出现重复的代码。
好的单元测试必须遵守AIR原则。
A: Automatic (自动化)
I: Independent (独立性)
R: Repeatable (可重复)
单元测试应该是全自动执行的,并且非交互式的。测试框架通常是定期执行的,执行 过程必须完全自动化才有意义。输出结果需要人工检查的测试不是一个好的单元测试。单元测 试中不准使用System.out来进行人肉验证,必须使用assert来验证。
保持单元测试的独立性。为了保证单元测试稳定可靠且便于维护,单元测试用例之间 决不能互相调用,也不能依赖执行的先后次序。
单元测试是可以重复执行的,不能受到外界环境的影响。
对于单元测试,要保证测试粒度足够小,有助于精确定位问题。单测粒度至多是类级 另U, 一般是方法级别。
核心业务、核心应用、核心模块的增量代码确保单元测试通过。
单元测试代码必须写在如下工程目录:src/test/java,不允许写在业务代码目录下。 说明:源码构建时会跳过此目录,而单元测试框架默认是扫描此目录。
单元测试的基本目标:语句覆盖率达到70%;核心模块的语句覆盖率和分支覆盖率都 要达到100%
编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量。
B: Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
C: Correct,正确的输入,并得到预期的结果。
D: Design,与设计文档相结合,来编写单元测试。
E: Error,强制错误信息输入(如:非法数据、异常流程、非业务允许输入等),并得 到预期的结果。
对于数据库相关的查询,更新,删除等操作,不能假设数据库里的数据是存在的, 或者直接操作数据库把数据插入进去,请使用程序插入或者导入数据的方式来准备数据。
和数据库相关的单元测试,可以设定自动回滚机制,不给数据库造成脏数据。或者 对单元测试产生的数据有明确的前后缀标识。
对于不可测的代码建议做必要的重构,使代码变得可测,避免为了达到测试要求而 书写不规范测试代码。
在设计评审阶段,开发人员需要和测试人员一起确定单元测试范围,单元测试最好 覆盖所有测试用例(UC)。
单元测试作为一种质量保障手段,不建议项目发布后补充单元测试用例,建议在项 目提测前完成单元测试。
为了更方便地进行单元测试,业务代码应避免以下情况:
构造方法中做的事情过多。
存在过多的全局变量和静态方法。
存在过多的外部依赖。
存在过多的条件语句。
表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint (1表示是,0表示否)。
表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。
表名不使用复数名词。
禁用保留字,如desc、range、match、delayed等,请参考MySQL官方保留字。
主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。 说明:pk_ 即 primary key; uk_ 即 unique key; idx_ 即 index 的简称。
小数类型为decimal,禁止使用float和double。
如果存储的字符串长度几乎相等,使用char定长字符串类型。
varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,如果存储长 度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索 引效率。
表必备三字段:id, gmt_create, gmt_modified。
表的命名最好是加上“业务名称_表的作用”。
库名与应用名称尽量一致。
如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。
字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:
不是频繁修改的字段。
不是varchar超长字段,更不能是text字段。
单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。
合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检 索速度。
业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
超过三个表禁止join。需要join的字段,数据类型必须绝对一致;多表关联查询时, 保证被关联的字段需要有索引。
在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度即可。
页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
如果有order by的场景,请注意利用索引的有序性。order by最后的字段是组合 索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort的情况,影响查询性能。
利用覆盖索引来进行查询操作,避免回表。
利用延迟关联或者子查询优化超多分页场景。
SQL性能优化的目标:至少要达到range级别,要求是ref级别,如果可以是consts 最好。
建组合索引的时候,区分度最高的在最左边。
防止因字段类型不同造成的隐式转换,导致索引失效。
创建索引时避免有如下极端误解:
宁滥勿缺。认为一个查询就需要建一个索引。
宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增速度。
抵制惟一索引。认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。
不要使用count(列名)或count(常量)来替代count(),count()是SQL92定义的 标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。
count(distinct col)计算该列除NULL之外的不重复行数,注意count(distinct col1, col2)如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。
当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为 NULL,因此使用sum()时需注意NPE问题。
使用ISNULL()来判断是否为NULL值。
在代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句。
不得使用外键与级联,一切外键概念必须在应用层解决。
禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
数据订正时,删除和修改记录时,要先select,避免出现误删除,确认无误才能执 行更新语句。
in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控 制在1。。。个之内。
如果有全球化需要,所有的字符存储与表示,均以utf-8编码,注意字符统计函数 的区别。
如果需要存储表情,那么选择utfmb4来进行存储,注意它与utf-8编码的区别。
TRUNCATE TABLE比DELETE速度快,且使用的系统和事务日志资源少,但TRUNCATE 无事务且不触发trigger,有可能造成事故,故不建议在开发代码中使用此语句。
在表查询中,一律不要使用星号作为查询的字段列表,需要哪些字段必须明确写明。
POJO类的布尔属性不能加is,而数据库字段必须加is_,要求在resultMap中进行 字段与属性之间的映射。
不要用resultclass当返回参数,即使所有类属性名与数据库字段一一对应,也需 要定义;反过来,每一个表也必然有一个与之对应。
sql.xml配置参数使用:#{},#param#不要使用${}此种方式容易出现SQL注入。
iBATIS 自带的 queryForList(String statementName, int start, int size)不推 荐使用。
不允许直接拿HashMap与Hashtable作为查询结果集的输出。
更新数据表记录时,必须同时更新记录对应的gmt_modified字段值为当前时间。
不要写一个大而全的数据更新接口。传入为POJO类,不管是不是自己的目标更新字 段,都进行叩date table set c1=value1,c2=value2, c3=value3;这是不对的。执行 SQL 时,不要更新无改动的字段,一是易出错;二是效率低;三是增加binlog存储。
@Transactional事务不要滥用。事务会影响数据库的QPS,另外使用事务的地方需 要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。
<isEqual>中的compareValue是与属性值对比的常量,一般是数字,表示相等时带 上此条件;<isNotEmpty>表示不为空且不为null时执行;<isNotNull>表示不为null值时 执行。
完成前台对应的前端开发(小组项目分为前台和后台)
进行相应功能的测试
完成前台对应的后端开发
进行相应功能的测试
本次项目前台的各功能模块划分如下
登录模块
地图模块
自习模块
单机自习模块
联机自习模块
个人中心模块
展示修改个人资料界面
自习数据概览模块
在完成制作与整体测试后,将项目部署至服务器上
时间 | 天数 | 安排 |
---|---|---|
4.26 | 1天 | 编写置顶集合随笔 编写代码规范、冲刺任务与计划 进行开发前的准备 每个组员拉取一条自己有关的分支,并做到正常运行 每个人登录Teambition在自己的任务下面将这次的任务细化为若干个子任务,方便做燃尽图 |
4.27-5.10 | 9天 | 完成各模块代码编写 |
5.11 | 1天 | 完成整体测试 |
5.12 | 1天 | 部署,发布alpha版本 编写测试随笔 |
5.13 | 1天 | 编写冲刺总结随笔 制作答辩PPT |
每天举行站立式会议并拍照
每日汇报:每天晚上10点前完成填写q群的在线文档
每天晚上11点负责人要负责合并代码到dev分支中
每天晚上11点前发布冲刺随笔
我们小组将各模块(详见本次冲刺任务部分介绍)参照照功能及开发难度的合理性划分为几个部分,然后由小组成员自行选择进行开发。最终,我们小组各部分的划分及分工如下所示:
序号 | 前端or后端 | 负责内容 | 人员 |
---|---|---|---|
1 | 前端 | 前台登录模块 个人中心模块——展示修改个人资料 | 李鸿翔 |
2 | 前端 | 个人中心模块——自习数据概览模块 | 李慧子 |
3 | 前端 | 地图模块 | 黄子龙 |
4 | 前端 | 自习模块——单机自习模块 | 王亚娇 |
5 | 前端 | 自习模块——联机自习模块 | 陈志霖 |
6 | 后端 | 前台登录模块接口 个人信息接口 | 詹鹏翔 |
7 | 后端 | 自习数据概览模块接口 | 陈玮鑫 |
8 | 后端 | 教室查询接口 推荐教室接口 | 王凯达 |
9 | 后端 | 白应用软件接口 添加自习记录接口 | 黄依灵 |
10 | 后端 | 联机自习接口 | 陈少峰 |
4月28日根据项目情况修改分工为:
序号 | 工作方向 | 负责内容 | 人员 |
---|---|---|---|
1 | 前端 | 前台登录模块 个人中心模块——展示修改个人资料 | 李鸿翔 |
2 | 前端 | 个人中心模块——自习数据概览模块 | 李慧子 |
3 | 前端 | 地图模块 | 黄子龙 |
4 | 前端 | 自习模块——单机自习模块 | 王亚娇 |
5 | 前端 | 自习模块——联机自习模块 | 陈志霖 |
6 | 后端 | 前台登录模块接口,个人信息接口 教室查询接口,推荐教室接口 | 詹鹏翔 |
7 | 后端 | 自习数据概览模块接口 | 陈玮鑫 |
8 | 后端 | 白应用软件接口 添加自习记录接口 | 黄依灵 |
9 | 后端 | 联机自习接口 | 陈少峰 |
10 | 文职和汇报 | 8篇冲刺随笔,1篇测试随笔,1篇冲刺总结随笔 ,其他工作,汇报 | 王凯达 |
tips:
由于各模块的开发可能存在部分的代码复用问题,在开发过程中由相关部分的负责人员自行讨论,根据具体情况灵活调整
前后端开发过程中有不确定、不明白的地方时,请联系对应部分的开发人员
职责 | 具体内容 | 人员 |
---|---|---|
前端负责人 | 合并代码,检查每个人的代码并微调,解答疑惑 | 王亚娇 |
后端负责人 | 合并代码,检查每个人的代码并微调,解答疑惑 | 詹鹏翔 |
编写博客 | 1篇置顶集合随笔,代码规范、冲刺任务与计划随笔,10篇冲刺随笔,1篇测试随笔,1篇冲刺总结随笔 | 李慧子 |
课堂演示、答辩 | 汇报 | 王凯达 |
课堂演示、答辩 | 制作PPT | 黄依灵 |
4月28日根据项目情况修改分工为:
职责 | 具体内容 | 人员 |
---|---|---|
前端负责人 | 合并代码,检查每个人的代码并微调,解答疑惑 | 王亚娇 |
后端负责人 | 合并代码,检查每个人的代码并微调,解答疑惑 | 詹鹏翔 |
编写博客 | 1篇置顶集合随笔,代码规范、冲刺任务与计划随笔,2篇冲刺随笔 | 李慧子 |
课堂演示 | 制作PPT | 黄依灵 |