数据类是应该跨层和应用程序重用还是映射到特定于层的类?

Pål*_*der 8 c# architecture dependency-injection decoupling

我正在创建一个使用WCF服务与数据源交互的WPF应用程序.我为客户端和WCF服务器使用DI来确保解耦代码,但我不确定如何处理从后端到用户界面的数据传输.

为了保持层分离,数据当前通过几个映射步骤从数据库传输到UI.在服务器端,数据实体映射到域对象,域对象再次映射到服务数据协定.在客户端,WCF代理类映射到视图模型.

一些开发人员声称,在看似相同的类之间"复制"数据会产生维护问题,因为在引入更改时必须更新许多类.相反,他们说你应该跨层使用共享类,因为我们控制客户端应用程序和WCF服务.我也担心所涉及的工作量并看到潜在的性能损失,但另一方面,使用跨层/抽象的共享类可能会产生我看到的紧密耦合.什么是最好的方法?

Ale*_*aga 9

使用DTO作为业务对象不是您可以做出的最佳决策.根据我的经验,我可以说,通常当您的对象对于所有层都相同时,那么在某处可能存在架构问题.

在实际业务场景中,服务器上的业务逻辑和客户端上的业务逻辑不太可能具有相同的上下文并且使用相同的对象进行操作.如果它们与数据库具有完全相同的结构......嗯......听起来像是一个数据驱动的应用程序.

但是如果它一个数据驱动的应用程序,当客户端访问一些数据,修改它并将其保存回来,那么你可能真的不需要这种复杂的分层?听起来很简单,让我们保持简单.如果它一个数据驱动的应用程序,为什么不在数据库之上创建一个WCF DataServices上下文,当你只是通过WCF访问数据时让它为你做所有的脏工作,甚至不考虑DTO,映射等.

如果它不是数据驱动的应用程序,那么您的服务器端可能有一些复杂的业务逻辑,并且此业务逻辑通常使用仅对其上下文有意义的对象进行操作.将这些对象一直推送到UI是没有意义的.

相反,UI可能会向服务器发送命令,以要求系统执行某些操作.例如,它将发送"DisableAccount(id = 123)"命令而不是加载AccountDTO,将其IsEnabled标志更改为false并将其推回.如果一个商业逻辑,那么它很可能会被这种触发命令从谁也不需要知道客户端如何禁用帐户或如何做其他事情.它只是知道并能指挥系统什么.

因此在这种情况下,客户端(UI)不需要服务器具有的相同对象.它可能需要向用户显示一些数据,但它肯定会采用对客户端视图有意义的格式,而不是业务逻辑.它可能包含一些非规范化数据,以某种方式组合.

比如,User for UI不是映射到Users表的DTO.它是另一个DTO,包含来自不同表的用户数据和统计信息,以某种方式处理.客户端不需要知道服务器数据存储的内部结构,因此不需要公开它.获取相关数据并发送相应的命令,就是这样.

说了这些,我应该强调它不是你做的二元选择.对于简单的功能,您可以使用一种简单的方法,对于具有业务逻辑意义的功能,您可以执行其他操作.

你不必为一切选择一个.因此,您不必总是创建3个类似的对象,因为它是"The Way"或始终将实体一直传递到UI.但你要做的是明确独立的上下文,并确定其中将要使用哪种方法.

在80%中你可能会得到一些简单的东西(比如WCF DataServices),而且你不需要做任何事情,并且它很好,就像你想要更改数据的很多操作一样.

但在其他20%(这是您的应用程序的"核心")中,真实的业务逻辑仍然存在 - 在这里,您可能希望这种分离不仅适用于对象,还适用于层之间的职责.


Mar*_*ann 6

所有映射确实造成了维护负担.是否有必要取决于您正在构建的内容以及业务逻辑的复杂程度.

但是,非常重要的是要意识到,一旦开始跨层和层共享数据结构,架构就不再分离.如果你这样做,你基本上是在构建一个单片应用程序.不要误解我的意思:如果您所做的只是一个美化的CRUD应用程序,那么构建单个应用程序没有任何问题,但明确做出决定至关重要.

至少有这些替代方案:

  • 保持严格的分层.映射成本仍然存在,但代码是分离的.
  • 构建一个单一的应用程序.折叠你可以崩溃的一切.保持尽可能简单.它将紧密耦合,但它可能变得如此简单,无关紧要.
  • 做一些根本不同的事情,比如构建CQRS应用程序或SOA mashup.

就个人而言,这些天我更喜欢第三种选择.


duf*_*ymo 0

我不认为层次有什么神圣之处。模型中每个实体的特定于层的版本将大大增加类的数量。在我看来,这是没有必要的。它违反了 DRY 原则:为什么要不断重复自己?

层纯度能为您带来什么?

所以我想说最好的方法是毫无恐惧地传递这些模型实体。