Mengapa Qt menyalahgunakan model / tampilan terminologi?

104

Saya pikir terminologi yang digunakan dalam Qt dengan kontrol model / tampilan cacat. Pada halaman penjelasan mereka menyatakan, bahwa mereka menyederhanakan MVC menjadi MV dengan menggabungkan View dan Controller dan mereka memberikan gambar sebagai berikut:

gambar menjelaskan Qt MVC

Namun menurut saya, mereka salah menamai peran objek dan saya pikir,

  1. Apa yang mereka sebut Tampilan dengan Pengontrol gabungan sebenarnya adalah Tampilan saja.
  2. Apa yang mereka sebut Model sebenarnya hanyalah Pengendali.
  3. Jika Anda benar-benar ingin memiliki model, itu akan berada di suatu tempat di mana "Data" mereka berada.

Saya berbicara tentang cara biasa dan waras Anda akan menggunakan komponen model / tampilan Qt di aplikasi Anda. Berikut alasannya:

  1. Ini biasanya merupakan komponen Qt yang digunakan apa adanya, tanpa menambahkan logika Pengontrol khusus untuk objek Anda)
  2. Ini bukan Model, hanya karena Anda harus mengimplementasikan beberapa metode Qt seperti rowCount, columnCount, data, dll. Yang tidak ada hubungannya dengan model Anda. Sebenarnya ada metode model khas yang ditemukan di Pengontrol. Tentu saja, Anda dapat mengimplementasikan logika Controller dan Model di sini, tetapi pertama-tama ini akan menjadi desain kode yang buruk dan kedua Anda akan menggabungkan Controller dan Model bukan Controller dan View seperti yang dinyatakan.
  3. Seperti yang dikatakan dalam alasan 2. jika Anda ingin memisahkan logika Model yang tentunya bukan kotak biru pada gambar, melainkan kotak "Data" yang putus-putus (tentu saja berkomunikasi dengan Data nyata).

Apakah Qt salah dalam terminologi mereka, atau hanya saya yang tidak mengerti? (BTW: Alasan mengapa ini bukan pertanyaan akademis adalah karena saya sudah mulai membuat kode proyek saya mengikuti penamaan mereka dan saya segera menemukan, bahwa kode itu jelas tidak benar. Baru setelah itu saya menyadari, saya harus tidak mencoba menempatkan logika Model dalam apa yang mereka sebut Model)

gorn
sumber
1
MFC menetapkan standar untuk 2 bagian model / tampilan guis dengan CDoc dan CView - tidak ada alasan bahwa MVC tertentu 'benar'
Martin Beckett
@ Martin B: Saya akan melihat MFC, namun meskipun ada model MVC yang berbeda, saya pikir mereka harus konsisten dalam terminologi mereka dan saya pikir saya telah menyajikan argumen yang valid, mengapa terminologi yang digunakan tidak konsisten dalam kasus khusus ini. Mereka hanya menyatakan bahwa mereka telah menggabungkan View dan Controller tetapi saya pikir itu hanya menyesatkan dalam kasus ini. Saya kira tidak ada model MVC di mana semua logika spesifik aplikasi baik itu logika presentasi atau model harus diletakkan dalam satu objek yang disebut Model.
gorn
1
@Martin B: Juga di bawah terminiologi qt semua Model memiliki api umum yang tidak ada hubungannya dengan struktur Model, tetapi semuanya berkaitan dengan struktur Pengendali umum, yang dengan jelas menunjukkan bahwa tidak benar untuk menyebutnya Model. Saya tidak mengatakan ada SATU model MVC yang benar, tetapi itu tidak berarti dari apa pun dapat disebut model MVC. Mungkin itu cacat di MFC juga dan saya bisa melihatnya, tapi saya lebih tertarik pada Qt melakukannya dengan benar, MFC yang tidak ingin saya gunakan. Apakah Anda memiliki tautan yang bagus untuk menjelaskan pemisahan model / tampilan MFC?
gorn
1
Terminologi MVC sama sekali tidak disetujui dengan suara bulat sehingga pertanyaan Anda dapat dianggap argumentatif. Namun banyak yang akan setuju dengan pekerjaan luar biasa yang dilakukan oleh Martin Fowler ( martinfowler.com/eaaDev/index.html ). Biasanya, pengontrol menangani input pengguna dan dalam pengertian ini, widget Qt pasti menggabungkan tampilan dan pengontrol.
Arnold Spence
1
Saya memahami bahwa MVC memiliki banyak rasa tetapi tidak berarti bahwa apa pun dapat menjadi MVC. Qt telah melewati batas dan saya memberikan beberapa alasan. Martin Fowler memang menjelaskan berbagai jenis MVC, tetapi keduanya tidak cukup mirip dengan apa yang diucapkan Qt sebagai MVC. Yang paling mirip adalah martinfowler.com/eaaDev/PresentationModel.html , tetapi ini membedakan antara bagian Model Presentasi = Pengontrol (interaksi pengguna) dan Model (logika data). Jadi, meskipun tidak ada definisi pasti tentang MVC, Qt tidak mengikuti salah satunya. Jika Anda dapat memberi saya tautan ke definisi tersebut, lakukanlah.
gorn

