DDD 应对具体业务场景,Domain Model 重新设计


  还有就是关于领域服务:

所谓服务,它强调与其他对象的联系。不像实体和值对象,服务完全是根据能够为客户做什么来定义的。服务往往代表一种行为,而不是一个实体,是一个动词而不是一个名词。服务可以有一个抽象的、有意图的定义,这与一个对象的定义有所不同。服务应该还有一个定义好的职责,它的职责和接口被定义为领域模型的一部分。操作名应该来自通用语言,如果通用语言中还没有这个操作名,则应该把它添加进去。调用的参数和返回的结果应该是领域对象。

  以上关于领域服务的概念来自《领域驱动设计-软件核心复杂性应对之道》,其实这一段描述只是这本书中的一点,还有很多精彩的讲解,朋友们感兴趣的话可以参考下,关于领域服务的描述,主要有几个注意点:

  • 强调与其他对象的管理;
  • 代表一种行为,是动词而非名词;
  • 职责和定义是领域模型的一部分;
  • 操作名来来自通用语言(比如发消息,那就可以定义为 SendMessage,谁都可以看得懂);
  • 调用的参数和返回结果应该是领域对象(比如实体)

  在领域驱动设计中,除了领域服务外,还包含基础层服务和应用层服务,有时候我们如果处理的不小心的话,容易把他们三个搞混掉,在领域驱动设计这本书中讲了一个转账事例,用来区分这三者之间的职责关系,如下:

  应用层-资金转账应用服务

  1. 读取输入(例如XML请求)
  2. 发送消息给领域服务,要求处理
  3. 监听确认消息
  4. 决定用基础结构层的服务发送通告

  领域层-资金转账领域服务

  1. 必要的账户和分类账对象的相互作用,完成正确的提取和存入
  2. 确认转账结果(转账是否被允许或拒绝等)

  基础结构层-发送通告服务

  1. 由应用选择通告方法,发送电子邮件、信件或者通过其他通信途径

  通过这个事例,我们可以很清晰的分辨出这三个服务所对应的职责:应用服务管流程;领域服务管业务;基础服务管后勤。在这个转账事例中,我们在设计领域服务的时候就可以设计为:FundsTransferService,代表的是资金转账服务,转账就是一个动词。可以想一想,如果按照我们之前的那种设计思想,肯定会在资金实体中,定义一个转账方法,用来表示资金对象可以转自己?还真是蛮可笑的。在设计领域服务的时候可以这样考虑,当一种业务逻辑,在实体中所不能表述的时候,或者表述的所不合理的时候,就要考虑一下领域服务设计的必要了。

  回到我们的消息领域模型,来看一下充血设计前后解决方案图:

                                        

  可以看到在设计之前,我对文件名的命名就有问题,而且 MessageState 是值对象,应该和实体是区分开来的,设计后,这三者组成才可以称之为领域模型,具体的实现代码如下。

  消息实体:

  View Code

  发送消息领域服务:

  View Code

  消息应用服务:

  View Code

  这边再简单描述下发送消息这个业务流程实现,其实看下应用层的代码就清楚了,首先,UI 发送一个发消息的请求给应用层(相当于系统),参数为:标题、内容、发送人登录名、收件人显示名,应用层服务接到请求之后,先根据发送人和收件人的名称去仓储中查找相对应的用户,如果用户不存在,直接越过下面的发送操作,如果用户存在,则创建一个消息对象,在消息实体的构造函数中去验证这些参数的规则(比如参数不为空、字符串长度限制等等),如果验证成功则创建消息对象成功,首先这这一方面的改进之处就是,把收件人的赋值操作放在这边了,发送消息这个业务逻辑的体现其实并不是简单的赋值操作,其实这种实现更符合实际生活,比如我写一封信给女朋友,写好标题、内容、收件人和发件人之后,我并没有寄出,但是这封信已经存在了(符合信存在的标准),但是没有寄出,也就是说这个消息对象已经存在,只是现在这个对象的状态是未寄出,关于这一点,其实是和之前的设计是完全不同的,具体不同我也就不说了。

  换个行,要不然看着太费劲。我们接着说,消息对象创建成功之后(状态是未发),调用发送消息领域服务,进行业务规则验证(比如发送人不能和收件人相同,发送人一天之内不能发送超过100个的短消息等等),其实这才是真正的发送消息业务逻辑,正如领域服务所定义的那样,参数和返回值都是领域对象,也就是消息实体,发送验证成功后进入持久化或者基础服务发送邮箱,整个发送消息的工作流程就是这样。

  在上述发送消息工作流程描述中,需要注意的最重要的一点,就是消息状态的体现,也就是消息对象的未发状态和已发状态,这两个状态确定的前提这个消息对象是存在的,也就是创建成功的。在以前的设计中,如何体现这个发送状态的确定?答案就是收件人的赋值,之前认为,只有填写了收件人,那这个消息的状态就是已发送,其实这种逻辑有点天马星空。我现在个人感觉,消息对象的发送状态不能由它自身确定,也就是说不能由它自己的某一个属性确定,它应该是一个动态的过程,也就是在验证发送业务规则成功后,retrun 之后的那个消息对象,表示这个消息对象的状态是已发送的,因为它是符合发送消息业务规则并验证通过,那它的状态就是已发送。




本文转自田园里的蟋蟀博客园博客,原文链接:http://www.cnblogs.com/xishuai/p/3827216.html,如需转载请自行联系原作者

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值