亚洲必赢app在哪下载应对具体业务场景

By admin in 亚洲必赢app在哪下载 on 2019年2月20日

写在面前

亚洲必赢app在哪下载 1

  阅读目录:

  在上一篇《自家的“第叁次”,就那样没了:DDD(领域驱动设计)理论结合实施》博文中,简单介绍了世界驱动设计的部分见解,并简短已毕基于领域驱动设计的现实品种 MessageManager,自身在设计
MessageManager 项目事先,并没有看过 Eric埃文思 的《Domain-Driven Design
–Tackling Complexity in the Heart of Software》和 马丁 Fowler的《Patterns of Enterprise Application
Architecture》,《公司应用架构格局》这本书正在阅读,关于世界驱动设计,主要学习来源是园中的
netfocus、dax.net、以及清培兄的一对博文(小弟先在此谢过各位大神的无私贡献),还有就是解道中的领域驱动设计专题,当然还有局部出自搜索引擎的有个别材料,再增进自身的有的衡量和精晓,也就改为了属于自己的“领域驱动设计”。

  MessageManager
项目是对友好所知晓领域驱动设计的检验,就算您精心看过上一篇博文,你会意识 MessageManager
其实只是天地驱动设计的“外壳”,似乎大家种黄瓜,首先要搭3个架子,以便黄瓜的发育,MessageManager
项目就一定于那一个架子,宗旨的事物“黄瓜”并不设有,当时在规划完 MessageManager
项目标时候,其实早就发现难题的留存,所以在博文最终留给了上边五个难题:

  • Domain
    Model(领域模型):领域模型到底该怎么设计?你会看到,MessageManager
    项目中的 User 和 Message
    领域模型是十分贫血的,没有包含其他的事体逻辑,将来网上广大关于 DDD
    示例项目多数也设有那种景观,当然项目本人没有工作,只是不难的“CUQX56D”操作,然而如若是一对大型项目的扑朔迷离工作逻辑,该怎么去落到实处?或者说,领域模型完结什么样的事体逻辑?什么才是确实的政工逻辑?那么些难题很重大,后续商量。
  • Application(应用层):应用层作为协调服务层,当蒙受复杂的工作逻辑时,到底怎么已毕,而不使其变为
    BLL(业务逻辑层)?认清本质很要紧,后续商量。

  此外再贴一些园友们在上一篇的标题评论:

亚洲必赢app在哪下载 2

亚洲必赢app在哪下载 3

亚洲必赢app在哪下载 4

  关于以上的难题,本篇博文只是做一些解读,希望可以对那三个迷恋于天地驱动设计的对象们有的启迪,写得有不当之处,也欢迎指出。

题材根源是怎么样?

亚洲必赢app在哪下载 5

  出现上述难题的缘由是哪些?须要不难?设计不创建?准确的来说,应该都不是,小编觉着难点的发源是从未真正去通晓领域驱动设计,或许说没有真的用世界驱动设计的看法去规划或落到实处,领域驱动设计的定义网上一找一大堆,你看过几篇小说之后也能写出来之类的篇章,为啥?因为皆以泛泛而论,诸如:领域模型是小圈子驱动的宗旨;领域驱动基本分为四层(用户层、应用层、领域层和基础层);领域涵盖实体、值对象和劳务;还有局地凑合和聚合根之类的定义等等,文中也会给你列出有个别有关这个概念的代码完结,让你弹指间倍感原来领域驱动设计是那般的宏大上。

  但假如拿这一个概念去实践吧?却一直不是那么回事,未来采用领域驱动设计去开发的商行实际是太少了,原因有为数不少种,下边大概列出一些:

  • 开发费用太高,换句话说,就是假使使用领域驱动设计开发,须要聘请高级程序员、高级架构师和建模专家,一般那种开发人士薪给都相比较高,COO确实舍得啊?
  • 开发周期长,花在须要分析的流年比较长,甚至比程序完成还要长,这一个对业主来说是极度的,开发周期长,一般会表示商户的赢利下跌,公司赢利下落,老董的钱包就瘪了,CEO会甘愿呢?
  • 支付考虑转变难点,使用世界驱动设计开发,必要公司里的程序员了解领域驱动设计,要对面向对象(OO)设计有必然的知晓,现实情状是,大多数的程序员纵然使用的是面向对象语言(比如
    Java、C#),却做着面向进程的事(类似 C
    语言函数式的付出)。以后让公司的程序员使用世界驱动设计开发,就好比以前是用手一向开饭,以往让您选用筷子吃饭,你会习惯吗?那亟需一种变更,很多程序员会很不习惯,那也是世界驱动设计执行难的根本缘由。
  • 关于世界驱动设计实践经验实在太少,大家脑子中唯有模模糊糊的概念,却绝非确凿的实践,像
    dax.net
    那样去做到多少个完全基于领域驱动设计项目标大神实在太少了,很多都以像作者同样,明白一些定义后,放出二个粗略的以身作则
    德姆o,然后就平昔不然后了。

  埃里克 Evans 在二零零二年提议 DDD(领域驱动设计)的见地,距今已经十年了,推广却墨守成规,确实值得我们程序员去反省。

  扯得有点远了,回到这几个副题目:题指标来自是怎么着?答案大概会不令你知足,就是从未真正清楚领域驱动设计。那您可能会问:那实在的世界驱动设计是怎么?那么些作者想唯有埃里克 埃文思可以回复,但也毫不把世界驱动设计看得那般绝对,领域驱动设计只是一种带领,具体的完毕要用具体的法子,正如有句古话:师父领进门,修行在个人。逐个人有种种人的切实悟道,但再转移也毫不忘了师出同门。

  还有少数就是,有心上人提议简单的政工逻辑是浮现不出领域驱动设计的,关于那或多或少先是小编是相比较赞成的,但一旦去拿一些巨型业务场景去做领域驱动设计的言传身教,笔者个人认为也不太现实,终究时间资产太高了。我个人觉得小的工作场景和大的工作场景都得以动用领域驱动设计完毕,只是工作逻辑的复杂度分化,还有就是适费用也不一致,小的业务场景用脚本驱动形式去贯彻,或许会比世界驱动设计区已毕更简便、飞快,但是但凡是业务场景(不论高低),必然蕴含业务逻辑(CRUD
除外),那也就可以动用领域驱动设计去付出,依然那句话,只是不太相符,但做示范示例如故得以的。

  业务逻辑的复杂度主要显示在领域模型中,复杂性的政工逻辑,领域模型也就越复杂,但与不难性的领域模型实质是同等的。关于什么真正了解领域驱动设计?那一点自身个人觉得方法就是“迭代”,除非时时刻刻的去执行,不断的去体会,才能真的的去领略领域驱动设计,就好像MessageManager
