MVVM anlamsız mı? [kapalı]


92

Ortodoks MVVM uygulaması anlamsız mı? Yeni bir uygulama oluşturuyorum ve Windows Forms ve WPF'yi düşündüm. WPF'yi seçtim çünkü geleceğe dönük ve çok fazla esneklik sunuyor. Daha az kod vardır ve XAML kullanarak kullanıcı arabiriminizde önemli değişiklikler yapmak daha kolaydır.

WPF seçimi açık olduğundan, uygulama mimarim olarak MVVM'yi kullanıp, karıştırılabilirlik, ayırma endişeleri ve birim test edilebilirliği sunduğu için sonuna kadar gidebileceğimi düşündüm. Teorik olarak, UI programlamanın kutsal kasesi gibi güzel görünüyor. Bu kısa macera; ancak gerçek bir baş ağrısına dönüştü. Pratikte beklendiği gibi, bir problemi başka bir problemle değiştirdiğimi görüyorum. Doğru sonuçları alabilmek ve muhtemelen daha iyi bir programcı olabilmek için işleri doğru şekilde yapmak istediğim için takıntılı bir programcı olma eğilimindeyim. MVVM kalıbı, üretkenlik konusundaki testimi geride bıraktı ve az önce büyük bir iğrenç hack'e dönüştü!

Buradaki açık durum, bir Modal iletişim kutusu için destek eklemektir. Doğru yol, bir iletişim kutusu koymak ve bunu bir görünüm modeline bağlamaktır. Bunun işe yaraması zordur. MVVM modelinden yararlanmak için, kodu uygulamanızın katmanları boyunca birkaç yere dağıtmanız gerekir. Ayrıca şablonlar ve lamba ifadeleri gibi ezoterik programlama yapılarını da kullanmalısınız. Başınızı kaşıyarak ekrana bakmanıza neden olan şeyler. Bu, bakım ve hata ayıklamayı, yakın zamanda keşfettiğim gibi olmasını bekleyen bir kabus haline getiriyor. İkinci seferde bir istisna elde edene kadar iyi çalışan bir kutum vardı, kapatıldığında iletişim kutusunu tekrar gösteremeyeceğini söyledi. İletişim penceresine yakın işlevsellik için bir olay işleyicisi eklemem gerekiyordu, IDialogView uygulamasında bir tane ve son olarak IDialogViewModel'de bir tane. MVVM'nin bizi bu kadar abartılı bilgisayar korsanlığından kurtaracağını düşünmüştüm!

Dışarıda bu soruna rakip çözümlere sahip birkaç kişi var ve bunların hepsi hackler ve temiz, kolayca yeniden kullanılabilir, zarif bir çözüm sağlamıyor. MVVM araç setlerinin çoğu, diyalogların üzerinde durur ve bunları ele aldıklarında, özel arayüzler veya görünüm modelleri gerektirmeyen uyarı kutularıdır.

MVVM görünüm modelinden, en azından ortodoks uygulamasından vazgeçmeyi planlıyorum. Ne düşünüyorsun? Varsa senin için zahmete değdi mi? Ben sadece beceriksiz bir programcı mıyım yoksa MVVM olması gerektiği gibi değil mi?


8
MVVM'nin aşırı mühendislik yapıp yapmadığını hep sorguladım. İlginç soru.
Taylor Leese

12
MVVM ve MVC gibi modeller, bazı değişiklikler yapmanız veya bir bileşeni değiştirmeniz gerekene kadar aşırı mühendislik gibi görünür. Bunu ilk kez yapmanız gerektiğinde, tüm törenler kendi
Robert Harvey

42
Lambdalar ezoterik mi? bana haber.
Ray Booysen

6
@Ray - Haha, bu yorum için +1! : D
Venemo

8
Alan Cooper'ın on yıldan uzun bir süre önce About Face'te belirttiği gibi , kullanıcı arayüzleri tasarlıyorsanız ve modal diyaloglar bir uç durum değilse, muhtemelen yanlış bir şey yapıyorsunuzdur.
Robert Rossney

Yanıtlar:


61

Cevabım biraz uzadıysa özür dilerim, ama beni suçlama! Sorunuz da uzun.

