编码规范

  1. 好的编码规范可以尽可能的减少一个软件的维护成本,并且几乎没有任何一个软件,在其整个生命周期中,均由最初的开发人员来维护。
  2. 好的编码规范可以改善软件的可读性,可以让开发人员尽快而彻底地理解新的代码。
  3. 好的编码规范可以最大限度的提高团队开发的合作效率。
  4. 长期的规范性编码还可以让开发人员养成好的编码习惯,甚至锻炼出更加严谨的思维。

一、安全规约

通过学习阿里巴巴的《阿里巴巴Java开发手册》和公司视频讲解,发现这七大强制约定和一个推荐约定的对于一个开发人员的良好编码习惯和逻辑思维有着重要的启发和引导作用。

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

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

1.2用户敏感数据禁止直接展示,必须对展示数据进行脱敏。

说明:查看个人手机号码会显示成:178****3012 ,隐藏中间4位,防止隐私泄露。
数据脱敏:对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。

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

METADATA:元数据,又称中介数据、中继数据,为描述数据的数据,主要描述数据属性的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能
#{}是通过占位?的形式对sql语句进行先编译后引用,可以有效的防止sql注入攻击
${}不经过预编译,直接通过字符串拼接是的形式。容易造成sql注入攻击

1.4用户请求传入的任何参数必须做有效性验证。

忽略参数校验可能导致:
1)page size过大导致内存溢出;
2)恶意order by导致数据库慢查询
3)任意重定向
4)SQL注入
5)反序列化注入
6)正则输入源串拒绝服务ReDoS【正则表达式拒绝服务攻击和防御】
说明:Java代码用正则来验证客户端的输入,有些正则写法验证普通用户输入没有问题,但是如果攻击人员使用的是特殊构造的字符串来验证,有可能导致死循环的结果。

1.5禁止向HTML页面输出未经安全过滤或未正确转义的用户数据。

出口:一般指的是web页面,系统的出口要堵住特殊字符,
入口:可能是web页面也可能是开发接口,保证系统入口也不要有特殊字符,
可以在不同版本和设备上的自由使用,而不会造成编码错误

1.6表单、AJAX提交必须执行CSRF安全过滤。

说明:CSRF(Cross-site request forgery)跨站请求伪造是一类常见编程漏洞。对于存在CSRF漏洞的应用/网站,攻击者可以事先构造好URL,只要受害者用户一访问,后台便在用户不知情情况下对数据库中用户参数进行相应修改。
攻击者不是获取用户的账户信息和控制权,而是通过欺骗用户浏览器,以用户的名义进行操作,
验证方法:
1)检查Referer字段
Refere:Header中的信息,代表访问来源站点的地址
优点:简单易行,工作量低,仅需要在关键访问增加一步校验
缺点:有局限性,完全依赖于浏览器,可能被恶意浏览器篡改referer内容
2)添加校验token
方式:服务器给在客户端发送请求时,生产一个随机数,并保存到redis或者服务器中,并发送到客户端。用户提交表单时,服务器会获取这个随机数并和服务器存储的数据进行比较验证
优点:更加安全,可以有效防止csrf
缺点:有一定的工作量

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

说明:如注册时发送验证码到手机,如果没有限制次数和频率,那么可以利用此功能骚扰到其他用户,并造成短信平台资源浪费。
作用1.减少资源的浪费2.防止刷新页面导致订单或者支付重复,

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

二、mysql数据库

底层数据库的规范有助于减少软件实现的复杂度,降低沟通成本,本
章主要说明建表规范 索引优化准则以及 ORM 层的处理约定。

(一)建表规范

1.1表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint( 1表示是,0表示否)。

说明:任何字段如果为非负数,必须是unsigned。
正例:表达逻辑删除的字段名is_deleted,1表示删除,0表示未删除。

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

说明: MySQL Wind 下不区分大小写,但在 inux 下默
认区分大小写 因此,数据库名 表名 字段名都不允
许出现任何大写字母 避免节外生枝
正例:getter_admin,task_config,level3_name
反例:GetterAdmin,taskConfig,level_3_name

1.3表名不使用复数名词。

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

1.4禁用保留字,如desc、range、match、delayed等,请参考MySQL官方保留字。

1.5主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。

说明:pk_ 即primary key;uk_ 即 unique key;idx_ 即index的简称。

1.6小数类型为decimal,禁止使用float和double。

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

1.7如果存储的字符串长度几乎相等,使用char定长字符串类型。

1.8 varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,

如果存储长度大于5000,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。

1.9表必备三字段:id, gmt_create/creat_time, gmt_modified/update_time。

说明:其中id必为主键,类型为unsigned bigint、单表时自增、步长为1。gmt_create/creat_time, gmt_modified/update_time的类型均为date_time类型。gmt_create/creat_time,建表时间,gmt_modified/update_time,修改时间。

