2016-05-30 56 views
0

我正試圖在工作中的一個應用程序中重寫非常難看的類。在我們的一個類中,有數百行代碼確保某些類的初始化和重新初始化。目前,這是通過可怕的強力-y方式完成的,在這種方式中,您編寫init代碼並手動將其複製到re-init部分(因爲它們非常相似)。延遲或可重複初始化的最優雅方式

因此,我開始將它重寫爲代表列表的形式,然後在兩個地方都使用參數調用它們(bool isReinit)。然後我注意到大多數代表也是相同的,因爲90%的類的初始化過程是相同的。這意味着我應該能夠創建一些默認的初始化函數來大幅簡化代碼。目前,我創造了這樣的事情:

https://dotnetfiddle.net/RVS5UT

我還創建類CustomInitializer它實現IInitializer,只需要一個Func鍵作爲參數,並運行它的初始化,對於初始化是很多不同的情況。

現在,這個簡化和匿名的工作代碼塊,但它的工作原理。問題是整個方法非常尷尬,構造函數簽名很糟糕。有什麼方法可以簡化嗎?我找不到可以幫助我的任何模式或方法?任何邁向更好代碼的步驟都是值得歡迎的,也許我只是錯過了一些東西。

還有一個問題。我想出的一個解決方案是將屬性對(var1a + var1b,var2a + var2b,..)存儲在一個對象中,並將其直接傳遞給Initialize方法。但是這意味着移動這些屬性,目前遺憾的是這些屬性是不可能的,因爲這個文件有超過18K行,並且由於重構了一個方法(即使它很長),代碼審查人員會因爲更改第三個而殺了我。我需要將目標屬性(var1a,var1b,var2a,..)留在現在的位置。這也可能意味着沒有優雅的方式來解決這個問題。

我使用.NET 4.0,C#5.0

編輯:我要初始化的類型沒有接入(另一種愚蠢的捕撈)

感謝您的幫助。

+0

爲什麼不簡單地用新的實例替換舊實例?重新初始化可以通過簡單地引用新實例來完成。無論如何,一個如此之大的班級沒有任何意義。所有這些屬性之間的凝聚力是什麼?這個班級的單一指數是多少?它有什麼行爲?重新初始化這個類是什麼意思?有時最好解釋最初的問題,並將所有當前的解決方案部分從圖片中刪除。 – plalx

回答

1

文件已超過18K線

哇,看起來像一個很大的樂趣。

試圖改善它是絕對好的。相信我,不管你的同事怎麼想,除了這個代碼不需要進化,沒有別的事可做。

但是,在我看來,你走在複雜性的道路上,試圖做到DRY而不是試圖表達。使用StandardInitializer和CustomInitializer管理lambda表達式的想法非常複雜。一個類的初始化應該在它負責初始化的類中。如果某些行爲真的被共享,他們可能共享一個基類或一個協作類。

我建議你在Working Effectively With Legacy Code的這個討論。正如你將會看到並且可能已經知道的那樣,第一個關鍵點是要進行測試。 請不要嘗試在沒有測試工具的情況下重構這樣的課程。否則,你會引入迴歸,你會感到沮喪,並且你的同事會對他們的願景感到欣慰,即在沒有破壞一切的情況下,任何事情都無法在這裏完成。

不要忘記,如果測試很難創建,那是因爲代碼不好,不是因爲測試昂貴。錯誤代碼很昂貴。

經過一些測試保護你,試着從責任和生命週期的角度思考。例如,在WPF應用程序中,具有「可初始化」的ViewModel是一個常見問題,因爲它們會執行一些異步Web服務調用來初始化它們自己。

在這種情況下,具有給定ViewModel生命週期責任的對象也有責任對其進行初始化。如果管理幾個Initializable視圖模型,那麼這種代碼是罰款:

foreach (var initializable in initializables) 
{ 
    initializable.Initialize(); 
} 

但是,請你選擇的任何解決方案,保持初始化並重新初始化(明確分開,如果他們有共同的東西,讓他們打電話給一個內部共享功能)。這是一個非常糟糕的主意,寫這樣的東西:

init.Initialize(true); 

它明確指出您的初始化函數的行爲將根據一個布爾值的改變。如果你有兩種行爲,你應該有兩個功能,命名清晰。

+0

我沒有提到(我認爲這不重要),初始化的對象是由COM庫構造的,所以我無法訪問該類,也無法將init添加到類本身。我需要創建一些鏡像輔助類,並將其保存在那裏或作爲擴展方法。也沒有測試,可悲的是不會有測試。 。所以我故意儘量保持變化儘可能小(因爲迴歸)。 –

+0

忘記感謝您的幫助。 。謝謝 –