在三层项目中DTO/POCO的放置

3
我一直在重写网站后端,并将其向三层架构转移。
我的意图是这样结构化的:
网站<->WCF服务(1)<->业务层(2)<->数据层(3)
我的问题是DTO在这个结构中的放置。我需要使用DTO在业务层和WCF服务之间移动数据,并从WCF服务移动到消费网站。
在这里进行研究期间,我阅读了一些很好的讨论,但我还是有点困惑。
  • 这篇文章中,Davide Piras提出了一些很好的观点,如果我要按照这种设计方式进行,则需要在一个单独的项目中声明POCO的接口。然后这些接口会被层(1)和(2)实现。虽然我喜欢使用接口,但是似乎通过在(1)和(2)中声明POCO并使用类似AutoMapper的东西来复制它们的数据来回传输会让我的工作更加繁琐。

  • 这篇文章使用了一个系统,在其中创建了一个业务对象项目,该项目将被所有层引用。这似乎比另一种解决方案更简单,并且似乎可以让我找到一个解决方案

网站 <--> WCF服务(1)<-->业务层(2)<-->数据层(3)

^               ^                       ^
|               |                       |
[ -- Business Objects Referenced here --]

我的问题是:在解决方案的三个层之间共享业务对象是否存在代码异味,还是我列出的两种方法只是解决同一个问题的两种不同方式?

1
很棒的问题。表述清晰、调研周到。我离能够提出这样的问题只差大约2天,但这个问题有助于把拼图的一些部分放到了正确的位置。听起来有点像“卡崇,卡崇!” - SleepyBoBos
2个回答

3
我认为这往往取决于你正在构建的项目的复杂性。对于我建立的较小项目,我跨层共享了我的“实体”(它们只是简单的DTO,可序列化的数据桶,带有getter和setter),并且并不太关心这个问题。最大的缺点之一是逻辑分散在整个项目中(不仅在“业务层”),而且具有过程式的风格。这似乎真的像贫血领域模型,但由于项目没有增长太多,所以复杂性并没有渗入。Entity Framework有一些模板可以用来构建实体(如果我没记错,它们被称为自跟踪实体?)。
对于中型/大型项目,我不会使用这种方法,并将实体和DTO分开,因为它们将发挥不同的角色。DTO可能与您的实体具有完全不同的形状,尝试在层之间共享它们通常会出现问题。

谢谢您的想法。在考虑这两种方法时,我没有考虑到项目的规模。由于网站并不是一个庞大的项目,而且大部分增长可能会重新使用现有的对象,所以我倾向于使用共享业务对象。 - GrandMasterFlush

2
让我们将您的UI(网站)和服务(WCF + BL + DAL)视为两个不同的实体。
- 如果您对两者都有100%的控制权,则应选择方法2,因为它将避免在UI层和WCF代理对象之间进行翻译。 - 否则,您最好选择方法1,因为其中一个实体是一种“黑盒子”,可能会受到外部利益相关者的更改影响。因此,维护内部一组业务对象更安全。这将需要通过扩展方法或翻译器框架在您的业务对象和WCF代理对象之间进行翻译。
现在,不确定您的UI层复杂性或其实现(MVC,WebForms等),因此您可能需要View特定的对象(用于数据绑定更轻,序列化为JSON更快等),让我们将此对象称为“Model”。
- 如果您不需要一个明确的UI特定Model,请建议将您的业务对象标记为DataContract(在WCF上下文中)并在各个层之间使用它们。如果您通过Web($ .ajax)调用WCF,则不要忘记将实体明确标记为Serializable。 - 否则,在服务中使用DataContract,并使用翻译器将DataContract转换为UI层中的Model。Service Adapter非常适合这里 - 它位于UI层,并负责消耗WCF服务并在DataContract和Model之间进行翻译。您可以在UI层中使用Service Proxy,它是WCF服务的包装器,并可通过Web使用。
最后,您的数据层是否缺少对业务对象的引用?我相信您将从数据存储中的数据层填充业务对象。

感谢抽出时间回复。我想我更倾向于第二种方法,因为你说我既控制网站又控制后端,而且这不是一个大型网站,使用第一种方法会给自己带来更多的工作但利益很少。该网站不是MVC,只是普通的Web表单。从长远来看,我可能会将其转移到MVC上,并没有考虑过这是否会受到影响。我会记住你说的话,谢谢! - GrandMasterFlush
关于数据层和业务对象引用,我的数据层只公开了一个静态类,允许业务层访问数据库。看起来,我可能在这样做时混淆了两个层之间的边界。 - GrandMasterFlush

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接