0

私の各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の最善の戦術はありますか?

4

3 に答える 3

3

このような問題を回避する最善の方法は、その問題を回避することです;)手段:図書館は、本来の目的を正確に実行する必要があり、バックグラウンドで「余分な作業」を実行しないでください。あなたの例では:WriteLog関数がパスを決定する必要があるのはなぜですか?また、呼び出し元がパスを定義してロギング関数/クラスに渡さないのはなぜですか?

それでもそのような関数が必要な場合は、インターフェイスを定義して問題を回避し、すべてのインターフェイスを単一のライブラリに配置できますが、それらを実装するクラスは配置できません。それでも、インターフェース定義を含むファイルをロードする必要がありますが、もちろん、それを実装するクラスをロードする必要はありません。

また、ある種のプラグインシステムを使用する場合があり、ロギングクラス(この例では)が作成されると、必要なアセンブリを動的にロードしようとする場合があります。それらが終了しない場合、クラスはそれらなしで終了します。そうでない場合は、ふりをしてそれらを使用できます。ただし、プログラマーの生活を楽にすることはできません(imho)。

「最良の」方法(再びimho)が最初の提案になります。他のライブラリを参照する「低レベル」ライブラリはありません。他のすべては、「解決策」ではなく、設計上の欠陥である可能性が最も高いと見なされます。

于 2012-12-11T08:08:43.330 に答える
1

VB.netでの参照のヒープ全体については説明していませんが、すべての基本モジュールを使用して.dllを作成することは可能でしょうか。これは、この.dllを参照して時間を節約できることを意味します。他のモジュールへの参照がある酌量すべき状況では、そのモジュールを手動で作成することができます。

于 2012-12-11T07:56:35.723 に答える
1

他の人がほのめかしているように、同じコードファイルを複数のプロジェクトに直接含めたくはありません。これは決して良い考えではなく、常に厄介なコードにつながります。2つの異なるプロジェクト間で共有する共通コードがある場合は、共通コードを含む3番目のプロジェクト(クラスライブラリ)を作成する必要があります。その後、他の2つのプロジェクトはクラスライブラリを参照するだけです。3つのプロジェクトすべてを同じソリューションに含めることができ、プロジェクト参照を使用できる場合に最適です。ただし、それができない場合でも、そのクラスライブラリプロジェクトによって出力される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ます。うまくいけば、この方法でそれを行うことが非常に便利で柔軟になり得ることがわかります。

于 2012-12-11T10:03:41.700 に答える