想象一下,您在服务器应用程序上拥有业务领域模型,并且您将开发富客户端应用程序。
您可以使用DTO将数据传输到客户端并更改为服务器或使用WCF服务并在客户端上生成新类。
另一种方法是在业务逻辑层中传输与服务器上使用的相同对象。这些也可以是ORM使用的类。在这种情况下,类不应包含特定于服务器的逻辑,但它们可以包含一些通用逻辑。
我的问题是:
答案 0 :(得分:4)
我们很难在项目中找到这个问题的答案。这就是故事:
我们认为重用类很棒,会减少许多重复的东西。 NHibernate允许从会话中分离和重新附加类,因此它似乎是微不足道的。
我们遇到的第一个也是最大的问题是你无法发送整个数据库,所以我们不得不将实体模型拆分成碎片并用guid而不是普通的引用来链接它们。这使查询变得非常复杂。
我们不得不实施一些技巧,因为序列化,持久性和数据绑定都存在问题。这个相当丑陋的黑客进入了同一个班级。它们变得越来越大。
属性似乎无害,直到您在每个类和每个属性上看到大量属性,因为每个层都会添加其属性。
实体隐式开始支持两种“模式”: DTO模式和持久模式。当PrepareSerialization
或AfterDatabaseRetrieval
等类型的方法出现时,这一点就很明显了。某些属性只能在服务器中使用,其他属性只能在客户端中使用。
然后我们开始切换到Dtos。
经过大量的工作,我们设法重写系统的一些重要部分以使用Dtos。而且 - 突然间每个人都开心了。
您可以维护序列化。您可以维护数据库模型并优化查询。您可以在不破坏任何内容的情况下对cient模型进行更改。
结论:与在所有层中使用相同类的可维护性损失相比,为每个层维护类似类的努力是荒谬的。
仍有一些普通的实体和值类型的类同时用作实体和Dtos。
我可以想象一个只包含普通实体的小应用程序可以在没有Dtos的情况下生存。
答案 1 :(得分:2)
您应该编写尽可能少的符合您要求的课程。这样你就不太可能重复自己了,测试的次数减少了,而且当你需要更改代码时,可能会出错的事情会更少。
如果您的客户端代码实际上需要执行域逻辑,您应该:
1)直接反序列化到域模型类中(特别是如果你使用支持持久性无知的ORM)。
// Customer is a business object / aggregate root with domain logic
ICustomer customer = customerRepository.Get<Customer>(customerId);
2)使用数据传输对象初始化域模型类:
// Given a customer data transfer object
ICustomer customer = new Customer(customerDto);
如果我不需要,我宁愿不写DTO,所以我更喜欢第一种方法。但有时候DTO是必要的,就像你正在使用服务代理生成的自动生成类一样 - 或者你是一个暴露自己的DTO的服务。
如果客户端不应该执行业务逻辑,则永远不需要了解您的域模型类。在这些情况下,客户端应使用数据传输对象或自定义视图模型类。
答案 2 :(得分:0)
我必须同意前两个答案。但是,请注意保持BO / DTO类同步的努力(我会考虑使用代码生成)。
对于想要向另一个方向前进的人,请参阅我的回答here - 他们希望在他们的系统中整合众多DTO / BO。