问题描述
我已经看到了很多与映射有关的问题没有觉得他们回答了我的问题.我以前使用过许多方法,并且有自己的意见,但我正在寻找一些更具体的东西.
情况:
我们有许多域对象.我们正在使用CSLA模型,因此我们的域对象可能非常复杂,并且它们包含自己的数据访问.您不想在电线上传递这些.我们将编写一些新服务,这些新服务将以多种格式返回数据(.NET,JSON等).由于这个(和其他原因),我们还创建了一个精益的数据传输对象,以传递电线.
我的问题是:如何连接DTO和域对象?
我的第一个反应是使用 fowler,dto pattern-type type解决方案.我已经看到了很多次,对我来说感觉很正确.域对象不包含对DTO的引用.调用外部实体("映射"或"汇编器")从域对象创建DTO.通常,在域对象端,有一个 orm .这样做的缺点是,在任何真实情况下,"映射"倾向于变得非常复杂,并且可能非常脆弱.
提出的另一个想法是域对象"包含" DTO,因为它只是一个精益数据对象.域对象属性将在内部引用DTO属性,如果需要,可以返回DTO.我看不到这一点,但感觉不错.我看过一些文章,人们使用 nhibernate 似乎使用了此方法.
还有其他方法吗?上述方式之一是值得使用的吗?如果是这样,为什么?
推荐答案
在您仅支持单个映射的情况下,在域和DTO之间坐在域和DTO之间的映射器的好处并不那么出面域更简单,更精简.您不会用很多额外的重量来混乱您的域名.
就个人而言,我尝试将映射放在我的域实体之外,并将责任放在我所谓的"经理/服务层"中.这是一个位于应用程序和呼吸器(IES)之间的层,并提供了诸如工作流程协调之类的业务逻辑(如果修改A,则可能还必须修改B,因此服务A将与服务B一起使用).
如果我有很多可能的结局格式,我可能会考虑创建一个可以使用访问者模式的可插的格式化器,例如来改变我的实体,但是我还没有发现对这种复杂的任何东西的需求.<<<<<<<./p>
其他推荐答案
您可以使用autoMapper,例如吉米·鲍加德(Jimmy Bogard)编写的对象之间没有连接,并且依赖于遵守的命名约定.
其他推荐答案
将映射逻辑保持在实体内部的内部意味着您的域对象现在已经意识到它不需要知道的"实现细节".通常,DTO是您通往外界的门户(来自传入请求或通过外部服务/数据库的读取).由于该实体是您业务逻辑的一部分,因此最好将这些细节保留在实体之外.
在其他地方保留映射将是唯一的选择 - 但是应该去哪里?我已经尝试介绍映射对象/服务,但是毕竟已经说过并完成了工程(可能是).我使用Automapper和此类项目取得了一些成功,但是像Automapper这样的工具都带有自己的陷阱.我遇到了一些与映射有关的很难找到的问题,因为汽车应用程序的映射是隐式的,并且完全与您的其他代码完全解耦(不像"关注点的分离",但更像是"教给了戈德福特的映射现场"的地方)因此,有时他们很难追踪.并不是说汽车应用程序没有其用途,因为它确实如此.我只是认为映射应该是避免问题的尽可能明显和透明的东西.
我没有创建映射服务层,而是将我的映射保留在DTOS内部.由于DTO始终坐在应用程序的边界上,因此可以使他们意识到业务对象,并弄清楚如何/向它们映射.即使映射的数量缩放到大量范围时,它也可以干净地工作.所有映射都位于一个地方,您不必在数据层,反腐败层或演示层中管理大量映射服务.取而代之的是,映射只是请求/响应所涉及的DTO的实现详细信息.由于序列化器通常仅在通过电线发送时序列化属性和字段,因此您不应遇到任何问题.就我个人而言,我发现这是最干净的选择,我可以说,根据我的经验,它在大型代码库上很好地缩放.
如果映射的数量缩放到不合理的数量(这在我十多年内尚未发生在我身上),那么您始终可以创建一个靠近DTOS的映射类.
问题描述
I've seen a lot of questions related to mapping DTOs to Domain Objects, but I didn't feel they answered my question. I've used many methods before and have my own opinions but I'm looking for something a little more concrete.
The Situation:
We have many domain objects. We are using a CSLA model so our domain objects can be pretty complex and they contain their own data access. You do not want to pass these around on the wire. We are going to be writing some new services that will return data in a number of formats (.Net, JSON, etc.). For this (and other reasons) we are also creating a lean, data transfer object to pass around on the wire.
My question is: How should the DTO and Domain object be connected?
My first reaction is to use a Fowler, DTO pattern-type solution. I've seen this done many times and it feels right to me. The domain object contains no reference to the DTO. An outside entity (a "mapper" or "assembler") is called to create a DTO from a Domain Object. Normally there is an ORM on the domain object side. The downside of this is that the "mapper" tends to get extremely complex for any real situation and can be very fragile.
Another idea put forth is for the Domain Object to "contain" the DTO, since it's just a lean data object. The Domain Object properties would internally reference the DTO properties and could just return the DTO if asked for. I can see no problems with this but it feels wrong. I have seen some articles where people using NHibernate appeared to use this method.
Are there other ways? Is one of the ways above worth using? If so or if not, why?
推荐答案
A benefit of having a mapper that sits between your domain and your DTO is not as appearent when you are only supporting a single mapping, but as the number of mappings increases, having that code isolated from the domain helps keep the domain simpler and leaner. You won't be cluttering your domain with a lot of extra weight.
Personally, I try and keep the mapping out of my domain entities and put the responsibility in what I call "Manager / Service layer". This is a layer that sits between the application and the respository(ies), and provides business logic such as workflow coordination (If you modify A, you might have to also modify B so service A will work with Service B).
If I had a lot of possible ending formats, I might look at creating a plugable formatter that could use the Visitor pattern, for example to transform my entities, but I've not found a need yet for anything this complex.
其他推荐答案
You could use an automapper such as the one written by Jimmy Bogard which has no connection between the objects and relies on naming conventions being adhered to.
其他推荐答案
Keeping the mapping logic inside of your entity means that your Domain Object is now aware of an "implementation detail" that it doesn't need to know about. Generally, a DTO is your gateway to the outside world (either from an incoming request or via a read from an external service/database). Since the entity is part of your Business Logic, it's probably best to keep those details outside of the entity.
Keeping the mapping somewhere else would be the only alternative - but where should it go? I've tried introducing mapping objects/services but it seemed like overengineering (and probably was) after all was said and done. I've had some success using Automapper and such for smaller projects but tools like Automapper come with their own pitfalls. I've had some pretty hard-to-find issues related to mappings because Automapper's mappings are implicit and completely decoupled from the rest of your code (not like "separation of concerns" but more like a "where does the godforsaken mapping live") so they can sometimes be hard to track down. Not to say that Automapper doesn't have its uses, because it does. I just think mapping should be something that is as obvious and transparent as possible to avoid issues.
Instead of creating a mapping service layer, I've had a lot of success keeping my mappings inside of my DTOs. Since DTOs always sit at the boundary of the application, they can be made aware of the Business Object and figure out how to map from/to them. Even when the number of mappings scales to a large amount it works cleanly. All the mappings are in one place and you don't have to manage a bunch of mapping services inside your Data Layer, Anticorruption Layer, or Presentation Layer. Instead, the mapping is just an implementation detail delegated to the DTO involved with the request/response. Since serializers generally only serialize properties and fields when sending it across the wire, you shouldn't run into any issues. Personally, I've found this the cleanest option and I can say, in my experience, it scales nicely on a large code base.
If the amount of mappings scales to an unreasonable amount (which has yet to happen to me in over 10 years) then you can always create a mapping class that lives close to your DTOs.