Qt neden model / görünüm terminolojisini yanlış kullanıyor?


104

Qt'de model / görünüm kontrolleri ile kullanılan terminolojinin hatalı olduğunu düşünüyorum. On onların açıklama sayfası onlar görüntüleme ve Kontrol birleştirilmesi ve aşağıdaki resim veriyoruz tarafından MV için MVC basitleştirilmiş olduğunu, devlet:

Qt MVC'yi açıklayan resim

Bununla birlikte, nesnelerin rollerini yanlış adlandırdıklarını düşünüyorum ve bence,

  1. Birleştirilmiş Denetleyicili Görünüm dedikleri şey aslında yalnızca bir Görünümdür.
  2. Model dedikleri şey aslında yalnızca Denetleyicidir.
  3. Gerçekten bir modele sahip olmak istiyorsanız, "Verilerin" olduğu bir yerde olacaktır.

Uygulamanızda Qt model / görünüm bileşenini kullanmanın olağan ve mantıklı bir yolundan bahsediyorum. İşte nedenleri:

  1. Bu, genellikle nesnelerinize özel herhangi bir Denetleyici mantığı eklemeden, olduğu gibi kullanılan Qt bileşenidir)
  2. Bu bir Model değildir, çünkü modelinizle hiçbir ilgisi olmayan rowCount, columnCount, data vb. Gibi birkaç Qt metodu uygulamanız gerekir. Aslında, Denetleyicilerde bulunan tipik model yöntemler vardır. Tabii ki, her iki Kontrolör uygulayabilir ve burada Modeli mantığı, ama önce oldukça kötü kod tasarım olacağını ve ikinci olarak sen Denetleyicisi ve Model değil Denetleyici ve Görünüm onlar devlet olarak birleştirmek olacaktır.
  3. 2. gerekçede söylendiği gibi, Model mantığını ayırmak istiyorsanız, kesinlikle resimdeki mavi kutu değil, kesikli "Veri" kutusu (tabii ki gerçek Verilerle iletişim halinde).

Qt terminolojisinde yanlış mı, yoksa anlamayan sadece ben miyim? (BTW: Akademik bir soru olmamasının nedeni, projemi isimlendirmelerine göre kodlamaya başlamam ve kısa sürede kodun açıkça doğru olmadığını anladım. Bundan sonra fark ettiğimde, yapmalıyım Model mantığını Model dedikleri şeye koymaya çalışmayın)


1
MFC, CDoc ve CView ile 2 parçalı model / görünüm kılavuzları için standardı belirledi - belirli bir MVC'nin 'doğru' olması için hiçbir neden yok
Martin Beckett

@Martin B: MFC'ye bir göz atacağım, ancak farklı MVC modelleri olsa bile terminolojilerinde tutarlı olmaları gerektiğini düşünüyorum ve geçerli argümanlar sunduğumu düşünüyorum, kullanılan terminolojinin bu özel durumda neden tutarlı olmadığını düşünüyorum. Sadece View ve Controller'ı birleştirdiklerini belirtiyorlar ama sanırım bu durumda sadece yanıltıcı. Sunum veya model mantığı olsun, uygulamaya özel tüm mantığın Model adı verilen tek bir nesneye konulması gereken bir MVC modeli olduğunu sanmıyorum.
Gorn

1
@Martin B: Ayrıca qt terminolojisi altında tüm Modeller, Model yapısıyla ilgisi olmayan ortak bir api'ye sahiptir, ancak her şeyin genel Denetleyici yapısı ile ilgisi vardır, bu da onu Model olarak adlandırmanın doğru olmadığını açıkça gösterir. Tek bir doğru MVC modeli olduğunu söylemiyorum, ancak bu MVC modeli olarak adlandırılabilecek herhangi bir şey anlamına gelmiyor. Belki MFC'de de kusurludur ve ona bir göz atabilirim, ancak Qt'nin doğru şekilde kullanması, kullanmayı düşünmediğim MFC ile daha çok ilgileniyorum. MFC modeli / görünüm ayrımının açıklandığı herhangi bir iyi bağlantınız var mı?
00:52

