Model-View-Presenter uygulama düşünceleri


34

Bir UI ile model arasında iyi bir ayrıştırmanın nasıl uygulanacağını iyi bir şekilde kavramaya çalışıyorum, ancak çizgileri tam olarak nereye böleceğimizi bulmakta güçlük çekiyorum.

Model-View-Presenter'a bakıyorum, ancak nasıl uygulanacağı konusunda tam olarak emin değilim. Örneğin, Görünümümde birden fazla iletişim kutusu var.

  • Her bir iletişim kutusunun örneklerini içeren bir View sınıfı olmalı mı? Öyleyse bu durumda, diyaloglar Presenter ile nasıl etkileşime girmeli? yani. Tek bir iletişim kutusunun Modelden Presenter üzerinden veri talep etmesi gerekiyorsa, iletişim kutusu Presenter'a nasıl başvuruda bulunmalıdır? İnşaat sırasında kendisine verilen Görünüm referans alınarak?
  • Sanırım manzara statik bir sınıf olmalıydı? Sonra iletişim kutuları GetView ve Presenter'ı oradan almak ...
  • Bunu, Presenter'ın Görünüm ve Modelin (Sunucunun ve Presenter'ın Modele sahip olduğu Görünümün aksine) sahip olmasıyla) ve Sunucunun Görünümdeki olaylar için geri çağrılmaları kaydettirmesini ayarlamayı düşünüyordum. daha fazla eşleşmiş (veya dile bağlı, en azından.)

