2010-01-28 49 views
3

我已經開發了一個自然規避函數中的長參數列表。雖然這在某種程度上是一件好事,但與「代碼複製」相比,由於「手動內聯」,有時候長參數列表是兩個惡意中的較小者。至少使這些怪物中的某些人可讀的好方法是什麼?例如:如何使長參數列表可讀?

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

這在可讀性範圍內得分不高,但在很多情況下四個參數是相當合理的。

回答

7

對於這種情況,我傾向於像這樣進行格式化:

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

我同意。對於非常長的參數列表,每行一個參數也有它自己的問題....但是我從來沒有看到任何其他解決方案只要您需要長參數列表就可以更好地工作。當我這樣做時,我也傾向於對齊類型和參數名稱......可能會使它稍微更具可讀性。 – SuperMagic 2010-01-28 17:52:04

+0

此外,如果您的參數列表比這長得多,那麼這是一個很好的跡象表明某些重構是有序的。 – Aaron 2015-03-13 14:26:44

1

我重新組合在一個(主要是內)類(或結構),以避免廣泛的函數聲明的參數/調用

+0

我也聽說過這樣做的人,但我不太喜歡創建一個新的類或結構來處理函數參數的想法。如果相同的參數列表(因此,相同的參數類/結構)被多次使用,我可能會更好地與這個想法。我並不是說這不是一個好主意,只是我個人不喜歡它。 – Aaron 2010-01-28 18:00:12

+0

當我使用第三方庫和我跌入了許多參數(我記得有一個17!)與布爾標誌的十一種方法,我想這個怪人方法的創造者不得不使用一個類來重組它們中的一個或更多課程! – Guillaume 2010-01-29 08:56:25

0

我喜歡亞倫的回覆,只是給每個參數添加一個換行符。

當它變得太多的時候,是時候重構一下了。

如果你仍然需要這麼多參數,切換到傳入一個包裝你的屬性的類,而不是。然後,您可以輕鬆添加默認參數到您的方法中,而無需搞亂簽名。

2
  • 的可讀性的原因 - 把每一個參數上新的生產線
  • 可用性和更好的DESGIN API的目的 - 將相關參數到新類,從而縮短參數的數目。
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意味着該類不與其外部類相關聯,即不能訪問/變更其字段。

+0

這是荒謬的詳細。 – dsimcha 2010-01-30 01:42:35

+0

dsimcha,你是絕對正確的。在像Java這樣的語言中,這種解決方案的唯一好處就是,如果你構建一個API並且你不想公開具有三個以上參數的構造函數或方法,這可能是一件好事。 API消費者將受益匪淺 – 2010-01-31 13:12:01

+1

請不要在原始表達式的末尾留下點,這很奇怪。以點開始的行清楚地表明它是來自上一行的繼續呼叫。 – 2017-11-24 18:09:48