导航

SpringBoot+JPA实现DDD(一)

Posted on 2020-08-16 18:33  ahau10  阅读(4577)  评论(0编辑  收藏  举报

前面2篇DDD入门之理解面向对象(一), DDD入门之解决了什么问题(二) 已经说明了为什么要使用DDD,现在来看一个具体的例子:

明确需求

业务需求

假设我们要实现一个商品中心这个核心领域。要求如下:

  • 商品包含一个或多个明细。一个明细也可以被包含在多个商品里。明细有三种:在线课程、实体书、线下服务。明细不可单独售卖,但可以单独编辑
  • 商品和明细都有类目
  • 商品的类目和明细的类目可以保持一致,也可以不保持一致
  • 明细在不同的商品中可以有不同的价格
  • 商品的价格是各明细的价格的总和。商品的价格不可修改,可通过添加优惠券实现减价。
  • 在线课程的有效期分两种:截止日期,下单后xx月。
  • 商品有状态,必须是上架状态才可以售卖,上架后不可修改
  • 商品要审核后才能上架,因为商品内可能有违规的图片、文字,所以必须要经过法务审核

构建模型

1.商品在其生命周期内是可修改的,且有唯一的标识,很明显是个实体。并且,商品是跟外界交互的入口,它是一个聚合根。
2.课程有唯一的标识,可被修改,虽然它被包含在商品内,但是它可以单独编辑。一个商品被下架了,但是这个课程在其它商品里仍然可以被售卖。它的生命周期是独立的,所以它也是一个聚合根。
3.实体书和线下服务同理,也是聚合根。
4.优惠券比较特殊。它有自己的生命周期。如果优惠活动很多,也很复杂,应该将优惠拆分成一个单独的支撑领域。这样优惠可以做的很复杂,比如弄一个规则引擎来配置各种优惠券。这里我只做一个实现DDD的demo,不搞那么复杂,暂时不考虑优惠。
5.审核也比较特殊,它应该是一个通用领域。这里不考虑审核。

实现模型

需要数据库设计吗? 个人认为不需要了。还记得hibernate的ORM和自动建表的功能吗?曾经我们对hibernate弃如敝履,现在回过头来看,也许我们用错了。
我们总以为Hibernate自动生成ddl的功能很鸡肋,那是因为我们太习惯于先建表,后写代码了。我们一直以为数据库设计是基石,只有把数据库设计好了,才能可靠地实现业务。人家DDD根本不是这么玩的。 先设计数据库,开发人员跟业务之间就被这个数据库的表结构给隔离开了。其关系是: 业务 <--> 数据库 <--> 开发。
DDD的玩法是: 开发 <--> 业务 <--> 仓储(数据库),看到区别了吗?这种玩法是直面业务。DDD好玩的地方就在于:

真正的程序员敢于直面复杂的业务!

我知道大家嫌弃hibernate,很重要的一个原因是关联表查询的时候很难受。一提到这个大家都感同身受。现在为什么我改变主意了呢?因为实现DDD的时候可以采用CQRS(读写分离)架构。这样一来,在写数据的时候只需要少量简单的查询即可,复杂的查询放在读模型里,读模型不需要跟写模型保持一致,读的时候可以选择原生的SQL,Mybatis,或者NoSQL,再也不用担心配置复杂的一对多,多对多等问题了。

据我所知,.Net的小伙伴比较熟悉DDD,可能是.Net有一整套DDD的框架吧。有人说Java用了Spring框架,天生的只能用贫血结构。因为实体里没有save,update等方法,所以是贫血的。这种说法是有问题的。原因我在DDD入门之理解面向对象(一)这篇文章里已经说过了,这里不再赘述了。 如果有不同看法,欢迎留言讨论。DDD最有争议的就是这个“贫血”和“充血”模型了吧。

我打算用Spring Boot + JPA写一个DDD的demo。Spring Data JPA 默认就是Hibernate实现的,本系列文章JPA就是指Spring Data JPA, 具体的ORM框架就是Hibernate。