Deniyorum:

  1. Bunu mümkün olduğunca dekolte edin
  2. ideal olarak Sunucuyu / Modeli diğer dillerin Görüşleriyle eşleştirmeyi mümkün kılar (Bir sürü dil arası iş yapmadım, ancak bunun mümkün olduğunu biliyorum, özellikle daha fazla void(void)yapışabileceğim, en azından bir C # uygulamasına C ++ kütüphanesi ...
  3. kodu temiz ve basit tutun

Yani .. herhangi bir etkileşimler nasıl ele alınması gerektiğini herhangi bir öneriniz?



1
Ben mümkün olduğunca az bağlantı .. gibi büyük bir projede birden diyaloglar nasıl işleneceğini daha iyi anlamak için arıyorum ben o Biraz çabuk ve yüksek seviyede bulunan .. var
trycatch

Yanıtlar:


37

Kaygan bir eğime hoş geldiniz. Bu noktada, tüm model-görünüm etkileşimlerinin sonsuz bir çeşitliliği olduğunu fark ettiniz. MVC, MVP (Taligent, Dolphin, Passive View), MVVM sadece birkaç isim.

Model View Presenter modeli, çoğu mimari desen gibi, çok çeşitli ve deneyime açıktır. Tüm varyasyonların ortak noktalarından biri, sunum yapan kişinin görüş ile model arasında "aracı" olarak rol almasıdır. En yaygın iki tanesi, Pasif Görünüm ve Denetleyici Sunum / Denetleyici - [ Fowler ]. Pasif Görünüm , kullanıcı arabirimine kullanıcı ve sunum yapan kişi arasında çok sığ bir arabirim olarak davranır. Herhangi bir mantık varsa, bir sunucuya çok fazla sorumluluk veren, çok az içerir. Sunucu / Denetleyiciyi Denetlemebirçok UI çerçevesine yerleşik veri bağlamasından yararlanmaya çalışır. UI veri senkronizasyonunu yönetir ancak sunucu / kontrol birimi daha karmaşık mantık için devreye girer. Her iki durumda da model, görünüm ve sunum üçlüsü oluşturur

Bunu yapmanın birçok yolu vardır. Her diyaloğu / formu farklı bir bakış açısı olarak ele alarak bunu ele almak çok yaygın. Çoğu zaman görüşlerle sunum yapanlar arasında 1: 1 ilişki vardır. Bu zor, hızlı bir kural değil. Bir sunum yapan kişinin birden fazla ilgili görüşü ele alması veya bunun tersi olması oldukça yaygındır. Her şey görüşün karmaşıklığına ve iş mantığının karmaşıklığına bağlıdır.

Görüşlerin ve sunum yapanların birbirlerine nasıl referans aldıklarına gelince, buna bazen kablolama denir . Üç seçeneğiniz var:

Görünüm sunum yapan kişiye referansta bulunur
Bir form veya iletişim kutusu bir görünüm uygular. Forma, doğrudan işlev çağrıları kullanarak sunum yapan kişiye ileten olay işleyicileri vardır:

MyForm.SomeEvent(Sender)
{
  Presenter.DoSomething(Sender.Data);
}

Sunucunun görünüme bir referansı olmadığından, görünümün verileri argüman olarak göndermesi gerekir. Sunucu, görünümün dinlemesi gereken olaylar / geri arama işlevlerini kullanarak görünüme geri dönebilir.

Presenter görüntülemek için bir referans tutar
Senaryoda görünüm, kullanıcıya gösterdiği verilerin özelliklerini gösterir. Sunucu, olayları dinler ve görünümdeki özellikleri değiştirir:

Presenter.SomeEvent(Sender)
{
  DomainObject.DoSomething(View.SomeProperty);
  View.SomeOtherProperty = DomainObject.SomeData;
}

Her ikisi de dairesel bir bağımlılık oluşturan birbirlerine atıfta bulunur.
Bu senaryo, diğerleriyle çalışmaktan daha kolaydır. Görünüm, sunucudaki yöntemleri çağırarak olaylara yanıt verir. Sunucu, görünümdeki verileri maruz kalan özellikler yoluyla okur / değiştirir.

View.SomeEvent(Sender)
{
  Presenter.DoSomething();
}

Presenter.DoSomething()
{
  View.SomeProperty = DomainObject.Calc(View.SomeProperty);
}

MVP modellerinde dikkat edilmesi gereken başka konular var. Yaratma düzeni, nesne ömrü, kablolamanın gerçekleştiği yer, MVP triadları arasındaki iletişim ancak bu cevap zaten yeterince uzadı.


1
Bu kesinlikle yardımcı olur. Triadlar ve ömür arasındaki iletişim şu an için sorun yaşadığım yer.
31'de buluşma

8

Herkesin söylediği gibi, onlarca görüş vardır ve hiçbiri doğru ya da yanlış değildir. Sayısız formata girmeden ve sadece MVP'ye odaklanmadan uygulama için bazı öneriler var.

Onları ayırın. Görünüm, görünüm ile sunum arasındaki bağı oluşturan bir arayüz uygulamalıdır. Görünüm, sunum yapan kişi oluşturur ve kendisini sunum yapan kişiye enjekte eder ve sunum yapan kişinin görünümle etkileşime girmesi için sunduğu yöntemleri açıklar. Bu yöntemleri veya özellikleri istediği şekilde uygulamaktan görüş sorumludur. Genel olarak bir görüşünüz vardır: bir sunum, ancak bazı durumlarda birçok görüş olabilir: bir sunum (web, wpf, vs.). Buradaki anahtar, sunum yapan kişinin UI uygulamalarıyla ilgili hiçbir şey bilmediği ve yalnızca arabirim görünümüyle etkileşime girdiğidir.

İşte bir örnek. Öncelikle, kullanıcıya bir mesaj görüntülemek için basit bir yöntemle bir görünüm sınıfına sahibiz:

interface IView
{
  public void InformUser(string message);
}

Şimdi burada sunum var. Sunucunun kurucusuna bir IView aldığını unutmayın.

class Presenter
{
  private IView _view;
  public Presenter(IView view)
  {
    _view = view;
  }
}

Şimdi asıl kullanıcı arayüzü. Bu bir pencere, bir iletişim kutusu, bir web sayfası vb. Olabilir. Önemli değil. Görünümün yapıcısının kendisini içine enjekte ederek sunum sunucusu yaratacağını unutmayın.

class View : IView
{
  private Presenter _presenter;

  public View()
  {
    _presenter = new Presenter(this);
  }

  public void InformUser(string message)
  {
    MessageBox.Show(message);
  }
}

Sunucu, görünümün yalnızca yaptığı yöntemi nasıl uyguladığını önemsemez. Sunum yapan herkesin bildiği gibi, bir günlük dosyasına yazıyor olabilir ve kullanıcıya göstermeyebilir.

Her durumda, sunum yapan kişi arka uçtaki modelle bazı çalışmalar yürütmekte ve bir noktada kullanıcıyı neler olup bittiği hakkında bilgilendirmek istemektedir. Şimdi sunucuda, InformUser mesajının görünümlerine çağrı yapan bir yerde bir yöntemimiz var.

class Presenter
{
  public void DoSomething()
  {
    _view.InformUser("Starting model processing...");
  }
}

Dekuplajını aldığın yer burası. Sunucu yalnızca IView uygulamasına atıfta bulunur ve nasıl uygulandığını gerçekten önemsemez.

Bu, aynı zamanda yoksul bir adamın uygulamasıdır; çünkü görünümdeki Presenter'a bir referansınız vardır ve nesneler yapıcılar aracılığıyla ayarlanır. Daha sağlam bir çözümde, talep üzerine çalışma zamanında sizin için IView uygulamasının çözülmesini ve böylece daha da ayrılmasını sağlayacak olan Windsor, Ninject vb. Gibi kontrol (IoC) konteynerlerinin ters çevrilmesine bakmak isteyebilirsiniz.


4

Denetçinin / Sunucunun eylemin gerçekleştiği yerde olduğunu hatırlamak önemlidir. Zorunluluk nedeniyle Kontrolördeki bağlantı kaçınılmazdır.

Denetleyicinin temel noktası, Görünümde bir değişiklik yaparsanız, Model'in değişmesi ve tam tersi olmamasıdır (Model Görünüm değiştirirse bunu yapmaz), çünkü Denetleyici çeviriyi çevirir. Manzaranın içine modelleyin ve tekrar geri getirin. Ancak, Model veya Görünüm değiştiğinde Kontrolör de değişecektir, çünkü Kontrol Cihazı içinde Modelin Görünümde yapılan değişikliklerin Moduna nasıl geri getirileceğini etkin bir şekilde çevirmek zorundasınız.

Verebileceğim en iyi örnek, bir MVC uygulaması yazarken, GUI görünümünde yalnızca veriye sahip olamayacağıma değil, aynı zamanda Modelden çekilen verileri stringhata ayıklayıcısında gösterilmesini sağlayan bir yordam yazabileceğimdir. (ve düz bir metin dosyasına genişletilerek). Model verisini alabilir ve Görünümü veya Modeli ve yalnızca Denetleyiciyi değiştirmeden serbestçe metne çevirebilirsem , doğru yoldayım.

Söyleniyor, hepsini çalıştırmak için farklı bileşenler arasında referanslar olması gerekecek. Denetleyicinin verileri zorlamak için Görünüm hakkında bilgi alması, Görünümün bir değişiklik yapıldığında (Kullanıcı "Kaydet" veya "Yeni ..." düğmesini tıklatması gibi) söylemesi için Denetleyici hakkında bilgi sahibi olması gerekir. Kontrolörün verileri çekmek için Model hakkında bilgi sahibi olması gerekir, ancak Modelin başka hiçbir şey bilmemesi gerektiğini savunuyorum.

Uyarı: Tamamen Mac, Objective-C, Cocoa kökenli, sizi gerçekten ister MVC paradigmasına zorluyor.


Bu kesinlikle benim hedefim. Benim asıl sorunum, Görünümü nasıl ayarlayacağımı - her iletişim kutusunun bir örneğiyle birlikte bir sınıf olması ve ardından Dialog.Getters'i çağıran View.Getters'ı veya Sunucunun doğrudan Dialog.Getters'ı arayabilmesi gerekip gerekmediğidir. Bu yüzden muhtemelen değil, çok sıkı bağlı görünüyor)?
trycatch

Sunucunun / Denetleyicinin Görünümlerden tamamen sorumlu olması gerektiğini düşünüyorum, bu nedenle ikincisi. Yine, bazı bağlantıların yapılması zorunludur, ancak en azından sorumluluk yönü açıksa, uzun vadede bakım daha kolay olmalıdır.
Philip Regan

2
P / C’nin Görünüm’den sorumlu olması gerektiğine kesinlikle katılıyorum, ancak MVP’yi güçlü kılacak şeylerin bir kısmını tüm UI kitaplığını çıkartma ve yenisini takma ve biraz masaj yapma kabiliyeti olarak düşündüm (dllimporting and notnot) onun yerine bir tane daha koyabilirsin. Kontrolör / Presenter ile doğrudan diyaloglara erişirken bu daha zor olmaz mıydı? Kesinlikle tartışmaya çalışmıyorum, sadece daha fazla anlıyorum :)
22:11

