很多时候在coding过程都或多或少听到隔壁的码农兄弟在吐槽:
1、这代码写的简直一坨shi...
2、这是谁写的代码,我看下提交记录,写的太辣鸡了...
3、我靠,还有tm这种操作的代码...
4、这培训刚出来的吧,代码写的这么烂...
5、这代码写的乱七八糟,根本看不懂...
以上声音,只要是干了几年的码农,绝对听到过不少,问题出在哪呢?难道码农真的是因为有看不惯别人写的代码的通病吗?这个答案这里先不回答,看完后面相信大家会得到答案和启发。
下面我们先看一段(张三实现的)伪代码,关注createrOrder方法:
/**
* <p>
* 订单服务类
* </p>
*
* @author lzy
* @since 2022/12/9.
*/
public class OrderHeadService {
@Autowired
private OrderHeadRepository orderHeadRepository;
@Autowired
private OrderLineRepository orderLineRepository;
@Autowired
private IntegralRepository integralRepository;
@Autowired
private StockRepository stockRepository;
@Autowired
private CapitalRepository capitalRepository;
/**
* 创建订单
* @param orderHead
*/
public void createOrder(OrderHead orderHead){
//校验订单参数
if (orderHead == null){
throw new RuntimeException("参数订单头对象不能为空");
}
if (CollectionUtils.isEmpty(orderHead.getOrderLineList())){
throw new RuntimeException("订单明细不能为空");
}
if (StringUtils.isEmpty(orderHead.getCustomerCode())){
throw new RuntimeException("客户编码不能为空");
}
if (StringUtils.isEmpty(orderHead.getMobile())){
throw new RuntimeException("联系电话不能为空");
}
if (StringUtils.isEmpty(orderHead.getReceiveAddress())){
throw new RuntimeException("收货地址不能为空");
}
orderHead.getOrderLineList().forEach(orderLine -> {
if (orderLine == null){
throw new RuntimeException("订单行对象不能为空");
}
if (StringUtils.isEmpty(orderLine.getLineNo())){
throw new RuntimeException("客户编码不能为空");
}
if (StringUtils.isEmpty(orderLine.getSkuCode())){
throw new RuntimeException("sku不能为空");
}
if (orderLine.getQuantity() == null || orderLine.getQuantity() < 1){
throw new RuntimeException("数量不能为空");
}
if (orderLine.getUnitPrice() == null){
throw new RuntimeException("单价不能为空");
}
});
//校验、占用库存、乐观锁控制并发
orderHead.getOrderLineList().forEach(orderLine -> {
int stockQuantity = stockRepository.queryStock(orderLine.getSkuCode());
if (stockQuantity < orderLine.getQuantity()){
throw new RuntimeException("库存不足 sku" + orderLine.getSkuCode());
}
stockRepository.preoccupyStock(orderLine.getSkuCode(), orderLine.getQuantity());
});
//占用资金
capitalRepository.preoccupyCapital(orderHead.getCustomerCode(), orderHead.getTotalAmount());
//保存订单信息
orderHeadRepository.saveOrderHead(orderHead);
orderLineRepository.saveOrderLine(orderHead.getOrderLineList());
//添加积分
BigDecimal addIntegralCondition = new BigDecimal(2000);
if (orderHead.getTotalAmount().compareTo(addIntegralCondition) > 0){
IntegralHead integralHead = new IntegralHead();
integralHead.setIntegral(orderHead.getTotalAmount());
integralRepository.addIntegral(integralHead);
}
}
}
张三实现的这段代码,我们先不说逻辑实现的是否合理,我们本次只聊可读性和扩展性,大家先自行体会下上面代码有没问题?在可读性和后续扩展性上方不方便?同样这里笔者先不评价,大家继续往下看。
下面我们继续看一段(老王实现的)伪代码,关注createrOrder方法:
/**
* <p>
* 订单服务类
* </p>
*
* @author lzy
* @since 2022/12/9.
*/
public class OrderHeadService {
@Autowired
private OrderHeadRepository orderHeadRepository;
@Autowired
private OrderLineRepository orderLineRepository;
@Autowired
private IntegralRepository integralRepository;
@Autowired
private StockRepository stockRepository;
@Autowired
private CapitalRepository capitalRepository;
/**
* 创建订单
*
* @param orderHead
*/
public void createOrder(OrderHead orderHead) {
//检查订单信息
this.checkOrder(orderHead);
//校验、占用库存、乐观锁控制并发
this.preoccupyStock(orderHead);
//占用资金
this.preoccupyCapital(orderHead);
//保存订单信息
this.saveOrder(orderHead);
//添加积分
this.addIntegral(orderHead);
}
}
老王实现的代码,可以清晰看到创建订单流程的顶层编排,可读性明细比张三的要清晰和简单,扩展性也明细容易很多,基本在子方法里面去改造或者新业务分支直接加方法即可。如果上来看到的这种代码实现方式,你还会吐槽吗,至少不会吐槽那么大声。
核心优化思路:
这里个人提出一个关键词【顶层流程编排】,任何代码只要遵循【顶层流程编排】习惯,基本可以让同事瞬间膜拜一阵,优化方式也很简单;
关键总结
【顶层流程编排】:就是将相同逻辑的代码块提取到一个方法去实现,总方法(例如createOrder)只负责调用编排这些方法块,而不是将各种逻辑混合在一块;
继续优化的思路:
在顶层流程编排的基础上,在配合设计模式,那写出来的代码,2个词6个字形容:【吊炸天、高大上】。
看完以上示例,大家是否有收货呢?
---------- 正文结束 ----------
长按扫码关注微信公众号
Java软件编程之家