项目,每两次有些体会作者就会认为这么做不创造,那就推倒重建,可能那样做又不创建,那就推倒再重建。。。

  闲话少说,来看那三次的“迭代”:

《领域驱动设计-软件基本复杂性应对之道》分层概念

  注:这一节点是本身背后添加的,真是造化,在本身写那篇博客的时候,正好有位不出名的情侣,发新闻说他看出本人事先的一篇博文,小编在文中跪求《领域驱动设计-软件基本复杂性应对之道》那本书,因为网上没得买。正好他有
Word
版,就算内容有点错别字,可是真诚感激那位不知名的心上人。大约阅读了下目录结构,确实是自身想要的,接下去会认真的拜读,有实质书的话当然更好,上面是摘自那本书的道岔概念。

亚洲必赢app在哪下载 6

  在面向对象的次序中,用户界面(UI)、数据库和其它协助代码,平日被直接写到业务对象中去。在UI和数据库脚本的表现中嵌入额外的作业逻辑。出现这种情景是因为从短时间的见地看,它是使系统运作起来的最简单的措施。当与世界有关的代码和大批量的其他代码混在共同时,就很难阅读并知道了。对UI的简约改动就会变动工作逻辑。改变工作规则恐怕需求如履薄冰地跟踪UI代码、数据库代码大概其余的次序成分。落成均等的模子驱动对象变得不切实际,而且自动化测试也难以使用。尽管在先后的各个行为中归纳了具备的技术和逻辑,那么它必须很粗略,否则会难以精晓。

  将二个错综复杂的程序举办层次划分。为每一层开展规划,每层都以内聚的同时只依靠于它的下层。采取规范的架构格局来形成与上层的松散关联。将装有与世界模型相关的代码都集聚在一层,并且将它与用户界面层、应用层和根基结构层的代码分离。世界对象能够将主要放在表明领域模型上,不要求关切它们本身的展现、存储和管理应用职务等故事情节。这样使模型发展得充裕充分和显著,足以挑动实质的业务知识并完结它。

用户界面层(表示层) 负责向用户显示信息,并且解析用户命令。外部的执行者有时可能会是其他的计算机系统,不一定非是人。
应用层 定义软件可以完成的工作,并且指挥具有丰富含义的领域对象来解决问题。这个层所负责的任务对业务影响深远,对跟其他系统的应用层进行交互非常必要这个层要保持简练。它不包括处理业务规则或知识,只是给下一层中相互协作的领域对象协调任务、委托工作。在这个层次中不反映业务情况的状态,但反映用户或程序的任务进度的状态
领域层(模型层) 负责表示业务概念、业务状况的信息以及业务规则。尽管保存这些内容的技术细节由基础结构层来完成,反映业务状况的状态在该层中被控制和使用。这一层是业务软件的核心。
基础结构层 为上层提供通用的技术能力:应用的消息发送、领域持久化,为用户界面绘制窗口等。通过架构框架,基础结构层还可以支持这四层之间的交互模式。

  1个目的所表示的事物是一个装有三番五次性和标识的概念(可以跟踪该事物经历的两样的动静,甚至足以让该事物跨越不一样的完成),依旧只是二个用来叙述事物的某种情形的质量?那就是实体与值对象最基本的界别。显明地接纳那三种模式中的一种来定义对象,可以使对象的意思更明显,并能够率领大家协会出多个敦实的宏图。

  此外,领域中还设有重重的方面,若是用行止或操作来讲述它们会比用对象来讲述尤其清楚。固然与面向对象建模理念稍有龃龉,但那么些然而是用劳动来讲述,而不是将以此操作的任务强加到某个实体或值对象身上。服务用来为客户请求提供服务。在软件的技术层中就有诸多劳务。服务也会在领域中出现,它们用于对软件必须形成的一部分运动开展建模,不过与气象非亲非故。有时大家亟须在目标模型中釆取一些和平解决的法子——那是不可反败为胜的,例如利用关周密据库举行仓储时就会产出这种情形。本章将会付给一些条条框框,当碰着那种复杂气象时,遵循那么些规则可以使我们维持正确的倾向。

  最终,大家对模块(Module)的座谈可以扶持掌握那样的观点:每种规划决策都应当是依照对天地的正确了解来做出。高内聚、低关联那种考虑往往被当做是一语双关的技术标准,它们对于概念本人也是适用的。在模型驱动的筹划中,模块是模型的一局地,它们应该力所能及反映出世界中的概念。

