【问题标题】:Business Layer Facade vs Mingled Business Components业务层外观与混合业务组件
【发布时间】:2012-10-28 00:24:46
【问题描述】:

我目前正在为一个大型应用程序设计基础。我们将使用传统的 3 层系统,在数据层使用 EF,在业务层使用纯 jane c# 类,在 ui 层使用 MVC/WCF。我们已经对应用程序进行了足够多的原型设计,以意识到这对我们有用,但是由于业务需求的复杂性某些业务组件之间的交互很常见。

考虑以下两个业务组件:

  • RetailManager - 处理系统中与零售相关的一切
  • CartManager - 处理与购物车体验相关的一切

例如,在购买商品时的结账过程中,两者会进行交互。所购商品的库存需要减少。

到目前为止,这是我的思考过程:

  1. 让业务组件相互引用并确保循环引用永远不会发生(CartManager 引用 RetailManager,但绝不会反过来)。 “Checkout”是 CartManager 类的一个方法,它会调用 RetailManager 的一个方法来调整库存。虽然这会起作用,但我不确定它的扩展性如何,以及随着时间的推移维护成本会是多少。我觉得这不是 100%“正确”的。

  2. 在业务组件和 UI 层之间创建一个外观。在本例中,Facade 将具有 checkout 方法和对两个管理器的引用。我比第一种方法更喜欢这种方法,但是我知道并不是我的所有业务对象都需要 Facade,而且我不想创建大量的 Facade 类只是为了有空的传递方法。

我倾向于 2,但需要注意的是,我只会在需要的地方创建外观类。 UI 层将可以访问 Facade 和业务层组件,并且必须知道何时使用哪个(我不喜欢这个解决方案的唯一部分)。

我进行了大量研究,但未能提出一个感觉完全正确的解决方案。

欢迎任何关于以这种方式使用外观模式的想法,或其他解决问题的想法。

提前致谢。

【问题讨论】:

标签: c# .net asp.net-mvc architecture n-tier-architecture


【解决方案1】:

这是使用管理器/服务类的典型问题。他们总是容易臃肿。当你达到这一点时,最好开始使用命令。

使用 IoC 的好处是,您不必直接重构所有代码,但可以在有时间时进行。只需开始为所有新功能编写命令,同时为其他一切保留旧架构。

这里是命令介绍:http://blog.gauffin.org/2012/10/writing-decoupled-and-scalable-applications-2/

还有我自己的框架的介绍:http://blog.gauffin.org/2012/10/introducing-griffin-decoupled/

【讨论】:

  • 但请注意,基于命令的架构在没有任何框架的情况下也能正常工作。
  • 我喜欢这种方法背后的想法,但是我不想像你所说的那样“欺骗用户”或“分散用户注意力”。需要这样做的味道是在不适合的地方强制设计模式。假设用户单击了一个按钮以从购物车中删除一个项目。使用命令方法,我会触发一个命令来执行此操作并重定向回购物车摘要屏幕。如何保证在向用户显示摘要屏幕之前完成命令?
  • 为什么要使用命令来删除购物车项目?使用命令发送订单。 Thank you for purchasing. You'll receive a confirmation email soon.
  • 如果用户想从他们的购物车中删除一个项目,你会使用这样的命令。
  • 在购物车完成之前我不会保存它,而是将它保存在 cookie 中。总是有几种方法可以解决同一个问题。总是尝试使用相同的方法更像是一种小型设计。恕我直言,必须处理无法从命令返回任何内容的限制。这是你必须付出的代价才能变得灵活。调用命令时,您应该尽一切努力确保它会成功。恕我直言,用户不在乎他是否在一分钟后或直接在他无法提供帮助的情况下出现错误。
【解决方案2】:

我倾向于使用外观实现。

我首先会问自己,在结账时确保减少库存是谁的责任?我认为减少库存不是CartManager 的责任。我将有第三类(在您的情况下为外观),以确保每当CartManager 签出一个项目时,相应的项目就会从库存中减少。

我会考虑的另一个选择是基于事件的实现。每当签出项目时,CartManager 将引发 ItemCheckedOut 事件。 RetailManager 将订阅此事件,并在引发事件时减少库存。如果您是事件驱动设计的新手,请在 quora 上关注此问题 - http://www.quora.com/What-are-some-good-resources-on-event-driven-software-design

【讨论】:

  • 我同意这不是 CartManager 的责任。我倾向于你在第一段中描述的内容。我对事件驱动设计有很高的理解,但对使用它的实际知识很少。我会看看你的链接,谢谢。
  • 我正在考虑基于事件的实现。假设CartManager 引发了ItemCheckedOut 事件。 RetailManager 应该如何/在哪里订阅该事件?我的想法是在应用程序启动期间(类似于设置 IoC 容器),但这不意味着有一些 RetailManager 的实例存储在某个地方等待吗?我想我可以创建一些 EventController 来监听事件并生成处理它所需的任何管理器的实例。
  • 没错,在最简单的实现中,您需要一个事件侦听器,它会找出订阅事件的类型,然后创建他们的实例并将事件传递给实例。我不会使用预先创建的单个实例,因为这可能会导致奇怪的问题
  • 我可能最终会混合您最初所说的内容。 Manager 类将公开核心功能。他们将在必要时提出其他经理可以订阅的事件,以便我可以完成因果关系。我还可以看到在这里和那里创建外观类来完成更大的协调工作流类型的任务。 UI 层可以访问 Managers 和任何 Facade 类,并且可以选择它想要做什么。
【解决方案3】:

我个人喜欢CQRS的模式,它与其他架构模式自然契合 比如Event Sourcing,适合复杂的域。

【讨论】:

  • -1 看起来您只是在抛出流行语,因为您没有提及为什么这些模式在这种情况下会起作用。在这种情况下,恕我直言 CQRS 只会让事情变得更复杂。另一方面,CQS 可能有助于让事情变得更容易。
  • 我认为 OP 正在寻找其他选项而不是外观方法来进行组件间通信。没有太多细节我可以解释这些模式在这种情况下可以工作,但 CQRS/CQS 值得探索。
  • 我昨天研究了很多 CQRS。值得探索,但我认为我们不会达到那种程度的变化。 +1 的建议,只是不是 100% 我要找的。​​span>
猜你喜欢
  • 2011-12-06
  • 2012-05-11
  • 2010-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
  • 1970-01-01
  • 2011-06-16
相关资源
最近更新 更多