问题
参数过多会导致:
- 不利于调用者理解parameters含义及api的使用条件
- 可读性、可写性差
- 同类型的多个参数同时使用时,调用顺序容易搞错了,但编译器不会指出,开发者以为自己写的代码没问题,但可能导致严重Bug
effective java 建议 参数在4个或以下,参数过多时要考虑减少参数。
解决方法
3 ways:
- break the method into multiple methods, each which require only a subset of the parameters
- create helper classes to hold group of parameters (typically static member classes)
- adapt the Builder pattern from object construction to method invocation.
code example
private static final String INDEX_PV_ERR_CODE_METRICNAME = "counter_upggate_pv_index_return_code_prometheus";
private static final String INDEX_PV_ERR_CODE_METRICCOMMENT = "about upggate_pv_index_return_code count";
private static final String INDEX_UV_ERR_CODE_METRICNAME = "counter_upggate_uv_index_return_code_prometheus";
private static final String INDEX_UV_ERR_CODE_METRICCOMMENT = "about upggate_uv_index_return_code count";
private static final String[] INDEX_ERR_CODE_LABELNAMES = {"errMsg", "airline", "flightNo", "deptCode", "destCode", "dateTime"};
public static void indexErrCodeCount(String errMsg, String airline, String flightNo, String deptCode, String destCode, String flightDate, String userId, String redisKey, RedisUtil redisUtil, String countType) {
if (StringUtils.isAnyBlank(errMsg, airline, flightNo, deptCode, destCode, flightDate, countType)) {
return;
}
try {
if (Boolean.TRUE.toString().equalsIgnoreCase(disconfManager.getConfigureInformation("upgGateIndexReturnCodeCountSwitch", "application", "false"))) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(Constants.DATE_TEMPLATE);
String dateTime = simpleDateFormat.format(new Date());
Map<String, String> objectHashMap = new HashMap<>();
objectHashMap.put("errMsg", errMsg);
objectHashMap.put("airline", airline);
objectHashMap.put("flightNo", flightNo);
objectHashMap.put("deptCode", deptCode);
objectHashMap.put("destCode", destCode);
objectHashMap.put("dateTime", dateTime);
if (Constants.PROMETHEUS_COUNT_TYPE_PV.equalsIgnoreCase(countType)) {
MetricCounterApi.labelinc(INDEX_PV_ERR_CODE_METRICNAME, INDEX_PV_ERR_CODE_METRICCOMMENT, INDEX_ERR_CODE_LABELNAMES, objectHashMap);
} else if (Constants.PROMETHEUS_COUNT_TYPE_UV.equalsIgnoreCase(countType) && ExposureUtil.upgGateIndexReturnCodeUvCount(flightNo, deptCode, destCode, flightDate, userId, redisKey, redisUtil)) {
MetricCounterApi.labelinc(INDEX_UV_ERR_CODE_METRICNAME, INDEX_UV_ERR_CODE_METRICCOMMENT, INDEX_ERR_CODE_LABELNAMES, objectHashMap);
Cat.logEvent("Prometheus", "indexReturn" + "_" + airline + "_" + flightNo + "_" + deptCode + "_" + destCode + "_" + dateTime + "_" + errMsg);
}
}
} catch (Exception e) {
LogUtil.error(Prometheus.class, String.join(",", errMsg, airline, flightNo, deptCode, destCode, countType, "Prometheus indexErrCodeCount exception, e: "), e);
}
}
10个参数。。。 太多了,
结合业务和需求,我建议如此改进:
- erroMsg,airline, flightNo, deptCode, destCode, flightDate 封装进一个对象(prometheusLabels,都是打点相关指标)。且erroMsg 可选(方便扩展),airline,flightNo,deptCode,destCode,flightDate 封装成一个必选对象(多个打点需求都要求必须打这几个指标,且这几个字段组合起来有点实际意义)。 最外层的对象采用builder构造,为了扩展新的可选打点指标。
- userId, redisKey, redisUtil 封装成一个对象(UvRedis)。uv过滤必须
- countType整一个 enum出来,有UV,PV 2种类型。 方便日后扩展(可以加enum种类,或者uv,pv这两类型中加新的字段表示某些属性)。 (不过基于需求来说,uv\pv是不太可能扩展了,也可以直接定义2个constants string)
如此便改进到3个参数。 再考虑拆分成多个方法。
更建议去看看《effective java 第3版》 item51.