Apple Developer Connection
Advanced Search
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page >

Model-View-Controllerデザインパターン

Model-View-Controllerデザインパターン(MVC)はかなり以前から存在します。MVCのバリエーションの登場は、少なくとも初期のSmalltalkの頃にまでさかのぼります。MVCは、アプリケーションのグローバルなアーキテクチャを対象とし、アプリケーションにおける大まかな役割に従ってオブジェクトを分類するという点では、高次元のパターンといえます。また、複数のより基礎的なパターンで構成されるという点では、複合パターンでもあります。

オブジェクト指向プログラムでは、そのデザインにMVCデザインパターンを応用することによって、いくつかの利点がもたらされます。MVCデザインパターンを応用したプログラムのオブジェクトの多くは再利用性、およびインターフェイス定義の質が高いという傾向があります。また、要件の変化に対するプログラム全体の順応性も高まります。つまり、MVCをベースとしていないプログラムよりも拡張しやすいのです。さらに、Cocoaの数多くの技術やアーキテクチャ(バインディング、ドキュメントアーキテクチャ、スクリプト対応など)はMVCをベースにしており、カスタムオブジェクトは、MVCによって定義されている役割の1つを担うことが求められます。

In this section:

MVCオブジェクトの役割と関係
Cocoaのコントローラオブジェクトの種類
複合デザインパターンとしてのMVC
MVCアプリケーションのためのデザインガイドライン
CocoaにおけるModel-View-Controller


MVCオブジェクトの役割と関係

MVCデザインパターンでは、モデルオブジェクト、ビューオブジェクト、コントローラオブジェクトの3種類のオブジェクトが存在するものとしています。このパターンでは、これらの種類のオブジェクトがアプリケーションの中で果たす役割およびオブジェクトどうしのやり取りの経路が定義されています。アプリケーションを設計する際の重要な手順の1つが、これら3つのグループの1つに該当するオブジェクトを選ぶこと(またはそのオブジェクトのカスタムクラスを作成すること)です。これら3種類のオブジェクトはそれぞれ、抽象的な境界によって分かれており、この境界を越えて互いにやり取りします。

モデルオブジェクトはデータと基本的な動作をカプセル化する

モデルオブジェクトは特別な知識や専門技術を表します。これらのオブジェクトは、アプリケーションのデータを保持し、それらのデータを操作するロジックを定義します。適切に設計されたMVCアプリケーションでは、アプリケーションの重要なデータがすべてモデルオブジェクトにカプセル化されます。アプリケーションの永続状態の一部となるデータはすべて、その永続状態の格納場所(ファイル、データベース、パンチカードなど)に関係なく、アプリケーションにロードされた後は、モデルオブジェクトになければなりません。モデルオブジェクトは特定の問題領域に関係する知識や専門技術を表すため、再利用性が高い傾向があります。

モデルオブジェクトには、その表示や編集に使用されるユーザインターフェイスへの明示的なつながりが存在しないことが理想です。たとえば、住所録などを開発する際に、個人を表すモデルオブジェクトを作成する場合、オブジェクトに誕生日を格納することが考えられます。そのようなデータをPersonというモデルオブジェクトに格納することはよい考えです。しかし、日付の表示方法に関する日付書式文字列その他の情報は、おそらく別の場所に格納したほうがよいでしょう。

実際にはこのような分離は必ずしも最善ではなく、柔軟に考える余地も多少ありますが、一般には、モデルオブジェクトはインターフェイスや表示に関することがらに関与すべきではありません。多少の妥当な例外が考えられる例として、描画アプリケーションがあります。描画アプリケーションには、表示されるグラフィックスを表現するモデルオブジェクトがあります。グラフィックオブジェクトがオブジェクト自身の描画方法を知っていることは理にかなっています。なぜなら、グラフィックオブジェクトの主な存在理由が視覚的な要素を定義することだからです。しかし、このような場合でも、グラフィックオブジェクトは特定のビューの中に自身が存在していることや、そもそもビューの中に存在すること自体を前提とするべきではなく、自身の描画のタイミングを知っている責任も負うべできはありません。それらの表示を必要とするビューオブジェクトに描画を要求されるべきなのです。