Jawaban:

78

Saya setuju dengan Anda bahwa penamaan Qt menyesatkan. Namun menurut saya, masalahnya bukan hanya pada Qt, tetapi juga dimiliki oleh semua kerangka kerja yang memungkinkan kita untuk mematuhi prinsip pemisahan masalah saat menerapkan UI kami. Ketika seseorang datang dengan kerangka kerja seperti itu, dan menemukan cara yang baik untuk memisahkan "hal-hal", mereka selalu merasa berkewajiban untuk memiliki modul yang mereka sebut "Model" dan modul lain yang mereka sebut "Tampilan". Selama bertahun-tahun saya telah bekerja dengan kerangka kerja ini:

  • MFC
  • Qt
  • Ayunan
  • SWT
  • WPF dengan MVVM

Jika Anda membandingkan bagaimana istilah "Model" dan "Tampilan" digunakan dalam kerangka kerja ini, dan tanggung jawab apa yang dimiliki kelas dalam "Tampilan", "Model", dan "Pengontrol" (jika ada), Anda akan menemukan bahwa terdapat perbedaan yang sangat besar. Tentu akan berguna untuk memiliki perbandingan konsep dan terminologi yang berbeda, sehingga orang-orang yang beralih dari satu kerangka ke kerangka lainnya memiliki kesempatan untuk tetap waras, tetapi itu akan membutuhkan banyak pekerjaan dan penelitian. Bacaan yang bagus adalah milik Martin Fowler gambaran umum .

Karena ada begitu banyak ide-ide yang berbeda apa yang pola MVC dapat terlihat seperti, mana yang benar? Menurut pendapat saya, orang-orang yang menemukan MVC harus berpaling ketika kita ingin tahu bagaimana seharusnya diimplementasikan dengan "benar". Di kertas smalltalk asli dikatakan:

Tampilan mengelola keluaran grafis dan / atau tekstual ke bagian tampilan yang dipetakan yang dialokasikan untuk aplikasinya. Kontroler menafsirkan input mouse dan keyboard dari pengguna, memerintahkan model dan / atau tampilan untuk berubah sesuai kebutuhan. Terakhir, model mengelola perilaku dan data domain aplikasi, menanggapi permintaan informasi tentang statusnya (biasanya dari tampilan), dan menanggapi instruksi untuk mengubah status (biasanya dari pengontrol).

Oleh karena itu saya akan menjawab tiga perhatian utama Anda sebagai berikut:

  1. Nyatanya, sebuah komponen Qt "mengatur keluaran grafis [...]", dan "menginterpretasikan masukan mouse dan keyboard", sehingga ia memang bisa disebut Tampilan dan Pengontrol gabungan sehubungan dengan definisi di atas.
  2. Saya setuju bahwa Anda / akan dipaksa untuk menggabungkan Kontroler dan Model (sekali lagi sehubungan dengan definisi di atas).
  3. Saya setuju lagi. Model seharusnya hanya mengelola data dari domain aplikasi . Inilah yang mereka sebut "data". Jelas, berurusan dengan baris dan kolom misalnya biasanya tidak ada hubungannya dengan domain aplikasi kita.