Özetle, MVVM anlamsız değildir.

Buradaki açık durum, bir Modal iletişim kutusu için destek eklemektir. Doğru yol, bir iletişim kutusu koymak ve bunu bir görünüm modeline bağlamaktır. Bunun işe yaraması zordur.

Evet, gerçekten öyle.
Ancak MVVM, kullanıcı arayüzünün görünümünü mantıklarından ayırmanın bir yolunu sağlar. Kimse sizi her yerde kullanmaya zorlamaz ve hiç kimse her şey için ayrı bir ViewModel oluşturmanızı sağlamak için alnınıza silah dayamaz.

İşte bu özel örnek için benim çözümüm:
Kullanıcı arayüzünün belirli bir girişi nasıl işlediği ViewModel'in işi değildir. View'ın .xaml.cs dosyasına, iletişim kutusunu başlatan ve DataContext ile aynı ViewModel örneğini (veya gerekirse başka bir şeyi) ayarlayan kod eklerdim.

MVVM modelinden yararlanmak için, kodu uygulamanızın katmanları boyunca birkaç yerde dağıtmanız gerekir. Ayrıca şablonlar ve lamba ifadeleri gibi ezoterik programlama yapılarını da kullanmalısınız.

Pekala, birkaç yerde kullanmak zorunda değilsin. Ben böyle çözerdim:

  • XAML'yi görünüme ekleyin ve .xaml.cs dosyasına hiçbir şey ekleyin
  • Her uygulama mantığını (doğrudan UI öğeleriyle çalışacak şeyler hariç) bir ViewModel içine yazın
  • Kullanıcı arabirimi tarafından yapılması gereken, ancak iş mantığı ile ilgisi olmayan tüm kodlar .xaml.cs dosyalarına gider

MVVM'nin amacının öncelikle uygulamanın mantığını ve somut kullanıcı arayüzünü ayırmak, dolayısıyla kullanıcı arayüzünde kolay değişikliklere (veya tamamen değiştirmeye) olanak sağlamak olduğunu düşünüyorum.
Şu prensibi kullanıyorum: View, ViewModel'den istediği her şeyi bilebilir ve varsayabilir, ancak ViewModel, View hakkında HİÇBİR ŞEYİ bilemez.
WPF, tam olarak bunu başarmak için kullanabileceğiniz güzel bir bağlama modeli sağlar.

(BTW, şablonlar ve lambda ifadeleri doğru kullanılırsa ezoterik değildir. Ancak istemiyorsanız kullanmayın.)

Başınızı kaşıyarak ekrana bakmanıza neden olan şeyler.

Evet, duyguyu biliyorum. MVVM'yi ilk gördüğümde tam olarak hissettiğim şey. Ama bir kez asıldığınızda, artık kötü hissetmeyeceksiniz.

İyi çalışan bir kutum vardı ...

Neden bir hakkında kutusunun arkasına bir ViewModel koyasınız? Bunun anlamı yok.

MVVM araç setlerinin çoğu, diyalogların üzerinde durur ve bunları ele aldıklarında, özel arayüzler veya görünüm modelleri gerektirmeyen uyarı kutularıdır.

Evet, çünkü bir UI öğesinin aynı pencerede veya başka bir pencerede olması veya şu anda Mars'ın yörüngesinde olması ViewModels'in endişelerinden biri değil.
Kaygıların Ayrılması

DÜZENLE:

İşte başlığı Kendi MVVM çerçevenizi oluşturun olan çok güzel bir video . İzlemeye değer.


3
Son üç kelime için +1. Ama cevabın geri kalanı da iyi. :)
Robert Harvey

13
Arka planda kod kullanımıyla ilgili tavsiye için +1. MVVM'de arka planda kod kullanmanın "kötü" olduğu yaygın bir yanılgıdır ... ama tamamen UI ile ilgili şeyler için, gidilecek yol budur.
Thomas Levesque

1
@Thomas: Evet, daha fazla katılamadım. İnsanların tüm kodu (hatta UI ile ilgili olanları) ViewModel'e koyduğu birkaç uygulama gördüm, çünkü (onlara göre) "kodun olduğu yer burasıdır". Oldukça huysuzdu.
Venemo