1
MVC terminolojisi üzerinde hiçbir şekilde oybirliğiyle mutabakata varılmadığından sorunuz tartışmaya açık kabul edilebilir. Ancak birçok kişi, Martin Fowler'ın ( martinfowler.com/eaaDev/index.html ) yaptığı mükemmel çalışmaya katılacaktır . Genellikle, denetleyici kullanıcı girdilerini yönetir ve bu anlamda, Qt parçacıkları kesinlikle görünümü ve denetleyiciyi birleştirir.
Arnold Spence

1
MVC'nin birçok çeşidi olduğunu anlıyorum ama bu hiçbir şeyin MVC olabileceği anlamına gelmiyor. Qt çizgiyi aştı ve birkaç neden verdim. Martin Fowler, farklı MVC türlerini açıklıyor, ancak ikisi de Qt'nin MVC dediği ile yeterince benzer değil. En benzer olanı martinfowler.com/eaaDev/PresentationModel.html'dir , ancak bu, Sunum Modeli = Denetleyici (kullanıcı etkileşimi) bölümü ve Model (veri mantığı) arasında ayrım yapar. Dolayısıyla, MVC'nin kesin bir tanımı olmamasına rağmen, Qt bunların hiçbirini takip etmez. Bana böyle bir tanım için bir bağlantı verebilirseniz, lütfen yapın.
Gorn

Yanıtlar:


78

Qt'nin isimlendirmesinin yanıltıcı olduğuna katılıyorum. Ancak bence sorun tek başına Qt değil, kullanıcı arayüzlerimizi uygularken endişelerin ayrılması ilkesine bağlı kalmamıza izin veren tüm çerçeveler tarafından paylaşılıyor . Birisi böyle bir çerçeve bulduğunda ve "şeyleri" ayrı tutmanın iyi bir yolunu bulduğunda, "Model" olarak adlandırdıkları modüllere ve "Görünüm" olarak adlandırdıkları diğerlerine sahip olmak zorunda hissederler. Yıllar boyunca bu çerçevelerle çalıştım:

  • MFC
  • Qt
  • Salıncak
  • SWT
  • MVVM ile WPF

Bu çerçevelerde "Model" ve "Görünüm" terimlerinin nasıl kullanıldığını ve "Görünüm", "Model" ve "Denetleyici" deki (varsa) sınıfların hangi sorumluluklara sahip olduğunu karşılaştırırsanız, çok büyük farklar olduğunu bul. Farklı kavramlar ve terminolojiler arasında bir karşılaştırma yapmak kesinlikle yararlı olacaktır, böylece bir çerçeveden diğerine geçiş yapan insanların aklı başında kalma şansı olur, ancak bu çok fazla çalışma ve araştırma gerektirir. İyi bir okuma, Martin Fowler'ın özeti .

Bir MVC modelinin neye benzeyebileceği çok fazla farklı fikir olduğundan hangisi doğru? Bana göre MVC'yi icat eden kişilere, nasıl "doğru" uygulanacağını bilmek istediğimizde başvurulmalı. Gelen orijinal smalltalk kağıt diyor:

Görünüm, bit eşlemli görüntünün uygulamasına tahsis edilen kısmına yönelik grafiksel ve / veya metinsel çıktıyı yönetir. Denetleyici, modelin ve / veya görünümün uygun şekilde değiştirilmesi için komut vererek kullanıcıdan gelen fare ve klavye girdilerini yorumlar. Son olarak model, uygulama etki alanının davranışını ve verilerini yönetir, durumu hakkında bilgi taleplerine yanıt verir (genellikle görünümden) ve durumu değiştirmek için talimatlara yanıt verir (genellikle denetleyiciden).

Bunun ışığında üç ana endişenize şu şekilde cevap vereceğim:

  1. Aslında, bir Qt bileşeni "grafik [...] çıktısını yönetir" ve "fare ve klavye girişlerini yorumlar", böylece yukarıdaki tanıma göre aslında birleştirilmiş Görünüm ve Denetleyici olarak adlandırılabilir.
  2. Denetleyici ve Modeli birleştirmek zorunda olduğunuzu / olacağınızı kabul ediyorum (yine yukarıdaki tanımla ilgili olarak).
  3. Yine katılıyorum. Model, yalnızca uygulama etki alanının verilerini yönetmelidir . "Veri" dedikleri budur. Açıktır ki, örneğin satırlar ve sütunlarla uğraşmanın normalde uygulama alanımızla hiçbir ilgisi yoktur.

