【问题标题】:Multi-Tier Architecture - Responsibility questions多层架构 - 责任问题
【发布时间】:2013-03-23 19:48:16
【问题描述】:

我正在开发一个实现多层模式的应用程序,其中 MySQL 用于持久性。有一个提供访问的 WCF 服务 数据并提供 DTO。

此外,我计划实现以下模式: - DTO - MVP(还不确定是被动视图还是监督控制器) - 在适用的情况下针对接口编写代码

目前,我的项目结构如下:

+-------------------------------+
|     MySQL DB Server           |
+------+------------------------+
       ^
       | Uses Entity Framework 5.0
       |
       +
+-------------------------------------------------------------------------------+
| Application Server                                                            |
|-------------------------------------------------------------------------------|
|+------------------+ +----------------+ +--------------+ +--------------------+|
|| Data Access Layer| | Contracts      | | Communication| | Business Layer     ||
||------------------| |----------------| |--------------| |--------------------||
|| - EF 5.0 Entities| | - WCF Contracts| | - WCF Service| | - Actual Service   ||
||                  | |                | |   Hosts      | | - Session management|
||                  | |                | |              | | - Security and     ||
|+------------------+ +----------------+ +--------------+ +--------------------+|
+-------------------------------------------------------------------------------+
        ^
        | Communicates via DTOs which are acutally wrappers for Entities
        | eg. GetUserByID() or SaveUser(userDTO)
        |
        |
+-------+-----------------------------------------------------------------------+
| Clients                                                                       |
|-------------------------------------------------------------------------------|
|+-------------------+                                     +-------------------+|
|| Business Layer    |+----------------------------------->| GUI (Winforms)    ||
||-------------------|  BLL receives DTOs and creates      |-------------------||
|| -Provide WCF Servi|  Domain Objects (eg. User) which are| -Implementation of||
||  ce Access        |  Processed by presenters and passed |  View Interfaces  ||
|| -Service Reference|  to views where they are bound to   |                   ||
|| -Implementation of|  controls.                          |                   ||
||  Presenter Interf.|                                     |                   ||
|+-------------------+                                     +-------------------+|
+-------------------------------------------------------------------------------+



+------------------------------------------------------------------------+
| General                                                                |
|------------------------------------------------------------------------|
|+---------------------+ +--------------------+ +-----------------------+|
|| DTOs                | | Interfaces         | | Library               ||
||---------------------| |--------------------| |-----------------------||
|| -DTO Definitions    | | -View Interfaces   | | -General Helper Classe||
||                     | | -Presenter Interf. | |  s eg. Cryptography   ||
||                     | | -Domain Model IF.  | |                       ||
|+---------------------+ +--------------------+ +-----------------------+|
+------------------------------------------------------------------------+

外框是 Visual Studio 中的项目文件夹。内盒是 C# 项目

在我继续编码并花更多时间实际实施之前,我只是 想得到一些关于我的项目结构/架构的反馈。

我正在思考以下问题:

  1. 上述结构是否符合“最佳实践”? 例如。接口、DTO 的位置​​
  2. 可以有两个业务层还是拆分业务层 进入客户端和服务器? 服务器 BLL 旨在提供会话管理等通用功能 和安全,而客户端 BLL 提供服务访问。它控制着 其演示者的观点也是如此。
  3. 服务器端目前不知道域对象。会不会 在这里也可以更好地使用它们?这将导致映射我的 实体到域对象,然后到 DTO
  4. 从 WCF 服务接收 DTO 是常见的还是我应该使用域 对象(我知道这里已经讨论了很多,但是从什么 我了解,如果域对象不是,它将适用 这很复杂,并且可以在更改时节省映射和编码工作 我的域对象和数据库) 这不会导致非常难以维护的通信链,例如: 实体域对象DTO域对象
  5. 您将验证放在哪里?我想将基本验证放入 视图或演示者(例如,格式化、null/not null 值,...)同时 主要验证转到域对象...?
  6. 在数据库中创建新记录时,假设是一个新用户, 客户端是否也应该将新的 DTO 传递给服务器,还是创建更好 接受简单数据类型(如字符串和 int)的服务方法?

很抱歉这篇长篇文章,但我认为最好结合我的 将问题放在一篇文章中,并在其中提供项目结构。

提前感谢您的任何回答。

问候

