2013-07-18 75 views
4

我最近(幾個月前)更改了作業並繼承了一個代碼庫,它違反了SOLID原則中的每一個原則,儘可能多次。看起來編寫這些代碼的人似乎決定詳細研究每一個好的編碼實踐,並儘可能經常地,最激進地違反它們。如何安全地將靜態類轉換爲C#中的實例化類#

我是該產品的唯一開發人員 - 組織中沒有人知道代碼和代碼庫太大又複雜,無法完全重寫。我正在研究可以使代碼庫靈活而強大的最高價值變化。放棄這種產品也不是一種選擇。

產品中所有問題的根源都來自於一組作爲核心業務邏輯數據結構的類。有很多的這些類的問題,但什麼我真正感興趣的是:

public static class NetCollection 
{ 
    private static Logger LogFile { get { return Logger.GetMethodLogger(2); } } 
    // Declare local variables. 
    private static Dictionary<string, NetObject> netObjectHashTable; 
    private static Dictionary<string, NetTitle> titlePropertyHashTable; 
    private static Dictionary<string, NetObject> referenceDataHashTable; 
    private static Dictionary<int, SortedDictionary<string, int>> picklistHashTable; 

    public static IEnumerable<NetObject> NetObjects 
    { 
     get 
     { 
      return netObjectHashTable.Values; 
     } 
    } 

    static NetCollection() 
    { 
     netObjectHashTable = new Dictionary<string, NetObject>(); 
     titlePropertyHashTable = new Dictionary<string, NetTitle>(); 
     referenceDataHashTable = new Dictionary<string, NetObject>(); 
     picklistHashTable = new Dictionary<int, SortedDictionary<string, int>>(); 
    } 

    public static void AddNetObject(NetObject newObject) 
    { 
     if (newObject == null) 
      return; 
     if (newObject.TitleType == "Reference Data") 
     { 
      // Check if hash table contains key 
      if (!referenceDataHashTable.ContainsKey(newObject.ID.ToString())) 
      { 
       referenceDataHashTable.Add(newObject.ID.ToString(), newObject); 
      } 
     } 
     else 
     { 
      // Check if hash table contains key 
      if (!netObjectHashTable.ContainsKey(newObject.ID.ToString())) 
      { 
       netObjectHashTable.Add(newObject.ID.ToString(), newObject); 
      } 
     } 
    } 
} 

我已經剪掉不少其他方法從這個類爲簡潔起見。如你所見,圍繞這個類有大量的問題(在靜態類中存儲狀態是一種巨大的代碼異味 - 在你的類中編寫你的整個應用程序只是瘋狂)。

我目前的意圖是將這個類重構成一個合適的單例類(最終成爲一個普通類,這樣我就可以讓用戶同時打開多個文檔)。

我應該這樣做嗎?

進行此更改最大的風險是什麼?我是否可以採取任何方法來降低進行此變更的風險?

+0

從整個班級中刪除靜態關鍵字並重建項目。你會得到錯誤。修復這些,它是安全的。 – Ehsan

+0

我沒有任何提示,但我不禁注意到你的頭像和你的問題一樣。 –

+1

我的默認頭像是我的gravatar圖片,與本網站無關。所以我改變了我的頭像,就是這個代碼。 – Stephen

回答

1

如果您對應用程序中這種類型的流式無所知,這是一項危險的任務。但如果你真的需要做,沒有,可能,打破一切,我會這樣做:

知道我需要的是文件之間的明顯分裂,我知道(這是時間證明),這種類型爲單個文檔工作,讓我們添加文檔切片。

假設DocumentName屬性,我們可以想想類似的信息(例如):

public static void AddNetObject(string documentName, NetObject newObject) 
{ 
    .... 
} 

使各領域靜:

//NO STATIC 
    ... 
    private Logger LogFile { get { return Logger.GetMethodLogger(2); } } 
    private Dictionary<string, NetObject> netObjectHashTable; 
    private Dictionary<string, NetTitle> titlePropertyHashTable; 
    private Dictionary<string, NetObject> referenceDataHashTable; 
    private Dictionary<int, SortedDictionary<string, int>> picklistHashTable; 

將它們轉換爲內部

private class NetDocument { 
     public string DocumentName {get;set;} //DEFINE DOCUMENT IT RELATED TO ! 
     ... 
     private Logger LogFile { get { return Logger.GetMethodLogger(2); } } 
     private Dictionary<string, NetObject> netObjectHashTable; 
     .... 

    } 

因此,您可以在單個文檔之間創建具體的隔離並與其相關數據。

主類內部之後喲可以有:

public static class NetCollection 
{ 
    ... 

    //Key: document name 
    //Value: NetDocument data 
    private Dictionary<string, NetDocument> documents = new .... 
} 

這只是一個一般的想法(草圖),你肯定需要改變,以適應您的需求

+0

我非常喜歡這個解決方案。如果我理解正確,我可以使用當前的靜態類作爲內部實例類的包裝器,因此不會破壞現有代碼,同時還可以進行可測試性和擴展。 – Stephen

+1

請假(只要有可能)的公共方法,所以外面的方法看到你的類型裏面,就像。這將幫助你不要更改所有的調用者代碼,因此可能會在class * internal *實現中造成混亂和f f。我再說一遍,這是一個指導,要走的路,但你會遇到問題(可以保留所有公共方法,一些類型的可見性問題,100多個其他的東西..),所以繼續一個簡單的想法:不要觸摸別人看到的內容,並改變類型的內部*行爲。因此,所有可用的呼叫者將繼續以同樣的方式呼叫它,就像以前一樣。 – Tigran

0

你能圍繞一個靜態工廠類來包裝它嗎?把你認爲你需要的所有東西都作爲一個單例來使用,並根據需要保持某些靜態的東西?它會解決一些問題,並給你一些靈活性。

+0

我不確定我會關注。你能提供一些示例代碼來說明你的觀點嗎? – Stephen

+0

查看此鏈接以獲取更好的示例http://my.safaribooksonline.com/book/programming/java/9780137150021/creating-and-destroying-objects/ch02lev1sec1 它應該有助於解釋我所做的更好。 –

4

是的,轉換爲單身人士似乎是一個很好的第一步。它仍然不是線程安全的,但它是一個開始。然後,您可以將其從真實單身更改爲一個允許單獨的實例被構造,但也具有與單身相同的方式的「默認」實例。 (當然,您可以將「實例持有者」分爲單獨的類)。這將允許您開始編寫每次都以新實例開始的可測試代碼。

之後,您可以開始引入依賴注入,以便每個需要訪問同一實例的類都可以獲取它並刪除「默認」實例。

當然,如果你可以減少需要訪問同一個實例的類的數量,那也會更好。

對於線程,您需要鎖定每種方法,或使用ConcurrentDictionary

+0

這是我要採取的方法的路線。感謝關於線程的提醒。目前還不可能實現多線程(由於繼承代碼和第三方非線程安全組件的結合),但是我希望在某些時候增加併發性,因爲在那裏有一些繁重的可並行CPU工作。 – Stephen

0

static類和單例之間沒有真正的區別。是的,它的實施方式不同,但你有相同的問題(只是爲了不需要採取行動)。

如果你能夠去「真實」的實例,那就去做吧。但只是重構辛格爾頓,因爲林特不抱怨是不是去恕我直言的方式。

+0

在我看來,我之所以首先考慮單身路徑的原因是它對所有相關代碼的影響最小。不得不直接管理實例將是一場噩夢。 – Stephen

相關問題