3

現在、作成済みのクラスをどのように編成/構造化するべきかを理解するのに苦労しています。クラスは次のことを行います。

  1. コンストラクターでの入力として、ログのコレクションを受け取ります
  2. コンストラクターでは、ビジネス ロジックを実装する一連のアルゴリズムを使用して、ログを検証およびフィルター処理します。
  3. すべてのフィルタリングと検証が完了すると、有効でフィルタリングされたログのコレクション (リスト) が返されます。これは、UI でグラフィカルにユーザーに表示できます。

ここに私がやっていることを説明するいくつかの単純化されたコードがあります:

class FilteredCollection
{
  public FilteredCollection( SpecialArray<MyLog> myLog)
  {   
  // validate inputs
  // filter and validate logs in collection
  // in end, FilteredLogs is ready for access
  }
  Public List<MyLog> FilteredLogs{ get; private set;}

}

ただし、このコレクションにアクセスするには、次のことを行う必要があります。

var filteredCollection = new FilteredCollection( specialArrayInput );
//Example of accessing data
filteredCollection.FilteredLogs[5].MyLogData;

その他の重要な入力事項:

  1. これらのフィルタリングされたコレクションのうち、アプリケーションに存在するのは 1 つだけだと思います (したがって、それを静的クラスにする必要がありますか? それともシングルトンにする必要がありますか?)
  2. オブジェクトの作成におけるテスト容易性と柔軟性は重要です (おそらく、テスト容易性のためにこれをインスタンス化されたクラスにしておくべきでしょうか?)
  3. 実際の変数名は非常に長く、実際のデータに到達するまでに 60 ~ 80 文字かかるため、可能であればログの逆参照を簡素化したいと考えています。
  4. このクラスをシンプルに保つための私の試みは、このクラスの唯一の目的が、この検証済みデータのコレクションを作成することであるということです。

ここに「完璧な」解決策がないことはわかっていますが、この設計で自分のスキルを向上させようとしているので、そのためのアドバイスをいただければ幸いです。前もって感謝します。


編集:

すべての回答者のおかげで、Dynami Le-Savard と Heinzi の両方が、私が最終的に使用することになったアプローチ (拡張メソッド) を特定しました。最終的に MyLogsFilter 静的クラスを作成しました

namespace MyNamespace.BusinessLogic.Filtering
{
    public static class MyLogsFilter
    {
        public static IList<MyLog> Filter(this SpecialArray<MyLog> array)
        {
            // filter and validate logs in collection
            // in end, return filtered logs, as an enumerable
        }
    }
}

そして、コードでこれの読み取り専用コレクションを作成するには、次のようにします

IList<MyLog> filteredLogs = specialArrayInput.Filter(); 
ReadOnlyCollection<MyLog> readOnlyFilteredLogs = new ReadOnlyCollection<MyLog>(filteredLogs);
4

4 に答える 4

3

ログに対して次の 3 つのことを行っているようです。

  1. それらを検証する
  2. それらをフィルタリングし、
  3. それらにアクセスする

ログをコレクションに保存します。標準の List コレクションは、その内容を気にせず、LINQ を提供し、読み取り専用ラッパーでコレクションをロックできるため、適切です。

懸念事項を上記の 3 つのステップに分けることをお勧めします。

検討

interface ILog
{
  MarkAsValid(bool isValid);
  ... whatever data you need to access...
}

検証ロジックを別のインターフェイス クラスに配置する

interface ILogValidator
{
  Validate(ILog);
}

そして、さらに別のフィルタリングロジック

interface ILogFilter
{
  Accept(ILog);
}

次に、LINQ を使用すると、次のようになります。

List<MyLog> myLogs = GetInitialListOfLogsFromSomeExternalSystem();
myLogs.ForEach(x => MyLogValidator(x));
List<MyLog> myFilteredLogs = myLogs.Where(x => MyLogFilter(x));

関心の分離により、テストと保守性が大幅に向上します。そして、シングルトンから離れてください。テスト容易性を含む多くの理由から、それらは支持されていません。

于 2010-05-25T23:43:50.273 に答える
1

私の見方では、ビジネス ロジックをラップするコレクション クラスではなく、フィルタリングされたログのコレクションを返すメソッドを見ています。そのようです:

class SpecialArray<T>
{
     [...]

     public IEnumerable<T> Filter()
     {   
         // validate inputs
         // filter and validate logs in collection
         // in end, return filtered logs, as an enumerable
     }

     [...]
}

ただし、実際には、ログのフィルタリングを担当するビジネス ロジックをクラスから分離することを実際に望んでいるように見えますSpecialArray。おそらく、ロジックが実際には関係のない多くのことに触れているように感じたり、すべてに適用されるわけではないSpecialArrayためです。Filterの一般的なケースSpecialArray

その場合、私の提案は、ビジネスロジックを別の に分離することですnamespace。おそらく、ビジネスロジックを適用するために他のコンポーネントを使用および/または必要とするものであり、具体的には拡張メソッドとして機能を提供します。

namespace MyNamespace.Collections
{
    public class SpecialArray<T>
    {
        // Shenanigans
    }
}

namespace MyNamespace.BusinessLogic.Filtering
{
    public static class SpecialArrayExtensions
    {
        public static IEnumerable<T> Filter<T>(this SpecialArray<T> array)
        {
            // validate inputs
            // filter and validate logs in collection
            // in end, return filtered logs, as an enumerable
        }
    }
}

そして、そのビジネス ロジックを使用する必要がある場合は、次のようになります。

using MyNamespace.Collections; // to use SpecialArray
using MyNamespace.BusinessLogic.Filtering; // to use custom log filtering business logic
namespace MyNamespace
{
    public static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main2()
        {
            SpecialArray<Logs> logs;
            var filteredLogs = logs.Filter();
        }
    }
}
于 2010-05-26T01:26:32.697 に答える
1

いくつかの考え:

  • ご指摘のとおり、インスタンス化されたクラスを使用すると、テスト容易性が向上します。

  • シングルトンは、(A) システム全体でクラスのインスタンスが 1 つしかなく (B) アプリケーションの複数の異なる場所でオブジェクトを渡すことなくこのインスタンスにアクセスする必要がある場合に使用する必要があります。シングルトン パターン (または他の種類の「グローバル状態」) の不必要な使用は避ける必要があるため、(B) があなたのケースでも満たされない限り、ここではシングルトンを使用しません。

  • 単純な逆参照については、indexerの使用を検討してください。これにより、次のように記述できます。

    FilteredCollectionfilteredlogs = new FilteredCollection( secialArrayInput );
    //データへのアクセス例
    フィルタリングされたログ[5].MyLogData;
  • クラスがコンストラクターと結果にアクセスするためのフィールドのみで構成されている場合は、クラスを使用するよりも単純なメソッド使用する方が適切な場合があります。派手な方法でやりたい場合は、 の拡張メソッドとして記述して、次のようにアクセスできるようにすることができます。SpecialArray<MyLog>
    List<MyLog>filteredlogs = secialArrayInput.Filter();
    //データへのアクセス例
    フィルタリングされたログ[5].MyLogData;
于 2010-05-25T23:41:50.403 に答える
0

最終的なフィルター処理された配列の SpecialArray のインターフェイスを継承する場合は、インスタンス メンバーを持つ代わりに SpecialArray から派生します。これにより、次のことが可能になります
。filteredCollection[5].MyLogData; 等..

于 2010-05-25T23:45:58.600 に答える