【问题讨论】:

    标签: architecture domain-driven-design dto n-tier-architecture multi-tier


    【解决方案1】:

    您提出的结构与我们 2 年前在生产中部署的应用程序之一非常相似 (mutatis mutandis)。它可以工作,但您必须仔细设计域模型,在不同的有界上下文中分离应用程序的各个方面。

    所以这些是我自己的答案:

    1. 不,这里没有“最佳实践”可以符合。经过 5 年的金融应用 DDD 实践,我个人的看法是,DDD 仍然是一个研究领域。但是,如果正确地应用于价值在于领域专家经验的项目,它证明是非常好的。但是,您必须区分业务需求(与领域相关)和技术需求(有助于绘制应用程序所需的组件和层)
    2. 业务层(如果您需要确定一个)应该只处理业务规则。它是 DDD 应用程序中的领域模型层。
    3. 根据我的经验,如果您可以信任客户端计算机并且正确设计了域模型,那么您根本不需要任何应用程序服务器。但是,如果您真的需要它(例如,因为客户端无法连接到数据库),我会使其尽可能简单和无状态。这里一个有用的考虑是大多数时候,业务规则已经阻止了对可变实体的并发访问。在这种情况下不要尝试处理对此类实体的并发访问,只需构建互斥机制即可。
    4. 对于进程间通信,仅使用 DTO。但是,您可以选择将整个域移动到应用程序服务器中(这将变得更加复杂和有状态),并在客户端中使用更简单的 MVC 模式。从客户端开发人员的角度来看,这更简单,但总体而言成本更高(特别是难以扩展)。
    5. 可以在视图中完成输入字段的简单类型验证(整数、日期时间等),但是您应该在将每个相关类型的值建模之前使用自定义值对象将其传递给域。例如,您永远不应将字符串或小数传递给域对象,而应将 EmailMoney。而且域中唯一负责业务不变性的:it should throw expressive exceptions,当某项操作无法执行时。
    6. DTO 更具表现力,因此更易于调试。

    在开始之前,我认为你应该问自己一些问题:

    1. 我是否需要领域专家,或者我可以通过阅读 Wikipedia 或一组编写良好的规范来了解足够多的业务?提示:(至少)不需要领域专家 == 不需要 DDD。
    2. 我可以信任将部署客户端的机器吗?如果不能,则应考虑将域移至应用程序服务器(并采用 MVC 模式客户端来处理 WCF 请求和 DTO 绑定)。

    最后,如果你真的需要 DDD,而且你是新手,你会发现 Epic's modeling patterns 很有用(免责声明,我是 Epic 开发人员之一,我在过去 5 年的 DDD 中设计了所有这些反复试验)。

    【讨论】:

    • 感谢您的回答。 WCF 的主要原因是第三方软件也应该连接,我不希望他们直接使用数据库。我尝试设计无状态的服务。我认为在应用程序服务器中完成大部分“域工作”以实现“单点控制”是一个很好的设计。但也许我必须重新考虑结构并简化它。谢谢你的链接,我去看看。
    • 如果 WCF 是供第三方访问的,则您不必对其进行 dogfood。如果您向第三方公开的服务是只读的,那么该结构就可以了。否则,您将不得不在服务中也使用域模型,否则您将在域模型和 WCF 服务中以一堆重复的业务逻辑告终。
    • 感谢您花时间为我可能愚蠢的问题 :-) 只读的东西是一个好点。第 3 方服务确实是只读的,因此将“智能”交给客户端似乎没那么复杂。我将做一些重组工作,看看它看起来如何,然后回到这里关闭这个线程或请求进一步的提示。再次感谢!
    【解决方案2】:

    我会一一解答

    1) 它取决于应用程序的复杂性。如果您正在处理复杂的领域,最好遵循领域驱动设计

    2) 如果你说 BLL,它应该只处理业务逻辑而不是任何技术细节,如会话、安全性......

    3) 在服务器端拥有域对象是件好事。它促进了可重用性

    4) 你不应该将域对象暴露在外面。 DTO 是更好的选择。您可以使用 Automapper 进行所有与映射相关的工作

    5) 最好根据范围在每个组件中进行验证

    6) DTO 会更好

    此外,您可以使用服务堆栈而不是 WCF,因为它是基于行业最佳实践构建的。

    【讨论】:

    • 库马尔,谢谢您的回复。关于第 2 点,这正是我拆分 BLL 的原因。也许 BLL 在服务器端不是正确的术语。经过考虑,使用我的问题第 4 点中描述的映射似乎很好。我们已经在使用 automapper。
    • ServiceStack 的另一个替代方案是 ASP.NET Web API
    猜你喜欢
    • 2012-02-27
    • 2012-03-12
    • 2011-04-03
    • 2013-06-30
    • 2022-01-14
    • 2013-09-27
    • 2011-04-13
    相关资源
    最近更新 更多