Dimana kita ditinggalkan? Menurut pendapat saya, yang terbaik adalah mencari tahu apa sebenarnya yang dimaksud Qt ketika istilah "Model" dan "View" digunakan dan menggunakan istilah tersebut dengan cara mereka saat kita memprogram dengan Qt. Jika Anda terus diganggu, hal itu hanya akan memperlambat Anda, dan cara pengaturan di Qt memungkinkan desain yang elegan - yang lebih berat daripada konvensi penamaan yang "salah".

Tilo
sumber
2
Saya akan mengatakan bahwa delegasi adalah pengontrol Qt, karena delegasi menerima dan mengirim input ke model, yang memperbarui tampilan melalui sinyal.
Peregring-lk
82

Jawaban singkat

MVC Qt hanya berlaku untuk satu struktur data . Saat berbicara tentang aplikasi MVC, Anda tidak boleh memikirkan QAbstractItemModelatau QListView.

Jika Anda menginginkan arsitektur MVC untuk seluruh program Anda, Qt tidak memiliki kerangka kerja model / tampilan yang "besar". Tetapi untuk setiap daftar / pohon data dalam program Anda, Anda dapat menggunakan pendekatan Qt MVC yang memang memiliki pengontrol dalam tampilannya. The Data adalah dalam atau di luar model; ini tergantung pada jenis model yang Anda gunakan (model subclass sendiri: mungkin di dalam model; misalnya QSqlTableModel: di luar (tapi mungkin di-cache di dalam) model). Untuk menyatukan model dan tampilan Anda, gunakan kelas sendiri yang kemudian mengimplementasikan logika bisnis .


Jawaban panjang

Pendekatan dan terminologi model / tampilan Qt:

Qt memberikan tampilan sederhana untuk model mereka. Mereka memiliki pengontrol bawaan: memilih, mengedit, dan memindahkan item adalah sesuatu yang dalam banyak kasus "kontrol" pengontrol. Yaitu, menafsirkan input pengguna (klik dan gerakan mouse) dan memberikan perintah yang sesuai ke model.

Model Qt memang model yang memiliki data dasar. Model abstrak tentu saja tidak menyimpan data, karena Qt tidak tahu bagaimana Anda ingin menyimpannya. Tapi Anda memperluas QAbstractItemModel sesuai kebutuhan Anda dengan menambahkan container data ke subclass dan membuat antarmuka model mengakses data Anda. Jadi sebenarnya, dan saya berasumsi Anda tidak menyukai ini, masalahnya adalah Anda perlu memprogram model, jadi bagaimana data diakses dan dimodifikasi dalam struktur data Anda.

Dalam terminologi MVC, model berisi data dan logika . Di Qt, terserah Anda apakah Anda menyertakan beberapa logika bisnis Anda ke dalam model atau meletakkannya di luar, menjadi "tampilan" sendiri. Bahkan tidak jelas apa yang dimaksud dengan logika: Memilih, mengganti nama, dan memindahkan item? => sudah diimplementasikan. Melakukan perhitungan dengan mereka? => Letakkan di luar atau di dalam subclass model. Menyimpan atau memuat data dari / ke file? => Taruh di dalam subclass model.


Pendapat pribadi saya:

Sangat sulit untuk menyediakan sistem MV (C) yang baik dan umum untuk programmer. Karena dalam banyak kasus modelnya sederhana (misalnya hanya daftar string) Qt juga menyediakan QStringListModel yang siap digunakan. Tetapi jika data Anda lebih kompleks daripada string, terserah Anda bagaimana Anda ingin merepresentasikan data melalui antarmuka model / tampilan Qt. Jika Anda memiliki, misalnya, sebuah struct dengan 3 bidang (katakanlah orang dengan nama, usia dan jenis kelamin) Anda dapat menetapkan 3 bidang ke 3 kolom berbeda atau ke 3 peran berbeda. Saya tidak menyukai kedua pendekatan tersebut.