Bizi nerede bırakıyor? Bana göre, "Model" ve "Görünüm" terimleri kullanıldığında Qt'nin gerçekte ne anlama geldiğini anlamak ve biz Qt ile programlama yaparken bu terimleri kendi tarzlarında kullanmak en iyisidir. Eğer rahatsız olmaya devam ederseniz, bu sadece sizi yavaşlatır ve Qt'de işlerin kurulum şekli zarif tasarıma izin verir - bu da onların "yanlış" adlandırma kurallarından daha ağırdır.


2
Delegenin Qt'nin kontrolörü olduğunu söyleyebilirim, çünkü delegeler girişi sinyallerle güncelleyen modele girişi alıp gönderirler.
Peregring-lk

83

Kısa cevap

Qt'nin MVC'si yalnızca bir veri yapısı için geçerlidir . Bir MVC uygulaması hakkında konuşurken QAbstractItemModelveya hakkında düşünmemelisiniz QListView.

Tüm programınız için bir MVC mimarisi istiyorsanız, Qt bu kadar "devasa" bir model / görünüm çerçevesine sahip değildir. Ancak programınızdaki her veri listesi / ağacı için, aslında kendi görünümünde bir denetleyiciye sahip olan Qt MVC yaklaşımını kullanabilirsiniz . Veri içinde veya modelin dışında; bu, kullandığınız modelin türüne bağlıdır (kendi model alt sınıfı: muhtemelen model içinde; örneğin QSqlTableModel: modelin dışında (ancak belki de önbelleğe alınmış) modelin içinde). Modellerinizi ve görünümlerinizi bir araya getirmek için, daha sonra iş mantığını uygulayan kendi sınıflarını kullanın .


Uzun cevap

Qt'nin model / görünüm yaklaşımı ve terminolojisi:

Qt, modelleri için basit görünümler sağlar . Yerleşik bir denetleyiciye sahiptirler: öğeleri seçmek, düzenlemek ve taşımak çoğu durumda bir denetleyicinin "kontrol ettiği" bir şeydir. Yani, kullanıcı girdisini yorumlamak (fare tıklamaları ve hareketleri) ve modele uygun komutları vermek.

Qt'nin modelleri aslında temel verilere sahip modellerdir. Elbette soyut modeller veri tutmaz çünkü Qt onları nasıl depolamak istediğinizi bilmiyor. Ama sen alt sınıf için veri konteynerleri ekleme ve veri erişimine modeli arabirimini yaparak ihtiyaçlarınıza bir QAbstractItemModel uzanır. Yani aslında, ben böyle yok farz sorun olduğunu sen accedere ve veri yapısında değiştirilir böylece nasıl modelini programlamak gerekir.

MVC terminolojisinde, model hem verileri hem de mantığı içerir . Qt'de, iş mantığınızın bir kısmını modelinize dahil edip etmemek veya dışarıya koymak, kendi başına bir "görünüm" olarak size kalmış. Mantığın ne anlama geldiği bile net değil: Öğeleri seçmek, yeniden adlandırmak ve taşımak? => zaten uygulandı. Onlarla hesap mı yapıyorsun? => Model alt sınıfının dışına veya içine koyun. Bir dosyadan / dosyaya veri depolamak veya yüklemek mi? => Model alt sınıfının içine koyun.


Kişisel görüşüm:

Bir programcıya iyi ve genel bir MV (C) sistemi sağlamak çok zordur . Çoğu durumda modeller basit olduğundan (örn. Sadece dizi listeleri) Qt ayrıca kullanıma hazır bir QStringListModel sağlar. Ancak verileriniz dizelerden daha karmaşıksa, verileri Qt modeli / görünüm arayüzü aracılığıyla nasıl temsil etmek istediğiniz size kalmıştır. Örneğin, 3 alanlı bir yapınız varsa (adı, yaşı ve cinsiyeti olan kişiler diyelim) 3 alanı 3 farklı sütuna veya 3 farklı role atayabilirsiniz. Her iki yaklaşımı da sevmiyorum.

