2011-07-13 9 views
2

私は、DIとORMを備えたASP.NET MVCアプリケーションのモデルで作業しています。どのようにドメインオブジェクトメソッドを消費する必要がありますか?

最近、私はサービス層にすべてのビジネスロジックを書くことと、エンティティクラス自体のエンティティに固有のロジックを配置するという長所について検討してきました。エンティティクラスで宣言されたメソッドは、エンティティの特定のインスタンスで明示的に呼び出されるため、そのインスタンスがクエリからORMにインスタンス化されたときにのみ呼び出すことができます。

私はProductエンティティを持っており、その上にApplyDiscountメソッドがあると宣言します。コントローラーのアクションメソッドから渡された製品のIDがある場合、まずこのIDを使用して製品のインスタンスを照会してから、ApplyDiscountメソッドを呼び出す必要があります。しかし、クエリコードはどこで行われるべきですか? IDを受け取り、Productインスタンスを照会し、そのインスタンスでApplyDiscountを呼び出すメソッドを宣言することは有効な方法ですか?または、そのコードは別の場所に移動する必要がありますか?

最終的には、サービス層でコードを照会し、エンティティクラス自体の結果のエンティティの変更コードを持つことが、太いサービス層を避けようとするときの共通の/正しい実装であることを知りたいと思います。&貧血ドメインモデル。

サービスレイヤでクエリコードを使用すると目的が完全に無効になりますか?

+0

誰かがこの問題について説明している参考文献を提供できればいいと思います。 – NoChance

答えて

0

これは目的を破るものではありませんが、必ずしもそうであってはならないサービス層に移行する機能(具体的には検証)が終了しています。

一般的に、検証はできるだけ早い時期に行うことをお勧めします。すなわち、あなたが無効なIDを与えられている場合は、ロジック全体を通して実行チェーンを開始する前に、その無効な条件を捕らえたことを確認する必要があります。通常、これはコントローラでクエリを実行し、結果のオブジェクトをサービスレイヤーに渡すことを意味します。これにより、実行チェーン内で上位レベルまでクエリを実行する機能が分離され、サービスレイヤに高レベルの除外ロジックを実装する必要がなくなります(たとえば、一連のIDが無効になっている場合は、あなたのサービスレイヤーの外側で、関連するロジックを分離し、サービスレイヤー内でそれを行う必要がないようにします。

一般的には、次のようなアプローチを考えてみましょう。オブジェクトレベルの検証とデシリアライズを可能な限りあなたのロジックをあなたのサービス層から遠くに移動させ、それによってサービス層を「薄く」することです。もちろん、ここにはある程度の柔軟性がありますが、一般的なルールとしては良いことです。

+0

"これはコントローラでクエリを実行し、結果のオブジェクトをサービスレイヤに渡すことを意味します。したがって、サービスレイヤメソッドは、単にProductをパラメータとし、それに 'ApplyDiscount'を呼び出します。まあ、単一行のmyproduct.ApplyDiscount()サービス層メソッドは確かに薄いです。コントローラーは、さまざまなリポジトリーへの参照を必要とし、照会して検証を実行する必要があります。 –

+0

@Sanjeev:はい、すべてのサービス層がそうであるとすれば、それは確かに薄いです。これは、サービス層にロジックが発生し始めたとき(時間が経つにつれてほぼ確実に)、アプローチとして価値あるものになり始めます。どんなロジックであれ、サービスレイヤーを使わなくても簡単にできます。副題として、ApplyDiscountはサービス層の機能ではありませんか?あなたはそれがあるべきかどうかを考えましたか? –

+0

よくApplyDiscountは単なる例ですが、トピックでは、これらのメソッドの配置場所を指示する機能の種類について、ガイドラインを使用することはできます。 ApplyDiscountは他のエンティティには影響しないので、最初はそれがProductメソッドであると仮定していました。 –

0

Iここではサービス層の必要性は実際には分かりません。論理が1つのエンティティにしか影響しないなら、私はその論理をエンティティ自体の中に入れます。 (もちろん、私はちょうどこのように仮想的なコードを示しています、ユーザーの入力を信用してはいけません。)

public ViewResult ApplyDiscount(int productId, decimal percent) 
{ 
    var product = Database.Get<Product>(productId); 
    product.ApplyDiscount(percent); 
    Database.Save(product); 
    return View(product); 
} 

製品:

public void ApplyDiscount(decimal percent) 
{ 
    this.Price = this.Price * (1 - discount); 
} 
+0

あなたは 'this.Price = this.Price *(1 - (percent/100)); 'という意味ですか?とにかく、コントローラーのアクションメソッドに配置したコードを専用のサービスレイヤーメソッドに配置するかどうかについては、紛争の問題と思われます。優先順位はどれですか:私のサービス層に最小限のコードがあるか、コントローラの最小限のコードですか?薄いコントローラーと薄いサービス層は、私が学んだことから重要です。 –

+0

@Sanjeevまあ、私は実際にそれが意味するものが明確ではないので、実際には「パーセント」よりも良い名前を選ぶだろう。私はすべてのサービスに入れて、非常に薄いコントローラを持っていましたが、私はUIのためだけにMVCを使用するので、私は不必要なレイヤーを追加していたことに気付きました。私はまだすべての論理をエンティティに保持しています。 – Ryan

-1

は現在、私は、エンティティの静的Findメソッドを使用しています例えば:

public ActionResult ApplyDiscount(int id, decimal percent) { 

    Product product = Product.Find(id); 

    if (product == null) 
     return HttpNotFound(); 

    var result = product.ApplyDiscount(percent); 

    if (result.IsError) 
     return ViewWithErrors(result); 

    return RedirectToAction("DiscountApplied"); 
} 

ApplyDiscountエラーをにModelStateにマッピングすることができる検証エラーとオブジェクトを返します。

関連する問題