在2019年我初次接触到领域驱动设计(Domain-Driven Design,简称DDD)的概念。在我的探索中,我发现许多有关DDD的教程过于偏重于战略设计,充斥着许多晦涩难懂的概念,导致阅读起来相当艰难。有些教程往往只是解释了DDD的概念,而未深入探讨为何要采用这种方式以及这样做能带来哪些好处,这导致很多人在实践应用DDD时遇到了诸多难题。甚至有些人为了引入DDD而在项目中强制采用DDD架构,结果却意外增加了代码的复杂性,带来了一系列潜在的风险。
为了解决这一问题,我计划从代码的基础入手,详细讲解如何将DDD的理念应用于实际开发中,以便解答为何DDD能使我们的代码更加整洁的问题。今天,我们将着重讨论如何运用DDD的思想来组织我们的代码,从而实现”高内聚、低耦合”的开发目标。
在接下来的讨论中,我将与大家分享我在将DDD理念融入实际项目中的一些心得和体会,以及如何在现实项目中充分发挥DDD的优势。无论是战略设计还是战术实施,我都将尽可能以通俗易懂的方式进行解释,希望能够帮助大家更好地理解和应用DDD,从而在编码的道路上越走越远。
首先,让我们看一个电商系统中下单功能的代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| @Autowired ProductDao productDao; @Autowired UserDao userDao; public void createOrder(String productId,String userId,int count){ Product product = productDao.queryById(productId); UserInfo user=userDao.queryByUserId(userId); RiskResponse riskRes= riskClient.queryRisk(xxx); if(riskRes!=null&&riskRes.getCode()==0&&riskRes.getRiskCode().equal("0001")){ throw new BizException("下单失败,请检查网络") } Order order=new Order(); order.setOrderId(IdUtils.generateId()); order.setPrice(product.getPrice()*count); order.setAddress(user.getAddress()); order.setStatus(OrderEnum.OrderSucess); orderDao.insert(order); redisService.set("Order:OrderID_"+order.getOrderId(),order); orderLogDao.addLog(order); MessageEntity message = new MessageEntity(); message.setOrderId(order.getOrderId()); message.setMessage("下单成功"); kafkaSender.sent(messageEntity);
}
|
代码分析
首先,我们对这段代码的逻辑进行整理,共涉及5个步骤:
- 查询商品和用户信息
- 下单行为的风控检测
- 订单创建和持久化
- 写入缓存和记录下单日志
- 发送订单下单成功消息,通知其他系统
我们从这几个过程入手,根据业务的重要性,我们可以将它们划分为核心业务和非核心业务。显然,下单及其相关操作属于核心代码(步骤1、2、3)。与此相比,写日志、写入缓存以及发送Kafka消息则属于下单过程的非核心业务
核心代码分析