Qtがモデル/ビューの用語を誤用しているのはなぜですか?


104

Qtでモデル/ビューコントロールを使用して使用されている用語には欠陥があると思います。上の彼らの説明ページ彼らはビューとコントローラをマージして、彼らは以下の画像を与えていることにより、MVにMVCを簡素化することを、状態:

Qt MVCを説明する画像

しかし、私は彼らがオブジェクトの役割を誤って名付けたと思います。

  1. マージされたコントローラーでビューと呼ばれるものは、実際にはビューのみです。
  2. 彼らがモデルと呼んでいるものは、実際にはコントローラのみです。
  3. あなたが本当にモデルを持ちたいなら、それは彼らの「データ」がどこかにあるでしょう。

アプリでQtモデル/ビューコンポーネントを使用する通常の方法について話しています。理由は次のとおりです。

  1. これは通常、オブジェクトに固有のコントローラーロジックを追加せずに、そのまま使用されるQtコンポーネントです)
  2. これはモデルではありません。モデルとは何の関係もない、rowCount、columnCount、dataなどのいくつかのQtメソッドを実装する必要があるからです。実際、コントローラーには典型的なモデルメソッドがあります。もちろん、ここでコントローラーモデルの両方のロジックを実装できますが、最初はコード設計が非常に悪くなり、次に、コントローラーとビューではなく、コントローラーとモデルをマージします。
  3. 理由2で述べたように、モデルロジックを分離したい場合、それは確かに画像の青いボックスではなく、破線の「データ」ボックスです(もちろん、実際のデータと通信しています)。

Qtの用語が間違っていますか、それとも理解できないのは私だけですか?(ところで、それが学術的な問題ではない理由は、プロジェクトの命名に続いてコードを書き始めたのですが、すぐにコードが正しくないことに気づきました。それが後になって初めて、彼らがモデルと呼ぶものにモデルロジックを入れないでください)


1
MFCは、CDocとCViewを使用して2partモデル/ビューguiの標準を設定しました-特定のMVCが「正しい」という理由はありません
Martin Beckett

@Martin B:私はMFCを見ていきますが、異なるMVCモデルがあったとしても、それらの用語は一貫しているはずであり、有効な議論を示したと思います。この特定のケースでは、使用されている用語が一貫していないのはなぜですか。彼らは単にViewとControllerを組み合わせたと述べているだけですが、私はそれがこのケースでは単なる誤解を招くものだと思います。プレゼンテーションやモデルロジックなど、アプリケーション固有のすべてのロジックをModelという1つのオブジェクトに配置する必要があるMVCモデルはないと思います。
11

1
@Martin B:また、qt用語では、すべてのモデルに共通のAPIがあります。これは、モデル構造とは関係ありませんが、一般的なコントローラー構造とはすべて関係があります。正しいMVCモデルが1つあると言っているわけではありませんが、MVCモデルと呼べるものはありません。多分それはMFCにも欠陥があり、私はそれを見ることができますが、私が使用するつもりのないMFC、それを正しく理解することにもっと興味があります。MFCモデル/ビューの分離が説明されている良いリンクはありますか?
11

1
MVC用語は満場一致で決して合意されていないので、あなたの質問は議論の余地があると見なすことができます。しかし、マーティンファウラー(martinfowler.com/eaaDev/index.html)が行った優れた作業には多くの人が同意します。通常、コントローラーはユーザー入力を処理し、この意味で、Qtウィジェットはビューとコントローラーを確実に組み合わせます。
アーノルドスペンス

1
MVCには多くのフレーバーがあることは理解していますが、MVCになることができるという意味ではありません。Qtは限界を超え、いくつかの理由を挙げました。Martin FowlerはさまざまなタイプのMVCについて説明していますが、どちらもQtがMVCを発音しているものと十分に類似しています。最も似ているのはmartinfowler.com/eaaDev/PresentationModel.htmlですが、これはPresentation Model = Controller(ユーザーインタラクション)の部分とModel(データロジック)を区別します。したがって、MVCの正確な定義はありませんが、Qtはそれらのいずれにも従いません。そのような定義へのリンクを提供していただける場合は、そうしてください。
11

