MVC の Cocoa バージョンは、MVC の実際の定義の一種のサブセットであると言えますが、それらは別個のエンティティではありません。通常、MVC の Cocoa バージョンは、ビュー (通常はNSWindow
および/またはNSView
)、コントローラー (通常はNSWindowController
)、およびモデル レイヤー (単純な配列から Core Data スタックまでのすべて) の使用を中心に展開します。このモデルにおける権限の分離は明確ですが、Wiki が定義する「層」構造のどこにこれらのそれぞれが属するべきでしょうか?
コントローラーとビューはクライアント層の一部であると私は主張します。コントローラーは、モデルとビューの間の委任を担当するだけでなく、ユーザー イベントに応答し、フレームワーク以外のエラー処理中に実行する正しい一連のアクションを決定する責任があります。このアプローチを MVC に適用することで、実際に Cocoa がパターンのより広い定義をどのように満たしているかを確認し始めることができます。
3 層アーキテクチャの基本的なルールは、クライアント層がデータ層と直接通信しないことです。
これはおそらく 3 つの中で最も推論が難しいものであり、パターンのコンテキストで「コミュニケーション」が実際に何を意味するのかを掘り下げる必要があります。コミュニケーションとは、コントローラーがモデルのアクションに直接関与しないことを意味します。これは、コントローラーがモデルの内容の変更を命令できないということではなく、コントローラーがモデル自体の更新方法に関与していないということです。コントローラーはインプリメンターではなくディレクターとして機能するため、データベース層の作成が大幅に簡素化されます。これが、Core Data と SQLite3 が Foundation クラスではなく外部フレームワークとして存在する理由の 1 つです。
ビュー オブジェクトは通常、MVC アプリケーションのモデル オブジェクトから切り離されます。
これは、パターンを使用してプログラミングする際に古くからあるタブーの 1 つを引き起こします: ビューを賢くしすぎることです。コントローラーはモデルとビューの間に強固なバリアを提供し、コントローラーがモデル レイヤーからのコンテンツのディレクタおよびフィルターとして機能するようにします。そのような障壁がなければ、たとえばテーブルビューは、すべてのセルにデータベースからのデータのコピーがあり、変更が別のセルに伝播されたときにいつどのように更新するかを各セルが認識していることを確認する必要があります。ココアでは、これが私たちの場所ですNSWindowControllers
それらはルート ビューの表示を管理し、一部のモデルとそれが管理するビューのコンテンツとの間の障壁として機能します。ただし、Cocoa のコントローラー オブジェクトはビューに偏っていることに注意することが重要です。これは主に、不要な接着剤をかなり使わずに、あらゆる種類のモデル レイヤーに汎用的なアウトレットを提供することがほぼ不可能であるためです。
モデル オブジェクトが変更されると (たとえば、ネットワーク接続を介して新しいデータを受信した場合)、コントローラー オブジェクトに通知され、適切なビュー オブジェクトが更新されます。
上で説明した理由から、そうあるべきです。しかし、あなたが与えたネットワーキングの例に基づいて構築するには、これを考慮してください: データをフェッチする NSOperation と、テーブルビューを管理するコントローラーが与えられた場合、おそらくコントローラーがその太い指を操作に突き刺したくないでしょう。テーブルビューは生NSData
で受信し、貴重なレンダリング時間を結果の処理と表示に費やさなければなりません。
等々。それで、ここで何が問題なのですか?一般的なものに関係なく、Cocoa は独自の MVC の考え方を採用していますか? それとも、MVC アーキテクチャの一般的な見方に欠けているものがありますか?
私がこれから導き出す結論は、MVC と Cocoa がそれを行う方法における権力の分離に関するあなたの定義が間違っているということだと思います。現在、Objective-C コミュニティ内でMVVMに向けた興味深い動きがありますが、Cocoa はこのパターンに固執することにかなり厳格です。