(MVCを大幅に使用する大きなMATLAB GUIを書いているので、私の例はMATLABで書かれています。しかし、この質問は言語に依存しないと思います。間違っている場合は修正してください。)
私はクラスModel
を持っています。これは明らかに私のMVCアプリケーションのモデルです。私が以下を持っていると仮定します:
classdef Model < handle
properties
objectA
objectB
objectC
end
end
objectA
、objectB
、およびobjectC
はすべて、監視可能なオブジェクトです。
classdef objectA < handle
events
ObjectAEvent
end
methods
function raise(this)
this.notify('ObjectAEvent', someEventData);
end
end
end
等.
View
がModel
への変更に応答するようにしたいとします。特に、View
がObjectAEvent
イベントに応答することを望んでいます。これを行うには2つの方法があります。
View
にObjectAEvent
イベントを直接サブスクライブさせます。これでView
をModel
の内部に結合しました。これはデメテルの法則に違反していると思います。これもMVCの概念に本質的に違反していると確信しています。
次のように、Model
にイベントをView
に「転送」させます。
classdef Model < handle
properties
objectA
objectB
objectC
listeners
end
events
eventFromObjectA
...
end
methods
function this = Model
this.listeners(1) = addlistener(this.objectA, 'ObjectAEvent', @(src, eventdata) this.notify('eventFromObjectA', eventdata);
...
end
end
end
これでView
はModel
を直接監視しますが、Model
はイベントと関連データをView
に渡す必要があります。これはMVCの要点の1つだと思いますが、今では各object_
とModel
の間に直接結合があります。私はModel
が彼のobject_
sについて知っておくべきだと思いますが、それでもまだ不快に感じます...
どちらのアプローチがより正しいですか?これらのどちらよりもきれいな他の選択肢はありますか?
(回答には、OOP言語の例があります。MATLABに最も慣れています。)
View
にObjectAEvent
イベントを直接サブスクライブさせます。ビューをモデルの内部に結合しました。これは、デメテルの法則に違反していると思います。これもMVCの概念に本質的に違反していると確信しています。
MVCはtotalデカップリングについてではありません。不安定な要素への結合を回避することです。デメテルの法則については、違反していると考える理由を示す必要があります。その名前に「法」という言葉が含まれているにも関わらず、それはまた、難しくて速い原則でもありません。ある時点で違反しないことはほぼ不可能です。
ビューはユーザーインターフェイスの一部であるため、ビュークラスはモデルクラスよりもstableになる傾向があります。ユーザーは情報を表示するための新しい方法を望む傾向があります(最初に正しく表示するのは難しい)など。 Microsoft WordのGUIが何回変更されたにもかかわらず、ドキュメントのモデル(段落、単語、文字、フォント、スタイルなどを考える)はあまり変更されていませんか?
MVCでは、モデルクラスがより安定する傾向があるため、ビューをモデルクラスに直接結合できます。 MVCは、この選択を設計上の選択として行います。モデルクラスが変更された場合(それが発生する可能性があります)、モデルに分離されている変更に対してすべての賭けが行われません。おそらく、ビューも変更する必要があります。
モデルクラスはビューと通信する必要がありますが、MVCは直接結合を避けたいと考えています。この問題を回避するには、ビューを「オブザーバー」に偽装します。 Observer APIは、それを実装するビューがそうでなくても、非常に安定しています。私がMVCを理解している限り、ポイント1で説明した方法で結合しても問題ありません。
ObjectAではなく実際のオブジェクトを使用してみましょう、engineTemperature
としましょう。温度を表示するビューは、それが何を表示しているかを確実に知るでしょう。ビューは値が温度であることを認識しているため、「度C」の単位が追加される場合があります。温度が上限値を超えると、赤色になる場合があります。ビューが表示するモデル要素にビューが直接結合されるのは正常です。
ただし、その逆は異なります。 engineTemperature
は、それがどのように表示されているか、どの色が使用されているか、誰が表示しているかなどを知らないはずです。ビューを変更すると、温度オブジェクトが「壊れる」可能性があります。したがって、MVCとオブザーバーを使用すると、engineTemperature
(オブザーバーパターンのサブジェクトとして)は、オブザーバーが存在することのみを認識します。オブザーバーはすべてオブザーバーAPIをサポートしています。
MVCおよびその他のUI設計の詳細については、 http://martinfowler.com/eaaDev/uiArchs.html#ModelViewController を参照してください。