2011-08-31 28 views
7

我們在我們的領域模型你會怎樣滑稽的長期進攻大的構造,如此之大,智能感知放棄試圖將其全部展示給你幾個對象......重構大型構造

提示一個類型有50左右的參數,主要是數值類型,幾種參考類型:

public class MyLegacyType 
{ 
    public MyLegacyType(int a1, int a2, int a3, ... int a50) // etc 
    { 
    } 
} 

我現在就說它,這種類型不能改變。類型本身邏輯上代表了一個實體,這恰好是財產沉重的。構造這種類型的調用者提供來自多個來源的大部分參數,儘管有些是默認的。也許有一種模式來爲施工提供來源而不是結果。

但是,可以改變的是如何創建類型。目前我們有部分代碼遭受:

一個直接的答案是利用可選參數的默認值和命名參數來幫助合併。我們在其他類型的某種程度上這樣做,工作好。

但是,它感覺好像是完全重構的一半。

另一個顯而易見的解決方案是使用具有用於構造函數參數的屬性的容器類型來減少構造函數參數。這很好地整理了構造函數,並允許您在容器中嵌入默認值,但本質上會將問題轉移到另一種類型,並可能與可選/命名參數用法相同。

還有Fluent構造函數的概念......每個屬性(WithIntA,WithIntB)或容器類型(WithTheseInts(IntContainer c))的基礎上。就我個人而言,我喜歡從調用方來的這種方法,但是對於一個大型的方法來說,它會變得羅嗦,並且感覺好像我剛剛提出了一個問題而不是解決問題。

我的問題,如果有一個埋在這個混亂,是:是這些可行的重構策略的問題?請有一些相關的經驗,陷阱或批評有所迴應的任何答案。我傾向於流利的東西,因爲我認爲它看起來很酷,而且非常易讀,並且合併友好。

我感覺好像我錯過了構造函數重構的聖盃 - 所以我願意接受建議。當然,這也可能只是一個不幸的和不可避免的副作用,首先有這麼多屬性的類型......

+1

我會用你的第二種方法(容器類型具有過去是構造函數參數的屬性)來選擇構造函數參數。流利的接口都不錯,但能有點混亂,如果你有鏈很多方法調用IMO –

回答

12

顯然我們這裏沒有太多的上下文,但是在50多個參數中我的解釋是這個班做得太多了,太複雜了。我首先想方設法將塊分成更簡單,更集中的類型 - 然後將每個這些概念的實例封裝到複合類中。因此,它變成:

public MyLegacyType(SomeConcept foo, AnotherConcept bar, ...) 
{ 
} 

其中僅需要編排概念之間邏輯保持在MyLegacyType(任何特定於SomeConcept邏輯去那裏,等等)。

這與您的「使用具有過去構造函數參數屬性的容器類型的構造函數參數減少」不同,因爲我們從根本上重構邏輯 - 不僅僅是使用對象來替換構造函數參數。

+0

我看着這裏的組成,但在本質上類型做一個任務 - 這恰好是屬性的實體的表示-重。正如你所說,那是因爲缺乏語境,我會看看我是否可以用這個來修改我的問題。 –

+0

實際上,考慮到這個想法,如果你打開它的頭並從調用者的上下文中編寫一個項目,可以更改構造函數參數以適應。在一個示例中,項目是從提供所有屬性的代碼的DAL區域構建的,而不失敗。這些可以包裝在提供所有屬性的提供類型。其他調用者要求特定的假設,其中某些屬性總是默認的,這些可以使用不同的構造器容器來隱藏這個事實。我相信肯定有這樣的模式。 –

4

我會去容器類型和使用C#4.0的直接屬性分配。通過這種方式,人們可以很容易地在結果類型上使用Intellisense,同時仍然保持與原始類型的不錯的解耦。

例如:

public class MyLegacyType 
{ 
    public MyLegacyType(MyConfiguration configuration) // etc 
    { 
     // ... 
    } 
} 

public class MyConfiguration 
{ 
    public int Value1 { get; set; } 
    public int Value2 { get; set; } 
    // ... 
} 

然後:

var myInstance = new MyLegacyType(new MyConfiguration 
{ 
    Value1 = 123, 
    Value2 = 456 
}); 
1

有一兩件事,我不知道你的問題,那就是爲什麼你要在構造函數中所有這些參數?你使用構造函數代碼中的所有參數嗎?您對智能感知的問題可能來自單一方法的參數過多。在單一類型上有許多字段/屬性不會導致任何問題。

看來你已經看到了管理args來數一些方法,但如果你能解釋一下爲什麼你需要獲得所有這些在構造函數中,我們可以認爲這個框外。可能有些事要看。

+0

構造函數中所有參數的原因之一,這是目前最糟糕的情況,也是遺留編碼風格的結果,因此DAL代碼可以從讀者構造對象。我認爲沒有其他任何「足夠好」的理由,我認爲它只是不重構代碼的人的受害者,並且只是追加它。大多數屬性只是從構造函數轉換到內部字段。 –

+0

爲什麼不使用屬性來填充DAL中的實體字段?或者,如果你需要它是在一個C#語句,你可以使用對象初始化語法在C#中 - '新的類名{PROP1 =值,PROP2 =值,...}' – Iravanchi

+0

並非所有屬性暴露setter方法。我認爲這樣做的唯一理由是因爲它總是這樣做 - 沒有人自己改變風格。實際上,我們最糟糕的類型之一是DAL專門使用的,唯一的其他地方就是我們的測試項目。 –