参考資料: モデルオブジェクトの適切なデザインと実装の詳細については、『Model Object Implementation Guide』を参照してください。

ビューオブジェクトは情報をユーザに提示する

ビューオブジェクトは、データの表示方法を認識しています。また、アプリケーションのモデルからのデータをユーザが編集できるようにする場合があります。ビューには、表示対象のデータを格納する役割を持たせるべきではありません(もちろんこれは、表示対象のデータを決して格納することはない、という意味ではありません。ビューはパフォーマンス向上のためにデータをキャッシュしたり、他の同様の技法を使ったりすることができます)。ビューオブジェクトには、モデルオブジェクトの一部のみ、またはモデルオブジェクトの全体、あるいは多数の異なるモデルオブジェクトを、表示する役割を持たせることができます。ビューには多数の異なるバリエーションが存在します。

ビューオブジェクトは再利用や設定が可能に場合が多く、複数のアプリケーションに一貫性を持たせることができます。Cocoaでは、Application Kitに非常に多くのビューオブジェクトが定義されており、その多くはInterface Builderパレットに用意されます。たとえば、Application KitのビューオブジェクトであるNSButtonオブジェクトを再利用することで、アプリケーション内のボタンがほかのCocoaアプリケーションのボタンとまったく同様に動作することが保証され、複数のアプリケーションにわたって外観や動作の一貫性が高いレベルで保たれます。

ビューは、モデルを正確に表示しなければなりません。そのため、通常はモデルに対する変更を知る必要があります。モデルオブジェクトは、特定のビューオブジェクトに結び付くことを避けるべきであるため、変更があったことを知らせる汎用の手段が必要になります。

コントローラオブジェクトはモデルをビューに結び付ける

コントローラオブジェクトは、アプリケーションのビューオブジェクトとモデルオブジェクトとの間の仲介役として機能します。多くの場合、コントローラは、ビューで表示する必要のあるモデルオブジェクトにビューが確実にアクセスできるようにする役割を担い、モデルに加えられた変更をビューが知るための伝達路として動作します。また、コントローラオブジェクトでは、アプリケーションの準備処理や調整処理を実行し、ほかのオブジェクトのライフサイクルを管理することもできます。

Cocoaの典型的なMVCデザインでは、ユーザがビューオブジェクトを通じて値を入力したり選択肢を示したりしたときに、その値や選択肢がコントローラオブジェクトに伝達されます。コントローラオブジェクトでは、たとえばアプリケーション固有の何らかの方法でユーザ入力を解釈した後、その入力に関して何を実行すべきか(“新しい値を追加する”や“現在のレコードを削除する”など)をモデルオブジェクトに指示したり、変更された値をモデルオブジェクトのプロパティの1つ反映させたりします。また、コントローラオブジェクトによっては、同じユーザ入力に応じて、外観や動作の一部を変更するようビューオブジェクトに指示する場合もあります(たとえばボタンを無効にするなど)。逆に、モデルオブジェクトが変更されたとき(新しいデータソースへのアクセスが発生したときなど)、通常はモデルオブジェクトからその変更がコントローラオブジェクトに伝達され、コントローラオブジェクトから1つまたは複数のビューオブジェクトに対して、変更に合わせて表示を更新するよう要求が出されます。

コントローラオブジェクトは、その大まかな種類に応じて、再利用可能であったり、そうでなかったりします。Cocoaにおける各種のコントローラオブジェクトの詳細については、“「Cocoaのコントローラオブジェクトの種類」”を参照してください。

役割の結合

オブジェクトが果たすMVCの役割を結合して、たとえば、オブジェクトにコントローラとビューの両方の役割を担うようにさせる、といったことができます。このようなオブジェクトは、ビュー-コントローラと呼ばれます。同様に、モデル-コントローラオブジェクトも可能です。アプリケーションによっては、そのデザインでこのような役割の結合が許容される場合があります。

