7

私はいくつかの研究開発作業を行っているので、デザインパターンを模索しています。私は最近、仕様パターンを読んでいて、この素晴らしい記事を参照されました。

私はコードの単純さと清潔さに興味をそそられましたが、他の手法を使用して同じ清潔さを実装することといくつかの比較を描き始めました。

サービス層の次のインターフェイスコントラクトを検討してください。

public interface IFooDataService
{
   ICollection<Foo> GetFoosBySpecification(Specification<Foo> specification);
   ICollection<Foo> GetFooByPredicate(Func<Foo,bool> predicate);
   ICollection<Foo> GetFooBySearchArgs(FooSearchArgs searchArgs);
}

だから、いくつかの最初のポイント:

  • 3つすべてがFooオブジェクトのコレクションを返します
  • 3つすべてが1つの引数を取る
  • 仕様方法は、特定の要件へのアクセスを制限します
  • 述語法には基本的に制限はありません
  • Search argsメソッドは、特定の要件へのアクセスを制限します

さて、実装に移りましょう。

public ICollection<Foo> GetFoosBySpecification(Specification<Foo> specification)
{
    return fooDataRepository
            .Find()
            .Where(f => specification.IsSatisfiedBy(f))
            .ToList();
}

public ICollection<Foo> GetFooByPredicate(Func<Foo, bool> predicate)
{
    return fooDataRepository
            .Find()
            .Where(predicate)
            .ToList();
}

public ICollection<Foo> GetFooBySearchArgs(FooSearchArgs searchArgs)
{
    return fooDataRepository
            .Find()
            .WhereMeetsSearchCriteria(searchArgs)
            .ToList();
}

実装のポイント:

  • 3つすべての実装は非常に簡単です(1行の連鎖コード)
  • フィルタリングされた仕様と検索引数は外部に実装されています。
  • Search argsメソッドは、単にIEnumerable拡張メソッドを使用してargsを検査します

そうは言っても、上記の3つのテクニックのいずれかをどのような条件下で使用しますか?

仕様パターンについての私の考え:

  • ビジネス/ドメイン要件を再利用可能なコンポーネントに分離するという点で優れています
  • 非常に読みやすく、コードが英語を話せるようにします
  • かなりの量のコードが含まれています(インターフェース、抽象クラス)。これを使用する場合は、抽象化を共通のアセンブリに配置します(したがって、ソリューションに静的ファイルがたくさんありません)。
  • サービス層ではなく、仕様を変更するだけで要件を簡単に変更できます。
  • ドメインロジックの最高のテスト容易性(仕様)

拡張メソッド(パイプとフィルター)に関する私の考え:

  • 論理的には「重量があります」が、それでも同じ単純さをもたらします。
  • クエリロジックをサービスレイヤーから静的メソッドに分離する
  • それでも、ある種の「反映」が必要です(提供された検索引数を検査し、クエリを構築します)
  • 特定のビジネス要件(特定のシナリオで便利)を考慮せずに、最初にアーキテクチャ(リポジトリ、サービスレイヤー)をコーディングできます

述語メソッドに関する私の考え:

  • クエリをきめ細かく制御する必要がある場合に使用できます。
  • 仕様がそれをやり過ぎているかもしれない小さなプロジェクトに適しています

私の最後の考えの論理は、ビジネス要件が事前にわかっているが、時間の経過とともに変化する可能性がある複雑なビジネスアプリケーションで作業している場合は、仕様パターンを使用するというものです。

しかし、「スタートアップ」であるアプリケーションの場合、つまり要件は時間の経過とともに進化し、複雑な検証なしでデータを取得する方法が多数ある場合は、パイプとフィルターのメソッドを使用します。

あなたの考えは何ですか?上記の方法のいずれかで問題が発生したことがありますか?何かお勧めはありますか?

新しいプロジェクトを開始しようとしているので、これらのタイプの考慮事項は重要です。

助けてくれてありがとう。

仕様パターンを明確にするための編集

これが仕様パターンの同じ使用法です。

Specification<Foo> someSpec; // Specification is an abstract class, implementing ISpecification<TEntity> members (And, Or, Not, IsSatisfiedBy).
someSpec = new AllFoosMustHaveABarSpecification(); // Simple class which inherits from Specification<Foo> class, overriding abstract method "IsSatisfiedBy" - which provides the actual business logic.    
ICollection<Foo> foos = fooDataService.GetFoosBySpecification(someSpec);
4

2 に答える 2

2

私の小さな経験から:

  1. ユーザーの要件は常に変化しますが、上司が常にその変更を許可する理由がわかりません。したがって、仕様に+1
  2. ここのプログラマーは「知識労働者」というよりは「肉体労働者」に近い。あなたが知っている..一日中タイプする人。仕様を使用することで、誰もが「タイプ」することを確認できます。これは、私のプロジェクトの性質によってサポートされています。同じ目的のために、多くの異なる実装が必要です。理由を聞かないでください。
  3. 最高のモジュール性と柔軟性、そしてもちろんテスト容易性を提供する設計パターンを使用してください。ここにちょっとした話があります。
    ある晴れた日に、私の友人は、X を計算する 32 種類の方法を計算できるようにするクラスを作成したことを教えてくれました。彼はすでにそれをすべて実装しています。ほほう、それはとても英雄的なプログラミングだったと思います。彼は真夜中にそれをするのに数週間を費やしました。彼は自分が優れたプログラマーであると信じていたので、誰もが彼の傑作を使うように主張しました。
    当時、私たちは単体テストを気にしていなかったので、彼の傑作を使用しました。それから何が起こったのですか?コードは常にクラッシュしました。その時から、単体テストとモジュール性がいかに重要であるかを実感しました。
于 2010-08-27T02:42:50.563 に答える
0

まず、他の 2 つのプライベート実装の詳細としてのみ使用される場合でも、Predicate メソッドを記述します。

private ICollection<Foo> GetFoosBySpecification(Specification<Foo> spec) 
{ 
    return GetFooByPredicate(f => spec.IsSatisfiedBy(f));
} 

検索引数関数は、同様のワンライナーになります。

それ以上は、抽象的には何も言えません。それらを探す最善の方法を決定するには、データ構造についてもっと知る必要があります。

于 2010-08-27T02:06:33.380 に答える