阿里编码规范

给你们转发一篇大厂的编码规范的(java版的)
虽然没在大厂任职过,不过有值得学习的内容流出来,仔细看看这都是先人门多年经验的总结,就是值得咱们学习的。java

声明转载的,原文https://blog.csdn.net/Daybreak1209/article/details/82378249
感受具体是否是大厂的(错别字很多)流出来的,仍是某培训机构本身编写的不重要,具体看下面吧web

  • CodeStyleredis

    • 驼峰 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。
    • 并发
      • SimpleDateFormat不是线程安全的,通常不要定义为 static 类型,若是非要这么作,那么请加锁使用,或者用DateUtils工具类
      • 锁代码块工做量尽量的小。避免在锁代码块中调用rpc方法
      • 线程池不容许使用Executors建立,用ThreadPoolExecutor建立
        1. FixedThreadPool和SingleThreadPool:容许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而致使OOM。
        2. CachedThreadPool和ScheduledThreadPool:容许的建立线程数量为Integer.MAX_VALUE,可能会建立大量的线程,从而致使OOM。
      • double-checked locking
      • 多资源加锁,加锁顺序必须一致,避免死锁
        • 线程1需对表A,B,C依次所有加锁才能够进行更新操做,那么线程2的加锁顺序也必须是A,B,C,不然可能出现死锁。
  • Exceptionsql

    • dao层 service视状况能够将错误往上抛,web层就别抛了,属于顶层,应直接给个友好页面
    • 通常dao层上抛,service作处理返回封装result
    • 各层自定义异常
  • MySQL数据库

    • 布尔类型 必须使用is_***,类型为unsigned tinyint - 不容许为负值,插入直接sql报错。
    • 小数点类型 使用decimal,禁止使用float和double(存在精度损失问题,比较值得不到正确的结果)
    • 表必须存在id、create_time,update_time3字段,且更新时必须更新update字段
    • 索引 建组合索引的时候,区分度最高的在最左边(=号),若是<>比较最左索引失效,eg:where a>? and b=? 那么即便a的区分度更高,也必须把b放在索引的最前列
    • sql性能
      • 至少要达到range级别,要求是ref级别,若是能够是consts最好。
      • consts 主键或惟一索引
      • ref 普通索引
      • range 索引进行范围检索
      • index 索引物理文件全扫描,速度慢
    • 事物 @Transactional 事物不要滥用。事物会影响数据库的QPS,另外使用事物的地方要考虑各方面的回滚方案,包括缓存混滚、搜索引擎回滚、消息补偿、统计修正等。
  • Unit Testjson

    • 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安全