モデル-コントローラは、主にモデル層に関与するコントローラです。モデル-コントローラはモデルを“所有”し、モデルの管理とビューオブジェクトとのやり取りを主な役割とします。モデル全体に適用されるアクションメソッドは、通常はモデル-コントローラに実装されます。ドキュメントアーキテクチャではこれらのアクションメソッドがいくつかあらかじめ用意されています。たとえば、ドキュメントアーキテクチャの中核であるNSDocumentオブジェクトは、ファイルの保存に関係するアクションメソッドを自動的に処理します。

ビュー-コントローラは、主にビュー層に関与するコントローラです。ビュー-コントローラはインターフェイス(ビュー)を“所有”し、インターフェイスの管理とモデル-コントローラとのやり取りを主な役割とします。ビューに表示されるデータに関与するアクションメソッドは、通常はビュー-コントローラに実装されます。ビュー-コントローラの例としては、同じくドキュメントアーキテクチャの一部であるNSWindowControllerオブジェクトがあります。

“「MVCアプリケーションのためのデザインガイドライン」”では、MVCの役割が結合されたオブジェクトに関するデザイン上のアドバイスを提供しています。

参考資料: 『Document-Based Applications Overview』では、モデル-コントローラとビュー-コントローラを別の観点から違い説明しています。

Cocoaのコントローラオブジェクトの種類

“「コントローラオブジェクトはモデルをビューに結び付ける」”のセクションでは、コントローラオブジェクトの抽象的な概要を示しましたが、実際にはその全体像ははるかに複雑です。Cocoaには、コントローラオブジェクトとして、大まかに分けて仲介コントローラと調整コントローラの2種類が存在します。これらのコントローラオブジェクトは、それぞれ異なるクラス群に関連付けられており、それぞれが異なる範囲の動作を提供します。

仲介コントローラは、通常はNSControllerクラスを継承するオブジェクトであり、Cocoaバインディング技術で使用されます。仲介コントローラは、ビューオブジェクトとモデルオブジェクトの間でデータの流れを促進します(つまり、仲介役となります)。

通常、仲介コントローラはInterface Builderパレットからドラッグする既製のオブジェクトです。これらのオブジェクトを設定することで、ビューオブジェクトのプロパティとコントローラオブジェクトのプロパティとを結ぶバインディングを確立した後、それらのコントローラプロパティとモデルオブジェクトの特定のプロパティとを結ぶバインディングを確立することができます。結果として、ビューオブジェクトに表示されている値をユーザが変更すると、仲介コントローラを通じて、新しい値がモデルオブジェクトに自動的に伝達されて格納されます。また、モデルのプロパティの値が変更されると、その変更がビューに伝達されて表示に反映されます。抽象クラスNSControllerとその具象サブクラスNSObjectControllerNSArrayControllerNSUserDefaultsController、およびNSTreeController)は、変更を確定および破棄する機能や、選択およびプレースホルダ値の管理などの、支援機能を提供します。

調整コントローラは、通常はNSWindowControllerオブジェクト、またはNSDocumentControllerオブジェクト、あるいはNSObjectのカスタムサブクラスのインスタンスです。調整コントローラは、アプリケーションの機能全体またはその一部(nibファイルから展開されるオブジェクトなど)を監視(つまり、調整)する役割を担います。調整コントローラが提供するサービスには次のものがあります。

NSWindowControllerおよびNSDocumentControllerは、Cocoaにおけるドキュメントベースアプリケーションを対象とするアーキテクチャの一部を構成するクラスです。これらのクラスのインスタンスは、前述のサービスのいくつかに対するデフォルト実装を提供します。それらのサブクラスを作成することでさらにアプリケーション固有の動作を実装できます。NSWindowControllerオブジェクトを使用して、アプリケーション内のウインドウのうちドキュメントアーキテクチャに基づいていないウインドウを管理することさえも可能です。