Saya pikir kerangka model / tampilan Qt hanya berguna ketika Anda ingin menampilkan struktur data sederhana . Ini menjadi sulit untuk ditangani jika data memiliki tipe khusus atau tidak terstruktur dalam pohon atau daftar (misalnya grafik). Dalam kebanyakan kasus, daftar sudah cukup dan bahkan dalam beberapa kasus, model hanya boleh menampung satu entri tunggal. Terutama jika Anda ingin memodelkan satu entri tunggal yang memiliki atribut berbeda (satu contoh dari satu kelas), kerangka kerja model / tampilan Qt bukanlah cara yang tepat untuk memisahkan logika dari antarmuka pengguna.

Singkatnya, saya pikir kerangka kerja model / tampilan Qt berguna jika dan hanya jika data Anda dilihat oleh salah satu widget penampil Qt . Sama sekali tidak berguna jika Anda akan menulis penampil Anda sendiri untuk model yang hanya berisi satu entri, misalnya pengaturan aplikasi Anda, atau jika data Anda bukan jenis yang dapat dicetak.


Bagaimana saya menggunakan model / tampilan Qt dalam aplikasi (lebih besar)?

Saya pernah menulis (dalam tim) sebuah aplikasi yang menggunakan beberapa model Qt untuk mengelola data. Kami memutuskan untuk membuat DataRoleuntuk menyimpan data aktual yang memiliki tipe kustom berbeda untuk setiap subclass model yang berbeda. Kami membuat kelas model luar yang disebut Modelmemegang semua model Qt yang berbeda. Kami juga membuat kelas tampilan luar yang disebut Viewmenahan jendela (widget) yang terhubung ke model di dalamnya Model. Jadi pendekatan ini adalah Qt MVC yang diperluas, disesuaikan dengan kebutuhan kita sendiri. Baik Modeldan Viewkelas itu sendiri tidak ada hubungannya dengan Qt MVC.

Dimana kita meletakkan logikanya ? Kami membuat kelas yang melakukan penghitungan aktual pada data dengan membaca data dari model sumber (saat model berubah) dan menulis hasilnya ke dalam model target. Dari sudut pandang Qt, kelas logika ini akan menjadi pandangan, karena mereka "terhubung" ke model (bukan "tampilan" untuk pengguna, tetapi "tampilan" untuk bagian logika bisnis aplikasi).

Dimana pengontrolnya ? Dalam terminologi MVC asli, pengontrol menafsirkan input pengguna (mouse dan keyboard) dan memberikan perintah ke model untuk melakukan tindakan yang diminta. Karena tampilan Qt sudah menafsirkan input pengguna seperti mengganti nama dan memindahkan item, ini tidak diperlukan. Tetapi yang kami butuhkan adalah interpretasi dari interaksi pengguna yang melampaui tampilan Qt.