回答:


78

Qtの命名が誤解を招くものであることに同意します。ただし、私の意見では、問題はQtだけではなく、UIを実装するときに懸念分離の原則に準拠できるようにするすべてのフレームワークによって共有されます。誰かがそのようなフレームワークを思いついて、「もの」を分離しておく良い方法を見つけたとき、彼らは常に「モデル」と呼ぶモジュールと「ビュー」と呼ぶモジュールを持っている義務があると感じています。長年にわたり、私はこれらのフレームワークを使用してきました:

  • MFC
  • Qt
  • スイング
  • SWT
  • MVVMを使用したWPF

これらのフレームワークで「モデル」と「ビュー」という用語がどのように使用されているかを比較し、「ビュー」、「モデル」、および「コントローラー」(存在する場合)のク​​ラスにどのような責任があるかを比較すると、非常に大きな違いがあることがわかります。異なる概念や用語を比較すると、あるフレームワークから別のフレームワークに切り替える人が正気を保つことができるようになりますが、多くの作業と調査が必要になります。読みやすいのは、Martin Fowlerの概要です。

非常に多くの異なる考えがあるので、どのようなMVCパターンは1つが正しいとする、のように見えることができますか?私の意見では、MVCを発明した人々は、それがどのように「正しく」実装されることになっているのかを知りたいときに頼るべきです。で、元のSmalltalkの紙それは言います:

ビューは、そのアプリケーションに割り当てられているビットマップ表示の部分へのグラフィックおよび/またはテキスト出力を管理します。コントローラーは、ユーザーからのマウスとキーボードの入力を解釈し、必要に応じてモデルやビューに変更を指示します。最後に、モデルはアプリケーションドメインの動作とデータを管理し、その状態に関する情報の要求(通常はビューから)に応答し、状態を変更する指示(通常はコントローラーから)に応答します。

それを踏まえて、私はあなたの3つの主な懸念にこう答えます。

  1. 実際、Qtコンポーネントは「グラフィカルな[...]出力を管理」し、「マウスとキーボードの入力を解釈する」ので、上記の定義に関して、実際にはマージされたビューとコントローラーと呼ぶことができます。
  2. 私はあなたがコントローラーとモデルをマージすることを強制される/することに同意します(ここでも上記の定義に関して)。
  3. 私も同意します。モデルは、アプリケーションドメインのデータのみを管理する必要があります。これが「データ」と呼ばれるものです。明らかに、たとえば行や列を扱うことは、通常、アプリケーションドメインとは何の関係もありません。

どこに行きますか?私の意見では、「モデル」と「ビュー」という用語が使用されているときにQtが実際に何を意味するのかを理解し、Qtでプログラミングしている間、それらの方法で用語を使用するのが最善です。煩わしさを感じ続けると、速度が低下するだけで、Qtでの設定方法によってエレガントなデザインが可能になります。これは、「間違った」命名規則よりも重要です。


2
デリゲートはQtのコントローラーであると私は言います。デリゲートは入力を受信して​​モデルに送信し、信号を通じてビューを更新するからです。
Peregring-lk 2016年

82

短い答え

QtのMVCは1つのデータ構造にのみ適用されます。MVC アプリケーションについて話すときは、QAbstractItemModelまたはについて考えるべきではありませんQListView

プログラム全体にMVCアーキテクチャが必要な場合、Qtにはそのような「巨大な」モデル/ビューフレームワークはありません。しかし、プログラムのデータのリスト/ツリーごとに、実際にはビュー内にコントローラーがあるQt MVCアプローチを使用できます。データは、内部または外部のモデルです。これは、使用しているモデルのタイプに依存します(独自のモデルサブクラス:おそらくモデル内。例:QSqlTableModel:外部(ただし、モデル内にキャッシュされる可能性があります))。モデルとビューを組み合わせるには、ビジネスロジックを実装する独自のクラスを使用します。


