Wzorce złożone: MVVM

Posted by Przemysław Owsianik on 2021-10-02
<p>Kolejnym wzorcem złożonym jest&nbsp;Model-View-ViewModel&nbsp;. Jest on najmłodszym (najnowszym?) wzorcem z trójcy do której należą jeszcze MVC i MVP. &nbsp;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), &nbsp;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 🙂 .</p> <p>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 :</p> <ul> <li><b>Warstwę modelu:</b>&nbsp; jest ona bliźniaczo podobna do jej odpowiedników w MVC i MVP</li> <li><b>Warstwę widoku:</b>&nbsp; ta służy identycznym celom, co widoki w pozostałych wzorcach.</li> <li><b>Warstwę widoku modelu:</b>&nbsp;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 😉</li> </ul> <p>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.</p> <img src="/static/img/blog/mvvm.png" alt="" class=" postImage" /> <p>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.</p> <p>Widok&nbsp;w WPF, pisany jest przy użyciu języka znacznikowego&nbsp;XAML, „fizycznie” jest też możliwość by posiadał tzw.&nbsp;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&nbsp;Mediator,&nbsp;dostarczanej wraz z frameworkiem&nbsp;MVVM Light&nbsp;– której odbiorcą jest widok. Nie jest to jednak najlepszy sposób, więc na mojej liście „to do”&nbsp;projektu pojawił się kolejny problem do rozwiązania 🙂</p> <p>Widok modelu&nbsp;stanowi najciekawszy element układanki. Na jeden&nbsp;ViewModel&nbsp;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. &nbsp;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.</p> <p>Na zakończenie screen pokazujący warstwy w HardTraining:</p> <img src="/static/img/blog/htMvvm.png" alt="" class=" postImage" />