4

我是 DDD 和 OO 原则的新手,很抱歉我知识贫乏。

我有CustomerDTOCustomer课程。

我将所有字段和属性存储在DTO类中,并将其用作Customer类的类。

使用DTO的主要目的是将其传递给View。我在Customer类中对其进行了扩展,使其不具有重复的属性。

这是正确的方法还是有更好的OO解决方案?

我已经阅读了有关 AutoMapper 的信息,但我想知道是否有替代解决方案。

非常感谢任何形式的帮助。

4

4 回答 4

6

我个人从未见过这种方法。使用 DTO 的原因是为了在 DAL 和 biz 层之间分离关注点。它让业务层和 DAL 可以按照自己的节奏进行更改,并且副作用最小。您所要做的就是更改 DTO 和 DO 之间的映射。如果你从你的 DTO 继承你的 DO,那么即使有一个 DTO 又有什么意义呢?

快速回答:不要从 DTO 继承你的 DO。现在可能很容易,但将来可能是维护的噩梦。

PS不要害怕Automapper。它相对容易使用。

于 2012-06-26T13:51:48.330 回答
2

这是一个坏主意。这里有两个原因(可能还有更多):

  • 域对象是专门为事务构建的。他们不应该提供对所有财产的公共访问。它们应该只包含提供行为目的的属性。DTO 有一个目的:向消费者提供数据(例如 UI/Web 服务/消息系统)。例如,客户 DTO 可能包含一个属性,该属性提供客户已下订单的数量以及他们已花费的总金额。然而,在域方面,客户聚合可能不包含任何此类信息,因为此订单信息存储在专门为订单交易量身定制的单独订单聚合中。
  • DTO 是愚蠢的 POCO,只有一堆 getter 和 setter。允许您的域对象在其所有属性上都有设置器是非常糟糕的做法。操作应该是原子的,并由具有描述其意图的明确名称的方法提供。这个问题的答案解释了这一点。
于 2012-06-27T08:54:40.203 回答
0

扩展答案:

让我们试着分析一下这种情况,不要盲目地说没有人做这样的事情。

DTO - 它是仅包含数据并在边界之间传输数据的结构。

领域模型——这里的关键词是“模型”,是解决问题的领域的抽象。从 OO 的角度来看,它是一个简单的类,如果将其拆分,它将是纯数据 (DTO) 和纯无状态行为(DDD 术语中的服务或域服务)。

现在让我们以 MVVM 模式为例,特别是它的 VM 部分。视图模型 - 这里的关键词再次是“模型”,它是解决其问题的视图抽象。人们实现它的方式有很多,一些包装域对象,一些进行转换,一些包装 DTO。这里的重点是视图模型是视图的域模型,它与任何模型几乎相同。那为什么人们要限制实现领域模型的方式。

现在回到 DTO 和域模型。正如我上面所说,我们可以将域对象分解为 DTO 和服务。让我们考虑一下,我们将域对象视为 DTO 的行为包装器(就像 MVVM 经常做的那样)。它把我们带到哪里:

  • 首先,我们打破 OO 封装。这很糟糕,因为它可以防止我们的对象数据被错误地使用。有人可以直接使用我们的域对象数据 (DTO) 操作它并将我们的模型置于无效状态。这是巨大的。
  • 我们可以轻松地转移我们的对象抛出边界、Web 服务、序列化、克隆,我们可以分离出数据部分,并将其提供给我们的数据存储或 Web 服务。这对于分布式系统来说是巨大的。

让我们继续,打破封装是一个严重的问题。我们需要的是一种方法来保证我们的域对象数据不会被直接操作,只有域对象应该操作它。当 DTO 在域对象之外时,我们可以通过使 DTO 不可变、只读对象来实现这一点。

现在关于重用 DTO,继承与组合。有人说:更喜欢组合而不是继承,我个人确实遵循这个规则。但是你需要分析你的具体情况。规则说“喜欢”不服从。

原始答案:

虽然我个人并没有经常看到这种方法,但我认为这种方法被低估了,它可能非常好。

我多次看到这样的问题被问到,所有的答案都是,不要这样做,因为没有人这样做。不要害怕尝试。

Ryan Bennet 在他的回答中写道:

现在可能很容易,但将来可能是维护的噩梦。

的确如此,但是如果没有未来或者这是一个小项目怎么办,我会在这里坚持 YAGNI、TDD 和敏捷规则,并做最少的工作来完成这项工作。

代码不是你刻在石头上的东西,永远不会碰,当你需要时,你可以重构,引入 DTO,使用自动映射器或其他任何东西。

于 2012-06-27T05:53:30.023 回答
0

老问题,我喜欢这里的其他几个答案,特别是关于将 DAL 与业务层分离的问题。但是,我想提一个在 DO 类从 DTO 类继承时可能会遇到的具体问题。

在 C# 和 VB 等 .NET 语言中,不能有真正的多重继承。那就是一个类不能扩展两个基类。因此,如果您的 DO 类已经扩展了一个 DTO 基类,那么您就排除了 DO 类和另一个 DO 类之间继承的可能性。

忽略实际保存数据的表的外观,或者您是否使用TPH、TPT 或 TPC,假设您有 DO 类

Vehicle
Car : Vehicle
Boat : Vehicle

你不能拥有Car : CarDto, Vehicle. 如果您的项目足够复杂,可以在 DO 类之间进行任何继承,那么这本身就是一个非常引人注目的论点。

最后,我想补充一点,在继承与组合之间进行选择时,您会根据“is a”与“has a”来思考。那么更有意义的是:“Car is a CarDto”还是“Car is a Vehicle”?后者国际海事组织。

于 2017-05-16T18:34:44.217 回答