A tervezési minták egy külön kategóriája az architekturális minták. Ezekből is millió és egy létezik, az igényeknek és a feladatoknak megfelelően. Azonban a két minta, ami újra és újra előkerül az az MVC és az MVVM.
De mitől lesz architekturális egy tervezési minta? Erre az a kedvenc válaszom, hogy sok mindenitől függ, de alapvetően az alkalmazással szemben támasztott követelményektől. Például egy konzol alkalmazás tekintetében, ami adatot manipulál és ez lépésekre bontható, akár egy Chain of Responsibilty is tekinthető architekturális mintának.
Ha picit mélyebbre ásunk, akkor azért van pár feltétel és szempont ami elő szokott kerülni architektúrális minták esetén:
Egy architektúrális minta alapvetően egy keretrendszert vagy struktúrát határoz meg a köztük lévő kapcsolatokkal együtt. A struktúra azért fontos, mert segít abban, hogy a nagyobb részek elkülönüljenek és megérthetőek maradjanak.
Másik fontos tulajdonságuk, hogy hasonló problémákat oldanak meg egy specifikus probléma helyett, így általánosíthatóak és széles körben felhasználhatóak.
Továbbá fontos kérdéskör az absztrakció és szeparáció. Ez picit a struktúra kiegészítése. Egy architekturális minta jól elválasztja az alkalmazás különböző részeit és felelősségi területeit, hogy a komponensek önállóan fejleszthetőek és karbantarthatóak legyenek.
Számos aspektust tudnék még említeni, de számomra egy minta attól lesz architekturális, hogy jól meghatározza a különböző komponensek közötti kommunikációt és interakciót és emellett jól kombinálható vagy egymásba ágyazható más mintákkal.
Az MVC éz az MVVM is megfelel ezeknek a kritériumoknak. Mindkét minta három fő réteget definiál, hasonló feladatkörrel. Eltérés a komponensek közötti kommunikáció irányában/módjában van. Mindkét mintát széleskörűen alkalmazzák a modern szoftverekben, egyes esetekben akár kombinálva is.
MVC
Az MVC gyökerei az 1970-es évekig nyúlnak vissza. A minta neve a három fő komponens nevének a rövidítéséből jön. Ezek: Model, View és Controller. Nézzük meg, mi ezeknek a feladata:
Model (Modell):
-
A Model a szoftver belső adattartalmát és üzleti logikáját reprezentálja.
-
Felelős az adatok tárolásáért, kezeléséért és frissítéséért.
-
Elválasztja az üzleti logikát az adatok megjelenítésétől, így a Modell független a felhasználói felülettől (View) és a vezérlőtől (Controller).
-
Értesíti a Controller-t és a View-t az adatok változásairól, hogy frissíthessék magukat.
Controller (Vezérlő):
-
A Controller fogadja a felhasználói interakciókat a View-tól, és továbbítja őket a Model felé.
-
Felelős az üzleti logika irányításáért és az adatok módosításáért a Modelben.
-
Meghatározza, hogy melyik View-t kell frissíteni az adatok változásakor.
-
Elválasztja a felhasználói interakciókat a Modeltől és a View-tól, így könnyűvé teszi a két komponens közötti kommunikációt.
View (Nézet):
-
A View a felhasználói felületet reprezentálja és az adatok megjelenítéséért felelős.
-
Passzív szereplő, mivel csak a Modelből kapott adatokat jeleníti meg.
-
A felhasználói interakciókat általában továbbítja a Controller felé.
-
Több különböző View is lehet ugyanarra a Modelre, így különböző módokon jeleníthetők meg az adatok.
MVVM
Az MVVM minta tekinthető az MVC továbbfejlesztésének, amit kifejezetten grafikus alkalmazások fejlesztéséhez terveztek. Az MVC igen flexibilis minta. Minden UI keretrendszerre rá lehet húzni, de előbb-utóbb abba a problémába ütközünk, hogy a View réteg meg fog hízni az interakciók továbbítása és a megjelenítés miatt. Ez azért okoz gondot, mert egyrészt ezt is karban kell tartani, de a nagyobb baj az, hogy nem teljesen lesznek függetlenek a Controller rétegtől. Természetesen ezt lehet absztrakció bevezetésével orvosolni, de ez tovább növeli a karbantartandó „glue” kód mennyiséget.
Az MVVM mintát a Microsoftnál találták ki. A WPF és az ezt követően megjelent XAML alapú platformok beépítetten támogatják. Ez azonban nem jelenti azt, hogy Microsoft specifikus technológia lenne, mert például az Angular is ezt alkalmazza.
A mozaikszó a Modell, View és ViewModel szavakat rövidíti. A három réteg feladata:
Model (Modell):
-
A Model a szoftver belső adattartalmát és üzleti logikáját reprezentálja, hasonlóan az MVC-hez.
-
Felelős az adatok tárolásáért, kezeléséért és frissítéséért.
-
Független a felhasználói felülettől és a ViewModel-től, és nem tartalmazza a megjelenítéssel kapcsolatos részleteket.
ViewModel (Nézet modell):
-
A ViewModel egy közvetítőréteg a Model és a View között.
-
Felelős az adatok előkészítéséért és formázásáért, amelyeket a View megjelenít.
-
Tartalmazza az üzleti logikát és a felhasználói interakciók kezelését.
-
Általában figyeli a Modelből érkező adatok változásait és frissíti a View-t szükség esetén.
-
A ViewModel általában nem tartalmaz olyan megjelenítéssel kapcsolatos részleteket, amelyek a View felelősségi körébe tartoznak.
View (Nézet):
-
A View a felhasználói felületet reprezentálja, de nem tartalmaz üzleti logikát.
-
Passzív szereplő, amely megjeleníti a ViewModel által szolgáltatott adatokat és lehetővé teszi a felhasználói interakciót.
-
Nem tartalmaz üzleti logikát vagy közvetlenül hozzáférést az adatokhoz, ehelyett a ViewModel-től kapja azokat.
Az MVVM esetén van egy negyedik implicit, vagy „rejtett” réteg, ami valójában nem a minta része, de enélkül nem működőképes. Ez pedig a Binder, ami kapcsolatot teremt a View és a ViewModel között. Ez a XAML alapú nyelvek esetén a XAML önmaga. Ezen implicit réteg miatt, ha nem rendelkezik támogatással eziránt a használt UI keretrendszer, akkor sokkal nehezebben alkalmazható, mint mondjuk egy MVC, mivel a Binder komponenst magunknak kell lefejlesztenünk.
MVVM és MVC hasonlósága és különbsége
A minták rétegeinek leírásából és a bevezetőből egyértelmű, hogy az MVVM az MVC egyfajta evolúciója egy problémakör megoldására. Ebből adódóan nem meglepő, hogy bár eltérőek a komponensek nevei hasonló a feladatuk. Egy lényeges különbség az adatáramlás irányában figyelhető meg, amit az alábbi ábra szemléltet:
Az ábrán a komponensek szervezése direkt hasonló. A legtöbb netes képen az MVC komponenseit piramisszerűen szemléltetik, míg az MVVM esetén minden esetben ez a kiterített nézet jellemző, mint amit ennél az ábránál alkalmaztam. Jól látható, hogy adatáramlás szempontjából a legnagyobb különbség a Model komponens használatában van. MVC esetén a View közvetlenül kérhet adatokat a Modelltől, ami kényelmes megoldás, de ugyan akkor veszélyes is tud lenni a későbbi karbantarthatóságra nézve.
Az MVC és az MVVM együtt is alkalmazható. Például egy tipikus Angular frontenddel rendelkező alkalmazásban MVC használt az API végpontok fejlesztésénél, a fogyasztói Angular oldalon meg MVVM, aminek a Modell rétegébe épül be így az MVC.