Repository(仓储)任务所在?

  言归正题。

  Repository(仓储)的定义能够参考:http://www.cnblogs.com/dudu/archive/2011/05/25/repository_pattern.html,作者个人相比较赞成
dudu 的驾驭:Repository
是两个独自的层,介于领域层与数量映射层(数据访问层)之间。它的留存让世界层备感不到数量访问层的存在,它提供1个类似集合的接口提必要世界层开展领域对象的走访。Repository
是堆栈管理员,领域层必要什么样东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不须求知道东西实际放在哪。

  关于 Repository
的概念,在《公司应用架构形式》书中也有认证:协调领域和多少映射层,利用类似于聚集的接口来做客领域对象。书中把
Repository 翻译为财富库,其实是和储存是壹个情趣,关于 Repository 这一节点的故事情节,作者大致阅读了两三篇才清楚了一些内容(那本书相比空虚难知晓,须要多读四回,然后依据自个儿的精通举办推敲酝酿),文中也交给了1个示范:查找一位所在的部门(Java),以便于深化对
Repository 的接头。

  大家先看一下 Repository
的定义前半句:协调领域和数据映射层,约等于 dudu
所说的在于领域层和数量映射层之间,通晓那点很要紧,非凡关键。然后大家再来看
MessageManager 项目中关于 Repository
的应用(已毕没有失常态),在哪应用呢?依据定义大家应有要与世长辞界层去找 Repository 的采纳,然而大家在
MessageManager.Domain 项目中找不到有关 Repository
的半毛应用,却在 MessageManager.Application
项目中找到了:

  1 /**
  2 * author:xishuai
  3 * address:https://www.github.com/yuezhongxin/MessageManager
  4 **/
  5 
  6 using System;
  7 using System.Collections.Generic;
  8 using AutoMapper;
  9 using MessageManager.Application.DTO;
 10 using MessageManager.Domain;
 11 using MessageManager.Domain.DomainModel;
 12 using MessageManager.Domain.Repositories;
 13 
 14 namespace MessageManager.Application.Implementation
 15 {
 16     /// <summary>
 17     /// Message管理应用层接口实现
 18     /// </summary>
 19     public class MessageServiceImpl : ApplicationService, IMessageService
 20     {
 21         #region Private Fields
 22         private readonly IMessageRepository messageRepository;
 23         private readonly IUserRepository userRepository;
 24         #endregion
 25 
 26         #region Ctor
 27         /// <summary>
 28         /// 初始化一个<c>MessageServiceImpl</c>类型的实例。
 29         /// </summary>
 30         /// <param name="context">用来初始化<c>MessageServiceImpl</c>类型的仓储上下文实例。</param>
 31         /// <param name="messageRepository">“消息”仓储实例。</param>
 32         /// <param name="userRepository">“用户”仓储实例。</param>
 33         public MessageServiceImpl(IRepositoryContext context,
 34             IMessageRepository messageRepository,
 35             IUserRepository userRepository)
 36             :base(context)
 37         {
 38             this.messageRepository = messageRepository;
 39             this.userRepository = userRepository;
 40         }
 41         #endregion
 42 
 43         #region IMessageService Members
 44         /// <summary>
 45         /// 通过发送方获取消息列表
 46         /// </summary>
 47         /// <param name="userDTO">发送方</param>
 48         /// <returns>消息列表</returns>
 49         public IEnumerable<MessageDTO> GetMessagesBySendUser(UserDTO sendUserDTO)
 50         {
 51             //User user = userRepository.GetUserByName(sendUserDTO.Name);
 52             var messages = messageRepository.GetMessagesBySendUser(Mapper.Map<UserDTO, User>(sendUserDTO));
 53             if (messages == null)
 54                 return null;
 55             var ret = new List<MessageDTO>();
 56             foreach (var message in messages)
 57             {
 58                 ret.Add(Mapper.Map<Message, MessageDTO>(message));
 59             }
 60             return ret;
 61         }
 62         /// <summary>
 63         /// 通过接受方获取消息列表
 64         /// </summary>
 65         /// <param name="userDTO">接受方</param>
 66         /// <returns>消息列表</returns>
 67         public IEnumerable<MessageDTO> GetMessagesByReceiveUser(UserDTO receiveUserDTO)
 68         {
 69             //User user = userRepository.GetUserByName(receiveUserDTO.Name);
 70             var messages = messageRepository.GetMessagesByReceiveUser(Mapper.Map<UserDTO, User>(receiveUserDTO));
 71             if (messages == null)
 72                 return null;
 73             var ret = new List<MessageDTO>();
 74             foreach (var message in messages)
 75             {
 76                 ret.Add(Mapper.Map<Message, MessageDTO>(message));
 77             }
 78             return ret;
 79         }
 80         /// <summary>
 81         /// 删除消息
 82         /// </summary>
 83         /// <param name="messageDTO"></param>
 84         /// <returns></returns>
 85         public bool DeleteMessage(MessageDTO messageDTO)
 86         {
 87             messageRepository.Remove(Mapper.Map<MessageDTO, Message>(messageDTO));
 88             return messageRepository.Context.Commit();
 89         }
 90         /// <summary>
 91         /// 发送消息
 92         /// </summary>
 93         /// <param name="messageDTO"></param>
 94         /// <returns></returns>
 95         public bool SendMessage(MessageDTO messageDTO)
 96         {
 97             Message message = Mapper.Map<MessageDTO, Message>(messageDTO);
 98             message.FromUserID = userRepository.GetUserByName(messageDTO.FromUserName).ID;
 99             message.ToUserID = userRepository.GetUserByName(messageDTO.ToUserName).ID;
100             messageRepository.Add(message);
101             return messageRepository.Context.Commit();
102         }
103         /// <summary>
104         /// 查看消息
105         /// </summary>
106         /// <param name="ID"></param>
107         /// <returns></returns>
108         public MessageDTO ShowMessage(string ID, string isRead)
109         {
110             Message message = messageRepository.GetByKey(ID);
111             if (isRead == "1")
112             {
113                 message.IsRead = true;
114                 messageRepository.Update(message);
115                 messageRepository.Context.Commit();
116             }
117             return Mapper.Map<Message, MessageDTO>(message);
118         }
119         #endregion
120     }
121 }

