我应该图也可与检向/从域实体在客户和服务器方?
-
18-09-2019 - |
题
我已经有了一个丰富域模型,其中大多数类有一些行为和某些属性,是计算或获得的属性成员对象(也就是说,这些属性的值是从来没有保留).
我的客户使用的语言服务器只能通过WCF。
因此,为每个领域实体,我有一个相应也可与检--一个简单的表示,只包含数据--以及一映射器类实现了 DtoMapper<DTO,Entity>
并且可以转换成一个实体,它也可与检等同或反之亦然通过一个静态网关:
var employee = Map<Employee>.from_dto<EmployeeDto>();
服务器侧的这个应用程序主要是关于持久性,在那里我的交互来自WCF服务,deserialized,然后一个任意的对象仍然存在,他们的数据库,或查询请求来自WCF和格林执行,查询该数据库,并返回目的是化和送回WCF。
鉴于这种情况, 它不会让任何感觉到的地图我的持久性存储区域实体,或者我应该只是地图直接的交互?
如果我使用领域实体,流会
- 客户要求的对象
- WCF发送请求到服务器
- 奥姆查询数据库和返回域实体
- 域实体转化为通过交互映射器
- WCF序列化也可与检和返回的客户
- 客户反序列化也可与检
- 也可与检转变成域实体的映射器
- 这个例子创建的, 等等。
类似于返回旅行
如果我地图觉也可与检,我可以消除一映射的每个目的,每个请求。什么我失去了通过这样做?
唯一想到的是另一个机会来验证之前插入/更新,因为我没有保证,也可与检曾经受到验证,或甚至存在作为一个域实体之前,正在通过网络发送的,我猜测一个机会来验证的选择(如果另一个进程可能已经把值无效的数据库)。是否还有其他的原因吗?这些原因足以保证所附加的映射的步骤?
编辑:
我没有说"任意的对象"以上,并且我想要的东西是作为对象和持久性无关作为可能的,但是如果你有什么特别的东西添加特定它能够,通过各种手段做。
解决方案
我个人建议保持你的映射服务器上面。你可能已经做了很多工作在建立你的设计要点,这是至现在;不要扔掉。
考虑什么样的一个网络服务。这不仅仅是一个抽象过你的对象;这是一个 合同.这是一个公共API为你的客户,内部和外部的。
公共API应该有点如果任何理由要改变。几乎任何改变一个API,除了增加新的类型和方法,是一项重大更改。但你域模型不是那么严格。你会需要改变它,时不时添加的新功能或发现的缺陷的原始设计。你想要能够确保变化你的内部模式不会导致叠的变化,通过服务的合同。
它实际上是一个共同的惯例(我也不会侮辱读者的短语"最佳做法")创建特定的 Request
和 Response
课程对于每一信息对于类似的原因;它变得更简单的扩展能力的现有服务和方法没有他们正在裂变化。
客户可能不会 想 这完全相同的模型,该模型内部使用的服务。如果你是你的唯一客户,那么也许这似乎是透明的,但是如果你有外部客户和有看到是多么遥远的他们解释你的系统往往可以,那么你就会明白的价值不允许您的完美模式泄露出局限的服务。
有时,它甚至不是 可能的 送你的模型后通过的。有许多原因,这可能会发生:
周期的对象图。完全现在面向对象;灾难性的,在序列化。你最终有作出痛苦的永久性选择"方向"的图表必须化。另一方面,如果使用也可与检,可以serialize在任何你想要的方向,无论适合手头的任务。
尝试使用某些类型的继承机制在肥皂/休息可能是一个暂且在最好的。旧式XML程序至少支持
xs:choice
;DataContract
不,我不要狡辩了理由,但我只想说你可能有一些多态性在你丰富的领域模型和它几乎不可能通道,通过网络服务。懒/推迟装载,这你可能使用的如果你使用一个奥姆.它是尴尬的足够确保它得到正常化--例如,使用皇宫SQL实体,WCF甚至没有触发懒惰的加载程序,它只会把
null
进入这一领域除非你载手,但问题变得甚至更糟糕的数据来回。简单的东西List<T>
自动属性,初始化的构造共同够在一个领域模型只是不工作WCF,因为它没有援引你的构造。而不是你必须添加一个[OnDeserializing]
初始化程序的方法,和你 真的 不要弄乱你域模型的与这个垃圾。我也只是注意到括号句话,你用它能够.考虑接喜欢
IList<T>
不能化,在所有超过一个网服务。如果你使用POCO类它能够,因为大多数我们这样做,那么这个根本不会的工作,期限。
还有可能许多情况时,内部域模式根本不相匹配客户的需要,这是没有意义的改变的领域模型以容纳这些需要。作为这方面的一个例子,让我们采取一些简单发票。它需要表明:
- 信息有关的帐户(账户编号、名称、等等)。
- 发票具体数据(发票编号、日期、到期日期,等等)。
- A/R级的信息(以前的平衡、逾期费用,新的平衡)
- 产品或服务的信息,用于一切的发票;
- 等等。
这个可能适合现在一个领域模型。但是,如果客户需要运行一份报告,显示了1200这些发票?某些种族和解的报告?
这个吮吸序列化。现在你发送1200发票的 同 数据序列化一遍又一遍同样的账户,同样的产品,同A/R。在内部,应用程序是跟踪所有的链接;它知道发票#35和发票#45都为同一客户,因此共享一个 Customer
参考;所有这些信息是失去了在化,并最终发送一个荒谬量的冗余数据。
你真正想要的是发送的定制报告,其中包括:
- 所有帐户包括在报告和他们的A/R;
- 所有的产品包括在报告;
- 所有的发票,与产品和账户Id只。
你需要执行额外的"正常化",在你的传出的数据之前,你向它发送给客户,如果你想要避免大量的冗余。这严重赞成也可与检的办法;它不会有意义的这种结构在您的领域模型,因为你领域模型 已经 需要照顾的冗余,以自己的方式。
我希望这些是足够的例子和足够的理由说服你让你的映射域 <-->服务合同的完整。你已经做了绝对正确的事情这么远,你有一个很好的设计,并且它将是一个耻辱,否定所有努力的赞成的东西,可能会导致主要头痛。
其他提示
你需要地图的交互在对客户的侧面,无论如何,所以,为对称性,这是更好地作出反映在服务器的一侧。这样你隔离转化成良好的分离抽象层。
抽象层是好的,不仅对于验证,而是要隔离你的代码变化,低于/高于它,让你的代码的更多的测试和与少重复。
此外,除非你发现一个伟大业绩的瓶颈,在额外的转换,记住:早期优化的根源的所有邪恶。:)
你绝对应该让你域实体独立自己也可与检是它们是不同的问题。也可与检的通常是heriachal、自描述的模式,因为你域实体另一方面封你的业务逻辑和具有很大的行为附带他们。
具有说,我不知道那里的额外的映射是什么?你检索数据的使用你的奥姆(aka域实体)和你的地图的那些对象你也可与检是如此,只有1映在吗?顺便说一句,如果您已经不用的东西喜欢 Automapper 要做到繁琐的映射。
这些同样也可与检的后deserialized到客户并从那里,你可以直接到你的UIViewModels.因此,最大的画面看起来是这样的:
- 客户要求实体通过Id从WCF服务
- WCF服务的实体从储存库/奥姆
- 使用AutoMapper到地图实体也可与检
- 客户也可与检接收
- 使用AutoMapper到地图的用户界面模型
- UIViewModel是绑定的GUI
当你说你的服务器侧程序为"主要"有关的持久性,我认为,这是关键的事情要考虑。是真的有一个服务器-侧域模型,需要一些情报周围的数据收到的还是你的WCF的服务纯粹的行为之间的网关领域模型和数据商店吗?
此外,考虑是否也可与检被设计为客户域。
这是唯一的客户领域需要访问该数据存储通过您服务吗?
是的服务器侧的交互柔性的或粗粒足够服务于不同的应用领域?
如果不是,则它可能是值得的努力来保持外部接口实现的抽象.
(DB->奥姆->EmployeeEntity->Client1DTOAssembler->Client1EmployeeDTO).
我们有一个类似应用程序,其中WCF服务的行为主要是作为通往持久性存储的数据。
在我们的情况下,我们的客户和服务器不再使用的组件包含"的交互." 这使我们有机会简单地添加码的分类产生的业务参考,所以我们常常都能够使用一个也可与检是在客户的侧面,并把它作为一个域对象。其他时候,我们可有客户端只域的对象是作为门面向一群持续的对象,我们得到了从周转基金的服务。
当你认为有关的行为和计算性能,你域的对象有多少重叠是存在的,真的很之间你的客户和服务器?在我们的情况下,我们确定的责任分工之间的客户和服务,意味着只有很小的,如果有的话,代码需要本(和完全相同)的两客户和服务器。
来回答你的问题直接的,如果你的目标是要完全保持持久性无关,我要肯定地图的持久性存储区域的对象和随后的地图的交互.有太多的持续的实现,可以渗入你的目的和复杂的使用他们作为WCF的交互.
在客户端,它可能没有必要做一个额外的映射如果你可以只是装饰或增强交互和,这是一个非常简单的解决方案。
你的架构似乎相当好想出来的。我的肠道感觉是,如果你已经决定减少对象,也可与检的送他们通过WCF,你目前没有一个需要额外的对象功能服务器上的边,为什么不让事情简单和地图的持久性存储直接的交互.
你怎么损失呢?我不认为你真的失去任何东西。你的架构是干净的,很简单。如果你决定在未来,有一个新的需要更丰富的功能服务器上的侧,你总是可以重新因素在这一点上重新创建域实体的存在。
我想保持它的简洁和重新因素,因为需要以后,尽量避免预先为成熟的优化的事情,等等。