给大家转发一篇大厂的编码规范的(java版的)
虽然没在大厂任职过,不过有值得学习的内容流出来,仔细看看这都是先人门多年经验的总结,就是值得我们学习的。
声明转载的,原文https://blog.csdn.net/Daybreak1209/article/details/82378249
感觉具体是不是大厂的(错别字不少)流出来的,还是某培训机构自己编写的不重要,具体看下面吧
-
CodeStyle
- 驼峰
DTO、BO、DO、VO、AO、PO
除外 - POJO
- Boolean类型变量不要加is,如isDelete,set方法也是isDelete,以防某些rpc框架反序列化时“以为”对应的属性名称时delete,导致反序列化异常
- 所有属性类型必为包装类型,RPC方法入参出参都为包装类型且没有初始值。提醒使用者使用前要显式赋值,NPE问题由使用者保证。
- method 方法前缀:
get,list,count,save/insert,remove/delete,update
- 常量
- 先定义后使用:不允许任何魔法值(未提前定义的常量)直接出现在代码中
String key="create"+tradeId
- 划分层次、client、service;勿统一一个常量类全包
- 先定义后使用:不允许任何魔法值(未提前定义的常量)直接出现在代码中
- 包装类
- 包装类对象之间值的比较,全部使用
equals
方法;Integer -128~127
中可以使用==
,jdk5+自动拆装箱。超过此范围一律使用equals
判断
- 包装类对象之间值的比较,全部使用
- 集合
- ArrayList
- ArrayList的subList方法返回的是ArrayList的内部类subList,不可强制转成arraylist。否则抛classCastException异常
- 在subList场景中,对原集合元素个数的修改,会导致子列表的遍历、增加、删除均会产生ConcurrentModificationException异常
- Arrays.asList将数组转成集合时,不能使用add,remove,clear等修改集合,抛UnsupportedOperationException异常。因为asList返回的时Arrays的内部类,没有实现集合的修改方法。
- Map
- 使用EntrySet遍历map的kv,而非使用KeySet,KeySet其实遍历了两次,一次是转为iterator对象,另一次使用hashmap中取出key所对应的value。
- ArrayList
- 并发
- SimpleDateFormat不是线程安全的,一般不要定义为
static
类型,如果非要这么做,那么请加锁使用,或者用DateUtils工具类 - 锁代码块工作量尽可能的小。避免在锁代码块中调用rpc方法
- 线程池不允许使用Executors创建,用ThreadPoolExecutor创建
- FixedThreadPool和SingleThreadPool:允许的请求队列长度为
Integer.MAX_VALUE
,可能会堆积大量的请求,从而导致OOM。 - CachedThreadPool和ScheduledThreadPool:允许的创建线程数量为
Integer.MAX_VALUE
,可能会创建大量的线程,从而导致OOM。
- FixedThreadPool和SingleThreadPool:允许的请求队列长度为
- double-checked locking
- 多资源加锁,加锁顺序必须一致,避免死锁
- 线程1需对表A,B,C依次全部加锁才可以进行更新操作,那么线程2的加锁顺序也必须是A,B,C,否则可能出现死锁。
- SimpleDateFormat不是线程安全的,一般不要定义为
- 驼峰
-
Exception
- dao层 service视情况可以将错误往上抛,web层就别抛了,属于顶层,应直接给个友好页面
- 一般dao层上抛,service做处理返回封装result
- 各层自定义异常
-
MySQL
- 布尔类型 必须使用is_***,类型为unsigned tinyint - 不允许为负值,插入直接sql报错。
- 小数点类型 使用decimal,禁止使用float和double(存在精度损失问题,比较值得不到正确的结果)
- 表必须存在
id、create_time,update_time
3字段,且更新时必须更新update字段 - 索引 建组合索引的时候,区分度最高的在最左边(=号),如果<>比较最左索引失效,eg:where a>? and b=? 那么即使a的区分度更高,也必须把b放在索引的最前列
- sql性能
- 至少要达到range级别,要求是ref级别,如果可以是consts最好。
- consts 主键或唯一索引
- ref 普通索引
- range 索引进行范围检索
- index 索引物理文件全扫描,速度慢
- 事物 @Transactional 事物不要滥用。事物会影响数据库的QPS,另外使用事物的地方要考虑各方面的回滚方案,包括缓存混滚、搜索引擎回滚、消息补偿、统计修正等。
-
Unit Test
- air 自动化、独立型、可重复
- BCDE
- border边界测试、循环边界、特殊取值、特殊时间点、数据顺序
- 正确输入
- 文档设计结合编写
- 强制错误输入非法数据、异常流程、非业务允许输入
- others
- Security 用户敏感数据 – 身份证、手机号 – 脱敏处理
- Log
- 业务日志、系统日志区分处理
- 不要打整个对象,浪费资源。关键字段打出来
贴出来是给大家参考的,有可鉴之处,一种约束,没要求必须去这样做,是希望您能去遵循规范。
否则您要写出像下面这种代码,
@RequestMapping(value = "/Getlist")
@ResponseBody
public ModelMap Getlist(HttpServletRequest request,
@RequestParam(value = Constants.DEFAULT_CURRPAGE_MODEL_KEY, required = false, defaultValue = Constants.DEFAULT_PAGE_START) Integer start,
@RequestParam(value = Constants.DEFAULT_PAGE_SIZE_MODEL_KEY, required = false, defaultValue = Constants.DEFAULT_PAGE_SIZE) Integer limit) {
ModelMap mm = new ModelMap();
int subWayCount = 0;
List<SubWayDrivingStatus> statusList = new ArrayList<>();
String status = request.getParameter("subwayStatus");
String cityId = request.getParameter("citys");
String routeId = request.getParameter("routeId");
List<SubWayDrivingStatus> cacheList = new ArrayList<>();
List<SubWayDrivingStatus> resultList = new ArrayList<>();//???
Jedis jedis = redisManager.getJedis();
if (jedis.isConnected() && jedis.exists(DRIVING_STATE)) {
Map<String, String[]> userCityRoutes = getUserCityRoute();
String json = jedis.get(DRIVING_STATE);
cacheList = JsonUtil.toList(json, SubWayDrivingStatus.class);
// 要筛选用户可以访问的数据
String[] routes = userCityRoutes.get(ROUTES);
String[] citys = userCityRoutes.get(CITYS);
if (routes != null && routes.length > 0) {
for(SubWayDrivingStatus sds : cacheList){
for(String route : routes){
if(route.equals(sds.getRouteId())){
resultList.add(sds);
// continue;
}
}
}
} else if (citys != null && citys.length > 0) {
for (SubWayDrivingStatus sds : cacheList) {
for (String city : citys) {
if (city.equals(sds.getCitys())) {
resultList.add(sds);
// continue;
}
}
}
} else {
resultList = cacheList;//TODO ????什么逻辑???
}
// 要筛选用户下拉框
if (isNotEmpty(routeId)) {
Iterator<SubWayDrivingStatus> it = resultList.iterator();
while (it.hasNext()) {
SubWayDrivingStatus sds = it.next();
if (!sds.getRouteId().equals(routeId)) {
it.remove();
}
}
} else if (isNotEmpty(cityId)) {
Iterator<SubWayDrivingStatus> it = resultList.iterator();
while (it.hasNext()) {
SubWayDrivingStatus sds = it.next();
if (!sds.getCitys().equals(cityId)) {
it.remove();
}
}
}
subWayCount = resultList.size();
logger.debug("user check the status: "+status);
statusList = getShowList(status, resultList);
sort(statusList);
int showSubWayCount = Math.min(statusList.size(), subWayCount);
mm.addAttribute(Constants.DEFAULT_RECORD_MODEL_KEY,
statusList.subList((start - 1) * limit, Math.min(start * limit, showSubWayCount)));
mm.addAttribute(Constants.DEFAULT_COUNT_MODEL_KEY, showSubWayCount);
mm.addAttribute("subWayCount", Math.min(statusList.size(), subWayCount));
mm.addAttribute("subWayOnline", jedis.get(DRIVING_STATE_ONLINE));
mm.addAttribute("subWayOffline", jedis.get(DRIVING_STATE_OFFLINE));
mm.addAttribute("subWayOnFault", jedis.get(DRIVING_STATE_FAULT));
mm.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
} else {
mm.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
}
if (jedis != null) {
jedis.close();
}
return mm;
}
还有下面这样的
public void getlist() {
Integer subWayCount = 0;// 列车总量
SubWayStatusCount ssc = new SubWayStatusCount();
try {
Set<String> faults = getAllFaultFromCache();
List<SubWayInfo> subwayListAll = getSubwayListAll();//取所有列车数据
subWayCount = subwayListAll.size();
if(subWayCount <= 0) {
return ;
}
// 取方法名集合
List<String> fieldSets = getFieldNamesFromSubWayDrivingStatus();
List<SubWayDrivingStatus> statusList = new ArrayList<>();
SubWayDrivingStatus sds = null;
BigDataParam bigParam = new BigDataParam();
SpecialFieldCache spc = SpecialFieldCache.getInstance();
for (SubWayInfo subway : subwayListAll) {
sds = initSubWayDrivingStatus(subway);
if(sds == null) {
continue;
}
Map<String, Map<String, String>> specialFieldCache = spc.findValue(subway.getCitys(), subway.getRouteId());
Map<String, String> specialfieldMap = spc.findField(subway.getCitys(), subway.getRouteId());
JSONObject json2 = getRealTimeDatas(bigParam, subway, specialFieldCache);//取实时数据
if (json2 == null || json2.isEmpty() || json2.isNullObject()) {
setSubWayStatus(sds, subway.getId(), ssc);// 无实时数据,表明离线
} else {// 有数据
if (specialFieldCache.values() != null && !specialFieldCache.isEmpty()) {
Iterator<String> it = specialFieldCache.keySet().iterator();
String itemValue = "";
String dataCoding = "";
Field field = null;
while (it.hasNext()) {
dataCoding = it.next();// 指标代码
itemValue = specialfieldMap.get(dataCoding);
if (!fieldSets.contains(itemValue)) {
continue;
}
try {// 过滤出所需要的目标数据
field = sds.getClass().getDeclaredField(itemValue);
field.setAccessible(true);
String value = "";
for (Iterator<?> iter = json2.keys(); iter.hasNext();) {
String key = iter.next().toString();// 时间序列
JSONObject json = JSONObject.fromObject(json2.getString(key));
if (!json.isNullObject() && !json.isEmpty()) {
sds.setUpdateTime(key);
if (json.containsKey(dataCoding)) {
value = json.get(dataCoding).toString();
try {
field.set(sds, specialCodeShowValue(
specialFieldCache.get(dataCoding), value));
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
continue;
}
}
} catch (Exception e) {
e.printStackTrace();
continue;
}
}
setSubWayStatus(sds, subway.getId(), ssc);
} else {
setSubWayStatus(sds, subway.getId(), ssc);
}
}//处理故障数据
if (faults.contains(keyOfFaultTrain(sds))) {
sds.setFaults("有故障");
ssc.setSubWayOnFault(ssc.getSubWayOnFault() + 1);
} else {
sds.setFaults("无故障");
}
statusList.add(sds);
}
Jedis jedis = redisManager.getJedis();
jedis.set(DRIVING_STATE, JsonUtil.toJson(statusList));
jedis.set(DRIVING_STATE_COUNT, subWayCount.toString());
jedis.set(DRIVING_STATE_ONLINE, String.valueOf(ssc.getSubWayOnline()));
jedis.set(DRIVING_STATE_OFFLINE, String.valueOf(ssc.getSubWayOffline()));
jedis.set(DRIVING_STATE_FAULT, String.valueOf(ssc.getSubWayOnFault()));
if (jedis != null) {
jedis.close();
}
fieldSets.clear();
faults.clear();
} catch (Exception e) {
e.printStackTrace();
}
}
你会忍不住的说一声,WCNMLGB