【问题标题】:What are better ways to create a method that takes many arguments? (10+?)有什么更好的方法来创建一个需要很多参数的方法? (10+?)
【发布时间】:2012-03-30 14:38:52
【问题描述】:

我在看一个开发人员的一些代码,差点哭了。在方法定义中有 12 个参数。根据我的经验..这不好。如果是我,我会送来某种物品。

是否有另一种/更优选的方法来做到这一点(换句话说,解决这个问题的最佳方法是什么并解释原因)?

public long Save (
    String today, 
    String name, 
    String desc, 
    int ID, 
    String otherNm, 
    DateTime dt, 
    int status, 
    String periodID, 
    String otherDt, 
    String submittedDt
)

忽略我可怜的变量名 - 它们是示例

【问题讨论】:

  • 参数是否以某种方式相关?如果是这样,则将它们分组到描述语义的对象中。希望对您有所帮助。
  • 我认为这是一个合理的问题,为什么有两票可以关闭它?

标签: language-agnostic coding-style


【解决方案1】:

这很大程度上取决于语言。

在没有编译时类型检查的语言(例如 python、javascript 等)中,您应该使用 关键字参数(在 python 中很常见:您可以像作为参数传入的字典一样访问它们)或 objects/dictionaries 作为参数手动传入(在 javascript 中很常见)。

但是,对于某些具有编译时类型检查的语言,您描述的“参数地狱”有时是“正确的做事方式”,因为使用对象会混淆类型检查器的语义。那么解决方案就是使用一种更好的语言和编译时类型检查,它允许对象的模式匹配作为参数。

【讨论】:

    【解决方案2】:

    是的,使用对象。此外,如果该函数需要所有这些信息,它可能做得太多,因此请使用较小的函数。

    【讨论】:

      【解决方案3】:

      使用对象。

      class User { ... }
      User user = ...
      Save(user);
      

      它的决定为添加新参数提供了简单的方法。

      【讨论】:

        【解决方案4】:

        这取决于函数的复杂程度。如果它对这些参数中的每一个都做了一些不平凡的事情,那么它可能应该被拆分。如果它只是通过它们,它们可能应该被收集在一个对象中。但如果它只是在表中创建一行,那也没什么大不了的。如果您的语言支持关键字参数,那就没那么重要了。

        【讨论】:

          【解决方案5】:

          我想您遇到的问题是能够查看方法调用并知道哪个参数正在接收什么值。这在像 Java 这样的语言中是一个有害的问题,它缺少诸如关键字参数或 JSON 散列之类的东西来传递命名参数。

          在这种情况下,Builder pattern 是一个有用的解决方案。它有更多的对象,总共三个,但会为您描述的问题带来更易于理解的代码。所以本例中的三个对象将是这样的:

          1. 事物:有状态的实体,通常是不可变的(即只有 getter)
          2. ThingBuilder:工厂类,创建一个 Thing 实体并设置其值。
          3. ThingDAO:对于使用 Builder 模式不是必需的,但可以解决您的问题。

          互动

          /* 
          ThingBuilder is a static inner class of Thing, where each of its 
          "set" method calls returns the ThingBuilder instance being worked with
          while the final "build()" call returns the instantiated Thing instance.
          */
          Thing thing = Thing.createBuilder().
                          .setToday("2012/04/01")
                          .setName("Example")
                          // ...etc...
                          .build();
          
          // the Thing instance as get methods for each property
          thing.getName();
          
          // get your reference to thingDAO however it's done
          thingDAO.save(thing);
          

          结果是你得到了命名参数和一个不可变的实例。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-02-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-08-30
            相关资源
            最近更新 更多