【问题标题】:Should controller methods take arguments?控制器方法应该带参数吗?
【发布时间】:2012-10-17 09:21:12
【问题描述】:

鉴于视图上有文件选择小部件,并且控制器需要处理选择文件的事件,我是否应该编写控制器方法:

public void fileSelected(String filePath){
  //process filePath
}

public void fileSelected(){
  String filePath = view.getSelectedFilePath();
  //process filePath
}

第一种方法似乎在 C 和 V 之间引入了较少的耦合:C 不知道 C 在处理给定事件时究竟需要什么数据。

但它需要在V端创建很多类似于getSelectedFile的详细方法。

另一方面,在比示例更复杂的情况下,第二种方法可能会导致控制器方法混乱(要传递的数据比 filePath 多得多)。

根据您自己的经验,您更喜欢哪种方法?

【问题讨论】:

    标签: model-view-controller design-patterns conventions


    【解决方案1】:

    第一种方法是要走的路;

    public void fileSelected(String filePath){
      //process filePath
    }
    

    Controller 不应该关心View 的外观或实现方式。在创建/更新视图时,开发人员也更清楚地知道控制器中的操作想要什么。它也使方法重载更容易。

    不过,我真的不知道String filePath = view.getSelectedFilePath(); 会如何工作。我们是在谈论解析视图代码/标记吗?

    另一方面,在比示例更复杂的情况下,第二种方法可能会导致控制器方法混乱(要传递的数据比文件路径多得多)。

    那时您将创建一个 View Model 类(假设我们将其命名为 MyViewModel)来存储您需要发送的所有属性(可能是 10 个属性),然后将其传递到操作中:fileSelected(MyViewModel model) .这就是它的用途以及 asp.net mvc 中的 *ModelBinder 可以帮助您。

    【讨论】:

    • 回答您的问题:假设我们在文件系统中传递选定的文件路径(我更新了问题)。我在示例中选择了文件路径,以避免不必要地讨论 View 是否应该知道与我的问题无关的 File 等类。
    • 是的,你的论点是合理的。但是这种方法的另一个缺点是在更复杂的情况下方法签名混乱(不仅仅是要传递的一件事)。带有 10 个参数的控制器方法似乎不是特别干净。如何处理这个问题?
    • @PiotrSobczyk 我在File 课程上不太关注你,而 View 知道它。为什么 View 需要知道它?
    • @PiotrSobczyk 对于您的第二条评论:我将创建一个 ViewModel 类(假设我们将其命名为 MyViewModel)来存储我需要发送的所有属性(可能是 10 个属性),然后我会在行动中传递它:fileSelected(MyViewModel model)。这就是它的用途以及 asp.net mvc 中的 *ModelBinder 可以为您提供帮助。
    • 应该有一个专门的 ViewModel 用于每个 View-Controller 交互(例如,选择文件、提交表单、选中复选框等......可能有很多)还是应该只有一个 ViewModel 来处理所有这些交互(传递给每个控制器方法)?第一个选项可能会在更复杂的情况下导致类爆炸,第二个选项我们有一个代表所有视图状态的大对象 - 那么为什么不直接从视图中获取这些数据呢?总而言之,如果我决定走那条路,我更喜欢第一种选择。
    【解决方案2】:

    第一种方法是我最喜欢的。唯一的区别是我宁愿使用一个对象(如马里奥建议的那样)将参数传递给该方法。当您添加或删除某些参数时,这种方法的签名不会改变。更少的耦合总是好的:)

    还有一点: 如果您想尝试第二种解决方案,我建议使用 ViewFactory 从控制器中删除视图逻辑。

    【讨论】:

      【解决方案3】:

      我认为你需要退后一步来看待这个问题。

      不用担心它是如何进入的,而更关心验证错误引发

      明天,您的需求可能会发生变化,并要求您通过不同的架构方法获取信息。您可以将 [输入/输入对象] 的设置重构为基本控制器类 - 或用于不同控制器域的多个类之一。

      如果您专注于正确的验证,无论是在控制器内部(清理)还是在控制器外部(单元测试),那么您可以通过 duck typing 执行更彻底的解耦。

      【讨论】:

        【解决方案4】:

        我会采用第一种方法。它是可重用的并且可以分离关注点。即使以后获取filePath的方法发生变化,也不会影响你方法的功能。

        【讨论】:

          猜你喜欢
          • 2014-11-18
          • 2011-05-23
          • 2017-02-09
          • 1970-01-01
          • 1970-01-01
          • 2013-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多