随着《阿里巴巴Java开发手册》的公开,从新又掀起一股编码规范的风口。结合《华为java编程规范》以及团队内部的实践,咱们也作了一段开发规范。不求最全,但求有效。java
里面的规范,暂时只分两类。“强制”,即若是违反就不能使用级别。好比说,在codereview有遇到 ,那就会直接把pull request打回去,拒绝合并到开发者稳定分支上。“推荐”,即建议怎么作,可是不强制,根据不一样的水平能够作一些参考。web
全部的状况下都通用sql
一、 【强制】命名所有使用英文,禁止中文或者中英混合。项目名除外,由于有的项目是按域名来命名的,域名自己有多是中文拼音。数据库
例子:编程
域名:kecheng.xxx.com
项目名:xxx-web-kecheng
复制代码
二、 【强制】禁止使用缩写,除非提供一个缩写列表设计模式
反例:缓存
# 这里的t究竟是什么意思?topic_id?仍是teacher_id?
字段:t_id
复制代码
三、 【强制】禁止出现除了后缀或者前缀3个单词。若是超过3个,说明想表达的职责太多,能够拆分或者封装。bash
这里主要指的是Java语言,其余的语言也能够借鉴这些准则架构
一、 【强制】须要有统一的后缀或者前缀。为了一看类名,就知道这个类干什么的。框架
前缀列表:
接口:IViewTag
抽象类:AbstractViewTag
具体实现类:UserViewTag
复制代码
后缀列表:
实体:UserEntity
基础服务:UserBaseService
业务服务:AuthorityBusinessService
复制代码
二、 【强制】全部参与业务的类禁止使用内部类。
一、 【强制】常量必须是:大写+下划线,禁止多个单词连在一块儿
正例:
private final static String PAGE_SIZE=10;
复制代码
反例:
private final static String PAGESIZE=10;
private final static String pageSize=10;
复制代码
二、 【强制】布尔类型禁止添加"is"前缀。部分框架解析会引发序列化错误。
反例:
# 对应的getter和setter为:isRead和setRead
private boolean isRead
复制代码
正例:
# 对应的getter和setter为:isRead和setRead
private boolean read;
复制代码
三、 【强制】计数器禁止使用复数
反例:
private int readCounts;
复制代码
正例:
private int readCount;
复制代码
四、 【强制】自描述属性里不要出现类名的描述
反例:
#UserEntity类
private String userName;
private int userAge;
复制代码
正例:
#UserEntity类
private String name;
private int age;
复制代码
五、【强制】关联其余实体的属性命名规则:对应的实体去掉后缀+用途
正例:
属性名:teacherId ,对应的实体是TeacherEntity
属性名:favorCount,对应的实体是FavorEntity
复制代码
反例:
属性名:tId。根本不知道是哪一个实体的外键。有多是Teacher有多是Topic,还得猜半天
复制代码
六、 【强制】禁止经过定义定义成常量(1,2)来维护类型值,须要经过枚举
反例:
private final static int SUCESS=1;
private final static int FAIL=2;
复制代码
正例:
定义一个枚举
复制代码
一、 【强制】接口里的方法禁止有修饰符。
反例
#接口里的方法public void eat();
复制代码
正例:
#接口里的方法void eat();
复制代码
二、 【推荐】方法参数必须使用final来修饰。final可提升程序响应效率。能够经过Eclipse的cleanup来实现。
正例:
public void eat(final int size);
复制代码
public void eat(int size);
复制代码
三、 【强制】每个方法参数都须要被处理。module层的方法里的对象参数
能够不判空,由于架构已经作处理了,不可能为空。
被处理指的是:
例子:
public void add(long userId,String content){
//异常验证
ExceptionUtil.checkId(userId,"用户id")
//直接返回
if(Util.isEmpty(content)){
return ;
}
}
public List<CourseEntity> list(int type){
Cnd cnd = Cnd.limit();
//有对应的业务逻辑处理
if(type>0){
cnd.and("type","=",type);
}
return dbDao.query(CourseEntity.class,cnd,null);
}
复制代码
四、 【强制】同一个类里有多个一致的参数(3个以上)的方法,须要抽取接口或者经过实体来承载
public FavorEntity add(int type,long sourceId,long userId);
public FavorEntity delete(int type,long sourceId,long userId);
复制代码
正例
public FavorEntity add(IFavor favor);
public FavorEntity delete(IFavor favor);
复制代码
五、 【强制】方法名必须是动词或者动宾。http接口须要知明达意,能够不按这个规则。好比:mycourse,home,banner
方法命名格式:
例子:
public void isSucess();
public void on();
public void sendEmail();
复制代码
统一命名列表:
方法前缀后缀命名说明:
原则上不添加后缀,若是添加后缀的话,若是有添加,命名格式为:updatexxxx4yyyyByzzzz
例子:
--xxxx状况:用户
public void updateName();();
public void updateNickName();
--yyyy状况:资讯
public List<NewsEntity> list4Latest();
public List<NewsEntity> list4Top();
--zzzz状况:课程
public List<CourseEntity> listByTeacher();
public List<CourseEntity> listByKnowledge();
--综合使用
public List<CourseEntity> listCourse4TopByTeacher();
复制代码
六、 【强制】一个方法里代码行数不能超过1屏(即30行)。通常来讲超过30的行,业务关注点、复杂数比较高,很难维护。超过30行须要封装方法
七、 【强制】局部变量命名不能有连续的名称。连续的命名不具备可维护性。每一个变量都须要有清晰的概念。
String head1;
String head2;
复制代码
正例:
String title;
String content;
复制代码
八、 【强制】禁止有任何魔鬼数据独立存在。能够定义一个有含义的变量来承载
if(type ==1){
//审核成功
下面15行代码
}
复制代码
正例:
private final static int SUCESS=1;
...
.if(type ==SUCESS){
下面15行代码
}
复制代码
九、 【强制】判断表达式要使用布尔变量或者封装方法。表达式是变化点。在维护的时候,表达式不知名达意。
if(user!=null&&!Util.isEmpty(user.name)&&!Util.isEmpty(user.provicne)){
//下面15行代码
}
复制代码
正例:
if(isFilledBaseInfo(user)){
//下面15行代码
}
复制代码
十、【强制】if()...else if()...else个数不能多于4个,嵌套不能深于3层
能够经过如下的方法来消除:
if(isAdmin()){
...
}else if(isTeacher()){
...
}
复制代码
正例:
if(isAdmin()){
... return;
}if(isTeacher()){
... return;
}
复制代码
十一、 【推荐】采用防护式编程,先判断错误的业务,而后再写正确的业务。防护式编程结构清晰分明:先把全部错误穷举,而后集中处理正确逻辑。
if(null!=user && user.hasAuth()){
正确逻辑
}
复制代码
正例:
if(null==user || !user.hasAuth()){ return;}
正确逻辑
复制代码
十二、 【推荐】for里不建议写io。io包括:数据库、缓存,文件读写等
1三、 【强制】多个不一样的结构(业务相近的代码),须要有且只有一个空行
long userId = fetchUser.getCurrentUserId();
Sql sql = latentCustomerQueryForm.pager(sqlManager);
Map<String, Object> map = FormUtil.list(dbDao, sql, pager);
List<DictInfoEntity> grades = dictBaseService.listDict(DictInfoEnum.GRADE.stringKey());
List<DictInfoEntity> infoOrigins = dictBaseService.listDict(DictInfoEnum.INFOORIGIN.stringKey());
map.put("queryForm", latentCustomerQueryForm);
map.put("grades", grades);
map.put("infoOrigins", infoOrigins);
return map;
复制代码
正例:
long userId = fetchUser.getCurrentUserId();
Sql sql = latentCustomerQueryForm.pager(sqlManager);
Map<String, Object> map = FormUtil.list(dbDao, sql, pager);
List<DictInfoEntity> grades = dictBaseService.listDict(DictInfoEnum.GRADE.stringKey());
List<DictInfoEntity> infoOrigins = dictBaseService.listDict
map.put("queryForm", latentCustomerQueryForm);
map.put("grades", grades);
map.put("infoOrigins", infoOrigins);
return map;
复制代码
1四、 【推荐】不参与计算的变量不要定义变量
long userId = fetchUser.getCurrentUserId();
Sql sql = latentCustomerQueryForm.pager(sqlManager);
Map<String, Object> map = FormUtil.list(dbDao, sql, pager);
List<DictInfoEntity> grades = dictBaseService.listDict(DictInfoEnum.GRADE.stringKey());
List<DictInfoEntity> infoOrigins = dictBaseService.listDict(DictInfoEnum.INFOORIGIN.stringKey());
map.put("queryForm", latentCustomerQueryForm);
map.put("grades", grades);
map.put("infoOrigins", infoOrigins);
return map;
复制代码
正例:
long userId = fetchUser.getCurrentUserId();
Sql sql = latentCustomerQueryForm.pager(sqlManager);
Map<String, Object> map = FormUtil.list(dbDao, sql, pager);
map.put("grades", dictBaseService.listDict(DictInfoEnum.GRADE.stringKey()));
map.put("infoOrigins", dictBaseService.listDict(DictInfoEnum.INFOORIGIN.stringKey()));
return map;
复制代码
1五、 【强制】若是有捕获异常,必须有对应的处理业务。若是没有对应的处理业务,不要捕获,能够直接throw,让架构统一处理
你本身catch,确定不但愿用户看到错误日志,那么 从用户那边看到是正常业务。catch了什么都没干,用户每每看到的是什么都没发生,他会觉得网站挂了或者功能快。
1六、 【强制】禁止使用exception.getMessge()处理错误信息。应该使用exception.toString()。由于exception.getMessage(),在npe抛出异常的时候,什么信息都不显示。
} catch (Exception e) {
logger.error(e.getMessage());
}
复制代码
正例:
} catch (Exception e) {
logger.error(e.toString());
}
复制代码
1七、 【强制】禁止使用System.out.print。统一使用Eclipse的log4e插件生成日志(不要定义具体的日志实现,要定义的是slf4j的接口)
1八、 【推荐】公开的接口,一旦发布成稳定版,禁止修改方法签名(方法名,参数)
若是要修改,须要提供新的接口,老的不能修改。由于一修改方法签名。
好比:js调用可能就报错了,功能就没办法使用;工具类接口一变,其余项目就会报错了,没办法向下兼容。
1九、 【推荐】方法放置顺序:public-->protected-->private。一个类,每每使用者更关注的是public的。构造方法、重载方法、雷同方法,按顺序放在一块儿