【问题标题】:Which layer is responsible for the business logic?哪一层负责业务逻辑?
【发布时间】:2014-12-09 19:48:08
【问题描述】:

我正在从事一个基于领域驱动设计的项目。

在这个项目中,我们有 5 层:

  1. 基础设施
  2. 应用服务
  3. 分布式服务
  4. 演示文稿

我对如何将我的业务逻辑放在基础架构、域和服务层之间感到困惑。有时我将业务逻辑条件放在存储库中的 iqueryable Linq 中;有时我将所有对象加载到内存中并将它们放入服务中;有时我把它们放在一个对象的方法中。我不知道哪种方式是正确的方式。哪个层应该负责这个业务逻辑?

我需要一些具体的理由来说服开发团队相信代码中的业务逻辑更好,因为它更易于维护。我曾经在 DB 中有很多业务逻辑,因为我相信它是单点访问。

【问题讨论】:

标签: oop design-patterns domain-driven-design business-logic


【解决方案1】:

存储过程对于加速某些数据库操作很有用。 存储过程是邪恶的,因为:

  • 很难进行版本控制(不是最难的事情,但比对项目进行版本控制更难)
  • 更难部署(例如,在我的工作中,我们在几台服务器上有数千个 DB 和数千个存储过程;当我们更改 SP 的逻辑时,我们必须更新每个 DB:脖子上的痛.)
  • 很难调试,
  • 很难进行单元测试

说...存储库的实现是基础设施,而基础设施不了解域和业务逻辑。 毕竟我在这个问题上看不到DDD,也许你应该加深一下实体、值对象和聚合根等概念,以及存储库和域模型。

我们现在唯一可以确认的是:作为领域逻辑的业务逻辑属于领域模型/领域层。域逻辑是除了用例之外总是以相同方式运行的规则(例如:如果订单价格高于 100 美元,则发货免费)。 如果您有一个取决于用例的规则(例如:如果用户使用 appmobile 浏览我的电子商务而不是...),这就是应用程序逻辑。

【讨论】:

    【解决方案2】:

    DDD 还遵循“关注点分离”规则,因此围绕域的业务保留在域层中,如果域外的某些东西是依赖的,那么我们将它们放在更高的层中,例如表示层中的模型视图。

    【讨论】:

      【解决方案3】:

      我知道这已经过时了,但我曾在一些旧项目上工作过,在这些项目中,数据库保存了所有逻辑,并且各种系统都使用了该逻辑。更新这些系统中的任何一个都变成了一场噩梦,对其中任何一个进行更改都会破坏其他地方的东西。

      DDD 旨在绕过这些确切的场景。

      可以将其想象为您拥有一个专注于控制其域的应用程序,定义域通常很困难,但假设您可以定义具有 3 个域的传统系统。

      Commerce Domain 控制如何接受订单。

      物流域控制如何运送订单。

      订单支付方式的计费域。

      理想情况下,这些领域中的每一个都可以表示为分层应用程序,但“订单”的整个端到端故事涉及所有 3 个应用程序。每个域都控制着它的业务,并负责以最好的方式完成它的工作。

      Billing Domain 可以像 Web api 一样简单,它将订单数据附加到 csv 文件中,会计人员每月打开一次该文件,然后手动输入发票。或者它可能会成长为一个庞大的复杂的快速书集成野兽,自动从保存的账户中提取资金。 Commerce and Logistics 域不必关心计费域将其数据保存在何处或如何获得报酬。他们只负责在商品售出和发货时通知计费域。

      Commerce 域同样不必关心运费是如何计算的,它只需要询问 Logistics 域即可。 Commerce 不应该在 Logistics 需要的数据库中扎根,因为如果 Logistics 想要调整并使用谷歌地图来确定运输成本,那么我们也需要更新 Commerce。

      一旦您理解了“每个域都控制着它的数据,如果您需要该域的数据,您可以询问该域”的概念。接下来的位有点排成一行。

      每个域都会有一个或两个表示层,这可以是网站、api、移动/桌面应用程序或以上的组合。每个域都将在域/应用程序层中具有业务逻辑。每个域都将得到数据库和 API 等基础设施的支持。

      在上面的示例中,我们可以有一个商务域。它的表示层将网站呈现给用户,它的领域层由 OrderPage 和命令/查询接口组成。它的基础设施层具有处理这些命令和查询的逻辑,其中大部分可能会转到私有数据库,但我们也有一些对物流和计费域的 api 调用。

      我们的计费域在其表示层中有 2 个项目。一个是用于处理来自 Commerce 和 Logistics 域的请求的 API,另一个是我们为会计编写的桌面应用程序。它们都与相同的域对象/接口进行通信,因此如果会计需要登录并手动修改订单,它们可以像在网站上一样轻松地进行操作。域中的接口由基础设施实现,该基础设施可能是一个 quickbooks api,它还将数据转发到新书,直到完成大迁移。 Commerce 和 Logistics 中的任何代码都不必关心 Freshbooks/quickbooks,如果我们愿意,我们可以同时使用它们。

      我们的 Logicstics 域在其表示层中同样有两个项目。一个控制台应用程序,每天早上在计划任务上运行一次,以批量处理订单和 api。对它的数据进行同样的处理。

      好吧,这有点太长了,我要总结一下。无论如何,没有人可能会在 4 年前的帖子上阅读此答案,哈哈。

      【讨论】:

        猜你喜欢
        • 2010-12-18
        • 2011-12-03
        • 2011-11-26
        • 2017-04-29
        • 2016-08-12
        • 1970-01-01
        • 2014-09-04
        • 2013-02-18
        • 1970-01-01
        相关资源
        最近更新 更多