Bence asıl güç iki yönden geliyor: Birincisi, Görünüm ve Modelin diğerleriyle hiçbir ilgisi olmadığı, ikincisi ise geliştirme çalışmasının çoğunluğunun, uygulamanın motorunun düzgün bir şekilde yapıldığı birim, denetleyici. Ancak bazı sorumluluk kanama olması şarttır. En azından arayüzlerin değiştirilmesinin çoğunluğu Kontrolörde yapılacak ve Görünümden herhangi bir bağlantı minimum olacaktır. Diğerlerinin dediği gibi, bir miktar mantık kanaması bekleniyor ve buna izin veriliyor. MVC sihirli bir kurşun değil.
Philip Regan

Ayrıştırma için önemli nokta, SUNUCU SADECE iyi tanımlanmış arabirimler (UI kitaplığından bağımsız) aracılığıyla görünüme erişebilmesidir, böylece UI kitaplığının başka bir taneyle (aynı arayüzü / window / dialog / page için aynı arayüzü uygulayacak başka biri) nasıl değiştirebileceğidir. / control / whatever)
Marcel Toth

2

Genel olarak, modelinizin bu modelle olan tüm etkileşimleri içine almasını istiyorsunuz. Örneğin, CRUD eylemlerinizin (Yarat, Oku, Güncelle, Sil) hepsi modelin bir parçasıdır. Aynı özel hesaplamalar için de geçerli. Bunun birkaç iyi nedeni var:

  • Bu kod için testinizi otomatikleştirmek daha kolaydır
  • Tüm bu önemli şeyleri bir yerde tutuyor

Kontrol cihazınızda (MVC uygulaması) yaptığınız tek şey, görünümünüzde kullanmanız gereken modelleri toplamak ve modelde uygun işlevleri çağırmaktır. Modelin durumundaki herhangi bir değişiklik bu katmanda gerçekleşir.

Görünümünüz yalnızca hazırladığınız modelleri görüntüler. Temel olarak, görünüm yalnızca modeli okur ve çıktısını buna göre ayarlar.

Genel ilkenin gerçek sınıflarla eşleştirilmesi

Diyaloglarınızın görünüm olduğunu unutmayın. Zaten bir iletişim sınıfınız varsa, başka bir "Görünüm" sınıfı oluşturmak için hiçbir neden yoktur. Presenter katmanı modeli esas olarak Görünümdeki kontrollere bağlar. İş mantığı ve tüm önemli veriler modelde saklanır.

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.