一、重新组织数据
- 拆分变量:变量有各种不同的用途,其中某些用途会临时被多次赋值,拆分临时变量可以方便稍后使用。每个临时变量只承担一个责任。
- 字段改名:命名很重要,对于程序中广泛使用的记录结构,其中字段的命名格外重要。为保持数据结构的整洁,记录结构中的字段可能需要改名。
- 以查询取代派生变量:可变数据是软件中最大的错误源头之一,尽量把可变数据的作用域限制在最小范围。有些变量可以很容易的随时计算出来,用查询替代临时变量可以直接使用数据源。
- 将引用对象改为值对象:在把一个对象嵌入另一个对象时,位于内部的这个对象可以被视为引用对象,也可以是值对象。两者的明显的差别在于如何更新内部对象的属性。如果想在几个对象之间共享一个对象,以便几个对象都能看见对共享对象的修改,那么这个共享对象应该是引用对象。
- 将值对象改为引用对象:如果共享的数据需要更新,这时使用引用对象可能会导致数据不一致,可以考虑将多分数据副本变成单一的引用。
二、简化条件逻辑
- 分解条件表达式:当判断条件或计算逻辑过长,可以将它们提取出来,每个函数处理小段计算逻辑,以提高代码的可读性。
- 合并条件表达式:如果检查条件各不相同,最终行为一致,那么就应该将“逻辑或”和“逻辑与”合并。这样做的前提是每段条件表达式彼此独立。
- 以卫语语句取代嵌套条件表达式:如果if…else…的条件表达式都应该独立检查,那么就应该拆分成多个if条件判断并在其中返回。
- 以多态取代条件表达式:可以把基本逻辑放进父类,把需要特别判断的逻辑单独放进子类,用多态承载各个类型特有的行为。可用于switch语句的重构。
- 引入特例:一个数据结构在使用的时候会检查某个特殊值,在别的地方同样需要对这个值进行处理,那么可以将处理的逻辑集中到一起,复用这段处理逻辑。
- 引入断言:断言是一个条件表达式,应该总是为真。如果和断言不一致,表示实际值和预期不一样。用断言可以便捷的处理掉异常,并且错误描述是可以自定义的。
三、代码重构
重构前主函数:
private String buildFluxRequestContext(String assembleRequestMessage){
if(StringUtils.isBlank(assembleRequestMessage)){
return null;
}
JSONObject jsonObject = JSON.parseObject(assembleRequestMessage);
Object paymentAmountObject = jsonObject.get(ExtConstants.PAYMENT_AMOUNT);
if(paymentAmountObject instanceof String){
paymentAmountObject = JSON.parseObject((String)paymentAmountObject);
jsonObject.remove(ExtConstants.PAYMENT_AMOUNT);
}
Money paymentAmount = null;
if(paymentAmountObject instanceof JSONObject){
paymentAmount = JSON.toJavaObject((JSONObject)paymentAmountObject, Money.class);
}
PayNotifyRequest payNotifyRequest = JSON.toJavaObject(jsonObject, PayNotifyRequest.class);
payNotifyRequest.setPaymentAmount(paymentAmount);
RtBridgeCallbackDTO rtBridgeCallbackDTO = new RtBridgeCallbackDTO();
rtBridgeCallbackDTO.setChannel(null);
rtBridgeCallbackDTO.setChannelResponseCode(payNotifyRequest.getChannelResponseCodeInfo().getChannelResponseCode());
rtBridgeCallbackDTO.setChannelResponseMessage(payNotifyRequest.getChannelResponseCodeInfo().getChannelResponseMessage());
rtBridgeCallbackDTO.setChannelResponseSubCode(payNotifyRequest.getChannelResponseCodeInfo().getChannelResponseSubCode());
rtBridgeCallbackDTO.setChannelResponseSubMessage(payNotifyRequest.getChannelResponseCodeInfo().getChannelResponseSubMessage());
rtBridgeCallbackDTO.setExternalRequestNo(payNotifyRequest.getExternalRequestNo());
rtBridgeCallbackDTO.setExternalReferenceNo(payNotifyRequest.getExternalReferenceNo());
Map<String, Object> channelResponseContext = new HashMap<>();
if(null != payNotifyRequest.getPaymentAmount()){
channelResponseContext.put(ExtConstants.PAYMENT_AMOUNT, payNotifyRequest.getPaymentAmount());
}
if(MapUtils.isNotEmpty(payNotifyRequest.getExtendInfo())){
channelResponseContext.put(ExtConstants.EXT, JSON.toJSONString(payNotifyRequest.getExtendInfo()));
}
rtBridgeCallbackDTO.setChannelResponseContext(channelResponseContext);
rtBridgeCallbackDTO.setCompositeContext(copyCompositeContext(rtBridgeCallbackDTO.getChannelResponseContext()));
return JSON.toJSONString(rtBridgeCallbackDTO);
}
重构动机:
1.函数不符合单一权责原则
2.函数过长,没有提取子函数
重构后主函数:
private String FluxRequestContextConvert(String assembleRequestMessage){
if(StringUtils.isBlank(assembleRequestMessage)){
return null;
}
JSONObject jsonObject = JSON.parseObject(assembleRequestMessage);
PayNotifyRequest payNotifyRequest = JSON.toJavaObject(jsonObject, PayNotifyRequest.class);
payNotifyRequest.setPaymentAmount(paymentAmountConvert(jsonObject));
RtBridgeCallbackDTO rtBridgeCallbackDTO = buildRtBridgeCallbackDTO(payNotifyRequest);
return JSON.toJSONString(rtBridgeCallbackDTO);
}
提取的字函数:
private Money paymentAmountConvert(JSONObject jsonObject){
Object paymentAmountObject = jsonObject.get(ExtConstants.PAYMENT_AMOUNT);
if(paymentAmountObject instanceof String){
paymentAmountObject = JSON.parseObject((String)paymentAmountObject);
jsonObject.remove(ExtConstants.PAYMENT_AMOUNT);
}
Money paymentAmount = null;
if(paymentAmountObject instanceof JSONObject){
paymentAmount = JSON.toJavaObject((JSONObject)paymentAmountObject, Money.class);
}
return paymentAmount;
}
private Map<String,Object> buildChannelResponseContext(PayNotifyRequest payNotifyRequest){
Map<String, Object> channelResponseContext = new HashMap<>();
if(null != payNotifyRequest.getPaymentAmount()){
channelResponseContext.put(ExtConstants.PAYMENT_AMOUNT, payNotifyRequest.getPaymentAmount());
}
if(MapUtils.isNotEmpty(payNotifyRequest.getExtendInfo())){
channelResponseContext.put(ExtConstants.EXT, JSON.toJSONString(payNotifyRequest.getExtendInfo()));
}
return channelResponseContext;
}
private RtBridgeCallbackDTO buildRtBridgeCallbackDTO(PayNotifyRequest payNotifyRequest){
RtBridgeCallbackDTO rtBridgeCallbackDTO = new RtBridgeCallbackDTO();
rtBridgeCallbackDTO.setChannel(null);
rtBridgeCallbackDTO.setChannelResponseCode(payNotifyRequest.getChannelResponseCodeInfo().getChannelResponseCode());
rtBridgeCallbackDTO.setChannelResponseMessage(payNotifyRequest.getChannelResponseCodeInfo().getChannelResponseMessage());
rtBridgeCallbackDTO.setChannelResponseSubCode(payNotifyRequest.getChannelResponseCodeInfo().getChannelResponseSubCode());
rtBridgeCallbackDTO.setChannelResponseSubMessage(payNotifyRequest.getChannelResponseCodeInfo().getChannelResponseSubMessage());
rtBridgeCallbackDTO.setExternalRequestNo(payNotifyRequest.getExternalRequestNo());
rtBridgeCallbackDTO.setExternalReferenceNo(payNotifyRequest.getExternalReferenceNo());
rtBridgeCallbackDTO.setChannelResponseContext(buildChannelResponseContext(payNotifyRequest));
rtBridgeCallbackDTO.setCompositeContext(copyCompositeContext(rtBridgeCallbackDTO.getChannelResponseContext()));
return rtBridgeCallbackDTO;
}