对,你曾经发现了 Repository
的踪迹,Repository
应用在应用层,那样就造成应用层和基础层(我把数量持久化放在基础层了)通讯,忽略了最要紧的天地层,领域层在内部起到的功能最多也等于传递3个卓殊贫血的圈子模型,然后通过
Repository
举办“CRUD”,那样的结果是,应用层不成为所谓的
BLL(常说的事务逻辑层)才怪,其它,因为事情逻辑都位于应用层了,领域模型也变得特别贫血。

  以上剖析可以回答上一篇中残留的题材:应用层作为协调服务层,当蒙受复杂的工作逻辑时,到底怎么落到实处,而不使其变为
BLL(业务逻辑层)?其实关于率先个难点(领域模型怎么着规划不贫血)也是足以拓展解答的,那一个后一节点有认证,关于这一多如牛毛难点的诱致自家觉得就是
Repository
设计,出现了深重和辩论偏移,以致于没有把设计重点发在业务逻辑上,在此和大家说声抱歉。

  关于“应用层中的业务逻辑”,比如上边那段代码:

 1         /// <summary>
 2         /// 查看消息
 3         /// </summary>
 4         /// <param name="ID"></param>
 5         /// <returns></returns>
 6         public MessageDTO ShowMessage(string ID, string isRead)
 7         {
 8             Message message = messageRepository.GetByKey(ID);
 9             if (isRead == "1")
10             {
11                 message.IsRead = true;
12                 messageRepository.Update(message);
13                 messageRepository.Context.Commit();
14             }
15             return Mapper.Map<Message, MessageDTO>(message);
16         }

  对,你早就看出来了,查看新闻,要基于阅读人,然后判断是或不是已读,若是是阅读人是收件人,并且新闻是未读状态,要把此新闻置为已读状态,业务逻辑没什么难题,可是却放错了岗位(应用层),应该放在领域层中(领域模型),其实那都是Repository
惹的祸,因为应用层根本未曾和天地层通讯,关于世界模型的宏图上边节点有教学。

  看了以上的故事情节,是否不怎么:拨开大雾,见晴天的感到?不精通你有没有?反正我是有,关于
Repository
大家再驾驭的深一点,先看一下后半句的概念:行使类似于聚集的接口来拜访领域对象。正如
dudu 领会的那样:Repository
是仓库管理员,领域层需求如刘毛毛西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不要求知道东西实际放在哪。可以如此精晓为 Repository
如同贰个查询集合,只提供查询给世界层,不过大家发未来骨子里运用中 Repository
也提供了持久化操作,那或多或少着实让 Repository
有点无缘无故了,关于那一点本人以为 CQ本田UR-VS(Command Query Responsibility
Segregation)形式能够很好的缓解,翻译为命令查询的职务分开,顾名思义,就是命令(持久化)和查询任务进行分离,因为笔者并未对
CQ酷路泽S
进行过研讨,也一贯不观看过具体的演示,所以这边就不多说,可是小编认为那是和世界驱动设计的无所不包组合,前面有机遇可以商量下。

  说了那么多,那Repository(仓储)义务到底是怎么?可以如此回复:Repository,请服务好