leemes
sumber
Hal yang paling menjengkelkan adalah, Anda harus mengimplementasikan kelas Model Qt yang sangat berbeda tergantung pada tampilan yang Anda inginkan. Model untuk tampilan daftar tidak akan mendukung tampilan hierarki dengan benar dan sebaliknya. Model MVC kanonik dapat mendukung banyak jenis tampilan yang berbeda.
smerlin
3
@smerlin: Saya rasa itu tidak benar. Baik QListView dan QTreeView hanya memerlukan antarmuka QAbstractItemView, yang berarti bahwa subkelas khusus dari itu, atau kelas konkret seperti QStandardItemModel harus memenuhi persyaratan tersebut untuk keduanya. Anda dapat mengendarai pohon dan membuat daftar dari satu model.
jdi
1
@jdi: ada kasus di mana data Anda adalah keduanya, daftar dan pohon ... misalnya Anda ingin menampilkan sistem file Anda sebagai pohon, atau semua file sebagai daftar. Model Qts tidak mengizinkannya dengan benar. Sebuah implementasi dari QAbstractItemModel mendukung tampilan pohon, hanya memungkinkan untuk menampilkan semua file / direktori di direktori root Anda sebagai daftar, tetapi Anda tidak dapat menampilkan semua file sebagai daftar. Dan jangan katakan bahwa menampilkan data pohon sebagai daftar tidak akan berguna. Misalnya, Anda dapat dengan mudah mengurutkan mereka untuk menemukan file dengan ukuran file terbesar jika Anda menampilkan file Anda sebagai daftar, tampilan hierarki tidak akan mengizinkannya.
smerlin
1
Yang mengatakan, model proxy lebih merupakan sesuatu dari pandangan Anda (karena itu memodifikasi bagaimana datanya demikian dilihat ) dan dengan demikian seharusnya menjadi bagian dari tampilan Anda. Jika Anda membaca jawaban panjang saya: Di kelas "besar" ViewAnda harus menambahkan model proxy, yang memiliki model pohon sebagai model dasarnya dan digunakan oleh tampilan daftar sistem file Anda. Seperti yang Anda katakan: seharusnya tidak ada dua model untuk data yang sama. Tidak pernah! (Tapi model proxy tidak dihitung sebagai model terpisah.)
leemes
1
@SamPinkus Itu karena tidak ada ya atau tidak yang jelas untuk pertanyaan ini. Juga, ada implementasi yang berbeda QAbstractItemModel, beberapa di antaranya adalah model dalam pengertian MVC dan beberapa di antaranya tidak.
leemes
12

Istilahnya tidak benar atau salah, itu berguna atau tidak berguna.

Anda mungkin mengubah pertanyaannya sedikit dan bertanya mengapa Qt tidak lebih ramah MVC. Jawabannya adalah bahwa pengembang Qt awal percaya bahwa memisahkan V dari C dalam aplikasi GUI menghasilkan Vs dan C yang buruk keduanya. Desain QWidget mencoba membuatnya sederhana untuk mengikat interperasi input mouse secara dekat dengan keputusan output piksel, dan Anda dapat melihat bagaimana itu bukan jalan menuju MVC.

arnt
sumber
Saya mengerti maksud Anda dan pada dasarnya saya AKAN bertanya mengapa Qt tidak lebih ramah MVC, tetapi sangat sulit dilakukan ketika terminologi MVC yang digunakan dalam dokumentasi Qt BERBEDA dari apa yang biasanya digunakan MVC (seperti yang saya jelaskan dalam pertanyaan). Dan ketika ada terminologi yang banyak digunakan dan seseorang menggunakannya dengan sangat berbeda dari bagian dunia lainnya, saya cenderung berpikir bahwa itu bukan hanya tidak berguna, tetapi juga SALAH dan membingungkan (kebingungan itu membuat saya bertanya pada pertanyaan pertama. tempat). Saya akan sangat tertarik jika Anda memiliki tautan ke hal-hal ini yang sedang dibahas atau dijelaskan di suatu tempat. Terima kasih
gorn
Saya tidak bisa mengatakan apa-apa tentang mengapa dokumen Qt sekarang berbicara tentang MVC dengan cara yang mereka lakukan. Saya meninggalkan Trolltech sejak lama, dan bingung dengan beberapa hal yang telah dilakukan pada dokumentasi sejak saya pergi. (Namun, di blog saya, saya terkadang mengoceh sedikit tentang itu.)
Bukankah
Apakah Anda mengetahui bagaimana terminologi MVC telah disepakati di Qt. Apakah itu digunakan saat menulis kode, atau hanya nanti selama proses dokumentasi.
gorn
Kami tidak menggunakan kata "MVC" dalam dokumentasi Qt selama saya bekerja di Trolltech. Secara umum menurut saya yang terbaik adalah mendokumentasikan apa yang ada di sana, bukan menulis tentang apa yang tidak ada di sana. Namun, lebih dari gitorious Anda dapat mengetahui siapa yang menambahkan teks itu dan menambahkan orang itu secara langsung.
Bukankah
1
Komentar yang berbeda. Kami membahas MVC selama desain dan implementasi awal frase Qt (ketika Trollech adalah perusahaan tiga orang), dan kami mengevaluasi toolkit GUI yang menggunakan MVC "dengan benar", saya tidak dapat mengingat namanya. Pendapat kami adalah bahwa toolkit itu buruk untuk digunakan, dan MVC adalah sebagian besar alasannya.
Bukankah
3