1.10.表的命名最好是加上“业务名称_表的作用”。

正例:tiger_task / tiger_reader / mpp_config

1.11库名与应用名称尽量一致。

(二)索引规约

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

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

2.2超过 个表禁止 join 需要 jo 川的字段,数据必须绝对 致;当多表关联查询时,保证被关联的宇段需要有索引。

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

2.3 varchar 字段上建立索引时,必须指定索引长度,没必要对全宇段建立索引,根据实际文本区分度决定索引长度即可。

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

2.4页面搜索严禁左模糊或者全模糊,如果需要请通过搜索引擎来解决

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

2.5创建索引时避免有如下极端误解

1)宁滥勿缺。认为一个查询就需要建一个索引
2)宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增
速度
3)抵制唯一索引。认为业务的唯一性,一律需要在应用层通过“先查后插”的方式解决

2.6建组合索引的时候,区分度最高的在最左边。

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

2.7如果有order by的场景,请注意利用索引的有序性。

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

(三)SQL语句

3.1【强制】不要使用count(列名)或count(常量)来替代count(*), count(*)是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。

说明:count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。

3.2 【强制】count(distinct col) 计算该列除NULL之外的不重复行数,

注意 count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。

3.3【强制】当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为NULL,因此使用sum()时需注意NPE问题。

正例:可以使用如下方式来避免sum的NPE问题:SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM table;

3.4 【强制】使用ISNULL()来判断是否为NULL值。注意:NULL与任何值的直接比较都为NULL

说明: 1) NULL<>NULL的返回结果是NULL,而不是false。
2) NULL=NULL的返回结果是NULL,而不是true。
3) NULL<>1的返回结果是NULL,而不是true。

3.5 【强制】 在代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句。

3.6 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。

说明:(概念解释)学生表中的student_id是主键,那么成绩表中的student_id则为外键。
如果更新学生表中的student_id,同时触发成绩表中的student_id更新,则为级联更新。
外键与级联更新适用于单机低并发,不适合分布式、高并发集群;
级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

3.7 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

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

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

3.10【参考】如果有全球化需要,所有的字符存储与表示,均以utf-8编码,注意字符统计函数的区别。

说明: SELECT LENGTH(“轻松工作”); 返回为12;
SELECT CHARACTER_LENGTH(“轻松工作”); 返回为4
如果要使用表情,那么使用utfmb4来进行存储,注意它与utf-8编码的区别

3.11【参考】 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但TRUNCATE无事务且不触发trigger,有可能造成事故,故不建议在开发代码中使用此语句。

说明:TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。

(四)ORM映射

4.1【强制】在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。

说明:1)增加查询分析器解析成本。
2)增减字段容易与resultMap配置不一致。

4.2【强制】POJO类的布尔属性不能加is,而数据库字段必须加is_,要求在resultMap中进行字段与属性之间的映射。

说明:参见定义POJO类以及数据库字段定义规定,在中增加映射,是必须的。
在MyBatis Generator生成的代码中,需要进行对应的修改。

4.3 【强制】不要用resultClass当返回参数,即使所有类属性名与数据库字段一一对应,也需要定义;

反过来,每一个表也必然有一个与之对应。 说明:配置映射关系,使字段与DO类解耦,方便维护。一般不用,resulttype和resultmap就够操作了

4.4 【强制】sql.xml配置参数使用:#{},#param# 不要使用${} 此种方式容易出现SQL注入。

4.5 【强制】iBATIS自带的queryForList(String statementName,int start,int size)不推荐使用。

说明:其实现方式是在数据库取到statementName对应的SQL语句的所有记录,再通过subList取start,size的子集合。分页,一般都用limit
正例:Map<String, Object> map = new HashMap<String, Object>();
map.put(“start”, start);
map.put(“size”, size);

4.6 【强制】不允许直接拿HashMap与Hashtable作为查询结果集的输出。

说明:resultClass=”Hashtable”,会置入字段名和属性值,但是值的类型不可控。

4.7 【强制】更新数据表记录时,必须同时更新记录对应的gmt_modified/update_time字段值为当前时间。

spring boot代码编写注意事项

一、ResTful API 风格

1.1 Restful简介

springMVC对编写Restful Api提供了很好的支持。
Restful Api有三个主要的特性:
1.是基于Http协议的,是无状态的。
2.是以资源为导向的
3.人性化的,返回体内部包含相关必要的指导和链接
面向资源?
传统的Api接口以动作为导向,并且请求方法单一。
例如 /user/query?id=1 GET方法 ;
/user/create POST方法
而在resultful风格下以资源为导向,
例如: /user/id(GET方法,获取) /user/(POST方法,创建)
restful api 用url描述资源,用Http方法描述行为,用Http状态码描述不同的结果,使用json作为交互数据(包括入参和响应)
restful只是一种风格并不是一种强制的标准
@PathVariable