Domain,而且只限服务于他(防止小三),他要什么你要给哪些,为啥?因为他是您小叔,跟着她有肉吃。

亚洲必赢app在哪下载 7

Domain Model(领域模型)重新设计

  领域模型是小圈子驱动设计的为主,这点是毋容置疑的,那世界模型中的宗旨是怎么样?大概说完成的是怎么?答案是业务逻辑,那事情逻辑又是怎样?或然说什么样的“业务逻辑”才能称为真正含义上的事情逻辑,关于那个难点,在上一篇中残留如下:

领域模型到底该怎么统筹?你会看出,MessageManager
项目中的 User 和 Message
领域模型是格外贫血的,没有包罗其余的作业逻辑,未来网上广大有关 DDD
示例项目多数也存在那种意况,当然项目作者并未事情,只是简短的“CRUD”操作,可是倘如果一对大型项目标复杂性工作逻辑,该怎么去已毕?大概说,领域模
型完毕什么样的作业逻辑?什么才是确实的作业逻辑?那几个难点很首要,后续探究。

  什么才是真正的事务逻辑?CRUD
?持久化?依旧诸如“GetUserByName、GetMessageByID”之类的查询,作者个人感觉那么些都不是确实含义上的政工逻辑(注意,是个人感觉),因为各类种类会有“CRUD”、持久化,并不只限于某一种工作场景,像“GetUserByName、GetMessageByID”之类的询问只是询问,精晓了上面Repository 的感觉,你会发觉这一个查询工作应当是 Repository
做的,他是为世界模型服务的。

  说了那么多,那什么样才是确实含义上的事情逻辑?本身个人感觉改变世界模型状态或作为的作业逻辑,才能称为真正意义上的事务逻辑(注意,是个人感觉),比如本人在
Repository
节点中说过的一个示范:读取新闻,要依据当前读书人和目前新闻的动静来安装当前音信的气象,倘若当前读书人为收件人和当下音信为未读状态,就要把当下音讯状态设置为已读,在此从前这一个工作逻辑的已毕是在应用层中:

 1         /// <summary>
 2         /// 查看消息
 3         /// </summary>
 4         /// <param name="ID"></param>
 5         /// <returns></returns>
 6         public MessageDTO ShowMessage(string ID, string isRead)
 7         {
 8             Message message = messageRepository.GetByKey(ID);
 9             if (isRead == "1")
10             {
11                 message.IsRead = true;
12                 messageRepository.Update(message);
13                 messageRepository.Context.Commit();
14             }
15             return Mapper.Map<Message, MessageDTO>(message);
16         }

  那种完毕格局就会把应用层变为所谓的
BLL(业务逻辑层)了,正确的不二法门贯彻应有在 Domain
Model(领域模型)中,如下:

 1         /// <summary>
 2         /// 阅读消息
 3         /// </summary>
 4         /// <param name="CurrentUser"></param>
 5         public void ReadMessage(User CurrentUser)
 6         {
 7             if (!this.IsRead && CurrentUser.ID.Equals(ToUserID))
 8             {
 9                 this.IsRead = true;
10             }
11         }

  因为 MessageManager
那些类型的政工场景万分简单,很多都以粗略的 CRUD
操作,可以抽离出真正的作业逻辑实在太少,除了上边阅读信息,还有就是在发送信息的时候,要基于发送用户名和承受用户名,来安装消息的殡葬用户和经受用户的
ID 值,这几个操作以前大家也是在应用层中完结的,如下:

 1         /// <summary>
 2         /// 发送消息
 3         /// </summary>
 4         /// <param name="messageDTO"></param>
 5         /// <returns></returns>
 6         public bool SendMessage(MessageDTO messageDTO)
 7         {
 8             Message message = Mapper.Map<MessageDTO, Message>(messageDTO);
 9             message.FromUserID = userRepository.GetUserByName(messageDTO.FromUserName).ID;
10             message.ToUserID = userRepository.GetUserByName(messageDTO.ToUserName).ID;
11             messageRepository.Add(message);
12             return messageRepository.Context.Commit();
13         }

  改善在 Domain
Model(领域模型)中的达成,如下:

 1         /// <summary>
 2         /// 加载用户
 3         /// </summary>
 4         /// <param name="sendUser"></param>
 5         /// <param name="receiveUser"></param>
 6         public void LoadUserName(User sendUser,User receiveUser)
 7         {
 8             this.FromUserID = sendUser.ID;
 9             this.ToUserID = receiveUser.ID;
10         }

  因为简单的 CRUD