4
@Venemo, özel Davranışlar gibi teknikleri kullanarak arka plana koymak isteyeceğiniz birçok şeyi özetleyebileceğinizi düşünüyorum, bu da kendinizi tekrar tekrar yapıştırıcı kod yazarken bulursanız kullanışlıdır. Genel olarak yine de, tutkal için arka planda kodlama kullanmanın garip XAML'yi birlikte hacklemekten daha iyi olduğunu düşünüyorum. Aklımda asıl mesele, arka plan kodunda birim testini gerektirecek kadar karmaşık bir şey olmadığından emin olmaktır. Yeterince karmaşık olan her şey, ViewModel'de veya Behavior veya MarkupExtension gibi bir uzantı sınıfında kapsüllenmek daha iyidir.
Dan Bryant

8
@ Thomas: Haklısın, MVVM hakkındaki en büyük efsane, MVVM'nin amacının arka planda koddan kurtulmak olduğu. Amaç, UI olmayan ocde'yi arkasındaki koddan çıkarmaktır. ViewModel'e yalnızca kullanıcı arabirimi kodunu koymak, sorunlu alan kodunu arka plana koymak kadar kötüdür.
Jim Reineri

8

Bunun işe yaraması zordur. MVVM modelinden yararlanmak için, kodu uygulamanızın katmanları boyunca birkaç yerde dağıtmanız gerekir. Ayrıca şablonlar ve lamba ifadeleri gibi ezoterik programlama yapılarını da kullanmalısınız.

Sıradan bir kalıcı iletişim kutusu için? Orada kesinlikle yanlış bir şey yapıyorsunuz - MVVM uygulamasının bu kadar karmaşık olması gerekmiyor.

Hem MVVM hem de WPF'de yeni olduğunuzu düşünürsek, muhtemelen her yerde yetersiz çözümler kullanıyorsunuz ve işleri gereksiz yere karmaşıklaştırıyorsunuz - en azından bunu WPF'ye ilk gittiğimde yaptım. Vazgeçmeden önce sorunun gerçekten MVVM olduğundan ve uygulamanız olmadığından emin olun.

MVVM, MVC, Document-View, vb. Eski bir model ailesidir. Dezavantajlar vardır, ancak tarif ettiğiniz türden ölümcül kusurlar yoktur.


5

PRISM kullanarak oldukça karmaşık bir MVVM geliştirmenin ortasındayım, bu nedenle bu tür endişelerle zaten başa çıkmak zorunda kaldım.

Benim kişisel çıkarım:

MVVM vs MVC / PopUps & co

  • MVVM gerçekten harika bir modeldir ve çoğu durumda WPF'deki güçlü veri bağlama sayesinde MVC'nin yerini alır.
  • Hizmet katmanınızı doğrudan sunum yapan kişiden aramak çoğu durumda yasal bir uygulamadır.
  • Oldukça karmaşık Liste / Ayrıntı senaryoları bile {Bağlama Yolu = /} sözdizimi sayesinde saf MVVM tarafından uygulanabilir
  • Bununla birlikte, birden çok görünüm arasında karmaşık koordinasyonun uygulanması gerektiğinde,
  • Olaylar kullanılabilir; IView (veya AbstractObserver) örneklerini denetleyicide depolamayı ima eden eski model artık kullanılmıyor
  • Denetleyici, her Sunumcuya IOC kabı tarafından enjekte edilebilir
  • Prism'in IEventAggregator hizmeti, denetleyicinin tek kullanımının olay dağıtımı olması durumunda olası başka bir çözümdür (bu durumda denetleyiciyi tamamen değiştirebilir)
  • Görünümler dinamik olarak oluşturulacaksa, bu denetleyici için çok uygun bir iştir (prizmada denetleyiciye bir IRegionManager enjekte edilir (IOC))
  • Zorunlu onaylar gibi işlemleri gerçekten engelleyen durumlar dışında, modal iletişim kutuları çoğunlukla modern bileşik uygulamalarda kullanılmamaktadır; bu durumlarda modsal etkinleştirme, denetleyici içinde çağrılan bir hizmet olarak soyutlanabilir ve özel bir sınıf tarafından uygulanabilir, bu da gelişmiş sunum düzeyinde birim testine izin verir. Denetleyici, örneğin, çalışma zamanında kalıcı bir iletişim kutusu gösterimini tetikleyecek ve birim testi sırasında kolayca alay edilebilecek IConfirmationService.RequestConfirmation ("emin misiniz") çağıracaktır