/*** 映射url片段到java方法参数*/
@GetMapping("/user/{id}")public User getUserInfo(@PathVariable("id") String id){return new User("sico","12345");}/*** 获取用户详情,利用正则表达式限定为只接收数字* @param id* @return*/@GetMapping("/user/{id:\\d+}")public User getUserInfo(@PathVariable("id") String id){return new User("sico","12345");}

RequestMapping的变体
RequestMapping有以下变体,他们分别对应了不同的请求方法
@GetMapping 对应GET方法
@PostMapping 对应POST方法
@PutMapping 对应PUT方法
@DeleteMapping 对应DELETE方法
@RequestBody将请求体映射到java方法参数
@(spring)RequestBody将请求中的请求体中的实体数据转换成实体对象,常用语PUT和POST

    /*** 创建用户* 仅有加入@RequestBody注解才能解析出请求体重传入的实体数据*/@PutMapping("/user")public void create(@RequestBody User user){User user1=new User("cocoa","123",1);}

@Valid注解和BindingResult验证请求参数的合法性并处理校验结果
1.将此注解加到实体类(pojo/entry)中的属性上。
@Null
限制只能为null
@NotNull
限制必须不为null
@AssertFalse
限制必须为false
@AssertTrue
限制必须为true
@DecimalMax(value)
限制必须为一个不大于指定值的数字
@DecimalMin(value)
限制必须为一个不小于指定值的数字
@Digits(integer,fraction)
限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future
限制必须是一个将来的日期
@Max(value)
限制必须为一个不大于指定值的数字
@Min(value)
限制必须为一个不小于指定值的数字
@Past
限制必须是一个过去的日期
@Pattern(value)
限制必须符合指定的正则表达式
@Size(max,min)
限制字符长度必须在min到max之间
@Past
验证注解的元素值(日期类型)比当前时间早
@NotEmpty
验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank
验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email
验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式
2.在请求方法的字段上加上@valid注解时,以上的注解将生效。如果请求接口的参数无法通过校验,将返回400
如果使用@valid注解,当参数不符合标准时。会直接返回400。而不会进入接口方法的方法体。如果需要对没通过校验的请求作一些处理。在使用BindingResult的情况下,如果用户传入的参数不符合约束。则相应的错误信息将会被放置在BindingRsult对象中。

 @PutMapping("/user")public void create(@Valid @RequestBody User user, BindingResult errors){//如果参数不符合,便可以取出错误信息if (errors.hasErrors()){errors.getAllErrors().stream().forEach(error->logger.error(error.getDefaultMessage()));}User user1=new User("cocoa","123",1);}

获取校验错误信息(包括字段信息)
使用fieldError可以获取错误的字段信息和错误信息

 @PutMapping("/user")public void update(@Valid @RequestBody User user,BindingResult errors){if (errors.hasErrors()){errors.getAllErrors().stream().forEach(error->{FieldError fieldError=(FieldError) error;String errorMessage=fieldError.getField()+" "+fieldError.getDefaultMessage();logger.error(errorMessage);});}User user1=new User("cocoa","123",1);}

自定义校验失败信息
用以上方式虽然能够获得错误字段和错误信息,但过于麻烦。可以在校验注解中指定message值自定义错误信息

@NotBlank(message = "用户名不能为空")private String username;

1.2 HTTP方法

GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新全部资源(客户端提供改变后的完整资源)。
PATCH(UPDATE):在服务器更新部分资源(客户端提供改变的属性)。
DELETE(DELETE):从服务器删除资源。

1.3 响应状态码

100~199:信息状态码,代表请求已被接受,需要继续处理。
200~299:成功状态码,代表请求已成功被服务器接收、理解、并接受。
300~399:重定向状态码,代表需要客户端采取进一步的操作才能完成请求。
400~499:客户端错误状态码,代表了客户端看起来可能发生了错误,妨碍了服务器的处理。
500~599:服务器错误状态码,代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。
特别注意几个常用的状态码:
200
请求已成功,请求所希望的响应头或数据体将随此响应返回。
400
1、语义有误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求。   
2、请求参数有误。
500
服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器的程序码出错时出现。

1.4 @JsonView

注解@JsonView的使用,有时候我们希望在不同的请求中隐藏一些字段。可以用@JsonView控制输出内容。
例子:条件查询时候不返回用户的密码,查看详情时候返回用户的密码
SpringMVC会将实体对象转换成json返回。有时候我们希望在不同的请求中隐藏一些字段。可以用@JsonView控制输出内容。
使用@jsonView注解有以下步骤:
1使用接口来声明多个视图
2在值对象的getter方法上指定视图
3在controller方法上指定视图
使用接口声明视图
此接口只作声明使用,可以直接放置到目标实体内部,

public class User implements Serializable{//定义两个视图public interface SimpleView{};public interface DetailView extends SimpleView{};//DetailView继承了SimpleView。即视图DetailView会显示被SimpleView标注的视图//....
}

在值对象上的getter方法上指定视图

    @JsonView(SimpleView.class)public String getUsername() {return username;}//...@JsonView(DetailView.class)public String getPassword() {return password;}

在方法上指定视图

   /*** 获取用户基本,利用正则表达式限定为只接收数字*///@GetMapping("/user/{id:\\d+}")// @JsonView(User.SimpleView.class)// public User getUserInfo(@PathVariable("id") String id){//   return new User("sico","12345");//  }/*** 获取用户详情,利用正则表达式限定为只接收数字* @param id* @return*/@GetMapping("/user/{id:\\d+}")@JsonView(User.DetailView.class)public User getUserInfo(@PathVariable("id") String id){return new User("sico","12345");}

1.5 代码逻辑必须写在service层,除非极为特殊情况,可以将少量逻辑放在controller

二、SpringBoot Web项目的参数

1.参数类型必须书写包装类型
2.表单里的参数和代码里的参数名不一样怎么办,这时候就可以用注解了:@RequestParam(value = “表单参数名”)
3.表单客户不填任何值,但是在控制器里如果希望它有默认值
可以这样:@RequestParam(defaultValue = “5”)
RequestParam还有个属性:required(必填)当required=true,和defaultValue= 同时出现时,required失效,可传可不传

三、AOP切面的理解与应用

AOP(Aspect Orient Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程(OOP)的一种补充和完善。它以通过预编译方式和运行期动态代理方式,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。例如登录验证,日志记录
▪切面(aspect): 横切面对象,一般为一个具体类对象(可以借助@Aspect声明)。
▪通知(Advice):在切面的某个特定连接点上执行的动作(扩展功能),例如around,before,after等。
▪连接点(joinpoint):程序执行过程中某个特定的点,一般指向被拦截到的目标方法。
▪切入点(pointcut):对多个连接点(Joinpoint)一种定义,一般可以理解为多个连接点的集合。

@Aspect
@Slf4j
@Component
public class SysLogAspect {@Pointcut("bean(sysUserServiceImpl)")public void doLogPointCut() {}@Around("doLogPointCut()")public Object around(ProceedingJoinPoint jp)throws Throwable{try {log.info("start:{}"+System.currentTimeMillis());Object result=jp.proceed();//最终会调用目标方法log.info("after:{}"+System.currentTimeMillis());return result;}catch(Throwable e) {log.error("after:{}",e.getMessage());throw e;}}
}

@Aspect 注解用于标识或者描述AOP中的切面类型,基于切面类型构建的对象用于为目标对象进行功能扩展或控制目标对象的执行。
@Pointcut注解用于描述切面中的方法,并定义切面中的切入点(基于特定表达式的方式进行描述),在本案例中切入点表达式用的是bean表达式,这个表达式以bean开头,bean括号中的内容为一个spring管理的某个bean对象的名字。
@Around注解用于描述切面中方法,这样的方法会被认为是一个环绕通知(核心业务方法执行之前和之后要执行的一个动作),@Aournd注解内部value属性的值为一个切入点表达式或者是切入点表达式的一个引用(这个引用为一个@PointCut注解描述的方法的方法名)。
ProceedingJoinPoint类为一个连接点类型,此类型的对象用于封装要执行的目标方法相关的一些信息。只能用于@Around注解描述的方法参数。

前端编码规范

一、 一般规范

1.1 文件/资源命名

1.文件命名总是以字母开头而不是数字
2.字母名称必须全为小写
3.对文件增加前后缀或特定的扩展名或一串前缀,建议使用点分隔符来区分这些在文件名中带有清晰意义的元数据
不推荐

 MyScript.js myCamelCaseName.cssi_love_underscores.html1001-scripts.js my-file-min.css

推荐

my-script.js
my-camel-case-name.css
i-love-underscores.html
thousand-and-one-scripts.js
my-file.min.css

1.2 协议

不要指定引入资源所带的具体协议。
当引入图片或其他媒体文件,还有样式和脚本时,URLs 所指向的具体路径,不要指定协议部分(http:, https:),除非这两者协议都不可用。
不指定协议使得 URL 从绝对的获取路径转变为相对的,在请求资源协议无法确定时非常好用,而且还能为文件大小节省几个字节。

1.3 文本缩进

一次缩进两个空格。

1.4 注释

注释是你自己与你的小伙伴们了解代码写法和目的的唯一途径。特别是在写一些看似琐碎的无关紧要的代码时,由于记忆点不深刻,注释就变得尤为重要了。
编写自解释代码只是一个传说,没有任何代码是可以完全自解释的。而代码注释,则是永远也不嫌多。
当你写注释时一定要注意:不要写你的代码都干了些什么,而要写你的代码为什么要这么写,背后的考量是什么。当然也可以加入所思考问题或是解决方案的链接地址。
JSDoc 或 YUIDoc 就是用来写 JavaScript 注释用的

1.5 代码检查

对于比较宽松自由的编程语言来说,严格遵循编码规范和格式化风格指南就显得极为重要

二、 HTML 规范

2.1文档类型

推荐使用 HTML5 的文档类型申明: <!DOCTYPE html>.
(建议使用 text/html 格式的 HTML。避免使用 XHTML。XHTML 以及它的属性,比如 application/xhtml+xml 在浏览器中的应用支持与优化空间都十分有限)。
HTML 中最好不要将无内容元素[1] 的标签闭合,例如:使用
而非
.

2.2 HTML 验证

一般情况下,建议使用能通过标准规范验证的 HTML 代码,除非在性能优化和控制文件大小上不得不做出让步。
使用诸如 W3C HTML validator 这样的工具来进行检测。
规范化的 HTML 是显现技术要求与局限的显著质量基线,它促进了 HTML 被更好地运用。
不推荐

<title>Test</title>
<article>This is only a test.

推荐

<!DOCTYPE html>
<meta charset="utf-8">
<title>Test</title>
<article>This is only a test.</article>

省略可选标签
HTML5 规范中规定了 HTML 标签是可以省略的。但从可读性来说,在开发的源文件中最好不要这样做,因为省略标签可能会导致一些问题。
省略一些可选的标签确实使得页面大小减少,这很有用,尤其是对于一些大型网站来说。为了达到这一目的,我们可以在开发后期对页面进行压缩处理,在这个环节中这些可选的标签完全就可以省略掉了。

2.3 脚本加载

出于性能考虑,脚本异步加载很关键。一段脚本放置在 内,比如 ,其加载会一直阻塞 DOM 解析,直至它完全地加载和执行完毕。这会造成页面显示的延迟。特别是一些重量级的脚本,对用户体验来说那真是一个巨大的影响。
异步加载脚本可缓解这种性能影响。如果只需兼容 IE10+,可将 HTML5 的 async 属性加至脚本中,它可防止阻塞 DOM 的解析,甚至你可以将脚本引用写在 里也没有影响。
如需兼容老旧的浏览器,实践表明可使用用来动态注入脚本的脚本加载器。你可以考虑 yepnope 或 labjs。注入脚本的一个问题是:一直要等到 CSS 对象文档已就绪,它们才开始加载。
脚本引用写在 body 结束标签之前,并带上 async 属性。这虽然在老旧浏览器中不会异步加载脚本,但它只阻塞了 body 结束标签之前的 DOM 解析,这就大大降低了其阻塞影响。而在现代浏览器中,脚本将在 DOM 解析器发现 body 尾部的 script 标签才进行加载,此时加载属于异步加载,不会阻塞 CSSOM(但其执行仍发生在 CSSOM 之后)。

所有浏览器中,推荐

<html><head><link rel="stylesheet" href="main.css"></head><body><!-- body goes here --><script src="main.js" async></script></body>
</html>

只在现代浏览器中,推荐

<html><head><link rel="stylesheet" href="main.css"><script src="main.js" async></script></head><body><!-- body goes here --></body>
</html>

2.4 语义化

根据元素(有时被错误地称作“标签”)其被创造出来时的初始意义来使用它。打个比方,用 heading 元素来定义头部标题,p 元素来定义文字段落,用 a 元素来定义链接锚点,等等。
有根据有目的地使用 HTML 元素,对于可访问性、代码重用、代码效率来说意义重大。
以下示例列出了一些的语义化 HTML 主要情况:
不推荐

<b>My page title</b>
<div class="top-navigation"><div class="nav-item"><a href="#home">Home</a></div><div class="nav-item"><a href="#news">News</a></div><div class="nav-item"><a href="#about">About</a></div>
</div><div class="news-page"><div class="page-section news"><div class="title">All news articles</div><div class="news-article"><h2>Bad article</h2><div class="intro">Introduction sub-title</div><div class="content">This is a very bad example for HTML semantics</div><div class="article-side-notes">I think I'm more on the side and should not receive the main credits</div><div class="article-foot-notes">This article was created by David <div class="time">2014-01-01 00:00</div></div></div><div class="section-footer">Related sections: Events, Public holidays</div></div>
</div><div class="page-footer">Copyright 2014
</div>

推荐

<!-- The page header should go into a header element -->
<header><!-- As this title belongs to the page structure it's a heading and h1 should be used --><h1>My page title</h1>
</header><!-- All navigation should go into a nav element -->
<nav class="top-navigation"><!-- A listing of elements should always go to UL (OL for ordered listings) --><ul><li class="nav-item"><a href="#home">Home</a></li><li class="nav-item"><a href="#news">News</a></li><li class="nav-item"><a href="#about">About</a></li></ul>
</nav><!-- The main part of the page should go into a main element (also use role="main" for accessibility) -->
<main class="news-page" role="main"><!-- A section of a page should go into a section element. Divide a page into sections with semantic elements. --><section class="page-section news"><!-- A section header should go into a section element --><header><!-- As a page section belongs to the page structure heading elements should be used (in this case h2) --><h2 class="title">All news articles</h2></header><!-- If a section / module can be seen as an article (news article, blog entry, products teaser, any otherre-usable module / section that can occur multiple times on a page) a article element should be used --><article class="news-article"><!-- An article can contain a header that contains the summary / introduction information of the article --><header><!-- As a article title does not belong to the overall page structure there should not be any heading tag! --><div class="article-title">Good article</div><!-- Small can optionally be used to reduce importance --><small class="intro">Introduction sub-title</small></header><!-- For the main content in a section or article there is no semantic element --><div class="content"><p>This is a good example for HTML semantics</p></div><!-- For content that is represented as side note or less important information in a given context use aside --><aside class="article-side-notes"><p>I think I'm more on the side and should not receive the main credits</p></aside><!-- Articles can also contain footers. If you have footnotes for an article place them into a footer element --><footer class="article-foot-notes"><!-- The time element can be used to annotate a timestamp. Use the datetime attribute to specify ISO timewhile the actual text in the time element can also be more human readable / relative --><p>This article was created by David <time datetime="2014-01-01 00:00" class="time">1 month ago</time></p></footer></article><!-- In a section, footnotes or similar information can also go into a footer element --><footer class="section-footer"><p>Related sections: Events, Public holidays</p></footer></section>
</main><!-- Your page footer should go into a global footer element -->
<footer class="page-footer">Copyright 2014
</footer>

2.5 多媒体回溯

对页面上的媒体而言,像图片、视频、canvas 动画等,要确保其有可替代的接入接口。图片文件我们可采用有意义的备选文本(alt),视频和音频文件我们可以为其加上说明文字或字幕。
提供可替代内容对可用性来说十分重要。试想,一位盲人用户如何能知晓一张图片是什么,要是没有 @alt 的话。
(图片的 alt 属性是可不填写内容的,纯装饰性的图片就可用这么做:alt="")。

不推荐

<img src="luke-skywalker.jpg">

推荐

<img src="luke-skywalker.jpg" alt="Luke skywalker riding an alien horse">

尽量用 alt 标签去描述图片,设想你需要对于那些只能通过语音或者看不见图片的用户表达图片到底是什么。
不推荐

<img src="huge-spaceship-approaching-earth.jpg" alt="Header image">

推荐

<img src="huge-spaceship-approaching-earth.jpg" alt="A huge spaceship that is approaching the earth">

2.6 关注点分离

理解 web 中如何和为何区分不同的关注点,这很重要。这里的关注点主要指的是:信息(HTML 结构)、外观(CSS)和行为(JavaScript)。为了使它们成为可维护的干净整洁的代码,我们要尽可能的将它们分离开来。
严格地保证结构、表现、行为三者分离,并尽量使三者之间没有太多的交互和联系。
就是说,尽量在文档和模板中只包含结构性的 HTML;而将所有表现代码,移入样式表中;将所有动作行为,移入脚本之中。
在此之外,为使得它们之间的联系尽可能的小,在文档和模板中也尽量少地引入样式和脚本文件。
清晰的分层意味着:

  • 不使用超过一到两张样式表(i.e. main.css, vendor.css
  • 不使用超过一到两个脚本(学会用合并脚本)
  • 不使用行内样式(<style>.no-good {}</style>
  • 不在元素上使用 style 属性(<hr style="border-top: 5px solid black">
  • 不使用行内脚本(<script>alert('no good')</script>
  • 不使用表象元素(i.e. <b>, <u>, <center>, <font>, <b>
  • 不使用表象 class 名(i.e. red, left, center

2.7 HTML 内容至上

不要让非内容信息污染了你的 HTML。现在貌似有一种倾向:通过 HTML 来解决设计问题,这是显然是不对的。HTML 就应该只关注内容。
HTML 标签的目的,就是为了不断地展示内容信息。

  • 不要引入一些特定的 HTML 结构来解决一些视觉设计问题
  • 不要将 img 元素当做专门用来做视觉设计的元素

2.8 Type 属性

省略样式表与脚本上的 type 属性。鉴于 HTML5 中以上两者默认的 type 值就是 text/css 和 text/javascript,所以 type 属性一般是可以忽略掉的。

2.9 HTML 引号

使用双引号(“”) 而不是单引号(”) 。

2.10 格式化规则

在每一个块状元素,列表元素和表格元素后,加上一新空白行,并对其子孙元素进行缩进。内联元素写在一行内,块状元素还有列表和表格要另起一行。

2.11 ID 和锚点

通常一个比较好的做法是将页面内所有的头部标题元素都加上 ID. 这样做,页面 URL 的 hash 中带上对应的 ID 名称,即形成描点,方便跳转至对应元素所处位置。
打个比方,当你在浏览器中输入 URL http://your-site.com/about#best-practices,浏览器将定位至元素处

三、JavaScript 规范

3.1 全局命名空间污染与 IIFE

总是将代码包裹成一个 IIFE(Immediately-Invoked Function Expression),用以创建独立隔绝的定义域。这一举措可防止全局命名空间被污染。
IIFE 还可确保你的代码不会轻易被其它全局命名空间里的代码所修改(i.e. 第三方库,window 引用,被覆盖的未定义的关键字等等)。
不推荐

var x = 10,y = 100;// Declaring variables in the global scope is resulting in global scope pollution. All variables declared like this
// will be stored in the window object. This is very unclean and needs to be avoided.
console.log(window.x + ' ' + window.y);

推荐

// We declare a IIFE and pass parameters into the function that we will use from the global space
(function(log, w, undefined){'use strict';var x = 10,y = 100;// Will output 'true true'log((w.x === undefined) + ' ' + (w.y === undefined));}(window.console.log, window));

3.2 变量声明

总是使用 var 来声明变量。如不指定 var,变量将被隐式地声明为全局变量,这将对变量难以控制。如果没有声明,变量处于什么定义域就变得不清(可以是在 Document 或 Window 中,也可以很容易地进入本地定义域)。所以,请总是使用 var 来声明变量。

采用严格模式带来的好处是,当你手误输入错误的变量名时,它可以通过报错信息来帮助你定位错误出处。

  • 把赋值尽量写在变量申明中
  • 只用一个 var 关键字声明,多个变量用逗号隔开

四、CSS 和 Sass (SCSS) 规范

4.1 合理的避免使用ID

一般情况下ID不应该被应用于样式。
ID的样式不能被复用并且每个页面中你只能使用一次ID。
使用ID唯一有效的是确定网页或整个站点中的位置。
尽管如此,你应该始终考虑使用class,而不是id,除非只使用一次。

4.2 CSS选择器中避免标签名

当构建选择器时应该使用清晰, 准确和有语义的class(类)名。不要使用标签选择器。 如果你只关心你的class(类)名
,而不是你的代码元素,这样会更容易维护。
从分离的角度考虑,在表现层中不应该分配html标记/语义。
它可能是一个有序列表需要被改成一个无序列表,或者一个div将被转换成article。
如果你只使用具有实际意义的class(类)名,
并且不使用元素选择器,那么你只需要改变你的html标记,而不用改动你的CSS。

4.3 0 和 单位

省略“0”值后面的单位。不要在0值后面使用单位,除非有值。

4.4 ID 和 Class(类) 名的分隔符

使用连字符(中划线)分隔ID和Class(类)名中的单词。为了增强课理解性,在选择器中不要使用除了连字符(中划线)以为的任何字符(包括没有)来连接单词和缩写。

另外,作为该标准,预设属性选择器能识别连字符(中划线)作为单词[attribute|=value]的分隔符,
所以最好的坚持使用连字符作为分隔符。

4.5 声明顺序

这是一个选择器内书写CSS属性顺序的大致轮廓。这是为了保证更好的可读性和可扫描重要。
作为最佳实践,我们应该遵循以下顺序(应该按照下表的顺序):

  • 结构性属性:
    1.display
    2.position, left, top, right etc.
    3.overflow, float, clear etc.
    4.margin, padding
  • 表现性属性:
    1.background, border etc.
    2.font, text

4.6 声明结束

为了保证一致性和可扩展性,每个声明应该用分号结束,每个声明换行。

4.7 属性名结束

属性名的冒号后使用一个空格。出于一致性的原因,
属性和值(但属性和冒号之间没有空格)的之间始终使用一个空格。

4.8 嵌套顺序和父级选择器(SCSS)

当使用Sass的嵌套功能的时候,
重要的是有一个明确的嵌套顺序,
以下内容是一个SCSS块应具有的顺序。
当前选择器的样式属性
1.父级选择器的伪类选择器 (:first-letter, :hover, :active etc)
2.伪类元素 (:before and :after)
3.父级选择器的声明样式 (.selected, .active, .enlarged etc.)
4.用Sass的上下文媒体查询
5.子选择器作为最后的部分

4.9 CSS引号

属性选择器或属性值用双引号(””),而不是单引号(”)括起来。
URI值(url())不要使用引号。

java入职学习一之编码规范相关推荐

  1. java入职学习四之sql语句

    一.SQL简介 SQL是一门用于操作关系型数据库的通用的语言(使用SQL可以操作所有的关系型数据库) 使用SQL可以操作数据库.表.表记录 (1)创建数据库.删除数据库.修改数据库.查询数据库 (2) ...

  2. Java杂乱无章-判断为空的编码规范

    Java杂乱无章-判断为空的编码规范 Test类 public class Test {private int userId;private String userName;public int ge ...

  3. Java入职实习生对于Java学习的一些心得

    Java实习生第一周,分享一些学习心得 本周入职,成为Java实习生,有些想法觉得还是有必要写出来分享的(以前觉得写博客太麻烦,现在进了公司觉得分享是很重要的,既可以总结也可以帮助以后学习Java的童 ...

  4. Cocos Creator入职学习日记——篇1(KeyWord:艺术字、渐变色、透明过渡特效)

    刚入职,事情不是特别多,看到了之前一直在找的Cocos Creator的一些使用技巧,简做记录 目录 一.艺术字 二.渐变色 三.透明过渡特效 四.分享时间 一.艺术字 Cocos Creator的艺 ...

  5. java入职华为,通过这9个Java面试题,就可以入职华为啦

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 1.Java程序的种类有(BCD ) A.类(Class) B.Applet C.Application D.Servlet 2.下列说法正确的有( BC ...

  6. java入职写不出代码_各位程序员是怎么度过看懂代码但写不出来的时期?

    说实话,我自己就没经历过这样的时期. 说看得懂代码的,大概是很少看开源代码,想看懂不仅自己水平要过硬,还要花挺大的精力把前前后后的东西都做充分的研究. 我自己总是会有自己写一个功能很有思路,但是搞懂别 ...

  7. 申通java入职流程_java查询申通快递

    1.用到了htmlunit的架包 2.可用于Js传值网页的抓取 3.速度比较慢,求牛人给个优化建议,增加查询速度 1.[代码]用到了htmlunit的架包 package org.sjcx.tool; ...

  8. 启明星辰入职学习规划2018.06.25

    一.一到两周 1)熟悉公式产品的使用(天镜网络安全事件应急处置工具箱): 2)熟悉产品操作,开发环境的搭建: 3)应急工具的收集和整理: 4)对虚拟机VM进行系统瘦身 5)kali系统的操作和使用 二 ...

  9. android程序安全编码向导,Android安全编码规范

    Android安全编码规范可分为Android平台上特有的(Android-Only).C.Java三个方面的安全编码规范. Android-Only 敏感信息不要保存到外部存储中,除非做了加密. 外 ...

最新文章

  1. 使用C#检验.NET FrameWork版本
  2. VS2010下使用dmp文件和pdb文件定位程序异常代码行号的注意事项
  3. java jbutton 禁用_java – 如何禁用JButton在禁用时变灰?
  4. Scala教程之:scala的参数
  5. 说说如何用JavaScript实现一个模板引擎
  6. mysql 索引条件推送_MySQL 处理where条件 index condition pushdown索引条件下推
  7. 微软XAML Studio - WPF, UWP, Xamarin等技术开发者的福音
  8. Codeforces 1144D Deduction Queries 并查集
  9. WebGoat系列实验Buffer Overflows Code Quality Concurrency
  10. 【Caffe代码解析】SyncedMemory
  11. 越界操作导致程序崩溃的原理
  12. mqtt客户端c语言开发
  13. dex字符串解密_DEX文件混淆加密
  14. Win10磁盘有很多磁盘0分区
  15. 小马哥-----高仿苹果6 plus刷机拆机多图展示 拆机主板图与开机界面图 6572芯片 v76机型
  16. VBA轻松实现多色渐变填充
  17. 2022-05-30 无法验证是否已安装所需的Microsoft更新KB2919355
  18. 微信小程序云开发打车系统实现附源码
  19. 递归与迭代,台阶问题,斐波那契,分治算法
  20. Python编程快速入门

热门文章

  1. 新版BIOS设置U盘启动
  2. DAG - 数据结构 有向无环图
  3. 关于Origin平台“发生了一些意料之外的事情”解决方案
  4. python2 TopLevel主窗体弹子窗体,标题名不对
  5. 基于Python的图像分类-Finetune训练模型
  6. 【在线社交功能】炫弛世界元宇宙商城
  7. mysql ignore into语法
  8. ABP VNext 利用QQ邮箱发送邮件
  9. 苹果的MACBOOK AIR (MBA)与SONY VAIO PRO 11/13之间
  10. java五子棋课程设计_JAVA课程设计+五子棋游戏