操作不会暴发变化,而这么些事情逻辑会平时发生变化,比如往音讯中加载用户消息,或者未来加载的是
ID
值,以往只怕会添加其他的用户值,比如:用户地理地方等等,那样大家若是去修改领域模型就足以了,应用层一点都不须要修改,如若依然事先的贯彻格局,你会发觉大家是必需要修改应用层的,领域模型只是1个空壳。

Domain Service(领域服务)的加盟

  关于 Domain
Service(领域服务)的概念,可以参见:http://www.cnblogs.com/netfocus/archive/2011/10/10/2204949.html#content_15,netfocus
兄关于世界服务讲解的很透彻,以下摘自个人感觉漂亮的局地:

  • 世界中的一些定义不太符合建模为目的,即归类到实体对象或值对象,因为它们本质上就是有的操作,一些动作,而不是东西。那一个操作或动作往往会涉及到多少个世界对象,并且须求协调那一个领域对象共同已毕那些操作或动作。假若强行将这么些操作职务分配给其他1个对象,则被分配的对象就是负责部分不应当承担的天职,从而会促成对象的职责不显明很凌乱。不过根据类的面向对象语言规定任何性质或作为都不可以不放在对象里面。所以大家需求寻找一种新的方式来代表这种跨三个指标的操作,DDD认为劳动是三个很当然的范式用来对号入座那种跨多少个目的的操作,所以就有了世界服务那个格局。
  • 自家以为模型(实体)与劳务(场景)是对天地的一种划分,模型关注世界的个体行为,场景关怀世界的群体行为,模型关切世界的静态结构,场景关注世界的动态功能。那也适合了切实中出现的各个现象,有动有静,有独立有合营。
  • 领域服务还有3个很重大的功能就是可以幸免领域逻辑败露到应用层。

  此外还有2个用于表明应用层服务、领域服务、基础服务的天职分配的小示例:

  应用层服务

  1. 收获输入(如贰个XML请求);
  2. 发送消息给世界层服务,需要其促成转帐的政工逻辑;
  3. 天地层服务处理成功,则调用基础层服务发送Email布告;

  领域层服务

  1. 获取源帐号和对象帐号,分别通报源帐号和目标帐号举办扣除金额和增加金额的操作;
  2. 提供重临结果给应用层;

  基础层服务

  1. 依据应用层的请求,发送Email公告;

  通过上述示范,能够很清楚的明白应用层服务、领域服务、基础服务的职务,关于那么些概念的驾驭,小编相信 netfocus
兄是经过广大推行得出的,因为未执行看这么些概念和履行过之后再看这一个概念,完全是见仁见智的感觉。

  言归正传,为何要进入 Domain
瑟维斯(领域服务)?领域服务在大家事先设计 MessageManager
项目的时候并从未,其实本身脑海中平昔是有这一个定义,因为 Repository
的天职混乱,所以最后领域模型变得那样鸡肋,领域服务也就从未出席,那干什么以往要加盟圈子服务呢?因为
Repository
的任务分开,使得世界模型变成重中之重,因为应用层不和 Repository
通讯,应用层又无法一贯和天地模型通讯,所以才会有天地服务的投入,也无法不有世界服务的加盟。通过地点概念的精通,你只怕会对天地服务的功能有自然的精晓,首先领域服务没有动静,只有行为,他和
Repository
一样,也是为世界模型服务的,只可是他像三个外交官一样,要求和应用层打交道,用来协调领域模型和应用层,而 Repository
只是3个老妈子,只是服务于世界模型。

  概念领悟的几近了,大家来看一下实际的贯彻,以下是
MessageDomainService 领域服务中的一段代码:

1         public Message ShowMessage(string ID,User CurrentUser)
2         {
3             Message message = messageRepository.GetByKey(ID);
4             message.ReadMessage(userRepository.GetUser(new User { Name = CurrentUser.Name }));
5             messageRepository.Update(message);
6             messageRepository.Context.Commit();
7             return message;
8         }

  那段代码表示查看新闻,可以看到实际领域服务做的工作就是办事流程的决定,注意是干活流程处理,并不是业务流程,业务流程
ReadMessage
是天地模型去落成的,领域模型的意义只是和谐。还有个问号就是,你会看出在世界服务中采取到了
Repository,在我们事先的讲授中,Repository
不是只服务于世界模型呢?其实换个角度来看,领域服务也足以作为是小圈子模型的一种表现,Repository
未来器重提供的是查询集合和持久化,领域模型不得以自作者操作,那那些工作唯有领域服务去做到,关于那或多或少,就足以看到 Repository
的使用有点不太合理,不明白使用 CQ哈弗S
形式会不会是另一种意况。

  此外,你会看出这一段代码:messageRepository.Context.Commit();,那么些是
Unit Of
Work(工作单元)的工作提交,那一个工作是小圈子服务要做的啊?关于那一点是有一部分疑难,在底下节点中有解读。

MessageManager.Domain.Tests 的加入

  关于单元测试能够参见:http://www.cnblogs.com/xishuai/p/3728576.html,MessageManager.Domain.Tests
