Wzorce złożone: MVVM

Kolejnym wzorcem złożonym jest Model-View-ViewModel . Jest on najmłodszym (najnowszym?) wzorcem z trójcy do której należą jeszcze MVC i MVP.  Pierwotnie miałem napisać o nim, jak Pan Bóg przykazał, w trzecim wpisie (żeby chronologia się zgadzała 😉 ) ,po przemyśleniach wskoczył jednak na drugie miejsce z dwóch powodów. Po pierwsze: Jego koncepcja różni się, według mnie, dosyć mocno od MVC (choć może to tylko złudzenie WPF’em),  co pozwoli świeżo spojrzeć na temat, a także pisać o MVP w trochę innym podejściu. I po drugie: Jako, że HardTraining jest pisany z wykorzystaniem WPF’a, MVVM wydał mi się być dzisiaj odpowiednim tematem 🙂 .

Zadanie jakie stawiane jest przed omawianym wzorcem, jest takie same jak dla każdego członka rodziny View-Model: separacja kodu w zależności od pełnionej funkcji. I jak w każdym innym wzorcu z tej rodziny, mamy trzy warstwy :

  • Warstwę modelu:  jest ona bliźniaczo podobna do jej odpowiedników w MVC i MVP
  • Warstwę widoku:  ta służy identycznym celom, co widoki w pozostałych wzorcach.
  • Warstwę widoku modelu: i tu już jest znacząca różnica. Widok modelu, owszem, stanowi                                         pewnego rodzaju łącznik między sąsiednimi warstwami ale robi to w dosyć                                 specyficzny sposób. Mianowicie „przygotowuje” model do stanu w jakim                                       może on być przedstawiony użytkownikowi.Innymi słowy nakłada puder 😉

Prawdziwą inność MVVM manifestuje w sposobie wiązania warstwy widoku i warstwy modelu. Ale zacznijmy od początku. MVVM został zaprojektowany (choć może w przypadku wzorców powinno się używać określenia „wynaleziony”) przez Microsoft, jako wsparcie dla implementacji aplikacji tworzonych w WPF’ie. Myk polega na tym, że WPF kładzie mocno nacisk na programowanie sterowane zdarzeniami. Jednocześnie możliwe jest, w prosty sposób, powiązanie kodu z interfejsem użytkownika unikając jednak sztywnych połączeń. Do tego celu wykorzystujemy właśnie MVVM.

mvvm

Trochę więcej o warstwach, przez pryzmat HardTraining:
Model, jak już wspominałem wcześniej, to warstwa odpowiedzialna za logikę biznesową, oraz dane. Może być to obraz bazy (klasy POCO), lub po prostu reprezentacja domenowa. W HardTraining dane to klasy POCO dla modelu bazy w Entity Framework, natomiast wiadomo, wszelkie serwisy itd. stanowią, jak to zwykle bywa obraz domeny aplikacji.

Widok w WPF, pisany jest przy użyciu języka znacznikowego XAML, „fizycznie” jest też możliwość by posiadał tzw. code behind, czyli kod pisany w C#, na przykład do obsługi zdarzeń, jednak aby wykorzystać wszystkie zalety wzorca MVVM, widok powinien zawierać tylko XAML. W HardTraining na razie ta sztuka nie do końca mi się udaje, bo w związku z tym, że poszczególne warstwy są w osobnych projektach, staram się żeby poszczególne elementy wiedziały o sobie możliwie jak najmniej. Chcąc otworzyć jakiś widok, wysyłam wiadomość, za pomocą Messengera – implementacji wzorca Mediator, dostarczanej wraz z frameworkiem MVVM Light – której odbiorcą jest widok. Nie jest to jednak najlepszy sposób, więc na mojej liście „to do” projektu pojawił się kolejny problem do rozwiązania 🙂

Widok modelu stanowi najciekawszy element układanki. Na jeden ViewModel może przypadać kilka widoków. VM zna model, i jego zadaniem jest pobranie z niego informacji by móc przedstawić je widokowi. W jaki sposób? Najefektywniej jest wykorzystać (oczywiście mówiąc o „czystym” WPF – frameworki takie jak MVVM Light, wprowadzają rozwinięcia idei, o czym napiszę w którymś z przyszłych postów) mechanizm bindowania danych (data binding), który pozwala w łatwy sposób na połączenie publicznej właściwości widoku modelu z widokiem.  Takie bindowanie może działać tylko w jedną stronę (albo od użytkownika do VM albo odwrotnie), ale także w obie strony. Co więcej nie wymaga to żadnego kodu C# w widoku. I właśnie w taki sposób realizuje to w moim projekcie, jednocześnie korzystając z rozwiązań dostarczanych w MVVM Light.

Na zakończenie screen pokazujący warstwy w HardTraining:

HardTrainingMvvm

 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *