encyklopedia.space

Model-View-ViewModel (MVVM)

Model-View-ViewModel (skrót MVVM) to architektura aplikacji, której celem jest rozdzielenie logiki biznesowej od warstwy prezentacji. Została opracowana przez firmę Microsoft w 2005 roku z myślą o ułatwieniu tworzenia interfejsów użytkownika w technologii Windows Presentation Foundation (WPF).

Historia

Początkowo koncepcja MVVM była rozwijana jako ewolucja wcześniejszych wzorców architektonicznych, takich jak Model-View-Controller (MVC) oraz Model-View-Presenter (MVP). Dzięki wprowadzeniu wiązania danych (data binding) i wzorca poleceń (Command), MVVM umożliwiło tworzenie interfejsów, które są less code‑behind i bardziej testowalne.

Składowe architektury

  • Model – warstwa zawierająca logikę biznesową, zasoby danych oraz reguły walidacji. Model jest niezależny od warstwy prezentacji i może być wykorzystywany w dowolnym kontekście aplikacji.
  • View – warstwa odpowiedzialna za prezentację danych użytkownikowi. W MVVM View jest zazwyczaj opisany w języku deklaratywnym, takim jak XAML, i nie zawiera logiki aplikacji.
  • ViewModel – pośrednik pomiędzy Modelem a View. Udostępnia właściwości i polecenia (komendy), które są wiązane (bound) do elementów interfejsu w View. ViewModel nie wie nic o konkretnym interfejsie graficznym, co ułatwia testowanie jednostkowe.

Relacje pomiędzy komponentami

W MVVM komunikacja odbywa się głównie w następujący sposób:

  1. View wiąże się (data binding) z właściwościami i poleceniami udostępnianymi przez ViewModel.
  2. Gdy użytkownik wywołuje akcję (np. kliknięcie przycisku), ViewModel otrzymuje wywołanie poprzez polecenie i deleguje je do Modelu.
  3. Model zwraca wyniki (np. pobranie danych z bazy) i powiadamia ViewModel o zmianach, najczęściej za pomocą interfejsu INotifyPropertyChanged.
  4. ViewModel aktualizuje własne właściwości, co automatycznie odświeża interfejs dzięki mechanizmowi wiązania danych.

Zastosowanie

MVVM jest szczególnie popularny w następujących środowiskach:

Przykład implementacji w C#

// Model
public class Person
{
    public string FirstName { get; set; }
    public string LastName  { get; set; }
}

// ViewModel
public class PersonViewModel : INotifyPropertyChanged
{
    private Person _person;

    public PersonViewModel()
    {
        _person = new Person { FirstName = "Jan", LastName = "Kowalski" };
        SaveCommand = new RelayCommand(Save, CanSave);
    }

    public string FirstName
    {
        get => _person.FirstName;
        set
        {
            if (_person.FirstName != value)
            {
                _person.FirstName = value;
                OnPropertyChanged(nameof(FirstName));
            }
        }
    }

    public string LastName
    {
        get => _person.LastName;
        set
        {
            if (_person.LastName != value)
            {
                _person.LastName = value;
                OnPropertyChanged(nameof(LastName));
            }
        }
    }

    public ICommand SaveCommand { get; }

    private void Save()
    {
        // zapis do bazy, serwisu itp.
    }

    private bool CanSave() => !string.IsNullOrWhiteSpace(FirstName) && !string.IsNullOrWhiteSpace(LastName);

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Porównanie z innymi wzorcami architektonicznymi

Cecha MVC MVP MVVM
Główny element pośredniczący Controller Presenter ViewModel
Wiązanie danych (data binding) Rzadko, wymaga ręcznej synchronizacji Możliwe, ale nie jest centralnym elementem Wbudowane, kluczowe
Testowalność View Trudna (logika w Controllerze) Możliwa (Presenter jest testowalny) Wysoka – logika w ViewModel, View jest czysto deklaratywna
Typowa platforma Web (ASP.NET, Ruby on Rails) Desktop (WinForms), Web (GWT) Desktop i mobilne (.NET, Xamarin)

Zalety

  • Silne wiązanie danych eliminuje konieczność ręcznego odświeżania UI.
  • Wyraźny podział odpowiedzialności ułatwia utrzymanie i rozwój aplikacji.
  • ViewModel można testować przy użyciu testów jednostkowych bez uruchamiania interfejsu.
  • Umożliwia współpracę wielu programistów: jeden zajmuje się UI, drugi logiką biznesową.

Wady

  • Wymaga znajomości mechanizmów data binding oraz wzorca Command, co może podnieść krzywą uczenia się.
  • W niektórych projektach (np. małe, jednorazowe aplikacje) wprowadza zbędną warstwę abstrakcji.
  • Nie każde środowisko UI natywnie wspiera wiązanie danych, co wymusza dodatkowe biblioteki.

Rozwój i wpływ

Po sukcesie w WPF, MVVM stało się inspiracją dla innych platform i frameworków. W Xamarin.Forms oraz .NET MAUI wzorzec jest domyślną architekturą. W świecie JavaScript podobne podejścia przyjęły KnockoutJS, Angular (z komponentami i usługami) oraz Vue.js (reactive data).

Przyszłość

MVVM pozostaje aktualny, zwłaszcza w ekosystemie Microsoft, gdzie rozwijane są kolejne biblioteki wspierające ReactiveUI i Prism. Jego zasady – separacja warstw, deklaratywne UI i testowalny kod – są fundamentem nowoczesnych architektur oprogramowania.

Źródła: dokumentacja Microsoft, 2005 rok publikacji pierwszych wytycznych, literatura z zakresu programowania wzorcowego.