主な違いは、サンダーソンの図に「プレゼンテーションモデル」が含まれていることです。ASP.NET MVCの実装では、モデルが異なる場合でも、プレゼンテーションモデルとして使用されることがよくあります(異なるはずですが、それは聖戦であり、それに入る必要はありません)。
最も単純なASP.NETMVCアプリケーションでは、モデルはデータエンティティです。EFエンティティでもLinq2Sqlエンティティでも、違いはありません。これは、ほとんどのアプリケーションが単純なデータ上のフォームであり、プレゼンテーションが永続性と1対1である可能性があるためです。
ただし、MVCパターン自体はこれを必要としません。より純粋なフレームワークにとらわれない形式で、Sandersonの図は、コントローラーがモデルと相互作用しているという事実を示しています。この意味で、モデルは実際には「ドメインコアへのゲートウェイ」です。コントローラーとビューはアプリケーションの一部ですが、モデルには基盤となるビジネスロジックがあり、その下には、アプリケーションには不明な永続性とその他のインフラストラクチャ情報(もちろん適切に分離されている)のレイヤーがあります。コントローラとモデルの境界はアプリケーションの境界であり、他のアプリケーションもドメインコアに接続してドメインコアと対話できるポイントです。
プレゼンテーションモデルは通常、単純な値オブジェクトにすぎません。永続的なビジネスエンティティのようにビジネス行動を示したり、ライフサイクルを維持したりする必要がないという意味では、いかなる種類のエンティティでもありません。これは、データのいくつかの属性を持つ単なるフラットオブジェクトです。
ある程度の動作をする可能性がありますが、その動作はアプリケーション用であり、ドメインコア用ではありません。たとえば、ビューで使用できるメソッドやプロパティがいくつかある場合があります。プレゼンテーションモデルはアプリケーションの一部であるため、プレゼンテーション層に対応しています。基本的に、コントローラーがビューに渡す必要がある(または、フレームワークによってはリクエストから受信する必要がある)データを保持するだけです。
ASP.NET MVCでは、プレゼンテーションモデルとしても使用されるモデルがよく見られます。そのような場合、同じオブジェクトが2つの役割を果たしている可能性がありますが、2つの役割は明らかに異なります。
編集:あなたの更新された質問に気づきました...
その例でAlbum
は、はドメインモデルとプレゼンテーションモデルの両方の役割を果たしています。(実際、それは貧血であるため、ドメインモデルではないと主張します。機能がなく、裸のデータだけであることに注意してください。)よりリッチなドメインモデルでAlbum
は、より多くの機能を備えている可能性があります。不自然な例として、自動実装されたプロパティの代わりに、設定時にビジネスロジックを適用するプロパティがあり、AddSong(Song song)
andPlay()
やその他のそのような動作などのメソッドがあると想像してください。
このよりリッチなモデルは引き続きプレゼンテーションモデルとして使用できますが、ビューの範囲では機能が意味をなさない場合があります。ビューは、裸のデータ要素だけに適しています。コントローラはモデルの機能と相互作用します。したがってAlbum
、構造がドメインモデルに似たプレゼンテーションモデルを作成すると、例のようになります。
今後、ビューに他のデータも必要な場合はどうなりますか?たぶん、ビューは、と同じ集合体の一部ではない他のモデルについて何かを知る必要がありますAlbum
。ビューに対応するようにドメインモデルを変更することは意味がありません。それは逆です。プレゼンテーションはドメインコアをラップアラウンドする必要があり、その逆ではありません。そのため、コントローラー内の他のものから入力されるプロパティをプレゼンテーションモデルに追加できます。
だからあなたはこのようなものになってしまうかもしれません...
ドメインモデル:
public class Album
{
public int ID { get; private set; } // might need to be immutable
private string _title;
public string Title
{
get { return _title; }
set
{
// don't allow empty titles
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentNullException("Title");
_title = value;
}
}
private Album() { }
public Album(int id, string title)
{
ID = id;
Title = title;
}
public void Play()
{
// some implementation
}
public void SomeOtherMethod()
{
// some implementation
}
}
ビジネスドメインが成長して変化するにつれて、このモデルもそれに伴って変化する可能性があります。重要な点は、UI実装の要求ではなく、ドメインコアとビジネスロジックの要求で変更されることです。
このドメインコアを使用する特定のWebサイトの特定の「ページ」には、アルバムに関する特定の情報が必要な場合があり、その他の情報も必要になる場合があります。それに合うようにプレゼンテーションモデルを調整します。
public class AlbumViewModel
{
public int ID { get; set; }
public string Title { get; set; }
public string Owner { get; set; }
public IEnumerable<Listener> Listeners { get; set; }
public string SomeCompletelyUnrelatedValueNeededByTheView { get; set; }
}
次に、コントローラーはビューのこのプレゼンテーションモデルを作成します。
public ActionResult Details(int id)
{
// TODO: validate and sanitize any inputs
var album = AlbumRepository.Get(id); // after all, why bind the UI _directly_ to the DB? that's just silly
var someOtherObject = SomeOtherRepository.Get(someOtherValueFromSomewhereElse);
var albumVM = new AlbumViewModel
{
ID = album.ID,
Title = album.Title,
Owner = somethingElse.SomeValue,
Listeners = someOtherObject.GetListeners(album),
SomeCompletelyUnrelatedValueNeededByTheView = "foo"
};
return View(albumVM);
}
これは、全体としてはるかに手動のアプローチです。より複雑なドメインモデル、そのドメインと相互作用する複数の複雑なアプリケーション、ドメイン全体のさまざまなテクノロジスタックなどがある場合に役立ちます。単純なフォームオーバーデータアプリケーションの場合、通常、標準のASP.NETMVC実装が正常に機能します。そのためのチュートリアルのほとんどはこれを反映しており、複数の責任をより少ないオブジェクトに統合し、明示的なコードの代わりにデコレータを使用します(全面的に同じツールスタックを使用することを前提としています)。
あなたが見ている例は、非常に少ないコードで非常に迅速に動作するアプリケーションに到達します。他のフレームワークと同様に、フレームワークが意図したとおりに実行すると、美しく機能します。フレームワークの境界を超える必要がある場合でも、より抽象的でフレームワークに依存しない方法でパターンを維持できます。
編集:もう一度更新するために...
ある意味、そうです。ASP.NET MVCは、一般的にMVCパターンから多くを借用するフレームワークです。すべてのものと同様に、それを行うには複数の方法があります。単純な実装と迅速なアプリケーションに固執し、ASP.NET MVCフレームワークによって提供され、さまざまなチュートリアルで説明されている機能は完全に受け入れられ、フレームワークの使用の優れた例です...ツールを使用して作業を完了します。
彼らはすべての最も意味のある方法でパターンに固執します。ただし、同時に、フレームワークの本質(通常はパターン記述の範囲外)では、実際の開発を非常に簡単に実行できるツールを提供しようとします。ドメインモデルをプレゼンテーションモデルから分離する差し迫った必要がない場合は、分離する必要はありません。1つのモデルが両方の役割を果たすことができます。たとえば、リポジトリパターンの背後でデータアクセスを抽象化する差し迫った必要性がない場合は、そうする必要はありません。いくつかの簡単なEntityFramework機能をモデルに直接まとめて、それで済ませることができます。
最終的には、プロジェクトのニーズ、開発者の好みなどに依存します。パターンはよりアカデミックであり、フレームワークはより実用的です。2つのバランスを取ることが重要です。