Seperti fungsi Model adalah untuk merespon permintaan informasi, saya pikir tidak ada yang salah dalam mendefinisikan metode seperti rowCount, columnCount, dll saya pikir Model adalah beberapa jenis pembungkus untuk sumber data (tidak peduli apa itu SQL meja atau hanya sebuah array) , ini menyediakan data dalam bentuk standar, dan Anda harus menentukan metode bergantung pada struktur sumber data Anda.

Dmitry
sumber
2

Saya yakin terminologi mereka benar ... meskipun dalam aplikasi nyata saya merasa sangat mudah untuk mengaburkan garis antara model, tampilan, dan pengontrol tergantung pada tingkat abstraksi Anda: pandangan satu tingkat mungkin merupakan model tingkat yang lebih tinggi.

Saya merasa kebingungan muncul dari kelas QAbstractModelItem mereka. Kelas ini bukan item model, melainkan antarmuka ke model. Untuk membuat antarmuka kelas tampilan mereka dengan model, mereka harus membuat antarmuka abstrak generik ke model. Namun, model dapat berupa satu item, daftar item, tabel dari 2 atau lebih dimensi item, dll; jadi antarmuka mereka harus mendukung semua variasi model ini. Memang, ini membuat item model cukup kompleks, dan kode perekat untuk membuatnya bekerja dengan model sebenarnya tampaknya sedikit meregangkan metafora.

Chris Morlier
sumber
Meskipun saya setuju dengan Anda dengan kelas QAbstractModelItem, saya juga berpikir bahwa bahkan tanpa komplikasi ini MVC mereka salah nama. Bisakah Anda menjelaskan mengapa menurut Anda terminologi mereka benar. Saya ingin sekali mendengar mengapa saya tidak benar dalam salah satu dari tiga argumen saya.
gorn
0

Saya pikir ... Yang mereka sebut Model sebenarnya hanyalah Pengendali.

Tidak, "model" mereka jelas bukan pengontrol.

Kontroler adalah bagian dari kontrol yang terlihat oleh pengguna yang memodifikasi model (dan karenanya secara tidak langsung mengubah tampilan). Misalnya, tombol "hapus" adalah bagian dari pengontrol.

Saya pikir sering terjadi kebingungan karena banyak yang melihat sesuatu seperti "controller memodifikasi model" dan berpikir ini berarti fungsi yang bermutasi pada model mereka, seperti metode "deleteRow ()". Tetapi di MVC klasik, pengontrol secara khusus adalah bagian antarmuka pengguna. Metode yang mengubah model hanyalah bagian dari model.

Sejak MVC ditemukan, perbedaan antara pengontrol dan tampilan menjadi semakin tegang. Pikirkan tentang kotak teks: ini menampilkan beberapa teks dan memungkinkan Anda mengeditnya, jadi apakah itu tampilan atau pengontrol? Jawabannya haruslah itu adalah bagian dari keduanya. Dulu ketika Anda mengerjakan teletype di tahun 1960-an, perbedaannya lebih jelas - pikirkaned - tetapi itu tidak berarti segalanya lebih baik bagi pengguna saat itu!

Memang benar bahwa QAbstractItemModel mereka memiliki level yang lebih tinggi daripada model biasanya. Misalnya, item di dalamnya dapat memiliki warna latar belakang (secara teknis kuas), yang merupakan atribut view-ish yang jelas! Jadi ada argumen bahwa QAbstractItemModel lebih seperti tampilan dan data Anda adalah modelnya. Sebenarnya itu ada di suatu tempat di antara makna klasik dari pandangan dan model. Tapi saya tidak bisa melihat bagaimana itu sebuah pengontrol; jika ada widget QT yang menggunakannya.

Arthur Tacca
sumber