Qt'nin model / görünüm çerçevesinin yalnızca basit veri yapılarını görüntülemek istediğinizde yararlı olduğunu düşünüyorum . Veriler özel tipte ise veya bir ağaçta veya listede (örneğin bir grafikte) yapılandırılmamışsa işlemek zorlaşır . Çoğu durumda listeler yeterlidir ve bazı durumlarda bile bir modelde yalnızca tek bir giriş olmalıdır. Özellikle farklı özniteliklere sahip tek bir girişi modellemek istiyorsanız (bir sınıfın bir örneği), Qt'nin model / görünüm çerçevesi, mantığı kullanıcı arayüzünden ayırmanın doğru yolu değildir.

Özetlemek gerekirse, Qt'nin model / görünüm çerçevesinin, ancak ve ancak verileriniz Qt'nin görüntüleyici widget'larından biri tarafından görüntüleniyorsa yararlı olacağını düşünüyorum . Yalnızca bir girişi tutan bir model için kendi görüntüleyicinizi yazmak üzereyseniz, örneğin uygulamanızın ayarları veya verileriniz yazdırılabilir türden değilse, bu tamamen işe yaramaz.


(Daha büyük) bir uygulamada Qt modelini / görünümünü nasıl kullandım?

Bir keresinde (bir takımda) verileri yönetmek için birden çok Qt modeli kullanan bir uygulama yazmıştım. DataRoleHer farklı model alt sınıfı için farklı bir özel tipte olan gerçek verileri tutmak için bir oluşturmaya karar verdik . ModelTüm farklı Qt modellerini tutan bir dış model sınıfı oluşturduk . Ayrıca View, içindeki modellere bağlı olan pencereleri (widget'lar) tutma adında bir dış görünüm sınıfı oluşturduk Model. Dolayısıyla bu yaklaşım, kendi ihtiyaçlarımıza göre uyarlanmış genişletilmiş bir Qt MVC'dir. Hem Modelve Viewsınıfların kendileri Qt MVC ile ilgisi yok.

Mantığı nereye koyduk ? Kaynak modellerden (değiştiklerinde) verileri okuyarak ve sonuçları hedef modellere yazarak veriler üzerinde gerçek hesaplamaları yapan sınıflar oluşturduk. Qt'nin bakış açısından, bu mantık sınıfları, modellere "bağlandıklarından" (kullanıcı için "görünüm" değil, uygulamanın iş mantığı bölümü için bir "görünüm") olduğundan görünümler olacaktır.

Denetleyiciler nerede ? Orijinal MVC terminolojisinde, kontrolörler kullanıcı girişini (fare ve klavye) yorumlar ve istenen eylemi gerçekleştirmek için modele komutlar verir. Qt görünümleri, öğeleri yeniden adlandırmak ve taşımak gibi kullanıcı girdilerini zaten yorumladığından, buna gerek yoktu. Ancak ihtiyacımız olan şey, Qt görüşlerinin ötesine geçen bir kullanıcı etkileşimi yorumuydu.


En rahatsız edici şey, istediğiniz görünüme bağlı olarak tamamen farklı Qt Modeli sınıfları uygulamanız gerektiğidir. Liste görünümü için bir model, bir ağaç görünümünü doğru şekilde desteklemez ve bunun tersi de geçerlidir. Kanonik bir MVC modeli, çok sayıda farklı görünüm türünü destekleyebilir.
smerlin

3
@smerlin: Bunun doğru olduğunu düşünmüyorum. Hem QListView hem de QTreeView yalnızca bir QAbstractItemView arayüzü gerektirir, yani bunun özel bir alt sınıfı veya QStandardItemModel gibi somut bir sınıf her ikisi için de bu gereksinimi karşılamalıdır. Bir ağaç sürebilir ve bir modeli listeleyebilirsiniz.
jdi

1
@jdi: Verilerinizin hem bir liste hem de bir ağaç olduğu durumlar vardır ... örneğin dosya sisteminizi bir ağaç olarak veya tüm dosyaları bir liste olarak görüntülemek isteyebilirsiniz. Qts modelleri buna tam olarak izin vermiyor. Ağaç görünümlerini destekleyen bir QAbstractItemModel uygulaması, yalnızca kök dizininizdeki tüm dosyaları / dizinleri bir liste olarak görüntülemeye izin verir, ancak tüm dosyaları bir liste olarak görüntüleyemezsiniz. Ve ağaç verilerini bir liste olarak göstermenin yararlı olamayacağını söylemeyin. Örneğin, dosyalarınızı liste halinde görüntülerseniz, örneğin, en büyük dosya boyutuna sahip dosyayı bulmak için bunları kolayca sıralayabilirsiniz, ağaç görünümleri buna izin vermez.
smerlin

1
Dedi ki, vekil modeli (değiştirdiği beri bakış daha şeydir nasıl veri olduğunu inceledi görünümünüze ait olmalıdır böylece) ve. Uzun cevabımı okursanız: "Büyük" Viewsınıfta, temel modeli ağaç modeline sahip olan ve dosya sistemi listesi görünümünüz tarafından kullanılan proxy modelini eklemelisiniz. Dediğiniz gibi: aynı veriler için iki model olmamalıdır. Asla! (Ancak proxy modeller ayrı modeller olarak sayılmaz.)
leemes

1
@SamPinkus orada Çünkü hayır berrak evet ya hayır bu soruya. Ayrıca, QAbstractItemModelbazıları MVC anlamında model olan ve bazıları olmayan farklı uygulamaları vardır.
leemes

12

Terminoloji doğru ya da yanlış değil, yararlı ya da yararsız.

Soruyu biraz değiştirebilir ve Qt'nin neden MVC dostu olmadığını sorabilirsiniz. Bunun cevabı, ilk Qt geliştiricilerinin GUI uygulamalarında C'den V'nin ayrıştırılmasının hem kötü V'ler hem de C'ler oluşturduğuna inanmasıdır. QWidget'in tasarımı, fare giriş etkileşimini piksel çıktı kararlarıyla yakından bağlamayı basitleştirmeye çalışır ve bunun MVC'ye giden yolun nasıl olmadığını görebilirsiniz.


Söylemek istediğiniz noktayı anlıyorum ve temel olarak Qt'nin neden MVC dostu olmadığını soracağım, ancak Qt dokümantasyonunda kullanılan MVC terminolojisi, MVC'nin normalde kullanıldığından FARKLI olduğunda (soruda açıkladığım gibi) bunu yapmak çok zor. Ve yaygın olarak kullanılan bir terminoloji olduğunda ve birisi onu dünyanın geri kalanından çok farklı şekilde kullandığında, bunun sadece faydasız olmadığını, aynı zamanda tamamen YANLIŞ ve kafa karıştırıcı olduğunu düşünme eğilimindeyim (bu kafa karışıklığı, beni ilk başta soruyu sormaya yöneltti. yer). Bir yerde tartışılan veya açıklanan bu konularla ilgili herhangi bir bağlantınız varsa çok ilgilenirim. Teşekkürler
gorn

Qt belgelerinin artık MVC hakkında neden bu şekilde konuştukları hakkında hiçbir şey söyleyemem. Trolltech'ten uzun zaman önce ayrıldım ve ayrıldığımdan beri belgelere yapılan bazı şeyler karşısında şaşkınım. (Blogumda bazen bunun hakkında biraz
söyleniyorum

Qt'de MVC terminolojisinin nasıl kararlaştırıldığına dair herhangi bir fikriniz var mı? Kod yazılırken mi yoksa daha sonra dokümantasyon işlemi sırasında mı kullanıldı?
gorn

Trolltech'te geçirdiğim süre boyunca Qt belgelerinde "MVC" kelimesini kullanmadık. Genel olarak bence en iyisi orada olanı belgelemek, orada olmayanlar hakkında yazmak değil. Ancak, gitorious'ta bu metni kimin eklediğini bulabilir ve bu kişiyi doğrudan ekleyebilirsiniz.
arnt

1
Farklı bir yorum. MVC'yi Qt'nin tasarımı ve erken uygulama cümlesi sırasında tartıştık (Trollech üç kişilik bir şirketken) ve MVC'yi "doğru" kullanan bir GUI araç setini değerlendirdik, adını hatırlayamıyorum. Bizim fikrimiz, bu araç setinin kullanımının korkunç olduğu ve bunun sebebinin MVC olduğuydu.
arnt

3

Model işlevi bilgi isteklerini yanıt verdiklerini olduğu gibi, ben yanlış bir şey gibi yöntemler tanımlanmasında olduğunu düşünüyorum rowCount, columnCountModel veri kaynağı için sarıcı çeşit olduğunu düşünüyorum, vb I (olursa olsun, SQL tablo ya da sadece bir dizi budur) , verileri standart biçimde sağlar ve veri kaynağı yapınıza bağlı olarak yöntemleri tanımlamanız gerekir.


2

Terminolojilerinin doğru olduğuna inanıyorum ... gerçi gerçek uygulamalarda, soyutlama seviyenize bağlı olarak model, görünüm ve kontrolör arasındaki çizgileri bulanıklaştırmanın çok kolay olabileceğini düşünüyorum: bir seviyenin görüşü daha yüksek seviyeli bir model olabilir.

Karışıklıkların QAbstractModelItem sınıflarından kaynaklandığını hissediyorum. Bu sınıf bir model öğesi değil, daha çok bir modele bir arayüzdür. Görünüm sınıflarını modelle arayüz oluşturmak için, modele genel bir soyut arayüz oluşturmaları gerekiyordu. Bununla birlikte, bir model tek bir öğe, bir öğe listesi, öğelerin 2 veya daha fazla boyutundan oluşan bir tablo vb. Olabilir; bu nedenle arayüzlerinin tüm bu model varyasyonlarını desteklemesi gerekir. Kuşkusuz bu, model öğelerini oldukça karmaşık hale getirir ve gerçek bir modelle çalışmasını sağlayan yapıştırıcı kodu, metaforu biraz uzatıyor gibi görünüyor.


QAbstractModelItem sınıfına katılıyorsam da, bu karmaşıklık olmasa bile MVC'nin yanlış adlandırıldığını düşünüyorum. Terminolojilerinin neden doğru olduğunu düşündüğünüzü açıklayabilir misiniz? Üç argümanımın hiçbirinde neden doğru olmadığımı duymak isterim.
Gorn

0

Bence ... Model dedikleri şey aslında sadece Denetleyici.

Hayır, "modelleri" kesinlikle bir kontrolör değil.

Kontrolör, modeli değiştiren (ve dolayısıyla dolaylı olarak görünümü değiştiren) kullanıcı tarafından görülebilen kontrollerin bir parçasıdır. Örneğin, "sil" düğmesi denetleyicinin bir parçasıdır.

Bence çoğu zaman kafa karışıklığı var çünkü çoğu kişi "denetleyici modeli değiştiriyor" gibi bir şey görüyor ve bunun modellerinde "deleteRow ()" yöntemi gibi değişime uğrayan işlevler anlamına geldiğini düşünüyor. Ancak klasik MVC'de kontrolör özellikle kullanıcı arayüzü parçasıdır. Modeli değiştiren yöntemler, modelin basit bir parçasıdır.

MVC icat edildiğinden beri, denetleyici ve görünüm arasındaki ayrım giderek daha gergin hale geldi. Bir metin kutusu düşünün: Hem size bir metin gösterir hem de onu düzenlemenize izin verir, yani görüntü mü yoksa denetleyici mi? Cevap, her ikisinin de parçası olması gerekir. 1960'larda bir teletype üzerinde çalışırken, ayrım daha netti - bir düşünün ed- ama bu, o zamanlar kullanıcı için işlerin daha iyi olduğu anlamına gelmez!

QAbstractItemModel'lerinin bir modelin normalde olacağından oldukça yüksek seviyede olduğu doğrudur. Örneğin, içindeki öğeler bir arka plan rengine (teknik olarak bir fırça) sahip olabilir, bu kesinlikle bir görünüm-ish niteliğidir! Dolayısıyla, QAbstractItemModel'in daha çok bir görünüme benzediğine ve verilerinizin model olduğuna dair bir argüman var. Gerçek şu ki, klasik görüş ve model anlamları arasında bir yerde. Ama nasıl bir denetleyici olduğunu göremiyorum; QT parçacığı olan herhangi bir şey varsa.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.