单元测试在头里的 MessageManager
项目中并没有拉长,不是不想添加,而是添加了不要紧意思,为何?因为事先的园地模型那么贫血,只是局部天性和字段,那添加单元测试有怎样意思?能测出来怎么着东西?当把工作聚焦在世界模型上的时候,对天地的单元测试将会丰盛的有必不可少。

  来看 DomainTest
单元测试的有个别代码:

 1 using MessageManager.Domain.DomainModel;
 2 using MessageManager.Domain.DomainService;
 3 using MessageManager.Repositories;
 4 using MessageManager.Repositories.EntityFramework;
 5 using NUnit.Framework;
 6 using System;
 7 using System.Collections.Generic;
 8 using System.Linq;
 9 using System.Text;
10 
11 namespace MessageManager.Domain.Tests
12 {
13     [TestFixture]
14     public class DomainTest
15     {
16         [Test]
17         public void UserDomainService()
18         {
19             IUserDomainService userDomainService = new UserDomainService(
20                 new UserRepository(new EntityFrameworkRepositoryContext()));
21             List<User> users = new List<User>();
22             users.Add(new User { Name = "小菜" });
23             users.Add(new User { Name = "大神" });
24             userDomainService.AddUser(users);
25             //userDomainService.ExistUser();
26             //var user = userDomainService.GetUserByName("小菜");
27             //if (user != null)
28             //{
29             //    Console.WriteLine(user.Name);
30             //}
31         }
32     }
33 }

  其实上边作者贴的单元测试的代码有个别不客观,你会看到只是测试的持久化操作,那一个本该是基础层已毕的工作,应该由基础层的单元测试举办测试的,那世界层的单元测试测试的是什么样事物?应该是小圈子模型中的业务逻辑,比如
ReadMessage 内的操作:

1         [Test]
2         public void MessageServiceTest()
3         {
4             IMessageDomainService messageDomainService = new MessageDomainService(
5                 new MessageRepository(new EntityFrameworkRepositoryContext()),
6                 new UserRepository(new EntityFrameworkRepositoryContext()));
7             Message message = messageDomainService.ShowMessage("ID", new User { Name = "小菜" });
8             Console.WriteLine(message.IsRead);
9         }

Application Layer(应用层)的协调?

Application
Layer(应用层):定义软件可以做到的干活,并且指挥具有丰硕意义的领域对象来化解难题。那几个层所负责的天职对业务影响深刻,对跟其他系统的应用层举办互相相当须要以此层要保持简练。它不包罗处理业务规则或文化,只是给下一层中相互同盟的天地对象协调职分、委托工作。在这几个层次中不显示工作景况的场地,但反映用户或程序的天职进度的动静。

  以上是《领域驱动设计-软件基本复杂性应对之道》书中有关应用层给出的概念,应用层是很薄的一层,纵然你的应用层很“厚”,那您的应用层设计就自然现身了难题。关于 Application
Layer(应用层)的采纳,正如 埃里克 Evans所说:不包含处理工作规则或知识,只是给下一层中相互合营的天地对象协调职务、委托工作。重点就是:不含有业务逻辑,协调职责。

  借使依据自己的知道去规划应用层,很只怕会像自身同一把它变成工作逻辑层,所以在设计进程中一定要谨记上边两点。不分包业务逻辑很好通晓,前提是要领悟什么才是的确的事务逻辑(上面有证实),后边一句协调义务又是怎么看头啊?在认证中前边还有一句:在那个层次中不反映工作情形的景况,但反映用户或程序的职责进程的地方。也等于干活流程的操纵,比如三个生育流程,应用层的功用就像这些生产工艺流程的控制器,具体生产什么它不须求管住,它一旦能够装配零件然后举行结合展示给用户,仅此而已,画了一张示意图,以便我们的领会:

亚洲必赢app在哪下载 8

  此外,应用层因为要对表现层和天地层开展任务协调,那当中会涉嫌到数量的对象转换,也等于DTO(数据传输对象),有关 DTO 的定义和 AutoMapper
的使用可以参见:http://www.cnblogs.com/xishuai/tag/DTO\_AutoMapper,那几个干活儿是在应用层中开展处理的,似乎生产工艺流程,组装完产品后,需求对其展开打包才能拓展浮现:

 1         /// 对应用层服务进行初始化。
 2         /// </summary>
 3         /// <remarks>包含的初始化任务有:
 4         /// 1. AutoMapper框架的初始化</remarks>
 5         public static void Initialize()
 6         {
 7             Mapper.CreateMap<UserDTO, User>();
 8             Mapper.CreateMap<MessageDTO, Message>();
 9             Mapper.CreateMap<User, UserDTO>();
10             Mapper.CreateMap<Message, MessageDTO>()
11                 .ForMember(dest => dest.Status, opt => opt.ResolveUsing<CustomResolver>());
12         }
13         public class CustomResolver : ValueResolver<Message, string>
14         {
15             protected override string ResolveCore(Message source)
16             {
17                 if (source.IsRead)
18                 {
19                     return "已读";
20                 }
21                 else
22                 {
23                     return "未读";
24                 }
25             }
26         }