調整コントローラはしばしば、nibファイルにアーカイブされているオブジェクトを所有します。これらのオブジェクトには仲介コントローラやビューオブジェクトも含まれます。File's Ownerとしての仲介コントローラの詳細については、“「複合デザインパターンとしてのMVC」”を参照してください。

NSObjectのカスタムサブクラスのインスタンスは、調整コントローラとして最適な候補です。この種のコントローラオブジェクトでは、仲介と調整の両方の機能が結合されています。仲介の動作に関しては、これらのコントローラはターゲット/アクションやアウトレット、委任、通知などのメカニズムを利用して、ビューオブジェクトとモデルオブジェクトとの間のデータの流れを促進します。これらのコントローラオブジェクトには“グルーコード”が多数含まれる傾向があります。また、これらのコードは特にアプリケーションに固有のものであるため、アプリケーションの中で再利用度の最も低いオブジェクトになります。

参考資料: コントローラオブジェクトの仲介役としての役割の詳細については、“「Mediator」”デザインパターンを参照してください。Cocoaバインディング技術の詳細については、『Cocoa Bindings Programming Topics』を参照してください。

複合デザインパターンとしてのMVC

Model-View-Controllerは、より基本的な複数のデザインパターンで構成されているデザインパターンです。これらの基本的なパターンが連携することで、MVCアプリケーションの特徴である機能の分離や通信経路を定義しています。しかし、従来のMVCの概念において適用される一連の基本パターンは、Cocoaで適用されるものとは異なります。その主な違いは、アプリケーションのコントローラオブジェクトとビューオブジェクトに与えられる役割にあります。

本来の(Smalltalkでの)概念では、MVCは、Composite、Strategy、Observerの各パターンで構成されます。

これらのパターンは、Figure 4-4に示すように連携して動作します。ユーザは、構成構造のいずれかのレベルで、ビューを操作します。その結果、イベントが生成されます。コントローラオブジェクトはそのイベントを受信し、アプリケーション固有の方法で解釈します(つまり、戦略を適用します)。この戦略では、モデルオブジェクトの状態を変更するための要求を(メッセージを通じて)行ったり、(構成構造のいずれかのレベルに存在する)ビューオブジェクトに対してその動作や外観を変更するよう要求したりできます。これらの要求に応答して、モデルオブジェクトは、オブザーバとして登録されているすべてのオブジェクトに対して、自身の状態が変更されたことを通知します。オブザーバがビューオブジェクトの場合は、その外観を必要に応じて更新する場合もあります。


Figure 4-4  複合パターンとしてのMVC(従来の場合)

Figure 4-4 複合パターンとしてのMVC(従来の場合)

Cocoaの場合における複合パターンとしてのMVCも、従来の場合といくつかの類似点があり、実際、Figure 4-4の図に基づいて動作するアプリケーションを構築することもまったく可能です。バインディング技術を使用することで、ビューからモデルオブジェクトを直接監視し、状態変更の通知を受信する、CocoaのMVCアプリケーションを簡単に作成できます。ただし、このデザインには理論上の問題があります。ビューオブジェクトとモデルオブジェクトは、アプリケーションの中で再利用性の最も高いオブジェクトであるはずです。ビューオブジェクトは、オペレーティングシステムと、そのシステムでサポートされるアプリケーションの、いわば“ルックアンドフィール”を表しています。外観と動作の一貫性は重要であり、そのためには再利用性の高いオブジェクトが必要になります。モデルオブジェクトは、その定義上、問題領域に関連するデータをカプセル化し、そのデータを対象に操作を実行します。デザインの面では、再利用性を高めるために、モデルオブジェクトとビューオブジェクトは互いに切り離しておくのが最善です。

ほとんどのCocoaアプリケーションでは、モデルオブジェクトにおける状態変更の通知はコントローラオブジェクトを通じてビューオブジェクトに伝達されます。Figure 4-5はこの別の構成を示します。基本的なデザインパターンがさらに2つ関与しているにもかかわらず、ずっと明快です。


