我是 DDD 和 OO 原则的新手,很抱歉我知识贫乏。
我有CustomerDTO和Customer课程。
我将所有字段和属性存储在DTO类中,并将其用作Customer类的基类。
使用DTO的主要目的是将其传递给View。我在Customer类中对其进行了扩展,使其不具有重复的属性。
这是正确的方法还是有更好的OO解决方案?
我已经阅读了有关 AutoMapper 的信息,但我想知道是否有替代解决方案。
非常感谢任何形式的帮助。
我是 DDD 和 OO 原则的新手,很抱歉我知识贫乏。
我有CustomerDTO和Customer课程。
我将所有字段和属性存储在DTO类中,并将其用作Customer类的基类。
使用DTO的主要目的是将其传递给View。我在Customer类中对其进行了扩展,使其不具有重复的属性。
这是正确的方法还是有更好的OO解决方案?
我已经阅读了有关 AutoMapper 的信息,但我想知道是否有替代解决方案。
非常感谢任何形式的帮助。
我个人从未见过这种方法。使用 DTO 的原因是为了在 DAL 和 biz 层之间分离关注点。它让业务层和 DAL 可以按照自己的节奏进行更改,并且副作用最小。您所要做的就是更改 DTO 和 DO 之间的映射。如果你从你的 DTO 继承你的 DO,那么即使有一个 DTO 又有什么意义呢?
快速回答:不要从 DTO 继承你的 DO。现在可能很容易,但将来可能是维护的噩梦。
PS不要害怕Automapper。它相对容易使用。
这是一个坏主意。这里有两个原因(可能还有更多):
扩展答案:
让我们试着分析一下这种情况,不要盲目地说没有人做这样的事情。
DTO - 它是仅包含数据并在边界之间传输数据的结构。
领域模型——这里的关键词是“模型”,是解决问题的领域的抽象。从 OO 的角度来看,它是一个简单的类,如果将其拆分,它将是纯数据 (DTO) 和纯无状态行为(DDD 术语中的服务或域服务)。
现在让我们以 MVVM 模式为例,特别是它的 VM 部分。视图模型 - 这里的关键词再次是“模型”,它是解决其问题的视图抽象。人们实现它的方式有很多,一些包装域对象,一些进行转换,一些包装 DTO。这里的重点是视图模型是视图的域模型,它与任何模型几乎相同。那为什么人们要限制实现领域模型的方式。
现在回到 DTO 和域模型。正如我上面所说,我们可以将域对象分解为 DTO 和服务。让我们考虑一下,我们将域对象视为 DTO 的行为包装器(就像 MVVM 经常做的那样)。它把我们带到哪里:
让我们继续,打破封装是一个严重的问题。我们需要的是一种方法来保证我们的域对象数据不会被直接操作,只有域对象应该操作它。当 DTO 在域对象之外时,我们可以通过使 DTO 不可变、只读对象来实现这一点。
现在关于重用 DTO,继承与组合。有人说:更喜欢组合而不是继承,我个人确实遵循这个规则。但是你需要分析你的具体情况。规则说“喜欢”不服从。
原始答案:
虽然我个人并没有经常看到这种方法,但我认为这种方法被低估了,它可能非常好。
我多次看到这样的问题被问到,所有的答案都是,不要这样做,因为没有人这样做。不要害怕尝试。
Ryan Bennet 在他的回答中写道:
现在可能很容易,但将来可能是维护的噩梦。
的确如此,但是如果没有未来或者这是一个小项目怎么办,我会在这里坚持 YAGNI、TDD 和敏捷规则,并做最少的工作来完成这项工作。
代码不是你刻在石头上的东西,永远不会碰,当你需要时,你可以重构,引入 DTO,使用自动映射器或其他任何东西。
老问题,我喜欢这里的其他几个答案,特别是关于将 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”?后者国际海事组织。