Unit Of Work(工作单元)工作范围及贯彻?

  关于 Unit Of
Work(工作单元)的定义可以参照:http://www.cnblogs.com/xishuai/p/3750154.html

亚洲必赢app在哪下载,Unit Of
Work:维护受工作工作影响的对象列表,并协调变化的写入和出现问题的化解。即管理对象的
CRUD 操作,以及对应的事体与产出难题等。Unit of Work
是用来解决世界模型存储和更改工作,而这么些数据层业务并不属于世界模型自己具有的。

  工作单元的概念在《集团应用架构方式》中也有表明,定义如下:维护受工作工作影响的靶子列表,并协调变化的写入和出现难题的化解。概念的知情并不曾什么难题,作者想表明的是做事单元的办事范围及怎样落到实处?先说下工作范围,大家看下小编曾经画的一张工作单元的流程图:
亚洲必赢app在哪下载 9

点击查阅大图

  从示意图中得以看到,工作单元的范围是遏制
Repository 的,相当于说工作单元是无力回天跨 Repository
提交业务的,只辛亏同1个仓储内管总管务的一致性,如同大家接纳的
using(MessageManagerDbContext context = new MessageManagerDbContext())
一样,只是局限于这几个 using
块,作者曾在天地层的单元测试中做如下测试:

 1         [Test]
 2         public void DomainServiceTest()
 3         {
 4             IUserDomainService userDomainService = new UserDomainService(
 5                 new UserRepository(new EntityFrameworkRepositoryContext()));
 6             IMessageDomainService messageDomainService = new MessageDomainService(
 7                 new MessageRepository(new EntityFrameworkRepositoryContext()),
 8                 new UserRepository(new EntityFrameworkRepositoryContext()));
 9             List<User> users = new List<User>();
10             users.Add(new User { Name = "小菜" });
11             users.Add(new User { Name = "大神" });
12             userDomainService.AddUser(users);
13             messageDomainService.DeleteMessage(null);
14         }

  小编在 MessageDomainService中付出业务,因为事先 UserDomainService已经添加了用户,可是并不曾增加用户成功,工作单元中的 Committed 值为
false,其实关于工作单元范围的题材,我明日并不曾显明的想法,今后是囿于在仓储中,那提交的业务操作就亟须放在领域服务中,也等于:messageRepository.Context.Commit();,可是又会以为这么有个别不客观,工作单元应该是贯通整个项目标,并不一定局限在某一储存中,而且工作的处理液应该放在应用层中,因为那是她的做事,协调工作流的处理。

  假如这种思考是不利的话,完结起来确实有个别难度,因为明日ORAV4M(对象关联映射)使用的是
EntityFramework,所以做事单元的贯彻是很粗略的,也等于采纳 SaveChanges()
方法来交付业务,小编在《公司应用架构方式》中观看工作单元的落到实处,书中列出了2个简练的例证,还只是聚众的管制,假如不行使部分
OLX570M 工具,已毕起来就不但是 SaveChanges()
一段代码的事了,太局限于技术了,确实是个难点。

  这一节点的始末只是指出一些疑难,并未有消除的措施,希望后边可以追究下。

本子发表

  MessageManager
项目消除方案目录:

亚洲必赢app在哪下载 10

  注:ASP.NET WebAPI
暂只蕴涵:获取发送放音信列表和取得接收方信息列表。

  调用示例:

  WebAPI 客户端调用可以参见
MessageManager.WebAPI.Tests 单元测试项目中的示例调用代码。

  注:因为 GitHub 中对 MessageManager
项目进展了立异,假若想看上一版本,下载地址:http://pan.baidu.com/s/1gd9WmUB,可以和水土保持版本对照下,方便学习。

  此外,《领域驱动设计.软件基本复杂性应对之道》Word
版本,下载地址:http://pan.baidu.com/s/1bnndOcR

后记

亚洲必赢app在哪下载 11

  那篇博文不知不觉写二日了(周末),左手也有点不那么灵活了,如若再写下去,大家也该骂作者了(看得太费事),那就做一下总计吧:

  关于世界模型的安顿性,我个人感觉是天地驱动设计中最难的一部分,你会合到目前自个儿在 MessageManager
项目中只有三个主意,一部分缘由是事情场景太简单,另一局部原因恐怕是本人设计的不创制,复杂性业务场景的天地模型是多个类之间协调处理,并会有一对设计方式的投入,是一定复杂的。

  需求小心的一些是,本篇以上内容并不是描述
Domain
Model(领域模型)到底如何贯彻?而是什么聚焦领域模型?唯有聚焦在世界模型上,才能把世界模型设计的更客观,那也多亏下一步须要追究的始末。

  要么那句话,真正领会和运用
DDD(领域驱动设计)的绝无仅有方法,个人感觉照旧“迭代”:不断的去实践,不断的去体会。不客观那就推倒重建,再不客观这就推倒再重建。。。

  假如你以为本篇小说对您有所协理,请点击右下部“推荐”,^_^

  参考资料:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 亚洲必赢app官方下载 版权所有