長い答え

Qtのモデル/ビューのアプローチと用語:

Qtはモデルにシンプルなビューを提供します。彼らは持っているコントローラの項目を編集し、移動、選択、ほとんどの場合、何か何コントローラ「コントロール」です:に建てられています。つまり、ユーザー入力(マウスのクリックと移動)を解釈し、適切なコマンドをモデルに与えます。

Qtのモデルは確かに基礎となるデータを持つモデルです。もちろん、Qtはそれらをどのように格納したいのかわからないため、抽象モデルはデータを保持しません。しかし、あなたはサブクラスにあなたのデータコンテナを追加し、あなたのデータにアクセスするモデル・インタフェースを作ることによって、あなたのニーズにQAbstractItemModelを拡張します。したがって、実際には、これが気に入らないと思いますが、問題は、モデルをプログラムする必要があることです。つまり、データにアクセスし、データ構造で変更する方法です。

MVC用語では、モデルにはデータロジックの両方が含まれます。Qtでは、ビジネスロジックの一部をモデルの中に含めるか、それを外部に置くか、それ自体が「ビュー」であるかは、あなた次第です。ロジックの意味すら明確ではありません。アイテムの選択、名前の変更、移動はどうでしょうか。=>すでに実装されています。それらを使って計算していますか?=>モデルサブクラスの外側または内側に配置します。ファイルとの間でデータを保存またはロードしますか?=>モデルサブクラス内に配置します。


私の個人的な意見:

良い提供することは非常に困難であるプログラマに一般的なMV(C)システムを。ほとんどの場合、モデルは単純なため(たとえば、文字列リストのみ)、Qtはすぐに使用できるQStringListModelも提供します。しかし、データが文字列よりも複雑な場合は、Qtモデル/ビューインターフェースを介してデータをどのように表現するかはあなた次第です。たとえば、3つのフィールドを持つ構造体(名前、年齢、性別を持つ人物など)がある場合、3つのフィールドを3つの異なる列または3つの異なるロールに割り当てることができます。どちらのアプローチも嫌いです。

Qtのモデル/ビューフレームワークは、単純なデータ構造を表示する場合にのみ役立つと思います。データがカスタムタイプであるか、ツリーやリスト(グラフなど)で構造化されていない場合、処理が難しくなります。ほとんどの場合、リストで十分であり、場合によっては、モデルは単一のエントリのみを保持する必要があります。特に、異なる属性を持つ1つのエントリ(1つのクラスの1つのインスタンス)をモデル化する場合、Qtのモデル/ビューフレームワークは、ロジックをユーザーインターフェイスから分離する適切な方法ではありません。

まとめると、Qtのモデル/ビューフレームワークは、データがQtのビューアウィジェットの 1つで表示されている場合にのみ役立つと思います。アプリケーションの設定など、1つのエントリのみを保持するモデルの独自のビューアを作成する場合や、データが印刷可能なタイプでない場合は、まったく役に立ちません。


(より大きい)アプリケーション内でQtモデル/ビューをどのように使用しましたか?

私はかつて、複数のQtモデルを使用してデータを管理するアプリケーションを(チームで)作成しました。DataRole異なるモデルサブクラスごとに異なるカスタムタイプの実際のデータを保持するを作成することにしました。Modelすべての異なるQtモデルを保持するという外部モデルクラスを作成しました。またView、内のモデルに接続されているウィンドウ(ウィジェット)を保持するという外部ビュークラスも作成しましたModel。したがって、このアプローチは、Qt MVCの拡張であり、私たち自身のニーズに適合しています。ModelViewクラス自体は、Qt MVCとは何の関係もありません。

