本文共 2172 字,大约阅读时间需要 7 分钟。
还有就是关于领域服务:
所谓服务,它强调与其他对象的联系。不像实体和值对象,服务完全是根据能够为客户做什么来定义的。服务往往代表一种行为,而不是一个实体,是一个动词而不是一个名词。服务可以有一个抽象的、有意图的定义,这与一个对象的定义有所不同。服务应该还有一个定义好的职责,它的职责和接口被定义为领域模型的一部分。操作名应该来自通用语言,如果通用语言中还没有这个操作名,则应该把它添加进去。调用的参数和返回的结果应该是领域对象。
以上关于领域服务的概念来自《领域驱动设计-软件核心复杂性应对之道》,其实这一段描述只是这本书中的一点,还有很多精彩的讲解,朋友们感兴趣的话可以参考下,关于领域服务的描述,主要有几个注意点:
在领域驱动设计中,除了领域服务外,还包含基础层服务和应用层服务,有时候我们如果处理的不小心的话,容易把他们三个搞混掉,在领域驱动设计这本书中讲了一个转账事例,用来区分这三者之间的职责关系,如下:
应用层-资金转账应用服务
领域层-资金转账领域服务
基础结构层-发送通告服务
通过这个事例,我们可以很清晰的分辨出这三个服务所对应的职责:应用服务管流程;领域服务管业务;基础服务管后勤。在这个转账事例中,我们在设计领域服务的时候就可以设计为:FundsTransferService,代表的是资金转账服务,转账就是一个动词。可以想一想,如果按照我们之前的那种设计思想,肯定会在资金实体中,定义一个转账方法,用来表示资金对象可以转自己?还真是蛮可笑的。在设计领域服务的时候可以这样考虑,当一种业务逻辑,在实体中所不能表述的时候,或者表述的所不合理的时候,就要考虑一下领域服务设计的必要了。
回到我们的消息领域模型,来看一下充血设计前后解决方案图:
前 后
可以看到在设计之前,我对文件名的命名就有问题,而且 MessageState 是值对象,应该和实体是区分开来的,设计后,这三者组成才可以称之为领域模型,具体的实现代码如下。
消息实体:
发送消息领域服务:
消息应用服务:
这边再简单描述下发送消息这个业务流程实现,其实看下应用层的代码就清楚了,首先,UI 发送一个发消息的请求给应用层(相当于系统),参数为:标题、内容、发送人登录名、收件人显示名,应用层服务接到请求之后,先根据发送人和收件人的名称去仓储中查找相对应的用户,如果用户不存在,直接越过下面的发送操作,如果用户存在,则创建一个消息对象,在消息实体的构造函数中去验证这些参数的规则(比如参数不为空、字符串长度限制等等),如果验证成功则创建消息对象成功,首先这这一方面的改进之处就是,把收件人的赋值操作放在这边了,发送消息这个业务逻辑的体现其实并不是简单的赋值操作,其实这种实现更符合实际生活,比如我写一封信给女朋友,写好标题、内容、收件人和发件人之后,我并没有寄出,但是这封信已经存在了(符合信存在的标准),但是没有寄出,也就是说这个消息对象已经存在,只是现在这个对象的状态是未寄出,关于这一点,其实是和之前的设计是完全不同的,具体不同我也就不说了。
换个行,要不然看着太费劲。我们接着说,消息对象创建成功之后(状态是未发),调用发送消息领域服务,进行业务规则验证(比如发送人不能和收件人相同,发送人一天之内不能发送超过100个的短消息等等),其实这才是真正的发送消息业务逻辑,正如领域服务所定义的那样,参数和返回值都是领域对象,也就是消息实体,发送验证成功后进入持久化或者基础服务发送邮箱,整个发送消息的工作流程就是这样。
在上述发送消息工作流程描述中,需要注意的最重要的一点,就是消息状态的体现,也就是消息对象的未发状态和已发状态,这两个状态确定的前提这个消息对象是存在的,也就是创建成功的。在以前的设计中,如何体现这个发送状态的确定?答案就是收件人的赋值,之前认为,只有填写了收件人,那这个消息的状态就是已发送,其实这种逻辑有点天马星空。我现在个人感觉,消息对象的发送状态不能由它自身确定,也就是说不能由它自己的某一个属性确定,它应该是一个动态的过程,也就是在验证发送业务规则成功后,retrun 之后的那个消息对象,表示这个消息对象的状态是已发送的,因为它是符合发送消息业务规则并验证通过,那它的状态就是已发送。
本文转自田园里的蟋蟀博客园博客,原文链接:http://www.cnblogs.com/xishuai/p/3827216.html,如需转载请自行联系原作者