简体   繁体   English

我们应该在服务器和客户端上使用相同的业务类吗?

[英]Should we use the same business classes on server and client?

Imagine you have business domain model on server application and you are going to develop rich client application. 想象一下,您在服务器应用程序上拥有业务领域模型,并且您将开发富客户端应用程序。

You can use DTO to transfer data to client and changes to server or use WCF services and generate new classes on the client. 您可以使用DTO将数据传输到客户端并更改为服务器或使用WCF服务并在客户端上生成新类。

Another way is to transfer the same objects as you use on server in your business logic layer. 另一种方法是在业务逻辑层中传输与服务器上使用的相同对象。 These can be also classes used by ORM. 这些也可以是ORM使用的类。 In this case classes shouldn't contain sever-specific logic, but they can contain some common logic. 在这种情况下,类不应包含特定于服务器的逻辑,但它们可以包含一些通用逻辑。

My questions are: 我的问题是:

  • Which variant do you use and which do you recommend to use in new projects? 您使用哪种变体?您建议在新项目中使用哪种变体?
  • Which is better? 哪个更好?
  • Is the second one better in some cases and how can you describe these cases? 在某些情况下,第二个更好吗?你如何描述这些案例?
  • How many applications use first/second approach? 有多少应用使用第一种/第二种方法?
  • How to choose in particular application? 如何在特定应用中选择?

We just had a hard time to find the answer to exactly this question in our project. 我们很难在项目中找到这个问题的答案。 This is the story: 这是故事:

We thought that reusing classes is great and will reduce many repetitive stuff. 我们认为重用类很好,会减少许多重复的东西。 NHibernate allows to detach and reattach classes from sessions, so it seemed to be trivial. NHibernate允许从会话中分离和重新附加类,所以它似乎是微不足道的。

  • First and biggest problem we had was that you can't send the whole database around, so we had to split the entity model into pieces and linked them by guids instead of normal references. 我们遇到的第一个也是最大的问题是你不能发送整个数据库,所以我们不得不将实体模型拆分成碎片并用guid而不是普通的引用来链接它们。 This made queries very complicated. 这使得查询非常复杂。

  • We had to implement some tricks because serialization, persistency and data binding all had their issues. 我们必须实现一些技巧,因为序列化,持久性和数据绑定都有它们的问题。 This rather ugly hacks went all into the same classes. 这个相当丑陋的黑客进入了同一个班级。 They became larger and larger. 它们变得越来越大。

  • Attributes seem to be harmless, until you see a large list of attributes on each class and each property, because every layer adds its attributes. 属性似乎是无害的,直到您在每个类和每个属性上看到大量属性,因为每个层都添加其属性。

  • Entities implicitly started to support two "modes": an DTO-mode and a persistency-mode . 实体隐式地开始支持两种“模式”: DTO模式持久性模式 This got evident when methods like PrepareSerialization or AfterDatabaseRetrieval and others of this kind showed up. PrepareSerializationAfterDatabaseRetrieval等方法出现时,这一点就很明显了。 Some properties could only be used in the server, others only in the client. 某些属性只能在服务器中使用,其他属性只能在客户端中使用。

Obviously, maintenance became a nightmare. 显然,维护成了一场噩梦。 Nobody took the risk of changing an entity anymore, because you had to change things in the whole system. 没有人冒更换实体的风险,因为你必须改变整个系统中的东西。

Then we started to switch to Dtos. 然后我们开始切换到Dtos。

After a huge amount of work we managed to rewrite some important parts of the system to use Dtos. 经过大量的工作,我们设法重写系统的一些重要部分以使用Dtos。 And - suddenly everyone got happy. 而且 - 突然间每个人都开心了。

You can maintain the serialization. 您可以维护序列化。 You can maintain the database model and optimize queries. 您可以维护数据库模型并优化查询。 You could make changes on the cient model without breaking anything. 您可以在不破坏任何内容的情况下对cient模型进行更改。