5

Hile yaparak diyalog sorununu çözüyorum. My MainWindow, uygulamaya özel tüm iletişim kutularını ortaya çıkaran bir IWindowServices arabirimi uygular. Diğer ViewModels'lerim daha sonra servis arayüzünü içe aktarabilir (MEF kullanıyorum, ancak arayüzü kuruculardan manuel olarak kolayca geçirebilirsiniz) ve gerekli olanı gerçekleştirmek için onu kullanabilir. Örneğin, benim küçük bir yardımcı program uygulamam için arayüz şöyle görünüyor:

//Wrapper interface for dialog functionality to allow for mocking during tests
public interface IWindowServices
{
    bool ExecuteNewProject(NewProjectViewModel model);

    bool ExecuteImportSymbols(ImportSymbolsViewModel model);

    bool ExecuteOpenDialog(OpenFileDialog dialog);

    bool ExecuteSaveDialog(SaveFileDialog dialog);

    bool ExecuteWarningConfirmation(string text, string caption);

    void ExitApplication();
}

Bu, tüm Diyalog uygulamalarını tek bir yere koyar ve birim testi için kolayca kaldırılabilir. İletişim kutusunun istemcisinin, daha sonra gerektiği gibi yapılandırabilecekleri uygun ViewModel'i oluşturmak zorunda olduğu kalıbı takip ediyorum. Yürütme çağrı blokları ve daha sonra istemci, Dialog sonuçlarını görmek için ViewModel'in içeriğine bakabilir.

Daha 'saf' bir MVVM tasarımı, daha temiz yalıtıma ve daha karmaşık bileşime ihtiyaç duyduğunuz büyük bir uygulama için önemli olabilir, ancak küçük ve orta ölçekli uygulamalar için, gerekli kancaları açığa çıkarmak için uygun hizmetlerle pratik bir yaklaşımın oldukça yeterli olduğunu düşünüyorum. .


Ama onu nereden çağırıyorsun? IWindowServices sınıfının işlevleri içinde diyaloğu iletmek yerine sadece oluşturmak daha iyi olmaz mıydı. Bu şekilde çağıran model görünümünün belirli diyalog uygulaması hakkında hiçbir şey bilmesine gerek kalmaz.
Joel Rodgers

Arayüz, ViewModel örneklerimden hangisinin uygulama iletişim kutularına erişmesi gerekiyorsa enjekte edilir. Çoğu durumda, iletişim kutusu için ViewModel'de geçiyorum, ancak biraz tembelleştim ve dosya iletişim çağrıları için WPF OpenFileDialog ve SaveFileDialog'u kullandım. Birincil hedefim, birim testi amacıyla izolasyondu, bu nedenle bu, bu hedef için yeterlidir. Daha iyi izolasyon istiyorsanız, muhtemelen iletişim kutuları için gerekli özellikleri çoğaltacak bir OpenFileViewModel ve SaveFileViewModel oluşturmak isteyeceksiniz.
Dan Bryant

Bunun kesinlikle saf bir yaklaşım olmadığını unutmayın, çünkü diyalogları kullanan ViewModel açmak istediği her diyalog için belirli ViewModel hakkında bilgi sahibidir. Bunun oldukça temiz olduğunu düşünüyorum, ancak bağlantı sırasında kullanılan ViewModel özelliklerinin gereksiz görünürlüğünü gizleyerek iletişim kutusu kullanımı için gerekli parametreleri tamamen ortaya çıkaran bir sınıfla her zaman ek bir yalıtım katmanı ekleyebilirsiniz. Daha küçük uygulamalar için, bu ek yalıtımın aşırı olduğunu düşünüyorum.
Dan Bryant

5

