6

我对函数中的长参数列表产生了一种自然的反感。虽然这在某种程度上是一件好事,但与代码重复或由于“手动内联”导致的冗长函数相比,有时长参数列表是两个弊端中较小的一个。至少让这些怪物中的一些人可读的好方法是什么?例如:

SomeClass[string] someFunction(SomeClass!(TemplateParam) foo, 
    string[][string] someAA, uint[] dataToProcess, SomeEnumType flag) {
    // Do stuff.
}

这在可读性方面得分并不高,但在很多情况下四个参数是相当合理的。

4

5 回答 5

10

对于这种情况,我倾向于这样格式化:

SomeClass[string] someFunction(
    SomeClass!(TemplateParam) foo, 
    string[][string] someAA,
    uint[] dataToProcess,
    SomeEnumType flag
)
{
    // Do stuff.
}
于 2010-01-28T17:48:55.917 回答
3
  • 为了可读性 - 将每个参数放在新行上
  • 为了可用性和更好的 API 设计 - 将相关参数分组到新类中,从而缩短参数的数量。
于 2010-01-28T18:01:41.707 回答
1

我在(主要是内部)类(或结构)中重新组合参数以避免广泛的函数声明/调用

于 2010-01-28T17:51:38.340 回答
1

可以引入参数对象:

class ParameterObject {
    public final SomeClass!(TemplateParam) foo; 
    public final string[][string] someAA;
    public final uint[] dataToProcess;
    public final SomeEnumType flag;

    private ParameterObject(
       SomeClass!(TemplateParam) foo, 
       string[][string] someAA,
       uint[] dataToProcess,
       SomeEnumType flag) {
       this.foo = foo;
       this.someAA = someAA;
       this.dataToProcess = dataToProcess;
       this.flag = flag;
    }

    private static class Builder {
        public SomeClass!(TemplateParam) foo; 
        public string[][string] someAA;
        public uint[] dataToProcess;
        public SomeEnumType flag;

        public Builder foo(SomeClass!(TemplateParam) foo) {
            this.foo = foo;
            return this;
        }

        public Builder someAA(string[][string] someAA) {
            this.someAA = someAA;
            return this;
        }

        public Builder dataToProcess(uint[] dataToProcess) {
            this.dataToProcess = dataToProcess;
            return this;
        }

        public Builder flag(SomeEnumType flag) {
            this.flag = flag;
            return this;
        }

        public ParameterObject build() {
            if (null == foo) throw Exception("init foo!");
            if (null == someAA) throw Exception("init someAA!");
            if (null == dataToProcess) throw Exception("init dataToProcess!");
            if (null == flag) throw Exception("init flag!");
            return new ParameterObject(foo, someAA, dataToProcess, flag);
        }
    }
}

现在,您的电话将如下所示:

SomeClass[string] myValue = 
   someFunction(
      new ParameterObject.Build().
          foo(myFoo).
          someAA(myAA).
          dataToProcess(myData).
          flag(false).
          build()
   );

在允许创建内联映射的语言中处理类似情况要容易得多:

someFunction(
    Map.new(
        foo => myFoo,
        someAA => myAA,
        dataToProcess => myData,
        flag => false
    )

限定符final意味着只能从类的构造函数中设置字段。类前面的限定符 static意味着该类不绑定到它的外部类,即不能访问/改变它的字段。

于 2010-01-28T18:13:38.337 回答
0

我喜欢 Aaron 的回复,只是给每个参数一个换行符。

当这变得太多时,是时候进行一些重构了。

如果您仍然需要这么多参数,请改为传入一个包装您的属性的类。然后,您还可以轻松地将默认参数添加到您的方法中,而不会搞砸您的签名。

于 2010-01-28T17:54:40.617 回答