命名规约
代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束
代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式
类名使用UpperCamelCase风格,必须遵从驼峰形式(某些情况诸如领域模型相关的命名除外);方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式
常量命名全部大写,单词间用下划线隔开
包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词
抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类的名称开始,以Test结尾
对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别
如果是形容能力的接口名称,取对应的形容词做接口名
枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开
如果使用到了设计模式,建议在类名中体现出具体模式
包名统一使用单数形式;类名如果有复数含义,类名可以使用复数形式
不允许出现任何魔法值(即未经定义的常量)直接出现在代码中
不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护
常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量
如果变量值仅在一个范围内变化用Enum类。如果还带有名称之外的延伸属性,必须使用Enum类
尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量
long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解
接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁性,并加上有效的Javadoc注释
所有的覆写方法,必须加@Override注解
可变参数必须放置在参数列表的最后。
对外暴露的接口签名,原则上不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么
不能使用过时的类或方法
序列化类新增属性时,请不要修改serialVersionUID字段,避免反序列失败
循环体内,字符串的联接方式,使用StringBuilder的append
final可提高程序响应效率
慎用Object的clone方法来拷贝对象
所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较
所有的POJO类属性必须使用包装数据类型
RPC方法的返回值和参数必须使用包装数据类型
所有的局部变量【推荐】使用基本数据类型
Service/DAO层方法命名规约
- 获取单个对象的方法用get做前缀
- 获取多个对象的方法用list做前缀
- 获取统计值的方法用count做前缀
- 插入的方法用save(推荐)或insert做前缀
- 删除的方法用remove(推荐)或delete做前缀
- 修改的方法用update做前缀
定义DO/DTO/VO等POJO类时,不要设定任何属性默认值
构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中
当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,便于阅读
类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter方法
setter方法中,参数名称与类成员变量名称一致,this.成员名=参数名。在getter/setter方法中,尽量不要增加业务逻辑
类成员与方法访问控制从严
缩进采用4个空格,禁止使用tab字符
单行字符数限不超过 120 个
IDE的text file encoding设置为UTF-8; IDE中文件的换行符使用Unix格式,不要使用windows格式
方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行
获取单例对象需要保证线程安全,其中的方法也要保证线程安全
创建线程或线程池时请指定有意义的线程名称,方便出错时回溯
线程资源必须通过线程池提供,不允许在应用中自行显式创建线程
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor去创建
多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题
使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法可以执行,
避免主线程无法执行至countDown方法,直到超时才返回结果回溯
volatile解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题
HashMap在容量不够进行resize时由于高并发可能出现死链
ThreadLocal无法解决共享对象的更新问题,ThreadLocal对象建议使用static修饰。这个变量是针对一个线程内所有操作共有的,所以设置为静态变量,
所有此类实例共享此静态变量
所有的枚举类型字段必须要有注释,说明每个数据项的用途
与其"半吊子"英文来注释,不如用中文注释把问题说清楚。专有名词与关键字保持英文原文即可
注释掉的代码尽量要配合说明,而不是简单的注释掉
好的命名、代码结构是自解释的,注释力求精简准确、表达到位
是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint( 1表示是,0表示否)
表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字
表名不使用复数名词
禁用保留字
唯一索引名为uk_字段名;普通索引名则为idx_字段名
表的命名最好是加上业务名称_表的作用
库名与应用名称尽量一致
表必备三字段:id, gmt_create, gmt_modified
如果存储长度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率
如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释
字段允许适当冗余,以提高性能,但是必须考虑数据同步的情况
单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表
合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度
业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引
超过三个表禁止join
在varchar字段上建立索引时,必须指定索引长度
页面搜索严禁左模糊或者全模糊
如果有order by的场景,请注意利用索引的有序性
利用延迟关联或者子查询优化超多分页场景
建组合索引的时候,区分度最高的在最左边
不要使用count(列名)或count(常量)来替代count(*)
在代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句
不得使用外键与级联,一切外键概念必须在应用层解决
禁止使用存储过程,存储过程难以调试和扩展,更没有移植性
in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内
在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明
推荐尽量少用else, if-else的方式可以改写成:
if(condition){
...
return obj;
}
// 接着写else的业务逻辑代码;
如果非得使用if()...else if()...else...方式表达逻辑,【强制】请勿超过3层,超过请使用状态设计模式
方法中需要进行参数校验的场景:
1) 调用频次低的方法。
2) 执行时间开销很大的方法,参数校验时间几乎可以忽略不计,但如果因为参数错误导致中间执行回退,或者错误,那得不偿失。
3) 需要极高稳定性和可用性的方法。
4) 对外提供的开放接口,不管是RPC/API/HTTP接口。
5) 敏感权限入口。
1.7.8 方法中不需要参数校验的场景:
1) 极有可能被循环调用的方法,不建议对参数进行校验。但在方法说明里必须注明外部参数检查
2) 底层的方法调用频度都比较高,一般不校验。毕竟是像纯净水过滤的最后一道,参数错误不太可能到底层才会暴露问题。一般DAO层与Service层都在同一个应用中,
部署在同一台服务器中,所以DAO的参数校验,可以省略
3) 被声明成private只会被自己代码所调用的方法,如果能够确定调用方法的代码传入参数已经做过检查或者肯定不会有问题,此时可以不校验参数
在quanta本来就在学SQL,数据库,想把后台只有php的技术栈扩充到java,所以选了阿里云的java编码规范,总之,用好这些编码规范肯定是会有收益的,代码的简洁和可读才是编码的艺术。
数学之美读后感想:
读了开头的几篇,就把我惊艳,这不正好是实验室搞得东西吗,之前也略有所学,感受到了人类科学的智慧,能用DNN做出语言模型来预测句子出现概率,还有通过词嵌入来
降维,还有卷积层和循环网络,遗忘门的设计,action机制都不得不佩服数学的精妙,把他们一个拼接起来组成模型,输入后就能产生输出,就像一个黑箱一样,懂的人自然懂,
不懂的人就觉得很高大上,我现在在加大力度学习深度学习,学习里面算法与思想,发现其实里面的原理也是基于基础的算法的,
书籍方面在阅读西瓜书,课程我是推荐吴恩达的机器学习和深度学习,直接把高大上的东西讲的平民化,人人有AI搞,),大爱吴恩达大大。