当前位置:网站首页>如何优雅的消除系统重复代码
如何优雅的消除系统重复代码
2022-08-01 23:55:00 【InfoQ】
引言
为什么要消除重复代码
系统维护成本高
程序Bug概率高
如何优雅的消除重复代码
统一参数校验
public OrderDTO queryOrderById(String id) {
if(StringUtils.isEmpty(id)) {
return null;
}
OrderDTO order = orderBizService.queryOrder(id);
if(Objects.isNull(Order)) {
return null;
}
...
}
public List<UserDTO> queryUsersByType(List<String> type) {
if(StringUtils.isEmpty(id)) {
return null;
}
...
}public class Assert {
public static void notEmpty(String param) {
if(StringUtils.isEmpty(param)) {
throw new BizException(ErrorCodes.PARAMETER_IS_NULL, "param is empty or null");
}
}
public static void notNull(Object o) {
if (Objects.isNull(o)) {
throw new BizException(ErrorCodes.PARAMETER_IS_NULL, "object is null");
}
}
public static void notEmpty(Collection collection) {
if(CollectionUtils.isEmpty(collection)) {
throw new BizException(ErrorCodes.PARAMETER_IS_NULL, "collection is empty or null");
}
}
}public OrderDTO queryOrderById(String id) {
Assert.notEmpty(id);
OrderDTO order = orderBizService.queryOrder(id);
Assert.notNull(order);
...
}
public List<UserDTO> queryUsersByType(List<String> type) {
Assert.notEmpty(type);
...
}统一异常处理
@GetMapping("list")
public ResponseResult<OrderVO> getOrderList(@RequestParam("id")String userId) {
try {
OrderVO orderVo = orderBizService.queryOrder(userId);
return ResponseResultBuilder.buildSuccessResponese(orderDTO);
} catch (BizException be) {
// 捕捉业务异常
return ResponseResultBuilder.buildErrorResponse(be.getCode, be.getMessage());
} catch (Exception e) {
// 捕捉兜底异常
return ResponseResultBuilder.buildErrorResponse(e.getMessage());
}
}@ControllerAdvice
@ResponseBody
public class UnifiedException {
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(BizException.class)
@ResponseBody
public ResponseResult handlerBizException(BizException bizexception) {
return ResponseResultBuilder.buildErrorResponseResult(bizexception.getCode(), bizexception.getMessage());
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseResult handlerException(Exception ex) {
return ResponseResultBuilder.buildErrorResponseResult(ex.getMessage());
}
}@GetMapping("list")
public ResponseResult<OrderVO> getOrderList(@RequestParam("id")String userId) {
List<OrderVO> orderVo = orderBizService.queryOrder(userId);
return ResponseResultBuilder.buildSuccessResponese(orderVo);
}优雅的属性拷贝
public class TaskConverter {
public static TaskDTO taskModel2DTO(TaskModel taskModel) {
TaskDTO taskDTO = new TaskDTO();
taskDTO.setId(taskModel.getId());
taskDTO.setName(taskModel.getName());
taskDTO.setType(taskModel.getType());
taskDTO.setContent(taskModel.getContent());
taskDTO.setStartTime(taskModel.getStartTime());
taskDTO.setEndTime(taskModel.getEndTime());
return taskDTO;
}
}public class TaskConverter {
public static TaskDTO taskModel2DTO(TaskModel taskModel) {
TaskDTO taskDTO = new TaskDTO();
BeanUtils.copyProperties(taskModel, taskDTO);
return taskDTO;
}
}核心能力抽象
public Class NormalUserSettlement {
//省略代码
...
public Bigdecimal calculate(String userId) {
//计算商品总价格
List<Goods> goods = shoppingService.queryGoodsById(userId);
Bigdecimal total = goods.stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getAmount()))).reduce(BigDecimal.ZERO, BigDecimal::add);
//计算优惠
Bigdecimal discount = total.multiply(new Bigdecimal(0.1));
//计算应付金额
Bigdecimal payPrice = total - dicount;
return payPrice;
}
//省略代码
...
}public Class VIPUserSettlement {
//省略代码
...
public Bigdecimal calculate(String userId) {
//计算商品总价格
List<Goods> goods = shoppingService.queryGoodsById(userId);
Bigdecimal total = goods.stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getAmount()))).reduce(BigDecimal.ZERO, BigDecimal::add);
//计算优惠
Bigdecimal discount = total.multiply(new Bigdecimal(0.2));
//计算应付金额
Bigdecimal payPrice = total - dicount;
return payPrice;
}
//省略代码
...
}public Class VIPUserSettlement {
//省略代码
...
public Bigdecimal calculate(String userId) {
//计算商品总价格
List<Goods> goods = shoppingService.queryGoodsById(userId);
Bigdecimal total = goods.stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getAmount()))).reduce(BigDecimal.ZERO, BigDecimal::add);
//计算优惠
Bigdecimal discount = total.multiply(new Bigdecimal(0.2));
//计算应付金额
Bigdecimal payPrice = total - dicount;
return payPrice;
}
//省略代码
...
}public Class AbstractSettlement {
//省略代码
...
public abstact Bigdecimal calculateDiscount();
public Bigdecimal calculate(String userId) {
//计算商品总价格
List<Goods> goods = shoppingService.queryGoodsById(userId);
Bigdecimal total = goods.stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getAmount()))).reduce(BigDecimal.ZERO, BigDecimal::add);
//计算优惠
Bigdecimal discount = calculateDiscount();
//计算应付金额
Bigdecimal payPrice = total - dicount;
return payPrice;
}
//省略代码
...
}
自定义注解和AOP
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeCost {
}
@Aspect
@Component
public class CostTimeAspect {
@Pointcut(value = "@annotation(com.mufeng.eshop.anotation.CostTime)")
public void costTime(){ }
@Around("runTime()")
public Object costTimeAround(ProceedingJoinPoint joinPoint) {
Object obj = null;
try {
long beginTime = System.currentTimeMillis();
obj = joinPoint.proceed();
//获取方法名称
String method = joinPoint.getSignature().getName();
//获取类名称
String class = joinPoint.getSignature().getDeclaringTypeName();
//计算耗时
long cost = System.currentTimeMillis() - beginTime;
log.info("类:[{}],方法:[{}] 接口耗时:[{}]", class, method, cost + "毫秒");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return obj;
}
}@GetMapping("/list")
public ResponseResult<List<OrderVO>> getOrderList(@RequestParam("id")String userId) {
long beginTime = System.currentTimeMillis();
List<OrderVO> orderVo = orderBizService.queryOrder(userId);
log.info("getOrderList耗时:" + System.currentTimeMillis() - beginTime + "毫秒");
return ResponseResultBuilder.buildSuccessResponese(orderVo);
}
@GetMapping("/item")
public ResponseResult<OrderVO> getOrderById(@RequestParam("id")String orderId) {
long beginTime = System.currentTimeMillis();
OrderVO orderVo = orderBizService.queryOrderById(orderId);
log.info("getOrderById耗时:" + System.currentTimeMillis() - beginTime + "毫秒");
return ResponseResultBuilder.buildSuccessResponese(orderVo);
}
@GetMapping("/list")
@TimeCost
public ResponseResult<List<OrderVO>> getOrderList(@RequestParam("id")String userId) {
List<OrderVO> orderVo = orderBizService.queryOrder(userId);
return ResponseResultBuilder.buildSuccessResponese(orderVo);
}
@GetMapping("/item")
@TimeCost
public ResponseResult<OrderVO> getOrderList(@RequestParam("id")String orderId) {
OrderVO orderVo = orderBizService.queryOrderById(orderId);
return ResponseResultBuilder.buildSuccessResponese(orderVo);
}引入规则引擎

public double calculate(int profit) {
if(profit < 1000) {
return profit * 0.1;
} else if(1000 < profit && profit< 2000) {
return profit * 0.15;
} else if(2000 < profit && profit < 3000) {
return profit * 0.2;
}
return profit * 0.3;
}// 奖励规则
package reward.rule
import com.mufeng.eshop.biz.Reward
// rule1:如果利润小于1000,则奖励计算规则为profit*0.1
rule "reward_rule_1"
when
$reward: Reward(profit < 1000)
then
$reward.setReward($reward.getProfit() * 0.1);
System.out.println("匹配规则1,奖励为利润的1成");
end
// rule2:如果利润大于1000小于2000,则奖励计算规则为profit*0.15
rule "reward_rule_2"
when
$reward: Reward(profit >= 1000 && profit < 2000)
then
$reward.setReward($reward.getProfit() * 0.15);
System.out.println("匹配规则2,奖励为利润的1.5成");
end
// rule3:如果利润大于2000小于3000,则奖励计算规则为profit*0.2
rule "reward_rule_3"
when
$order: Order(profit >= 2000 && profit < 3000)
then
$reward.setReward($reward.getProfit() * 0.2);
System.out.println("匹配规则3,奖励为利润的2成");
end
// rule4:如果利润大于等于3000,则奖励计算规则为profit*0.3
rule "reward_rule_4"
when
$order: Order(profit >= 3000)
then
$reward.setReward($reward.getProfit() * 0.3);
System.out.println("匹配规则4,奖励为利润的3成");
endpublic class DroolsEngine {
private KieHelper kieHelper;
public DroolsEngine() {
this.kieHelper = new KieHelper();
}
public void executeRule(String rule, Object unit, boolean clear) {
kieHelper.addContent(rule, ResourceType.DRL);
KieSession kieSession = kieHelper.getKieContainer().newKieSession();
//插入判断实体
kieSession.insert(unit);
//执行规则
kieSession.fireAllRules();
if (clear) {
kieSession.dispose();
}
}
}public class Profit {
public double calculateReward(Reward reward) {
String rule = "classpath:rules/reward.drl";
File rewardFile = new File(rule);
String rewardDrl = FileUtils.readFile(rewardFile, "utf-8");
DroolsEngine engine = new DroolsEngine();
engine.executeRule(rewardDrl, reward, true);
return reward.getReward();
}
}消除重复代码方法论


总结
边栏推荐
- 多御安全浏览器android版更新至1.7,改进加密协议
- Dynamic Scene Deblurring with Parameter Selective Sharing and Nested Skip Connections
- OpenCV DNN blogFromImage()详解
- 【Leetcode】473. Matchsticks to Square
- Thinkphp 5.0.24变量覆盖漏洞导致RCE分析
- Excel表格数据导入MySQL数据库
- Axure教程-新手入门基础(小白强烈推荐!!!)
- Is TCP reliable?Why?
- [LeetCode304 Weekly Competition] Two questions about the base ring tree 6134. Find the closest node to the given two nodes, 6135. The longest cycle in the graph
- 【Leetcode】2360. Longest Cycle in a Graph
猜你喜欢
随机推荐
cdh6 opens oozieWeb page, Oozie web console is disabled.
How to get the best power efficiency in Windows 11?
Is TCP reliable?Why?
1个月写900多条用例,二线城市年薪33W+的测试经理能有多卷?
ICLR 2022 Best Paper: Partial Label Learning Based on Contrastive Disambiguation
很多人喜欢用多御安全浏览器,竟是因为这些原因
Leetcode 129求根节点到叶节点数字之和、104二叉树的最大深度、8字符串转换整数(atoi)、82删除排序链表中的重复元素II、204二分查找、94二叉树的中序遍历、144二叉树的前序遍历
仿牛客网项目第三章:开发社区核心功能(详细步骤和思路)
Several interview questions about golang concurrency
Architecture basic concept and nature of architecture
An interview question about iota in golang
Quartus 使用 tcl 文件快速配置管脚
信息系统项目管理师必背核心考点(五十七)知识管理工具
好好活就是做有意义的事,有意义的事就是好好活
使用Ganache、web3.js和remix在私有链上部署并调用合约
工作5年,测试用例都设计不好?来看看大厂的用例设计总结
在MySQL中使用MD5加密【入门体验】
yay 报错 response decoding failed: invalid character ‘<‘ looking for beginning of value;
在linux下MySQL的常用操作命令
[Camp Experience Post] 2022 Cybersecurity Summer Camp









