2012-12-11 98 views
0

我的每個VB.NET項目都需要一組特定的自定義模塊。 例如:VB.NET:避免冗餘

modLog modGUID modControls modRegistry

在一些這些模塊中的我必須其他模塊幾個引用。

例如子modLog.WriteLog是這樣的:

Public Sub WriteLog(Byval uText As String) 

If globalclassOEM.IsOEMVersion Then 
    sPath = (some custom path) 
Else 
    sPath = (some default path) 
End if 

'Write log text to file 

End Sub 

這是非常愚蠢的,因爲有時我必須真正許多模塊和類添加到一個很小的項目,正好解決了一些依賴如上面和能夠使用我真正需要的幾個模塊。

是否有任何VB.NET最好的策略,以避免這種情況?

+0

是的,不要硬鏈接類,模塊和dll,如果他們獨立工作。 –

+0

不要使用全局靜態變量(模塊級別的變量),neverever。考慮使用依賴注入等技術。使用iterfaces來分離依賴關係。 – sloth

回答

3

,以避免此類問題的最好辦法,是避免這個問題)是指:圖書館應做什麼,他們是爲了做與不做的backgorund一些「額外工作」。在你的例子中:爲什麼WriteLog函數需要確定路徑以及調用者爲什麼不定義它並將它傳遞給日誌記錄函數/類?

如果你仍然想還是需要有這樣的功能,你可以通過定義接口繞過這個問題,然後把所有的接口集成到單個庫,而不是實現它們的類。這仍然需要用接口定義加載文件,但是當然你不需要加載任何實現它的類。

您還可以使用某種類型的插件系統,並創建你的日誌類(在這個例子中)時,它可能會嘗試動態加載所需的組件。如果他們不退出,班級將會沒有他們,否則它可以使用他們作爲假裝。雖然(imho)不會讓程序員的生活更輕鬆。

「最好」的方式(再次恕我直言)將是第一個建議。不要有「低級」庫引用其他庫。其他一切最有可能被認爲是設計缺陷而不是「解決方案」。

+0

非常感謝! – tmighty

1

我還沒有介紹VB.net中引用的一大堆,但是,纔有可能爲您與所有的基本模塊創建一個.dll。這意味着你可以參考這個.dll節省你的時間。對於可引用其他模塊的情有可原的情況,您可以手動編寫該模塊。

1

正如其他人所提到的,你永遠不希望直接包括在多個項目相同的代碼文件。這幾乎不是一個好主意,它總是會導致代碼混亂。如果你想要在兩個不同的項目之間共享代碼,那麼你需要創建第三個項目(一個類庫),它將包含通用代碼,然後其他兩個項目將只引用類庫。如果您可以將所有三個項目放在同一個解決方案中,然後您可以使用項目引用,那麼最好。但是,如果你不能這樣做,你仍然可以直接獲得該類庫項目輸出的DLL的文件引用。

其次,如果你真的想避免意大利麪條代碼,你應該認真考慮依賴注入(DI)。我和其他人建議這樣做的原因是,即使將公共代碼移動到類庫中以便它可以被多個項目共享,您仍然會遇到問題,即您的類庫充當「黑盒子「魔法般地爲您找出一切,並在各種情況下適當採取行動。從表面上看,這聽起來像是一個開發人員應該努力的好事情,但實際上,從長遠來看,這導致了糟糕的代碼。

例如,當您想在100個不同的項目中使用相同的日誌記錄類庫時,會發生什麼情況,它們都需要以稍微不同的方式進行日誌記錄。現在,你的類庫必須神奇地檢測出所有這些不同的情況並處理它們。例如,某些項目可能需要將日誌保存到不同的文件名。有些可能需要將日誌存儲到Windows事件日誌或數據庫。有些人可能需要在記錄錯誤時自動發送電子郵件通知。等等。你可以想象,隨着項目的增加和需求的增長,日誌類庫需要變得越來越複雜和混亂,這將不可避免地導致更多的錯誤。另一方面,DI則解決了所有這些問題,如果您堅持這種方法,那麼它本質上會迫使您編寫可重用的代碼。簡而言之,它只是意味着一個類的所有依賴關係都應該被注入(通過參數傳遞)到它中。換句話說,如果Logger類需要事件日誌或數據庫連接,它不應該創建或伸出並自己找到這些東西。相反,它應該只需要將這些依賴關係傳遞給它(通常在構造函數中)。使用DI您的例子可能是這個樣子:

Public Interface ILogFilePathFinder 
    Function GetPath() As String 
End Interface 

Public Class LogFilePathFinder 
    Implements ILogFilePathFinder 

    Public Sub New(isOemVersion As Boolean) 
     _isOemVersion = isOemVersion 
    End Sub 

    Private _isOemVersion As Boolean 

    Function GetPath() As String Implements ILogFilePathFinder.GetPath 
     If _isOemVersion Then 
      Return "C:\TestOem.log" 
     Else 
      Return "C:\Test.log" 
     End If 
    End Function 
End Class 

Public Interface ILogger 
    Sub WriteLog(ByVal text As String) 
End Interface 

Public Class FileLogger 
    Implements ILogger 

    Public Sub New(pathFinder As ILogFilePathFinder) 
     _pathFinder = pathFinder 
    End Sub 

    _pathFinder As ILogFilePathFinder 

    Public Sub WriteLog(text As String) Implements ILogger.WriteLog 
     Dim path As String = _pathFinder.GetPath() 
     ' Write text to file ... 
    End Sub 
End Class 

正如你所看到的,它需要額外的工作一點點,但是當你設計這樣的代碼,你將永遠不會後悔。您會注意到記錄器類會請求路徑查找器作爲依賴項。路徑查找器反過來請求OEM設置作爲依賴關係。所以,要使用它,你需要做這樣的事情:

Dim pathFinder As ILogFilePathFinder = New FileLogPathFinder(_OemSettings.IsOemVersion) ' Note, don't use a global to store the settings, always ask for them to be injected 
Dim logger As ILogger = New FileLogger(pathFinder) 
logger.WriteLog("test") 

現在,你可以很容易地在任何情況下重用所有這些代碼。例如,如果您有不同的項目需要使用不同的日誌文件路徑,他們仍然可以使用普通的FileLogger類,他們只需要各自實現它們自己的版本ILogFilePathFinder,然後將該自定義路徑查找器注入公共FileLogger。希望你看到如何以這種方式做到這一點非常有用和靈活。