我正在创建一个使用WCF服务与数据源交互的WPF应用程序。我为客户端和WCF服务器使用DI来确保解耦代码,但我不确定如何处理从后端到用户界面的数据传输。
要保持图层单独,数据当前通过几个映射步骤从数据库传输到UI。在服务器端,数据实体映射到域对象,域对象再次映射到服务数据协定。在客户端,WCF代理类映射到viewmodels。
一些开发人员声称,在看似相同的类之间“复制”数据会产生维护问题,因为在引入更改时必须更新许多类。相反,他们说你应该跨层使用共享类,因为我们控制客户端应用程序和WCF服务。我也担心所涉及的工作量并看到潜在的性能损失,但另一方面,使用跨层/抽象的共享类可能会产生我看到的紧密耦合。什么是最好的方法?
答案 0 :(得分:9)
使用DTO作为业务对象并不是您可以做出的最佳决策。 根据我的经验,我可以说,通常当您的对象对于所有层都相同时,那么在某处可能存在架构问题。
在实际业务场景中,服务器上的业务逻辑和客户端上的业务逻辑不太可能具有相同的上下文并使用相同的对象进行操作。如果它们与数据库具有完全相同的结构......嗯......听起来像是一个数据驱动的应用程序。
但是,当客户端访问某些数据时, 是数据驱动的应用程序,修改它并将其保存回来,那么您可能真的不需要这种复杂的分层吗?听起来很简单,让我们保持简单。如果 是一个数据驱动的应用程序,为什么不在数据库之上创建一个WCF DataServices上下文,让它在您通过WCF访问数据时为您完成所有脏工作甚至没有考虑DTO,映射等。
如果它是不数据驱动的应用程序,那么您的服务器端可能有一些复杂的业务逻辑,而这种业务逻辑通常使用仅对其上下文有意义的对象进行操作。将这些对象一直推送到UI是没有意义的。
相反,UI可能会将命令发送到服务器,以便让系统执行某些操作。例如,它将发送“DisableAccount(id = 123)”命令而不是加载AccountDTO,将其IsEnabled标志更改为false并将其推回。 如果是业务逻辑,那么它可能会被来自客户端的命令触发,而该客户端不需要知道如何禁用帐户或者如何做其他事情。它只知道并且可以命令系统做某事。
因此在这种情况下,客户端(UI)不需要服务器具有的相同对象。它可能需要向用户显示一些数据,但它肯定会采用对客户端视图有意义的格式,而不是业务逻辑。它可能包含一些非规范化数据,以某种方式组合。
说,UI用户不是映射到Users表的DTO。它是另一个DTO,包含来自不同表的用户数据和统计信息,以某种方式处理。客户端不需要知道服务器数据存储的内部结构,因此不需要公开它。获取相关数据并发送相应的命令,就是这样。
说这一切我应该强调它不是你做的二元选择。对于简单的功能,您可以使用一种简单的方法,对于具有业务逻辑意义的功能,您可以执行其他操作。
您不必为一切选择一个。因此,您不必始终创建3个类似对象,因为它是“The Way”或始终将实体一直传递到UI。 但是 必须做的是明确区分上下文并定义将使用哪种方法。
在80%中你可能最终会得到一些简单的东西(比如WCF DataServices),而且你不需要做任何事情,并且它很好,就像你想要更改数据的很多操作一样。
但是在真实业务逻辑所在的其他20%(这是应用程序的“核心”)中 - 您可能希望这种分离不仅适用于对象,还适用于各层之间的职责。
答案 1 :(得分:6)
所有映射确实会造成维护负担。是否有必要取决于您正在构建的内容以及业务逻辑的复杂程度。
然而,认识once you start sharing data structures across layers and tiers, the architecture is no longer decoupled非常重要。如果你这样做,那么你基本上就是构建一个单一的应用程序。不要误解我的意思:如果您所做的只是一个美化的CRUD应用程序,那么构建一个单一的应用程序没有任何问题,但是明确做出这个决定是必不可少的。
至少有这些替代品:
就个人而言,我最近更喜欢第三种选择。
答案 2 :(得分:0)
我认为没有什么神圣的层。在模型中具有每个实体的特定于层的版本将大大增加类的数量。在我看来,这是不必要的。它违反了DRY原则:为什么要不断重复自己?
层纯度会给你带来什么?
所以我说最好的方法就是毫不畏惧地传递这些模型实体。