ロジックをどこに配置しましたか?ソースモデルからデータを読み取り(変更された場合)、結果をターゲットモデルに書き込むことにより、データの実際の計算を行うクラスを作成しました。Qtの観点から見ると、このロジッククラスはモデルに「接続」するため、ビューになります(ユーザーの「ビュー」ではなく、アプリケーションのビジネスロジック部分の「ビュー」)。

コントローラはどこにありますか?元のMVC用語では、コントローラーはユーザー入力(マウスとキーボード)を解釈し、要求されたアクションを実行するコマンドをモデルに提供します。Qtビューはアイテムの名前変更や移動などのユーザー入力をすでに解釈しているため、これは必要ありませんでした。しかし、必要なのは、Qtビューを超えるユーザーインタラクションの解釈です。


最も苛立たしいことは、必要なビューに応じて、まったく異なるQtモデルクラスを実装する必要があることです。リストビューのモデルはツリービューを適切にサポートしません。逆も同様です。正規のMVCモデルは、さまざまな種類のビューをサポートできます。
smerlin

3
@smerlin:私はそれが正しいとは思いません。QListViewとQTreeViewはどちらもQAbstractItemViewインターフェースのみを必要とします。つまり、そのカスタムサブクラス、またはQStandardItemModelのような具象クラスが両方の要件を満たしている必要があります。ツリーを駆動して、1つのモデルをリストアップできます。
jdi 2012年

1
@jdi:データがリストとツリーの両方である場合があります...たとえば、ファイルシステムをツリーとして表示したり、すべてのファイルをリストとして表示したりできます。Qtsモデルはそれを適切に許可しません。ツリービューをサポートするQAbstractItemModelの実装では、ルートディレクトリ内のすべてのファイル/ディレクトリをリストとして表示することしかできませんが、すべてのファイルをリストとして表示することはできません。また、ツリーデータをリストとして表示することは役に立たないことは言うまでもありません。たとえば、ファイルをリストとして表示する場合、たとえば、それらを簡単に並べ替えて、最大のファイルサイズを持つファイルを見つけることができます。ツリービューではそれができません。
smerlin

1
とはいえ、プロキシモデルはビューの一部であり(データの表示方法を変更するため)、ビューに属する必要があります。私の長い答えを読んだ場合:「ビッグ」クラスでは、ツリーモデルを基礎モデルとして持ち、ファイルシステムリストビューで使用されるプロキシモデルを追加する必要があります。あなたが言っているように:同じデータに対して2つのモデルがあってはなりません。絶対に!(ただし、プロキシモデルは個別のモデルとしてカウントされません。)View
leemes

1
@SamPinkusそれこの質問に明確なイエスノーがないからです。また、にはさまざまな実装がありQAbstractItemModel、その一部はMVCの意味でのモデルであり、一部はそうではありません。
leemes 2014年

12

用語は正しいか間違っているかではありません、それは役に立つか役に立たないです。

質問を少し変えて、QtがMVCに適さない理由を尋ねるかもしれません。答えは、初期のQt開発者は、GUIアプリケーションでVをCから分離することは、VとCの両方に悪い影響を与えると信じているということです。QWidgetの設計は、マウス入力の操作をピクセル出力の決定と密接に結び付けることを簡単にすることを試みており、それがMVCへの道ではないことがわかります。


私はあなたの意見を理解し、基本的に私はQtがよりMVCフレンドリーではない理由を尋ねますが、Qtドキュメントで使用されるMVC用語が通常使用されるMVCと異なる場合(質問で説明したように)は非常に困難です。そして、広く使われている用語があり、誰かが他の世界と非常に異なる方法で使用している場合、それは役に立たないだけでなく、混乱して混乱していると思う傾向があります(混乱が原因で最初に質問をしました)場所)。どこかで議論または説明されているこれらのことへのリンクがあれば、私は非常に興味があります。ありがとう
12:15に作成

