web-dev-qa-db-ja.com

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

モデル/ビューコントロールでQtで使用される用語に欠陥があると思います。 彼らの説明ページ 彼らは、ViewとControllerをマージすることでMVCをMVに単純化し、次の図を提供していると述べています:

picture explaining Qt MVC

しかし、私は彼らがオブジェクトの役割を間違って命名したと思う、と私は思う、

  1. コントローラーが統合されたビューと呼ばれるものは、実際にはビューのみです。
  2. 彼らがモデルと呼ぶものは、実際にはコントローラーのみです。
  3. モデルが本当に必要な場合は、その「データ」がある場所になります。

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

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

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

96
gorn

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

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

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

非常に多くの異なるアイデアがあるので、MVCパターンはどのanのように見えるのか、正しいのはどれですか?私の意見では、MVCを発明した人々は、「正しく」実装されることになっている方法を知りたい場合に頼るべきです。 元のSmalltalk論文 には次のように書かれています:

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

それに照らして、私はあなたの3つの主な懸念にこのように答えます:

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

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

73
Tilo

短い答え

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

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


長い答え

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

Qtは、モデルに対して単純なviewsを提供します。これらにはcontrollerが組み込まれています:アイテムの選択、編集、移動は、ほとんどの場合コントローラーが「制御」するものです。つまり、ユーザー入力(マウスのクリックと移動)を解釈し、モデルに適切なコマンドを与えます。

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

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


私の個人的な意見:

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

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

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


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

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

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

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

79
leemes

用語は正しいか間違っているかではなく、役に立つか役に立たない。

質問を少し変えて、なぜQtがMVCフレンドリではないのかと尋ねるかもしれません。答えは、初期のQt開発者は、GUIアプリケーションでVをCから分離すると、悪いVとCの両方が発生すると考えているということです。 QWidgetの設計では、マウス入力の相互作用とピクセル出力の決定を簡単に結び付けようとしていますが、MVCへの道ではないことがわかります。

12
arnt

Model関数は情報の要求に応答するため、rowCountcolumnCountなどのメソッドを定義するのに何も問題はないと思います。Modelはデータソースのラッパーのようなものだと思います( SQLテーブルまたは単なる配列)に関係なく、標準形式でデータを提供し、データソース構造に応じてメソッドを定義する必要があります。

3
Dmitry

私は彼らの用語が正しいと信じています...実際のアプリケーションでは、抽象化のレベルに応じてモデル、ビュー、コントローラーの間の線を曖昧にすることは非常に簡単です:1つのレベルのビューはより高いレベルのモデルかもしれません。

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

2
Chris Morlier