Conclusion: The effort to maintaining similar classes for each layers is ridiculous compared to the loss of maintainability when the same classes are used through all the layers. 结论:与通过所有层使用相同类的可维护性损失相比,为每个层维护类似类的努力是荒谬的。

There are still some trivial entities and value-type kind of classes which are used as entities and Dtos at the same time. 仍然存在一些简单的实体和值类型的类,它们同时用作实体和Dtos。

I could imagine that a small application that consists of only trivial entities could live without Dtos. 我可以想象一个只包含琐碎实体的小应用程序可以在没有Dtos的情况下生存。

You should write the fewest possible classes that meet your requirements. 您应该编写尽可能少的符合您要求的课程。 That way you're less likely to repeat yourself, there's less to test, and there are fewer things that can go wrong when you need to change your code. 这样你就不太可能重复自己了,测试的次数减少了,而且当你需要更改代码时,可能出现的问题就更少了。

If your client code actually needs to perform domain logic , you should either: 如果您的客户端代码实际上需要执行域逻辑 ,您应该:

1) Deserialize directly into domain model classes (especially if you're using an ORM that supports persistence ignorance). 1)直接反序列化为域模型类(特别是如果您使用支持持久性无知的ORM)。

// Customer is a business object / aggregate root with domain logic
ICustomer customer = customerRepository.Get<Customer>(customerId);

2) Use data transfer objects to initialize your domain model classes: 2)使用数据传输对象初始化域模型类:

// Given a customer data transfer object
ICustomer customer = new Customer(customerDto);

I'd rather not write DTOs if I don't have to, so I prefer the first approach. 如果我不需要,我宁愿不写DTO,所以我更喜欢第一种方法。 But sometimes DTOs are necessary, as when you're consuming autogenerated classes produced by service proxies - or if you're a service exposing your own DTOs. 但有时DTO是必要的,因为当您使用由服务代理生成的自动生成的类时 - 或者如果您是一个暴露您自己的DTO的服务。

If the client shouldn't perform business logic , it never needs to know about your domain model classes. 如果客户端不应该执行业务逻辑 ,则永远不需要了解您的域模型类。 In these cases the client should use data transfer objects or custom view model classes. 在这些情况下,客户端应使用数据传输对象或自定义视图模型类。

I have to agree with the previous two answers. 我必须同意前两个答案。 However, be aware of the effort of keeping the BO/DTO classes in sync (I would consider using code generation). 但是,请注意保持BO / DTO类同步的努力(我会考虑使用代码生成)。

See my answer here for someone who wanted to go in the other direction - they wanted to consolidate the multitude of DTOs/BOs within their system. 见我的答案在这里的人谁希望在另一个方向走-他们想巩固自己的系统内的DTO / BO的甚多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在单例类上使用Moq,以便我们只能测试业务逻辑并忽略日志记录 - How to use Moq on singleton classes so that we can only test Business logic and ignore logging WCF:我应该如何在客户端和服务器中维护合约类? - WCF: How should I maintain contract classes in client and server? 如何像只在RIA Services中一样在客户端和服务器之间共享域类和业务规则,只需编写一次即可 - How to share domain classes and business rules between client and server like in RIA Services by writing them only once 什么时候应该使用私有变量,什么时候应该使用属性。 是否在同一课程中使用背景栏? - When should we use private variables and when should we use properties. Do Backing Fields should be used in same class? C2DM服务器。我们现在应该使用OAuth吗? - C2DM server. Should we use OAuth now? 我们还应该使用服务器端网格还是Javascript网格? - Should we still use a server side grid or a Javascript grid? 我们应该使用“工作站”垃圾收集还是“服务器”垃圾收集? - Should we use "workstation" garbage collection or "server" garbage collection? 我们应该在业务逻辑层(BLL)中拥有什么 - What should we have in a Business Logic Layer (BLL) Windows客户端和Web客户端-相同的业务层和数据层 - Windows client and Web client - same business tier and data tier 我们应该使用HtmlString的编码吗? - Should we use encoding for HtmlString?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM