トップ回答者
ASP.NET MVC コントローラの分け方

質問
-
お世話になります。
ASP.NET MVCのコントローラの分け方について質問させて下さい。
例えば、複数人のスケジュール(TODOリストのような)を管理するソフトを作るとします。
このソフトには、スケジュールを閲覧・編集するための次のようなビューがあります。
選択ビュー:スケジュールを閲覧・編集したいメンバーを選択する
日次ビュー:選択したメンバーのスケジュールを1日分表示する
週次ビュー:選択したメンバーのスケジュールを1週間分表示する
月次ビュー:選択したメンバーのスケジュールを1ヶ月分表示する
日次・週次・月次ビューは、それぞれ表示される情報量が異なり、日次ビューは最も詳細な情報が表示されます。
上記4つのビューに対して、コントローラはいくつ作るべきか、悩んでいます。
※このソフトは長期に渡る機能強化が前提となっているため、目先の作業量よりも、保守性の確保が重要です。
どれも同じ、スケジュールの閲覧と編集、という同じ目的のためのビューなので、ひとつのコントローラでも良いのかなとも思います。
しかし根拠はその程度(同じ目的だから同じで良さそう?)でしかなく、逆に「全部別々のコントローラにしたら何がダメなの?」と自問しても、うーん、という感じです。
皆さんは、コントローラをどのような単位に切り分けて作りますか?
何か目安などを教えて頂けるとありがたいです。
よろしくお願いします。
回答
-
それぞれ4つのコントローラーを別々に作った方が良いように思います。理由は、ファイルの構成がわかりやすいからです。わかりやすければ、どこを直せば良いかが明確になり、直した際に出る影響も限定的になりますので、例え改修に重大なバグがあったとしても、影響の範囲を抑えることができます。限定的なのでバグも取りやすいでしょう。つまり、保守がやりやすくなる期待が持てます。さらに、コントローラーが分かれていれば、それぞれのビューに対する改修も、チームのメンバーが同時に行うことができます。
私の経験上(といっても、ASP.NET MVCの経験はほとんど無いですが・・・)、ごく稀にモデルを共用することはあっても、コントローラーを共用したことはあまりありません。コントローラーは同じ目的のものをまとめるために存在するのではないので、目的が同じだからといって1つにまとめるのは筋が違うように思います。コントローラーはあくまでビューとのやり取りとのセットで考えるべきものではないでしょうか? そうであれば、1つのビューに対して必ず1つのコントローラーが存在するというポリシーにした方が、わかりやすく、結果的に保守もやりやすくなると思います。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2013年12月18日 6:31 誤字修正
- 回答としてマーク femp 2013年12月18日 10:58
-
自分の意見では説得力がないので、マイクロソフト公式解説書「プログラミング ASP.NET MVC」の受け売りですが、ASP.NET MVC アーキテクチャの中心は本質的にコントローラーにあるということで、最初にビューありきではなく、まずコントローラーを考えます。
通常、アプリで操作するオブジェクトごとにコントローラクラスを定義し、予想されるリクエストを処理するアクションメソッドをそのクラスにまとめるということになると思います。
例えば、EmployeesScheduleController というクラスを一つ作って、その中に Index, Month, Week, Day というようなアクションメソッドを定義するといった感じでしょうか。
- 回答としてマーク femp 2013年12月18日 10:58
すべての返信
-
それぞれ4つのコントローラーを別々に作った方が良いように思います。理由は、ファイルの構成がわかりやすいからです。わかりやすければ、どこを直せば良いかが明確になり、直した際に出る影響も限定的になりますので、例え改修に重大なバグがあったとしても、影響の範囲を抑えることができます。限定的なのでバグも取りやすいでしょう。つまり、保守がやりやすくなる期待が持てます。さらに、コントローラーが分かれていれば、それぞれのビューに対する改修も、チームのメンバーが同時に行うことができます。
私の経験上(といっても、ASP.NET MVCの経験はほとんど無いですが・・・)、ごく稀にモデルを共用することはあっても、コントローラーを共用したことはあまりありません。コントローラーは同じ目的のものをまとめるために存在するのではないので、目的が同じだからといって1つにまとめるのは筋が違うように思います。コントローラーはあくまでビューとのやり取りとのセットで考えるべきものではないでしょうか? そうであれば、1つのビューに対して必ず1つのコントローラーが存在するというポリシーにした方が、わかりやすく、結果的に保守もやりやすくなると思います。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2013年12月18日 6:31 誤字修正
- 回答としてマーク femp 2013年12月18日 10:58
-
自分の意見では説得力がないので、マイクロソフト公式解説書「プログラミング ASP.NET MVC」の受け売りですが、ASP.NET MVC アーキテクチャの中心は本質的にコントローラーにあるということで、最初にビューありきではなく、まずコントローラーを考えます。
通常、アプリで操作するオブジェクトごとにコントローラクラスを定義し、予想されるリクエストを処理するアクションメソッドをそのクラスにまとめるということになると思います。
例えば、EmployeesScheduleController というクラスを一つ作って、その中に Index, Month, Week, Day というようなアクションメソッドを定義するといった感じでしょうか。
- 回答としてマーク femp 2013年12月18日 10:58
-
回答ありがとうございます。
全く逆の意見を頂きましたが、今回はビューごとにコントローラを作る方針にしようかと思います。
チームで作業するにあたってはルールを設ける必要がありますが、trapemiya様のおっしゃるように、「1つのビューに対して必ず1つのコントローラーが存在する」というルールが、メンバーを混乱させずに守らせるためには良さそうだと考えました。
SurferOnWww様からご紹介頂いた書籍ですが、先ほどちらっと立ち読みしてきました。
今回の質問に対する答えそのもの(コントローラの粒度)も、SuferOnWww様が引用されているように書かれており、それに従えば、今回の質問の答えは「4つとも同じコントローラ」となります。
ただ、解説の中には、「そうした方が良い理由」が書かれておらず、あくまで「通常はそうする、けど最終的にはあなたが決めて」という内容でしたので、メリットがはっきりしているtrapemiya様の方針でいこうと思います。
余談ですが、書籍中にあった文言の「ASP.NET MVC アーキテクチャの中心は本質的にコントローラーにある」というのは、最低限IControllerインタフェースの実装さえあれば(=コントローラさえあれば)、ビューもモデルも無くてもASP.NET MVCは動作する、というASP.NET MVCの動作原理を言っているのかな、とちょっと思いました。 -
-
コントローラーは私もコントローラークラスの意味で使っています。アクションメソッドはASP.NET MVCで、MVCアーキテクチャを実現するための仕組みに過ぎず、アクションメソッドはコントローラーに含まれているというのが私の認識です。参考までに、MVVMで言えば、アクションメソッドはバインドのような仕組みの一つだと思うのです。
SurferOnWwwさんが書かれた、
>通常、アプリで操作するオブジェクトごとにコントローラクラスを定義し、
の、オブジェクトはモデルのことだと私は思ったのですが、いかがでしょうか? 日次ビューや週次ビューでは扱うモデルが違うので、そのモデル毎にコントローラーを用意するという意味なのかな?と思いました。
MVCをどのようなクラス構成にするのかは、一般論はあったとしても、最終的にはどのようなポリシーで設計するかにかかっていると思います。私は、単純に一つの画面は、それ専用の1つのMVCのセットからなるのがわかりやすいということを優先するのが好みです。それに、私はこのようなアーキテクチャパターンはT4で生成しますので、どうしてもこういう形がやりやすいというのも理由の一つになっています。
先にも書きましたが、ASP.NET MVCで実際に運用するシステムを私は開発したことがありませんので、ASP.NET MVCの場合は、そうはならないというところがあればご指摘ください。★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
-
確認ですが、
> それぞれ4つのコントローラーを別々に作った方が良いように思います。
ということは、質問者さんの言われる「選択ビュー」「日次ビュー」「週次ビュー」「月次ビュー」それぞれに別々のコントローラークラスを作るということですか?
つまり、例えば、GeneralScheduleController, DailyScheduleController, WeeklyScheduleController, MonthlyScheduleController というようなクラスを 4 つ作って、それぞれに目的のビューを表示するためのアクションメソッドを実装すると言われてますか?
自分に言わせてもらえれば、先にも書きましたように、それはかなり理解に苦しみます。
MVC のコントローラークラスも「クラス」です。クラスには関連するメソッドをまとめて実装するのが普通で、メソッド別にクラスを作ったりすることは決してないですよね。
なので、これも先に書きましたが、例えば、EmployeesScheduleController というクラスを一つ作って、その中に Index, Month, Week, Day というようなアクションメソッドを定義するのが普通だと思うのですが。
質問者さんは保守性を問題にされてましたが、どちらが保守性に優れているかと言えば、後者(一つのクラスに関連するメソッドをまとめて実装)だと思います。
> SurferOnWwwさんが書かれた、
>
>>通常、アプリで操作するオブジェクトごとにコントローラクラスを定義し、
>
> の、オブジェクトはモデルのことだと私は思ったのですが、いかがでしょうか? 日次ビューや
> 週次ビューでは扱うモデルが違うので、そのモデル毎にコントローラーを用意するという意味な
> のかな?と思いました。逆に質問ですが、trapemiya さんがここで言われるモデルとは何ですか?
たぶん、コントローラーとビューの間でデータをやり取りする「ビューモデル」のことだと想像してますが、そうだとすると、自分が言う「オブジェクト」とは違います。
EmployeesSchedule オブジェクト(そういうものが実際に質問者さんのケースで存在するのか分かりませんが)というような感じのものです。
-
>ということは、質問者さんの言われる「選択ビュー」「日次ビュー」「週次ビュー」「月次ビュー」それぞれに別々のコントローラークラスを作るということですか?
その通りです。
>なので、これも先に書きましたが、例えば、EmployeesScheduleController というクラスを一つ作って、その中に Index, Month, Week, Day というようなアクションメソッドを定義するのが普通だと思うのですが。
どういう粒度でオブジェクトを設計するかによると思いますが、SurferOnWwwさんは、従業員のスケジュールを1つのオブジェクトとして捉えているようですね? そうであれば、それに対応するコントローラーが1つのEmployeesScheduleControllerであっても良いと思います。
おそらくSurferOnWwwさんは、コントローラー中心で考えられているからだと思いますが、私はそうではなく、まずビューに何を表示するかを考えます。その結果、モデルが決まります。そして、最後にモデルとビューを結びつけるコントローラーを作成します。確かにMVCの肝はコントローラーであり、中心的な存在ですが、それはビューとモデルを分離するために必要になるものであって、主役はあくまでもビューとモデルです。なぜなら、ビューとモデルが存在しなければ、アプリケーションとして成り立たないからです。例えば、Windowsフォームのアプリケーションでは、通常、以下の組み合わせになります。
日次画面 <--> 日次データテーブル
月次画面 <--> 月次データテーブル
ここにMVCを適用すれば、
日次ビュー <--> 日次コントローラー <--> 日次モデル
月次ビュー <--> 月次コントローラー <--> 月次モデル
となるのが、私はわかりやすいと思うのです。SurferOnWwwさんは以下のようになることをイメージされているのですよね?
日次ビュー
<--> 日次月次コントローラー <--> 日次月次モデル
月次ビュー>質問者さんは保守性を問題にされてましたが、どちらが保守性に優れているかと言えば、後者(一つのクラスに関連するメソッドをまとめて実装)だと思います。
日次ビューを操作するメソッドと、月次ビューを操作するメソッドが関連しているようには私には思えません。例えば、日次ビューを操作するためにインスタンス化したオブジェクトに、全く関係ない月次ビューを操作するメソッドが含まれていることに意味があるのでしょうか?
クラスをオブジェクトとして捉えず、単なるグルーピングの道具として見れば関連しているかもしれません。しかし、オブジェクト指向的には関連しているようには思えないのです。
保守性に関しても、日次ビューでは日次に関するコントローラー部分しか見ないわけですから、余計なソースが含まれたクラスから当該の部分を探す必要がなくなります。命名的にも、日次ビューであれば、同じ日次が語頭にある日次コントローラーを見れば良いということがすぐにわかりますが、共通の1つのコントローラーにした際にはそのような命名にできませんから、どのコントローラーを見えれば良いのかがわかりにくくなります。また、先にも書きましたが、日次コントローラーを弄っても日次ビュー以外には一切の影響が出ませんが、共通の1つのコントローラーの場合ですと、知らぬ間に他のビューに影響が出てしまう可能性が残ります。そもそもMVCはビューとモデルを疎結合にしますが、他に影響を与えにくいように設計することは、良質のアプリケーションにとって欠かせないことだと思います。>たぶん、コントローラーとビューの間でデータをやり取りする「ビューモデル」のことだと想像してますが、そうだとすると、自分が言う「オブジェクト」とは違います。
いえ、違います。一般論ですので、ごくベーシックな意味でモデルという言葉を使っています。つまり、プロパティしか存在しないクラスです。例えば、以下のようになります。
public partial class 日次ビュー
{
public int スケジュールID { get; set; }
public int スケジュール名 { get; set; }
public DateTime スケジュール日 { get; set; }
}>EmployeesSchedule オブジェクト(そういうものが実際に質問者さんのケースで存在するのか分かりませんが)というような感じのものです。
先にも述べた通り、私はビュー毎にモデルを定義、つまりクラスを作成します。なぜなら、これも繰り返しになりますが、ビューとモデルのセットがあくまで主役であり、それらを疎結合にするためにコントローラーを導入するというのがMVCだと思うからです。
ただ、SurferOnWwwさんの考え方も理解できます。個々のコントローラーを持つのか、一つの共通のコントローラーを持つのかの2択ですが、どちらが誤っているかということではなく、2者を比較検討した際に、個々のコントローラーが良いと思ったのは、保守性がより優れていると判断したのが最大の理由です。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2013年12月19日 3:36 追記
-
話が噛み合ってないようです。
まず、先の私のレスの以下の点は納得していただけるでしょうか?
> クラスには関連するメソッドをまとめて実装するのが普通で、メソッド別にクラスを
> 作ったりすることは決してないですよね。trapemiya さんのスタンダードでは違うと言われると、この先いくら議論しても噛み合うことはなさそうです。
それが OK なら、実態が分からない質問者さんの例で議論していてもたぶん埒は明かないと思いますので、VS2010 のテンプレートで作る ASP.NET Web サイト(Razor でない方)の AcountController.cs, AccountModel.cs, LogOn.aspx 他をベースに話ができるでしょうか?
-
議論の内容が詳細化されてきたので、私が想定している背景事情を少し補足しておきます。
> EmployeesSchedule オブジェクト(そういうものが実際に質問者さんのケースで存在するのか分かりませんが)というような感じのものです。
私は、そのようなオブジェクトを作るつもりでいます。
EmployeesScheduleオブジェクト(単一のクラスか複数のクラスの集まりかは分からないですが)は、SQL文発行などのデータアクセス層を隠蔽しており、スケジュールの取得・追加・更新・削除などのインタフェースを持ちます。
それぞれ、1件ずつ、あるいは条件を指定して複数人分、あるいは週・月単位での操作が可能です。
このEmployeesScheduleオブジェクトは、プレゼンテーション層(ビューとコントローラ)の都合は一切考えていません。
EmployeesScheduleオブジェクトとコントローラのアクションメソッドの間には、ファサードクラスを配置します。
ファサードクラスとコントローラクラスは1:1で作り、ファサードクラスのメソッドとコントローラクラスのアクションメソッドも1:1で作ります。
ファサードは、コントローラからの呼び出しに応じて、EmployeesScheduleオブジェクトなどのビジネスロジック層のオブジェクトに対して処理の指示を出し、その処理結果からビューモデル(のインスタンス)を構築する責務を持ちます。
ここでいうビューモデルは、trapemiya様が例示された「プロパティしか存在しないクラス」そのものです。
EmployeesScheduleオブジェクトという「モデル」から、個別のビューに依存した情報だけを切り出したものです。
※プロパティだけで構築されていることが本質ではなく、ビュー依存で切り出された情報の塊=ビューモデル、と考えています
以上のような想定をしています。
今にして思えば、先に説明しておけばよかったですね。申し訳ありませんでした。
私個人としてはまだ方針を確定したわけでもなくこだわりもないので、このような議論から得られる知見は大変助かります。
ありがとうございます。 -
>SurferOnWwwさん
>話が噛み合ってないようです。
噛み合っていると思いますよ。なぜなら、SurferOnWwwさんが言われていることを間違って私が受け取っているとは思っていないからです。よって、的を外れたことを言っているつもりはないです。
>まず、先の私のレスの以下の点は納得していただけるでしょうか?
メソッド別にクラスを作るかどうかを争点にしているつもりはないです。メソッド別にクラスを作るかどうかは、前提の元に導かれるものであり、導かれるものを最初に持ってきて正しいかどうかを判断することはできないです。
一つのクラスに属すべきメソッドであれば、一つのクラスに全てのメソッドを定義すべきです。そうでなければ、それぞれ別のクラスにメソッドが属すべきです。私は、日次ビューに関するメソッドと、月次ビューに属するメソッドは、一つのクラスに属すべきではないという判断をしたまでです。理由は上で述べた通りで、スケジュール管理と言う意味では関連したメソッドだと思いますが、それよりもオブジェクト指向的にオブジェクトの分離、保守性を考えての上です。>trapemiya さんのスタンダードでは違うと言われると、この先いくら議論しても噛み合うことはなさそうです。
噛み合わないということと、お互いの主張を理解し合うということは別だと思います。それとも、どちらの意見が正しいと決めることを噛み合うと言われていますか? もし違うなら、どの辺りが噛み合ていないと感じられていますか?
>VS2010 のテンプレートで作る ASP.NET Web サイト(Razor でない方)の AcountController.cs, AccountModel.cs, LogOn.aspx 他をベースに話ができるでしょうか?
MVCだから、こう作るべきという会話にすり替えたとしても、何も進展しないように思います。もし、噛み合っていないのでしたら、それは一つのコントローラーにメソッドを全て定義するかどうかという点についてのみでしょう。私は一般的にはクラスを分けるべきという理由を述べていますが、SurferOnWwwさんからはそれに対する意見をいただいていません。そういう意味では、噛み合っていないのかもしれませんね。
おそらく争点はここだけですので、これについて以下のような議論をすれば良いだけだと思います。
先にも書きましたが、私はSurferOnWwwさんの考え方を全面的に否定しません。アプリケーションが本当にシンプルであれば、必要以上にソースコードも増えず、日次も月次も1つのスケジュール処理の塊と考えれば、そちらの方がわかりやすく、私の考え方が過剰かもしれません。SurferOnWwwさんは私の考え方はどのような場合もあり得ないとお考えですか?もし、そうであれば、その考えの理由をお聞かせ下さい。★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
-
>fempさん
>EmployeesScheduleオブジェクト(単一のクラスか複数のクラスの集まりかは分からないですが)は、SQL文発行などのデータアクセス層を隠蔽しており、スケジュールの取得・追加・更新・削除などのインタフェースを持ちます。
このようなクラスは必要でしょう。ただし、これを一般的にはモデルとは言いません。カテゴリー的にはモデルに入るのでモデルと言っても誤りではありませんが、私は通常は、プロパティからのみなるモデルとは別にこのようなクラスを定義します。ただし、モデルとこのようなクラスは1対1に対応します。クラスが増えてわかりにくくなると思われるかもしれませんが、フォルダで分けて管理すればそれほどわかりにくいものではありません。1つのWord文書に日次レポートと月次レポートが含まれているか、売上というフォルダを設けて、その中に日次レポートと月次レポートの2つの文書を入れるかの違いのようなものだと思いますが、私は後者を好みます。状況や人によっては前者を好むこともあるでしょう。
なので、ファサードクラスも私の場合は必要ありません。>ここでいうビューモデルは、trapemiya様が例示された「プロパティしか存在しないクラス」そのものです。
これも一般的には誤解を与えます。ビューモデルはMVCで言えばコントローラーに当たる部分で使われます。ちなみに私はこのようなクラスは、UIオブジェクトという言い方が好きです。MVVMになりますが、通常、私が用いるパターンの1例は、以下のようになります。MVVMはMVCの派生ですから、ある程度は参考になると思います。
おそらくfempさんが言われているEmployeesScheduleクラスは、AccessLayerに当たるでしょう。
View <------------> ViewModel <-------->AccessLayer
UIObject
Model
#実際にはもう少しクラスがあります。ちなみに、AccessLayer, UIObject, ModelはT4で自動生成します。そういう意味でも、Viewについては上記のセットが必ず1セット存在することになります。
>今にして思えば、先に説明しておけばよかったですね。申し訳ありませんでした。
1つのコントローラにするかどうかは直接関係のない部分ですので、大丈夫ですよ。
#繰り返しになりますが、実務で使用するASP.NET MVCの開発経験はありませんので、あくまで参考程度にして下さい。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2013年12月19日 6:14 追記
-
ぜんぜん噛み合ってないです。
それは多分 trapemiya さんのスタンダードが私の考えるスタンダードと違うか、もしくは前提となる条件が違うからだと思います。
自分のスタンダードは、一番最初の回答に書いたとおり、以下の通りです。
> ASP.NET MVC アーキテクチャの中心は本質的にコントローラーにあるということで、最初
> にビューありきではなく、まずコントローラーを考えます。
> 通常、アプリで操作するオブジェクトごとにコントローラクラスを定義し、予想されるリ
> クエストを処理するアクションメソッドをそのクラスにまとめるということになると思い
> ます。「前提となる条件」が違うというのは、上記で言う「オブジェクト」のイメージが違うのではないかと思います。
なので、私の言う「オブジェクト」を理解していただいたうえで、この話をしないと埒が明かないと思って、
> VS2010 のテンプレートで作る ASP.NET Web サイト(Razor でない方)の AcountController.cs,
> AccountModel.cs, LogOn.aspx 他をベースに話ができるでしょうか?という提案をしました。
上記の例では、オブジェクトは MembershipProvider であり、予想されるリクエストはメンバーシップへのログオン、ログオフ、初期登録、パスワード変更です。
その目的を果たすため AccountController クラスというのを一つ作り、その中に LogOn, LogOff, Register, ChangePassword, ChangePasswordSuccess というアクションメソッドを実装してます。
これが私の言う私のスタンダードの例です。これからは、ビューごとにコントローラークラスを分けるなんて発想は出てきません。
trapemiya さんが言われるように、ビューごとにコントローラークラスを分けることが適切という実例が MSDN ライブラリ他のサンプルにあれば、具体的に教えてください。
-
SurferOnWwwさんが言われるスタンダードは知っています。複数のビューに対して1つのコントローラーということです。これは私は間違っていないと言っています。AccountControllerのような件についても、先の発言でありだと認めています。
しかし、どのような場合でも複数のビューに対して1つのコントローラーで設計することを勧めていないだけです。特に、日次ビュー、月次ビューなど画面に表示する項目が大幅に違い、業務処理なのである程度複雑になることが予想されたため、ビュー毎にコントローラーを分けることを推薦したまでです。あくまで推薦であって、こうしないから間違いというつもりはありません。
もう一度お聞きしますが、どのような場合も、ビュー毎にコントローラーを作成してはダメでしょうか? その答えを聞かなけば、話が収束しません。(追記)
>trapemiya さんが言われるように、ビューごとにコントローラークラスを分けることが適切という実例が MSDN ライブラリ他のサンプルにあれば、具体的に教えてください。複数ビューで複数コントローラーがある例はいくらでもあると思いますが、問題はそれを示すことではないでしょう。
これらのビューはそれぞれコントローラーが別でもOKなのかダメなのかが争点なのだろうと思いますので。
例えば、ログインビューと伝票登録ビューがそれぞれのコントローラーに分かれていても問題ないですよね?
じゃあ、日次ビューと月次ビューはどうなの?っていう考え方の違いが争点なのでしょう。この辺りは明確な基準がないように思います。よって、サンプルを探してもあまり役に立たない気がします。(さらに追記)
ですから、私にとっては、複数のビューに一つのコントローラーも、複数のビューにそれぞれのコントローラーも、どちらもスタンダードです。ただ、開発量としては、複数のビューにそれぞれのコントローラーの方が多くなりそうですが。(連続追記)
結局、ビューを物理的な1つのファイルとして捉えるのか、パスワード変更のような複数のビューで構成されていても人間的に見れば論理的な1つのビューとして捉えられるかということも関連しそうです。論理的に1つのビューであれば、物理的に1つのコントローラーでも問題ないでしょう。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2013年12月19日 7:01 連続追記
-
> どのような場合も、ビュー毎にコントローラーを作成してはダメでしょうか?
いかなる場合もダメとは思いませんが、先にも述べましたように「最初にビューありきではなく、まずコントローラーを考えます」が基本だと自分は思っていますので、自分にはそもそもそういう発想がないです。
Visual Studio のウィザードでビューを作る場合は、コントローラーのアクションメソッドを右クリックして作るということからも、「ビュー毎にコントローラーを作成」ということは考えにないです。
ViewResult を返さないアクション、例えば AccountController では LogOff、もありますし。
-
>ビュー毎にコントローラーを作成」ということは考えにないです。
すみません。私の追記と時間差があまりなかったので、私の追記を読まれていないかもしれません。
私が追記したように、ビューを必ずしも1つの物理的なファイルに対応させず、複数の物理的なビューからなる1つの論理的なビューと考えれば、うまく説明できるのではないかと思いました。アカウント関連の複数のビュー(1つの論理ビューと考える) <--> 1つのコントローラー
日次スケジュールビュー <--> 1つのコントローラー
月次スケジュールビュー <--> 1つのコントローラー
上記は、2つの1つのアプリケーションには存在するパターンだと思います。SurferOnWwwさんが言われているのは主に上で、私が言っているのは主に下です。場合によっては、
スケジュール関連の複数のビュー(日次スケジュールビュー、月次スケジュールビューから成る1つの論理ビューと考える) <--> 1つのコントローラーもありだろうというのは、これまでも述べた通りです。
実際、正解はないと思います。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
-
どうも「初めにビューありき」にこだわっておられるよう見えます。それに対して自分は「初めにコントローラーありき」と考えているあたりに、お互い越えられない壁があるような感じがします。
> 正解はないと思います。
いかなるケースにおいても「初めにコントローラーありき」が正解とは言いませんが、Visual Studio のウィザードを使ってアプリを作っていく場合は基本的にそうなるという事実はあります。すなわち正解とは言わないまでも一般的な標準とは言えると思います。
そんなことは受け入れられないということなら、自分としてはそれならそれでご勝手にと言うしかないです。
-
>どうも「初めにビューありき」にこだわっておられるよう見えます。それに対して自分は「初めにコントローラーありき」と考えているあたりに、お互い越えられない壁があるような感じがします。
どちらか一方ではなく、どちらもあり得るという立場です。アカウント管理のような画面は複数のビューから成っていても、実際には1つの論理的な画面と考えられ、1つのコントローラーで対応するのが良いように思います。この場合は、初めにコントローラーありきでも良いと思います。しかし、多くのデータを扱う場合は、どういったデータをどう用意して、どう扱うかを考えるのが普通だと思います。ですから、「初めにビューありき」ではなく、「初めにモデルありき」の方が近いと思います。実際に流れるデータを考えますから、初めにモデルを考えると考えやすいと思います。例えば、
ASP.NET MVC アプリケーション開発入門: 第 1 回 ASP.NET MVC 2 の具体的な開発の全体像
http://code.msdn.microsoft.com/1-ASPNET-MVC-2-054b7b0e/には、以下のように書かれています。
「このようにデータを表示する流れは「モデル」→「コントローラー」→「ビュー」の順に作っていくと実装がしやすくなります。」
>いかなるケースにおいても「初めにコントローラーありき」が正解とは言いませんが、Visual Studio のウィザードを使ってアプリを作っていく場合は基本的にそうなるという事実はあります。すなわち正解とは言わないまでも一般的な標準とは言えると思います。それについては同意します。しかし、ウィザードで生成されるパターンが全てのケースにおいて唯一適切なパターンであるとは考えていません。つまり、適切で標準的なパターンの1つを示しているだけであり、作成するアプリケーションによってはそれが合わない場合もあると考えています。
今回のスケジュールに関するビューの構成を見た時に、いろいろな理由を述べた通り、1のビューに1つのコントローラーとするポリシーが良いという判断を私はしました。これを否定する理由が、Visual Studioのウィザードが生成するパターンから外れているという理由だけでは、私は納得できないのです。外れた場合のメリット、デメリットがあるはずですので、そこを技術者としては議論すべきだと思いますし、私はそうしているつもりです。
よって、>そんなことは受け入れられないということなら、自分としてはそれならそれでご勝手にと言うしかないです。
については、標準ということは受け入れますが、そこから外れているという理由だけで私の提案を否定されて勝手に突き放されたら、悲しいものがあります。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2013年12月20日 0:23 わかりやすい言い回しに変更
-
「モデル」って何だ?・・・と言う議論ももう少しすべきだったかもしれませんね。
> 「このようにデータを表示する流れは「モデル」→「コントローラー」→
> 「ビュー」の順に作っていくと実装がしやすくなります。」そこで言う「モデル」とは Entity Data Model (サンプルのコードでは Models.mvcdbEntities) もしくはもっと狭義には自動生成される .Designer.cs のコードで定義されるクラス (TProduct) のことですが、それは私が最初に書いた、
"アプリで操作するオブジェクトごとにコントローラクラスを定義し、予想されるリクエストを処理するアクションメソッドをそのクラスにまとめるということになると思います。"
の中で「アプリで操作するオブジェクト」と同じものを意味してます。
さらに狭義には、ビューが知っているオブジェクト、即ち、ViewPage<TModel> を継承するビューの Model プロパティで取得できるオブジェクト(即ち TModel。サンプルコードでは IEnumerable<MvcApplication1.Models.TProduct>)という捉え方もあるようです。
> 今回のスケジュールに関するビューの構成を見た時に、いろいろな理由を述べた通り、
> 1のビューに1つのコントローラーとするポリシーが良いという判断を私はしました。
> これを否定する理由が・・・否定はしていません。そういうケースがあるかもしれないという可能性は、自分のつたない経験では排除し切れません。
ただし納得はしてません。なので何かサンプルがあれば教えていただきたいとお願いしました。
-
>「モデル」って何だ?・・・と言う議論ももう少しすべきだったかもしれませんね。
そうかもしれませんね。以下のSurferOnWwwさんの発言を見て、日次も週次も月次も一つのテーブルで賄おうと考えられているのかな?と思いました。
>クラス (TProduct) のことですが、それは私が最初に書いた、
>
>"アプリで操作するオブジェクトごとにコントローラクラスを定義し、予想されるリクエストを処理するアクションメソッドをそのクラスにまとめ>るということになると思います。"
>
>の中で「アプリで操作するオブジェクト」と同じものを意味してます。コントローラーは一つですから、Tproductのようなテーブルが一つしかないということでしょうか? であれば、ここが私とは根本的に違います。私は、日次、週次、月次毎に3つのテーブルが必要だと考えました。よって、コントローラーも3つになります。
>ただし納得はしてません。なので何かサンプルがあれば教えていただきたいとお願いしました。
上でも書いた通り、前提にしているものが根本的に違うような気がしてきましたので、どう書いてよいのかわからなくなりました。私は以下のように考えています。
日次ビュー ---- 日次コントローラー ---- 日次モデル(日次テーブル。要は日次を表示するために必要なデータ)
月次ビュー ---- 月次コントローラー ---- 月次モデル(月次テーブル。要は月次を表示するために必要なデータ)それに対して以前も書きましたが、SurferOnWwwさんは以下をイメージされており、TProductが日次月次モデルにあたる(もしくは日次月次モデルがTproductのような1つのテーブルを含む)ということでしょうか?
日次ビュー
<--> 日次月次コントローラー <--> 日次月次モデル
月次ビューこれであれば、日次月次コントローラー 1つで良いと思います。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
-
trapemiya さんの論点が変わってきているような気がしますが・・・ ビューごとに(テーブルごとではなくて)コントローラクラスを定義するのがよいというご意見ではなかったのでしょうか?
それはとりあえず置いといて・・・
> 日次も週次も月次も一つのテーブルで賄おうと考えられているのかな?と思いました。
DB にある物理的なテーブル、ビュー、ストアドなどの構成がどうなってるかなんてことは自分は全く考えてないです。
データ層とコントローラーの間を取り持つ中間層が、例えば SqlMembershipProvider ように決まった必須メンバを実装してデータ層の構造の違いを吸収してくれれば、DB のテーブルが 1 つでも、3 つでも、もっと多くても全く何の関係もないです。
何にせよ、質問者さんの例の日次、週次、月次うんぬんをベースに話をするのは止めましょう。明確に目に見える実体がないので、たぶん、みんな違うイメージを持っていて、いつまで議論していても話が収束しません。
なので、私が挙げた VS2010 のテンプレートで作る AcountController や、trapemiya が紹介されたサンプルとか、実例が見えるものをベースに話をしましょう。
先のレスの「何かサンプルがあれば教えていただきたい」というのは、質問者さんの例の日次、週次、月次うんぬんをベースにした話ではなくて、Microsoft が Visual Studio に実装したウィザードやチュートリアルに逆行するような目からウロコ的なサンプルを、Microsoft が紹介していたら教えていただきたいというお願いです。
-
まず、前提がお互い違っていては話が合うわけありませんので、はっきりともう一度確認しておきます。
私はずっと、日次スケジュールや月次スケジュールについてどうするかということについてのみ話をしています。MVCの標準の作り方がどうかという話ではありません、仮に標準から外れているのであれば、それでも良いと思っていますし、その理由を示しています。なのであとは、それがダメだというSurferOnWwwさんの理由を聞くだけです。
>trapemiya さんの論点が変わってきているような気がしますが・・・ ビューごとに(テーブルごとではなくて)コントローラクラスを定義するのがよいというご意見ではなかったのでしょうか?
日次スケジュールや月次スケジュールにおいて、ビューに表示したいものはモデルと考えました。モデルはこの場合、データテーブルとわかりやすく考えても良いです。モデル毎にコントローラーを用意しますから、ビュー毎にコントローラーが用意されることになります。つまり、今回の日次スケジュール、月次スケジュールにおいて、ビューとモデルは1対1の関係になります。
>DB のテーブルが 1 つでも、3 つでも、もっと多くても全く何の関係もないです。
MVCの話をしていたので、テーブルと言えばデータテーブルだとわかっていただけるかと思いました、すみません。謝ります。これはデータテーブル、もしくはエンティティのことです。そうだとして、もう一度私の質問にお答えください。
>何にせよ、質問者さんの例の日次、週次、月次うんぬんをベースに話をするのは止めましょう。明確に目に見える実体がないので、たぶん、みんな違うイメージを持っていて、いつまで議論していても話が収束しません。そうは思いません。これは質問者さんの質問に回答するためのスレッドです。質問者さんを無視して、私とSurferOnWwwさんが議論するスレッドではありません。ただでさえ、スレッドが長くなり、質問者さんには申し訳ないと思っています。
>なので、私が挙げた VS2010 のテンプレートで作る AcountController や、trapemiya が紹介されたサンプルとか、実例が見えるものをベースに話をしましょう。
AcountControllerについては、何度も言っていると思いますがその作りで全く問題ありません。私が提案した案に少なくともSurferOnWwwさんは疑問に思われているわけですから、その理由を教えていただくだけです。もし、世の中に私の思い付きと同じサンプルが無いなら、私がそのパターンの偉大な発明者かもしれませんし(笑)偉大な発明かそうじゃないかを議論したいだけです(大げさ)。議論するためには反対の理由を聞かなければ話が進まない、それだけのことだと思っています。その両方の意見を出し、あとは質問者さんがいずれ判断するような形にして、このスレッドは閉じれば良いと思います。質問者さんが考察できるためには、理由が必要です。私は理由を述べているつもりですが、SurferOnWwwさんからは理由をあまりいただいていません。
私は単に、私の意見、SureferOnWwwさんの意見、そしてそれぞれの理由を揃えて、質問者さんに提示したいだけですし、それが質問者さんへの回答だと思います。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2013年12月21日 5:56
-
やっぱりぜんぜん話が噛み合ってないようです。
> 私が提案した案に少なくともSurferOnWwwさんは疑問に思われているわけです
> から、その理由を教えていただくだけです。先のレスですでに述べています。理解していただけないか、聞く耳を持たれていないだけだと思います。
この先も議論を続けるというご希望ならもう一回お願いします。
> 質問者さんの例の日次、週次、月次うんぬんをベースにした話ではなく
> て、Microsoft が Visual Studio に実装したウィザードやチュートリ
> アルに逆行するような目からウロコ的なサンプルを、Microsoft が紹介
> していたら教えていただきたいというお願いです。 -
すみません。とりあえず私の質問に答えていただけませんか?私は、SurferOnWwwさんがおかしいと思われているという理由が、Visual Studioのウィザードから作成されるパターンと外れている以外に答えていただいていないと思っています。しかも、私が述べた理由に対してもいただいていません。私の意見がおかしいと思われているなら、サンプルを差し出す必要がなく、ダメだと思われている理由を述べていただくだけです。この部分がダメとはっきり言っていただければ済むことです。サンプルは出せません。私が勝手に言っているだけです。ごめんなさいでかまいません。ただ、私は私の意見に対するSurfeOnWwwさんの見解が聞きたいのです。ずっと私は同じことを言っていますが、私の言い方が悪くて理解していただけないのでしょうか? もしくは私の理解力が低くて、もう答えているけど私が理解できていないからでしょうか? 先のレスですでに述べていますと書かれていますが、具体的にどの部分でしょうか? わかりませんでした。
話がかみ合うも何も、私の質問に答えていただけなければ、かみ合わないのも当然です。かみ合わないのであれば、お互いにかみ合うように努力しましょうよ。ですから、ダメだと思われている理由を教えて下さい。お願いします。先に私が書いた以下についてどう思われているか教えて下さい。>クラスをオブジェクトとして捉えず、単なるグルーピングの道具として見れば関連しているかもしれません。しかし、オブジェクト指向的には関連しているようには思えないのです。
保守性に関しても、日次ビューでは日次に関するコントローラー部分しか見ないわけですから、余計なソースが含まれたクラスから当該の部分を探す必要がなくなります。命名的にも、日次ビューであれば、同じ日次が語頭にある日次コントローラーを見れば良いということがすぐにわかりますが、共通の1つのコントローラーにした際にはそのような命名にできませんから、どのコントローラーを見えれば良いのかがわかりにくくなります。また、先にも書きましたが、日次コントローラーを弄っても日次ビュー以外には一切の影響が出ませんが、共通の1つのコントローラーの場合ですと、知らぬ間に他のビューに影響が出てしまう可能性が残ります。そもそもMVCはビューとモデルを疎結合にしますが、他に影響を与えにくいように設計することは、良質のアプリケーションにとって欠かせないことだと思います。>MVCの話をしていたので、テーブルと言えばデータテーブルだとわかっていただけるかと思いました、すみません。謝ります。これはデータテーブル、もしくはエンティティのことです。そうだとして、もう一度私の質問にお答えください。
あと、コントローラーがわかれている方がチームでも開発しやすいとも発言しているので、それについても意見を下さい。私は私の回答が誤っているとは思っていません。例え標準と外れていたとしてもです。私はサンプルだから絶対に良いと信じることはありません。サンプルはもちろん参考にしますが、あくまで他のサンプルや情報から最終的に自分で考えて判断します。ですから、その考えに間違いがあれば教えてほしいのです。純粋にそう思っているだけです。日次ビュー、月次ビューに対して如何によいアドバイスができるか? それが回答者の責任でしょう? ごめんなさい、話が進まないので少し厳しい言い方をします。私にはSurferOnWwwさんが質問者さんの質問から逃げているように見えます。なぜならこれについて話すわけではなく、Visual Sudioのウィザードやサンプルを求めてばかりいるからです。Visual Studioやサンプルの件を持ち出してはいけないわけではありません。ただ、肝心の日次ビューや月次ビューの問題が不在のままでそれらを持ち出しても仕方ないと思います。Microsoftのサンプルが無いから私の意見が間違っているとか、私と議論できないというのは、一般的におかしいと私は思います。サンプルとかの話ではなく、私は私の意見に対するSurferOnWwwさん自身の意見が知りたいのです。そしてそれが、この質問のスレッドの有益な情報の一つになると思っています。
>私は単に、私の意見、SureferOnWwwさんの意見、そしてそれぞれの理由を揃えて、質問者さんに提示したいだけですし、それが質問者さんへの回答だと思います。
繰り返します。これでこのスレッドを閉めるべきだと思いませんか? これ以上のことをここで議論することは、筋から外れると思います。どう思いますか?
#少なくとも私の質問には答えていただけませんか? そうしなければ私にはSurfeOnWwwさんがどう考えておられるかわからないわけですから、話がかみ合わなくなるのも当然だと思います。繰り返します。お互い、かみ合う努力をしませんか?
- 編集済み trapemiyaModerator 2013年12月21日 13:58 追記
-
整理しましょう。あくまで日次、月次スケジュールなど、このスレッドの質問に関してです。それ以外は本筋から外れますから、取り上げません。これはモデレータとしてのお願いでもあります。
▼私の意見
ビュー毎にコントローラーを持たせるのが良いと思う。この場合、ビューには1つのモデルを使用すれば十分だと思うので、結果的に1つのモデルに1つのコントローラーということになる。このスレッドの質問からビューを基準に答えていますが、実際にはモデルをベースに考えるべきだと思う。
理由
1.コントローラーが分かれているので、チームで開発した際に平行して開発できる。
2.コントローラーが分かれているので、あるビューに関するコントローラーの修正が他のコントローラーに影響を与える可能性がない。
3.語頭に同じ名前つけることにより、あるビューに対するコントローラーがどれかがすぐにわかる。
4.仮に複数ビューを1つのコントローラーにまとめたとしても、各ビューに表示するモデルはかなり違うことが予想され、関連の無いメソッドが並ぶことになり、編集する際にそれらのコードが目障りである。また、関連性がないメソッドが同一クラスにいるのはオブジェクト指向的にもおかしい。関連がないのは、一つのインスタンスで違うビューに関するメソッドを同時に使うことがないからである。であれば、それらまでインスタンス化するのは全くの無駄である。▼SurferOnWwwさん。
ビュー毎にコントローラーを持たせるのはあり得ない。絶対ではないが、納得できない。
理由
1.同じスケジュールを扱うのだからメソッドは関連している。それらは同じクラスにいるべきである。
2.Visual Studioのウィザードは、複数メソッドで一つのコントローラーという形で生成する。だから、それが標準でありそこから外れるのはおかしい。◆私の意見に対するSurferOnWwwさんの意見
何もいただいていない。
◆SurferOnWwwさんの意見に対する私の意見
1.に対して。既に私の理由で述べた通り。モデルが異なるのにコントローラーを一つのインスタンスで作成する意味があるのか? インスタンスを作成する時、あるビューに関するメソッドなど特定の部分のみ使用するためにインスタンス化する。これは設計の段階で明らかなため、オブジェクトとして分離すべき。
2.に対して。ウィザードはあくまで標準の一つを示しているだけで、標準が一つしかないということを証明するものではない。例え私の意見に沿ったサンプルがMicrosoftに無くても、私の意見が間違いと言えるだろうか? その発想ではMicrosoftのサンプル以上に良いものは生まれない。むしろ、いろんな異なるサンプルや情報を検討し、新しくて良いものを生み出すように努力すべき。私は私の考えをある一つのサンプルから導いているわけでなく、そうやって考えたものである。私がいろいろな経験から考えたものだから、世の中にサンプルが無い(かもしれない)。だから私の意見が間違っているかどうかをSurferOnWwwさんに指摘してほしい。■最終的に私が思っていること。
私の意見がどのような場合でも適切とは思っていない。SurferOnWwwさんが言われることも間違いではないので、何らかの理由により、そのように設計にすることもありだと思う。ケースバイケース。だから正解を決めることはできない。なので、どちらいいとか悪いではなく、私は私の考えに対する意見を聞きたい。それは、このスレッドの回答としても有益なものになると思う。
#以上、間違いや「私の意見に対するSurferOnWwwさんの意見」の欄を埋めて下さい。それでこのスレッドを閉めましょう。決して逃げるわけではありませんが、モデレーターの立場として、これはモデレーターとしてでのお願いでもあります。ご理解下さい。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2013年12月21日 14:51 誤字修正
-
私の意見をご自分の都合のいいように勝手に変えておられるような気がしますので、そこのところだけ訂正して終わりにします。
▼SurferOnWww の意見ASP.NET MVC アーキテクチャの中心は本質的にコントローラーにあるということで、最初にビューありきではなく、まずコントローラーを考えます。
通常、アプリで操作するオブジェクトごとにコントローラクラスを定義し、予想されるリクエストを処理するアクションメソッドをそのクラスにまとめるということになると思います。(以上は一番最初のレスで述べたとおり)
理由
1.「ASP.NET MVC アーキテクチャの中心は本質的にコントローラーにある」に同意。
2.事実上の標準と認識している。ASP.NET MVC に関する数々の文献、チュートリアル、Visual Studio のウィザードなどがそれを裏付けている。
◆trapemiya さんの意見に対する SurferOnWww の意見(これも先に述べたとおり)
否定はしていません。そういうケースがあるかもしれないという可能性は、自分のつたない経験では排除し切れません。
ただし納得はしてません。なので何かサンプル(目からウロコ的な)があれば教えていただきたいとお願いしました。 -
>私の意見をご自分の都合のいいように勝手に変えておられるような気がしますので、そこのところだけ訂正して終わりにします。
そんなつもりは全くありません。常に第3者の目から自分の考えを確認し直すようにしているつもりですし、自分の考えを正当化しようと強引に論理を進めているつもりは全くありません。しかし、書き方に失礼があったのであれば謝らなければなりません。「そこのところ」とはどこのところでしょうか?もう少し詳しく教えて下さい。
お互い、気まずい思いでクローズしてもよくありませんので、ご指摘ください。お願いいたします。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2013年12月22日 13:28 追記