Tasarım kalıpları size yardımcı olmak için var, engel değil. İyi bir geliştirici olmanın küçük bir kısmı, ne zaman "kuralları çiğnemeniz" gerektiğini bilmektir. MVVM bir görev için hantalsa ve gelecekteki değerin çabaya değmeyeceğini belirlediyseniz, o zaman kalıbı kullanmayın. Örneğin, diğer posterlerin de söylediği gibi, neden basit bir about kutusu uygulamak için tüm ek yüklerin üzerinden geçersiniz?

Tasarım kalıplarının asla dogmatik bir şekilde takip edilmesi amaçlanmadı.


2
Doğru. Basit bir kutu basit olmalıdır, ama ya sürüm, lisanslama, çalışan süreç, şirket adı vb. Gibi bilgileri görüntülemeniz gerekirse. Bunlar bir yerde yaşayan tüm bilgilerdir. Standart formlarda, tüm bu bilgileri bağlayabilir ve onunla işinizi halledebilirsiniz. MVVM, bunun için gereksiz olan bir görünüm modeli oluşturmanız gerektiğini söylüyor.
ATL_DEV

1

Modelin kendisi gibi MVVM harika. Ancak NET 4.0 veri bağlama desteği ile gönderilen WPF'nin kontrol kitaplığı çok sınırlıdır, WinForm'dan çok daha iyidir, ancak yine de bağlanabilir MVVM için yeterli değildir, gücünün bağlanabilir MVVM için gerekli olanın yaklaşık% 30'u olduğunu söyleyebilirim.
Bağlanabilir MVVM: ViewModel'in yalnızca veri bağlamayı kullanarak View ile kablolandığı UI'dir.
MVVM modeli, ViewState'in nesne temsiliyle ilgilidir, View ve ViewModel arasındaki senkronizasyonu nasıl sürdürdüğünüzü açıklamaz, WPF'de veri bağlamadır, ancak herhangi bir şey olabilir. Ve aslında MVVM modelini, olayları \ geri çağırmalarını destekleyen herhangi bir UI araç setinde kullanabilirsiniz, bunu WinForms'ta saf WinAPI'de kullanabilirsiniz (yaptım ve olaylar \ geri aramalarla daha fazla çalışmıyor) ve hatta bunu Metin içinde bile kullanabilirsiniz. Konsol, MVVM modelini kullanarak DoS'un Norton Commander'ını yeniden yazmak gibi.

Kısacası: MVVM anlamsız değil, harika. NET 4.0 WPF'nin kontrol kitaplığı çöptür.

İşte WPF kullanarak saf MVVM tarzında veri bağlayamayacağınız ViewModel'in basit kanıtı.

public class PersonsViewModel
{
    public IList<Person> PersonList;
    public IList<ColumnDescription> TableColumns;
    public IList<Person> SelectedPersons;
    public Person ActivePerson;
    public ColumnDescription SortedColumn;
}

WPF'nin DataGrid sütun başlıklarını veri bağlayamazsınız, seçilen satırları vb. Bağlayamazsınız, bunu basit bir şekilde kodla yaparsınız veya bu en basit ViewModel 5 satırı için 200 satır XAML hack kodu yazarsınız. Karmaşık ViewModel'lerle işlerin nasıl daha da kötüleştiğini yalnızca hayal edebilirsiniz.
Yani cevap basittir, Hello World uygulaması yazmıyorsanız, WPF'de bağlanabilir MVVM kullanmak anlamsızdır. ViewModel'i bağlamak için zamanınızın çoğunu hack üzerinde düşünerek geçireceksiniz. Veri bağlama iyidir, ancak etkinliğin% 70'ine geri dönmeye hazır olun.


Bunu dönüştürücülerle bir DataGrid'e bağlayabilirsiniz.
Cameron MacFarland

@CameronMacFarland: Hepsi değil, bazı özellikler salt okunur ve bağlanamaz, bazıları mevcut değil ve yalnızca durum değişikliğini bildiren olaylar var.
Alex Burtsev