QtのドキュメントがMVCについて今なぜ話しているのかについては何も言えません。私はずっと前にTrolltechを去りましたが、去ってからドキュメントに対して行われたいくつかのことに戸惑っています。(ただし、私のブログでは、それについて時々
怒鳴る

QtでMVC用語がどのように合意されているかについて洞察がありますか。コードの記述時に使用されましたか、それとも後で文書化プロセス中に使用されましたか?
12

Trolltechにいる間、Qtのドキュメントで「MVC」という言葉を使用しませんでした。一般的に、そこにないものについて書くのではなく、そこにあるものを文書化するのが最善だと思います。ただし、Gitoriousでは、誰がそのテキストを追加したかを確認し、その人を直接追加できます。
ARNT

1
別のコメント。Qt(Trollechが3人の会社だったとき)の設計と初期実装フレーズの間にMVCについて話し合い、MVCを「適切に」使用したGUIツールキットを評価しましたが、その名前を思い出せません。私たちの意見では、そのツールキットは使用するのがひどいものであり、その理由の多くはMVCでした。
ARNT

3

モデルの機能は、情報の要求に応答するように、私はこのような方法を定義する上で何も間違っがあると思いrowCountcolumnCountなど、私は(関係なく、それはSQLテーブルまたは単にアレイものです)モデルは、データ・ソースのラッパーのいくつかの種類だと思います、データを標準形式で提供します。メソッドを定義する必要があるのは、データソースの構造によって異なります。


2

彼らの用語は正しいと思います...実際のアプリケーションでは、抽象化のレベルによっては、モデル、ビュー、コントローラーの間の線をぼかすのが非常に簡単になる場合があります。

QAbstractModelItemクラスから混乱が生じているように感じます。このクラスはモデルアイテムではなく、モデルへのインターフェイスです。ビュークラスをモデルとインターフェイスさせるには、モデルへの一般的な抽象インターフェイスを作成する必要がありました。ただし、モデルは、単一のアイテム、アイテムのリスト、アイテムの2つ以上の次元のテーブルなどにすることができます。したがって、それらのインターフェースは、これらすべてのモデルのバリエーションをサポートする必要があります。確かに、これはモデル項目をかなり複雑にし、実際のモデルで機能させるためのグルーコードはメタファーを少し伸ばしているようです。


QAbstractModelItemクラスについては同意しますが、この複雑さがなくてもMVCの名前が間違っていると思います。彼らの用語が正しいと思う理由を説明してください。私が3つの議論のどれでも正しくない理由を聞きたいです。
2010年

0

私はそう思います...彼らがモデルと呼ぶものは、実際にはコントローラーのみです。

いいえ、彼らの「モデル」はコントローラではありません。

コントローラは、モデルを変更する(したがって、ビューを間接的に変更する)ユーザーに表示されるコントロールの一部です。たとえば、「削除」ボタンはコントローラの一部です。

多くの場合、「コントローラがモデルを変更する」のようなものを見るので混乱があると思います。これは、「deleteRow()」メソッドのような、モデルの変更機能を意味すると思います。ただし、クラシックMVCでは、コントローラーは特にユーザーインターフェイス部分です。モデルを変更するメソッドは、単にモデルの一部です。

MVCが発明されて以来、コントローラーとビューの違いはますます緊張してきています。テキストボックスについて考えてみましょう。テキストボックスが表示され、編集できるので、ビューとコントローラーのどちらですか。答えは、それが両方の一部であるということでなければなりません。1960年代にテレタイプに取り組んでいた頃は、その違いはより明確でしたed– 考えてみてください–しかし、それは、当時のユーザーにとってより優れていたということではありません。

QAbstractItemModelがモデルが通常よりもかなり高いレベルであることは事実です。たとえば、その中のアイテムは背景色(技術的にはブラシ)を持つことができます。これは明らかに見栄えの良い属性です!したがって、QAbstractItemModelはよりビューに近く、データはモデルであるという議論があります。真実は、ビューとモデルの古典的な意味の中間にあるということです。しかし、それがコントローラーなのかわかりません。どちらかと言えば、それを使用するQTウィジェットです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.