业务对象是否应该能够创建自己的DTO? [英] Should business objects be able to create their own DTOs?

查看:122
本文介绍了业务对象是否应该能够创建自己的DTO?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下课程:

class Camera
{
    public Camera(
        double exposure,
        double brightness,
        double contrast,
        RegionOfInterest regionOfInterest)
    {
        this.exposure = exposure;
        this.brightness = brightness;
        this.contrast = contrast;
        this.regionOfInterest = regionOfInterest;
    }

    public void ConfigureAcquisitionFifo(IAcquisitionFifo acquisitionFifo)
    {
        // do stuff to the acquisition FIFO
    }

    readonly double exposure;
    readonly double brightness;
    readonly double contrast;
    readonly RegionOfInterest regionOfInterest;
}

...和一个DTO,用于跨服务边界(WCF)传输摄像机信息,例如,以便在WinForms/WPF/Web应用程序中查看:

... and a DTO to transport the camera info across a service boundary (WCF), say, for viewing in a WinForms/WPF/Web app:

using System.Runtime.Serialization;

[DataContract]
public class CameraData
{
    [DataMember]
    public double Exposure { get; set; }

    [DataMember]
    public double Brightness { get; set; }

    [DataMember]
    public double Contrast { get; set; }

    [DataMember]
    public RegionOfInterestData RegionOfInterest { get; set; }
}

现在,我可以向Camera添加方法以公开其数据:

Now I can add a method to Camera to expose its data:

class Camera
{
    // blah blah

    public CameraData ToData()
    {
        var regionOfInterestData = regionOfInterest.ToData();

        return new CameraData()
        {
            Exposure = exposure,
            Brightness = brightness,
            Contrast = contrast,
            RegionOfInterest = regionOfInterestData
        };
    }
}

,我可以创建一个方法,该方法需要传入特殊的IReporter以便Camera可以将其数据公开给它.这消除了对合约"层的依赖(相机不再需要了解CameraData):

or, I can create a method that requires a special IReporter to be passed in for the Camera to expose its data to. This removes the dependency on the Contracts layer (Camera no longer has to know about CameraData):

class Camera
{
    // beep beep I'm a jeep

    public void ExposeToReporter(IReporter reporter)
    {
        reporter.GetCameraInfo(exposure, brightness, contrast, regionOfInterest);
    }
}

那我该怎么办?我更喜欢第二个,但是它要求IReporter有一个CameraData字段(由GetCameraInfo()更改),感觉很奇怪.另外,如果有更好的解决方案,请与我分享!我仍然是一个面向对象的新手.

So which should I do? I prefer the second, but it requires the IReporter to have a CameraData field (which gets changed by GetCameraInfo()), which feels weird. Also, if there is any even better solution, please share with me! I'm still an object-oriented newb.

推荐答案

我通常会说 no ,他们不应该这样做,因为DTO特定于服务或应用程序,而域模型是您的最内层"图层,并且应该没有依赖项. DTO是域模型之外的其他的实现细节,因此,它破坏了域模型了解它们的抽象.

I would generally say no, they shouldn't, because DTOs are specific to a service or application, whereas the domain model is your "innermost" layer and should have no dependencies. DTOs are an implementation detail of something other than the domain model, and therefore, it's breaking the abstraction for your domain model to know about them.

您是否考虑过为此目的查看 AutoMapper ?这样您最终将编写更少的代码.在这种情况下,我认为您可以简单地摆脱:

Have you considered looking at AutoMapper for this? You'll end up writing a lot less code that way. In this case, I think you'd be able to get away with simply:

Mapper.CreateMap<RegionOfInterest, RegionOfInterestData>();
Mapper.CreateMap<Camera, CameraData>();

随后:

CameraData cd = Mapper.Map<Camera, CameraData>(camera);

这不仅减少了代码流失,而且在其自己的映射层"中划分了映射代码-您拥有一个或多个模块来注册这些映射,可以将它们放置在真正使用DTO的任何程序集中.

This not only reduces the code churn but compartmentalizes the mapping code in its own "mapping layer" - you have one or several modules that register these mappings that you can put in whichever assembly really uses the DTOs.

当然,您始终可以创建扩展方法来简化实际映射:

And of course you can always create extension methods to simplify the actual mapping:

public static class CameraExtensions
{
    public static CameraData ToCameraData(this Camera camera)
    {
        return Mapper.Map<Camera, CameraData>(camera);
    }
}

这使整个过程像编写camera.ToCameraData()一样简单,但是没有在域对象(Camera)和DTO(CameraData)之间创建了硬依赖性.基本上,您具有原始版本的所有易用性,但没有耦合.

Which makes the whole thing as simple as writing camera.ToCameraData(), but without creating a hard dependency between the domain object (Camera) and the DTO (CameraData). You have basically all of the ease-of-use of your original version, but without the coupling.

如果要创建这些依赖关系是因为您试图根据未公开公开的私有Camera数据创建CameraData对象,那么我的直接反应就是,这种设计不太正确.为什么不公开Camera对象上的只读属性?如果您仍然通过ToData方法使外界能够访问它们,那么您显然并没有隐藏此信息,只是使获取这些信息变得更加麻烦.

If you're creating these dependencies because you're trying to create the CameraData object from private Camera data which isn't exposed publicly then my immediate reaction would be, something's not quite right about this design. Why not expose read-only properties on the Camera object? If you're giving the outside world access to them anyway, through the ToData method, then you're clearly not hiding this information, you're just making it more cumbersome to get to.

如果您在未来三个月内决定需要另一种DTO,该怎么办?您不必在每次想要支持新用例时都修改以域为中心的Camera对象.我认为最好将一些只读的公共属性放在类中,以便映射器可以访问所需的属性.

What if you decide 3 months down the road that you need a different kind of DTO? You shouldn't have to modify your domain-centric Camera object every time you want to support a new use case. Better, in my opinion, to put a few read-only public properties in the class so that mappers can get access to the attributes they need.

这篇关于业务对象是否应该能够创建自己的DTO?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