WPF DataGrid'i kullanma deneyimim olmadığını itiraf edeceğim. Çirkin olduğu ve artık WPF'ye uymadığı için bundan kaçınma eğilimindeyim. Olayları işlemek için dönüştürücüler ve AttachedProperties kombinasyonunun size ihtiyacınız olanı vermesi gerektiğini söyledi.
Cameron MacFarland

1
Alex, yaşadığınız problemler MVVM ile değil DataGrid'in tasarımıyla ilgili. "Veri bağlama güzeldir, ancak etkinliğin% 70'ine geri dönmeye hazır olun" demek yanlıştır. (Telerik) veri ızgarasının başlatma için ihtiyaç duyduğu olay işleyicisi dışında, kullanıcı arayüzünde hiçbir olay işleyicisinin bulunmadığı bazı nesnel olarak büyük WPF uygulamaları yazdım.
Robert Rossney

3
"Bu kötü tasarlanmış ve çalışmıyor" tavrını benimsemek yerine, "Bu neden başkaları için çalışıyor ama benim için çalışmıyor?" Tavrını benimsemek yerine daha başarılı olabileceğinizi düşünüyorum. İşleri yapmanın zor olmasının sebebinin henüz onları nasıl yapacağınızı bilmemeniz olduğunu fark edebilirsiniz.
Robert Rossney

0

Hayır, anlamsız değil, ama kalıbın kendisi gülünç derecede basit olmasına rağmen başınızı sarmak zordur. Dışarıda tonlarca yanlış bilgi ve doğru yol için savaşan çeşitli gruplar var. Bence WPF ve Silverlight ile MVVM kullanmalısınız, yoksa aşırı kodlama yapıp yeni bir modeldeki sorunları çözmeye çalışacaksınız, "eski" kazanç formları metodolojisi sizi belaya sürükleyecek. Her şeyin asenkron olması gerektiğinden bu daha çok Silverlight'ta söz konusudur (bununla ilgili hacklemeler mümkündür, ancak başka bir platform seçmelisiniz).

MVVM'nin nasıl iyi bir şekilde uygulanabileceğini görmek ve kazanç formları zihniyetinizi MVVM'deki yeni düşünme biçimine değiştirmenize izin vermek için ViewModel Modelini dikkatlice Kullanarak WPF TreeView'i basitleştirme bu makaleyi okumanızı öneririm . Kısacası, bir şeyi halletmek istediğinizde mantığı önce View'e değil ViewModel'e uygulayın. Bir öğe seçmek mi istiyorsunuz? Bir simgeyi değiştirmek mi? UI öğelerini yinelemeyin, yalnızca model özelliklerini güncelleyin ve veri bağlamanın işin özünü yapmasına izin verin.


-1

(Modal) diyaloglar söz konusu olduğunda aynı sorunu birçok MVVM uygulamasında gördüm. MVVM Modelinin katılımcılarına baktığımda, tutarlı bir uygulama oluşturmak için bir şeylerin eksik olduğu hissine kapılıyorum.

  • View , belirli GUI kontrollerini içerir ve kullanıcı arayüzünün görünümünü tanımlar.
  • ViewModel , sunumun durumunu ve davranışını temsil eder.
  • Model , etki alanı katmanından bir iş nesnesi veya gerekli verileri sağlayan bir hizmet olabilir.

Ancak eksik olan:

  • ViewModelleri kim yaratır?
  • Başvuru iş akışından kim sorumludur?
  • ViewModel'lar birbirleriyle iletişim kurmaları gerektiğinde arasında kim arabuluculuk yapar?

Yaklaşımım, eksik noktalardan sorumlu olan bir (Kullanım Durumu) Kontrolörü sunmaktır. Bunun nasıl çalıştığı, WPF Uygulama Çerçevesi (WAF) örnek uygulamalarında görülebilir .


Josh Smith tarafından uygulanan Arabulucu modeli tüm Görünüm Modeli iletişim sorunlarımı çözdü. Messenger.NotifyColleagues, herhangi iki görünüm modelinin birbirini bilmesine gerek kalmadan küresel olaylara (umursuyorlarsa) nasıl yanıt vereceğini bilen tamamen bağımsız görünüm modellerine sahip olmanın bir yolunu sağladı. Pastırmamızı şimdiden birkaç kez kurtardı.
JasonD
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.