学习DDD的初步尝试,从最基础的开始,业务介绍,划分限界上下文 ,建立模型
Conference业务简介
Conference是这样一个系统,它提供了一个在线创建会议以及预订会议座位的平台。这个系统的用户有两类: 1:客户,可以创建和管理会议。 2:会议座位预定者,可以预订会议座位。 具体的关键业务描述如下: 1.客户登陆系统,客户可以创建一个会议,并录入会议的基本信息,比如名称、时间段、地点,参会人数等。 2.客户定义某个会议的座位类型,可以定义多个,每个座位类型包含的信息有:名称、座位价格、座位数量 ,根据座位类型自动生成座位编号。 3.客户发布或取消发布某个会议,当一个会议发布后,预订者就可以在线预订会议的座位了;如果取消发布,则该会议对预订者不可见。 4.预订者在预订会议座位时,会生成订单,订单需要进行支付才会生效。 5.订单生成后,预订者可以有15分钟的时间付款,超过15分钟,订单预定的座位就会回收,允许其他人预定。 6.预订者成功预订了座位后,可以指定每个座位的实际参会人信息; 7.客户(会议的Owner)可以管理他创建的每个会议的所有订单,比如可以查看该会议的所有订单以及参会人信息,以方便联系参会人;这个案例是汤总的Conference案例,案例地址: https://www.cnblogs.com/netfocus/p/4591407.html ,案例源码地址:https://github.com/tangxuehua/Conference 这个案例是汤总的博客,这里有一些小改动,因为自己前面写了一个RBAC权限的简单小DEMO,可能会融入进来,以前都是拿到需求基本上都是直接建表,开发,很少分析,第一次真正的尝试,希望大家能指出缺点,一起交流沟通。 后面会写出这个案例Demo,打算从最基础的开始,因为在写的过程中一定会有收获,带个问题去解决,总比不去尝试的好,看起来简单的东西,一去实践会发现困难重重,看起来难的东西,不断的去尝试,会发现其实并没有想象的难
业务流程梳理,上下文划分
1.发现业务概念,画出业务流程图 2.找出业务场景,根据角色,画出用例图 (用户故事),根据场景的语义相关性,以及业务相关性,将场景归类 (将业务分类,不要太过于纠结,后面分析可以完善)限界上下文 3.分析每一个业务场景,找出场景中的参与者 ,参与者的基本特征 ,分析场景中交互的过程,识别业务场景中的规则,分析状态变化的影响,比如(取消会议,对预定者不可见),状态比较复杂时:可以考虑画出状态变迁的流程图或者以其他方式表达出变化的过程,比如(订单状态的变化),识别出聚合根,实体,值对象 ,领域服务 ,领域事件 4.分析多个场景之间的交互过程与方式,以及交互过程中产生的影响,确实协作的方式,画出 上下文映射图 ,比如(订单和支付场景,支付成功之后,通知订单,改变状态)一:发现业务概念,画出业务流程图 ![](https://img2018.cnblogs.com/blog/1297333/201906/1297333-20190603233040176-1809180040.png)
二:找出业务场景,根据角色,画出用例图 (用户故事),根据场景的语义相关性,以及业务相关性,将场景归类 (将业务分类,不要太过于纠结,后面分析可以完善)限界上下文
业务场景:
1,客户创建会议 2,客户定义会议座位类型,生成座位号 3,客户发布会议 4,客户取消会议 5,预定者预定会议 6,生成订单 7,订单支付 8,指定座位参会人信息
用例图:
场景归类:
三:分析每一个业务场景,找出场景中的参与者 ,参与者的基本特征 ,分析场景中交互的过程,识别业务场景中的规则,分析状态变化的影响,比如(取消会议,对预定者不可见),状态比较复杂时:可以考虑画出状态变迁的流程图或者以其他方式表达出变化的过程,比如(订单状态的变化),识别出聚合根,实体,值对象 ,领域服务 ,领域事件
ConferenceContext
一:客户创建会议 参与者:客户 ,会议 ,座位类型 ,座位 客户 Customer:Id ,CustomerId ,CustomerName ,CustomerAddress ,CustomerPassWord (聚合根) 会议 Conference:Id ,ConferenceName ,ConferencePublishStatus , ConferenceStrartTime , ConferenceEndTime , ConferenceAddress,ConferenceContent ,CustomerId ,ConferenceParticipantNum,SeatTypeList (聚合根) 规则: 1,客户必须登陆系统,创建会议时,客户必须在系统中存在 二:客户定义座位类型 参与者:客户 ,会议 ,座位类型 ,座位 座位类型 SeatType:Id ,SeatTypeName ,SeatTypePrice ,SeatTypeNum ,ConferenceId , SeatList 实体 座位 Seat:Id ,SeatNumber , SeatTypeId 实体 规则: 1,客户定义座位类型的数量,不能超过会议的参会人数 2,座位编号随机生成,不允许出现重复编号,最大编号不能超过会议参会人数 交互过程以及影响:座位类型成功后,根据规则生成座位号
三:客户发布会议,取消会议
参议者:客户 ,会议
作为会议的状态
规则:
3,客户没有定义座位类型,不能发布会议
4,发布会议,对预定者可见 ,取消会议,对预订者不可见
交互过程以及影响:发布会议后,会改变会议的状态为:已发布,对预定者可见,取消会议,会改变会议的状态为:未发布 ,对预订者不可见
预订者在预订会议座位,生成订单,订单需要进行支付才会生效 1,预定者,登陆会议系统 2,浏览已发布的会议 3,选择要预定的会议 4,选择要预定的会议座位类型 4,选择要预定的座位(可以选择多个座位) 5,点击提交,生成订单 6,系统处理订单 7,进入支付的页面,用户确认支付信息 8,用户点击确认支付, 9,系统处理支付,成功时:修改支付的状态为:已支付,发送一个事件通知订单,订单扣除会议座位,修改订单的状态为:支付订单成功 失败时:修改支付的状态为:支付失败,发送一个事件通知订单,修改订单的状态为:支付订单失败,回收会议座位 10,用户点击拒绝支付,修改支付的状态为:已拒绝,发送一个事件通知订单,订单回收会议座位,修改订单的状态为:拒绝支付 11,订单超过15分钟未支付,修改订单的状态为:支付已超时
ScheduledContext
预定会议座位 ,生成订单 参与者:预定者 ,订单 ,订单明细,会议 ,会议座位类型 ,会议座位 预定者(PredestineUser):Id ,PredestineUserName ,PredestineUserPhone ,PredestineUserPassWord 聚合根 订单 (Order):Id , ConferenceId , PredestineUserId , OrderTotalPrice , CreateTime , OrderStatus ,OrderItemList 订单明细(OrderItem)Id ,OrderId ,SeatId ,SeatPrice 规则: 1,会议的状态必须是发布的状态 2,订单中必须包含一条订单明细的信息 3,预定座位时检测座位是否被选择 4,预定成功后,15分钟必须支付,过期回收预定的座位
订单的状态:
1.已生成订单 (初始化状态)
2.预定座位成功 (预定成功,预扣会议座位,记录预定成功的时间,修改订单状态为:预定座位成功)
3.预定座位失败 (预定失败,修改订单状态为:预定座位失败)
4.支付已超时 (订单支付超时,回收的会议座位,修改订单状态为:支付已超时)
5.支付订单成功 (扣除会议座位,修改订单状态为:支付订单成功)
6.拒绝支付 (预定者拒绝支付,回收会议座位,修改订单状态为:拒绝支付)
PayContext
支付订单 参与者:订单 ,支付 支付(Pay):Id ,OrderId ,PayPrice , PayStatus , PayCreateTime 聚合根 支付明细(PayItem): Id , PayId , SeatId , SeatPrice 实体 规则: 1.支付时验证余额 支付的状态:1, 待支付 2, 支付成功 3, 拒绝支付 4, 支付失败 交互过程: 1,系统处理支付,成功时:修改支付的状态为:已支付,发送一个事件通知订单,订单扣除会议座位,修改订单的状态为:支付订单成功 失败时:修改支付的状态为:支付失败,发送一个事件通知订单,订单回收会议座位,修改订单的状态为:支付订单失败 2,用户点击拒绝支付,修改支付的状态为:已拒绝,发送一个事件通知订单,订单回收的会议座位,修改订单的状态为:拒绝支付 3,订单超过15分钟未支付,修改订单的状态为:支付已超时
指定座位实际参会人信息
参与者:订单 ,座位 ,参会人
订单座位(OrderSeat):Id ,OrderId ,ParticipantName ,ParticipantPhone 聚合根
![](https://img2018.cnblogs.com/blog/1297333/201906/1297333-20190604093818953-1281196654.png)
4.分析多个场景之间的交互过程与方式,以及交互过程中产生的影响,确实协作的方式,画出 上下文映射图 ,比如(订单和支付场景,支付成功之后,通知订单,改变状态)