Figure 4-5  複合パターンとしてのMVC(Cocoaの場合)

Figure 4-5 複合パターンとしてのMVC(Cocoaの場合)

この複合デザインパターンにおけるコントローラオブジェクトには、StrategyパターンだけでなくMediatorパターンも組み込まれています。このコントローラオブジェクトは、モデルオブジェクトとビューオブジェクトとの間の双方向のデータの流れを仲介します。モデルの状態の変更は、アプリケーションのコントローラオブジェクトを通じてビューオブジェクトに伝達されます。また、ビューオブジェクトには、ターゲット/アクションメカニズムの実装を通じて、Commandパターンも組み込まれています。

注: ビューオブジェクトからユーザの入力や選択肢を伝達できるようにするターゲット/アクションメカニズムは、調整と仲介の両方のコントローラオブジェクトに実装できます。ただし、メカニズムのデザインはそれぞれの種類のコントローラで異なります。調整コントローラの場合、Interface Builderでビューオブジェクトをそのターゲット(コントローラオブジェクト)につなぎ、特定のシグネチャに準拠する必要のあるアクションセレクタを指定します。調整コントローラは、ウインドウおよびグローバルアプリケーションオブジェクトのデリゲートであるため、レスポンダチェーンの中に置くこともできます。仲介コントローラで使用されるバインディングメカニズムもまた、ビューオブジェクトをターゲットにつなげ、任意の数の任意の型の引数を持つアクションシグネチャを使用できます。ただし、仲介コントローラはレスポンダチェーンの中に置かれることはありません。

Figure 4-5に示した改正版の複合デザインパターンを使用する理由としては、特にMediatorデザインパターンの場合において、理論上の理由だけでなく実用上の理由もあります。仲介コントローラはNSControllerの具象サブクラスから派生され、それらのクラスは、Mediatorパターンの実装以外に、アプリケーションで利用すべき機能(選択やプレースホルダ値の管理など)を数多く提供します。仮にバインディング技術を使用しないことを選択した場合、ビューオブジェクトではCocoaの通知センターなどのメカニズムを使用して、モデルオブジェクトから通知を受信することも可能です。しかし、そのためにはカスタムビューサブクラスを作成し、モデルオブジェクトによってポストされる通知を受け取る手段を追加しなければならなくなります。

適切に設計されたCocoaのMVCアプリケーションでは、多くの場合、調整コントローラが仲介コントローラを“所有”します(仲介コントローラはnibファイルにアーカイブされます)。Figure 4-6は、2種類のコントローラオブジェクトの関係を示します。


Figure 4-6  nibファイルの所有者としての調整コントローラ

Figure 4-6 nibファイルの所有者としての調整コントローラ

MVCアプリケーションのためのデザインガイドライン

次のガイドラインは、アプリケーションのデザインにおけるModel-View-Controllerにかかわる事項に適用されます。

CocoaにおけるModel-View-Controller

Model-View-Controllerデザインパターンは、Cocoaの数多くのメカニズムや技術の基礎になっています。したがって、オブジェクト指向のデザインにおいてMVCを使用することの重要性は、アプリケーションの再利用性および拡張性を高めることだけにとどまりません。MVCに基づくCocoa技術をアプリケーションに組み込む場合、その設計もMVCのパターンに従っていれば、アプリケーションの動作が最適になります。アプリケーションのMVCの分離が適切であれば、これらの技術を利用するのは比較的容易になるはずです。逆に分離が適切でなければ、より多くの作業が必要になります。

Cocoaには、Model-View-Controllerに基づく次のアーキテクチャ、メカニズム、および技術が組み込まれています。

参考資料: 『“Other Cocoa Architectures”』では、ドキュメントアーキテクチャ、アプリケーションのスクリプト対応機能、およびCore Dataの概要について説明しています。また、これらの技術について詳しく説明している文書への相互参照もあります。



< Previous PageNext Page >


Last updated: 2006-05-23




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice