【问题标题】:Controller <-> Service component interaction控制器 <-> 服务组件交互
【发布时间】:2010-01-23 22:16:31
【问题描述】:

更新:

我有一个桌面应用程序,与以下组件交互:

  • Winform 用户界面。
  • 服务(包含实际执行工作的业务逻辑的进程内 C# 类)。
  • 控制器(协调 UI 引发的事件并调用服务方法的 C# 类)。

如果控制器要求服务做某事,但该服务首先需要控制器提供更多信息(即控制器必须使用 UI 从用户那里获取数据),服务应该如何获取控制器这样做?


我对这个概念很满意

  • 用户与
  • 通信
  • 通信的 UI
  • 与之通信的控制器
  • 与之通信的服务组件(不要与 Web 服务或进程外服务混淆)
  • 通信的数据/存储库...

等等。

但是,对于 Controller 与 Service 的通信,什么方法最适合呢?应该:

  1. 服务方法是相当细粒度的,如果有什么不对劲的时候抛出异常,这样控制器就知道是继续前进还是告诉用户出了什么问题?或者...
  2. 服务方法返回控制器可以检查以决定下一步做什么的对象?

我喜欢第一个选项,因为第二个可能意味着类爆炸,每个 Service 方法都需要一个 ServiceResult 样式的类。

我问是因为 Service 组件当然不能告诉 UI 要做什么,只有控制器可以,但是控制器不知道要告诉 UI 什么而没有从 Service 获得一些反馈。

你怎么看?

【问题讨论】:

    标签: model-view-controller architecture


    【解决方案1】:

    您最好的选择可能是使用事件或委托模型 - 例如,控制器订阅“需要更多信息”事件并显示适当的表单。可以通过几种不同的方式将附加数据返回给服务,但很大程度上取决于您的设计细节(例如,您的服务是无状态的等)

    您是否为您的服务编写了单元测试?如果没有,此过程可能会帮助您阐明您想要从设计中得到什么。

    【讨论】:

      【解决方案2】:

      在设计服务层/类时,您需要牢记的第一件事是使它们具有高度可重用性。它们应该是原子服务对象,不仅可以为您的控制器提供服务,还可以为将来的任何其他客户端提供服务。

      这里有几个问题:

      1. 控制器如何找到服务?
        如果您希望拥有高度可重用、可扩展和......服务对象,那么您的控制器和服务类之间的依赖关系应该是松散耦合的。避免任何紧耦合技术。相反,请尝试将服务类 inject 发送到您的控制器(使用 IOC 容器),您也可以使用 Service Locator Design Pattern

      2. 如何与服务通信?
        好吧,这取决于您的应用程序的大小。您可能会选择企业服务技术,例如 Web 服务,只使用应用程序服务。在此基础上,您可以定义控制器和服务之间的协议。

      3. 服务应该向控制器返回什么数据?
        请记住,服务层不应该知道有关 UI 导航的任何信息。控制器负责根据服务对象的响应来决定去哪里以及做什么。为什么?想象一下,这个服务类需要用于另一个 UI(比如从 web 到 flex、silverlight 或桌面应用程序)。如果您在服务类中添加导航逻辑(作为一个极端的示例,UI 逻辑/格式),它将不能被另一个 UI 系统重用,甚至不能被同一应用程序中的其他服务类和控制器重用.

      底线,尽量保持服务类没有任何导航逻辑。控制器确实是为此目的而设计的。

      【讨论】:

      • 控制器通过 IoC 容器获取服务。诀窍在于,有时服务无法走得更远,因为它需要更多信息,但它无法访问 UI - 它需要控制器来执行此操作。那么服务应该如何通知控制器它需要收集更多信息呢?
      • 如果你认为服务是一个完整的、独立的组件,具有一定的责任(只是让我想起了 CRC),它可能有一个主要(成功)场景和一些例外(替代场景)。在这种情况下,您正在谈论异常。这是一个高水平的意见。现在对于实现,我喜欢使用异常是一种优雅的方式。当在应用程序中正确使用时,它们是不言自明的并且管理得很好。即使您更改控制器或为您的服务提供其他客户端,它仍然可以工作。希望这是您问题的答案。
      【解决方案3】:

      查看我的问题here

      有一些遗漏的细节可以更好地回答你的问题:

      它是网络场景还是桌面场景?

      如果桌面 ​​- 是断开连接的场景吗? (例如,具有远程服务的富客户端)还是客户端和服务在同一台机器上?

      如果 web - 它是经典的 web 1.0 应用程序吗? (视图被创建为页面)还是富客户端? (AJAX、Flex、SilverLight)哪里的控制器有时可以在客户端? (弹性)

      所有这些都会显着影响决策。

      顺便问一下,你是不是故意省略了模型?

      【讨论】:

      • 桌面 - 查看问题的更新。这都是进程内的——在这种情况下,“服务”是指包含业务逻辑的服务对象——服务使用模型来完成实际工作,但控制器和服务之间的交互是我真正感兴趣的在。
      【解决方案4】:

      我经常使用 MVC(尽管我的是 Java Web 应用程序风格),而且我经常偶然发现一些情况,服务似乎需要以某种方式与控制器进一步交互。但在每种情况下,事实证明我在控制器中做错了什么,或者我的服务接口不够灵活(即细粒度)。

      当服务没有收到足够的数据时,这是因为用户提供了无效的输入吗?如果是这样,那么控制器应该对输入执行验证并显示适当的提示或错误消息。

      如果预计用户不会一次提供所有数据,那么控制器应该知道服务不会按原样接受数据。因此,控制器应该通过 UI 管理与用户的对话,然后最终将所有内容传递给服务。

      或者控制器可能需要在向导的整个流程中查询服务。在这种情况下,服务的接口可能应该更细粒度。

      我会选择您提出的选项#1。如果控制器能够从 UI 收集所有需要的输入并将它们提供给服务,但它无法做到这一点,那么服务应该抛出异常。使用异常是明智的,因为您试图将无效数据传递给服务。 (这并没有改变不应抛出异常来控制程序流这一事实,而是表明控制器实际上在向服务提供一些无效数据时搞砸了。)

      【讨论】:

        【解决方案5】:

        您是否考虑过使用Model View Presenter

        您的 UI 视图将实现接口,而这些接口将为您的服务所知。这样,您的服务可以调用 UI 以请求更多信息以执行其任务。这是一种dependency inversion (pdf)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-12-28
          • 2019-08-02
          • 2017-11-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多