8

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

为了使图层保持独立,当前通过几个映射步骤将数据从数据库传输到 UI。在服务器端,数据实体被映射到域对象,域对象又被映射到服务数据契约。在客户端,WCF 代理类映射到视图模型。

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

4

3 回答 3

9

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

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

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

如果它不是一个数据驱动的应用程序,那么你的服务器端可能有一些复杂的业务逻辑,而这个业务逻辑通常与只对它的上下文有意义的对象一起操作。将这些对象一直推送到 UI 是没有意义的。

相反,UI 可能会向服务器发送命令以要求系统做某事。例如,它将发送“DisableAccount(id=123)”命令而不是加载 AccountDTO,将其 IsEnabled 标志更改为 false 并将其推回。如果有业务逻辑,那么它可能会被客户端的这种命令触发,不需要知道如何禁用帐户或如何做其他事情。它只知道并且可以命令系统做某事

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

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

说了这一切,我应该强调这不是你做出的二元选择。对于简单的功能,您可以使用简单的方法,对于具有业务逻辑的功能,您可以做其他事情。

您不必为所有事情选择一个。因此,您不必总是因为它是“The Way”而创建 3 个相似的对象,或者总是将实体一直传递到 UI。但是您必须做的是清楚地分离上下文并定义将使用哪种方法。

在 80% 的情况下,您可能最终会得到一些简单的东西(例如 WCF DataServices),并且您不需要做任何事情,这很好,因为在很多操作中您只想更改数据。

但是在真正的业务逻辑所在的其他 20%(这是应用程序的“核心”)中 - 在这里,您可能希望这种分离不仅用于对象,还用于层之间的职责。

于 2012-02-08T10:49:22.090 回答
7

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

但是,非常重要的是要意识到,一旦您开始跨层和层共享数据结构,架构就不再是解耦的。如果你这样做,你实际上是在构建一个单体应用程序。不要误会我的意思:如果您所做的只是一个美化的 CRUD 应用程序,那么构建一个单体应用程序并没有错,但明确地做出该决定是必不可少的。

至少有这些选择:

  • 保持严格的分层。映射成本仍然存在,但代码是解耦的。
  • 构建一个单体应用程序。折叠所有可以折叠的东西。尽可能简单。它将紧密耦合,但它可能变得如此简单以至于无关紧要。
  • 做一些完全不同的事情,比如构建CQRS应用程序或 SOA mashup。

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

于 2012-02-09T23:08:20.303 回答
0

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

层纯度能给你带来什么?

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

于 2012-02-08T10:14:35.260 回答