Niedawno w artykule o dość wyzywającym tytule 😉 Gdzie są te cholerne szczegóły pisałem o złożoności wymagań i tym, gdzie ta złożoność jest (mogła by być, powinna być dokumentowana, jak kto woli). Tam skupiłem się na takich szczegółach jak reguły biznesowe i złożone typy danych, czyli tym co potocznie (i nie do końca słusznie) nazywa się “walidacjami” ([[walidacja]]).
Drugim elementem “niosącym” szczegóły jest dialog użytkownika z aplikacją czyli “ekrany”. Tu pojawia się kolejna porcja wymagań, nie raz bardzo szczegółowych, zaciemniających nie raz główny sens tworzenia danego oprogramowania: scenariusze pracy z ekranem (formatką ekranową itp.).
Jak już nie raz pisałem, ogólna zasadą (dobrą praktyką) w inżynierii jest abstrahowanie oraz zarządzanie poziomem szczegółowości każdego etapu pracy na projektem. Operowanie pojęciami (terminami) zamiast ich definicjami, to abstrahowanie od szczegółów czyli ich hermetyzacja, np. “Kontrahent” to “nazwa podmiotu, jego NIP, adres”.
Wymagania wobec aplikacji związane z interakcją aktor-system, ich definiowanie i projektowanie realizacji, nie należą do łatwych etapów analizy i projektu, są nie raz bardzo szczegółowe. To powód dla którego warto je także “hermetyzować”. Jak? Pomagają w tym dwie rzeczy: wyodrębnienie projektowania (dokumentowania) szczegółów interakcji jako etap projektowania nazywany [[User Experience]] (dalej UX) oraz użycie wzorca projektowego MVVM-MVC.
Najpierw jednak wzorce, bo te dadzą nam kontekst i granice hermetyzacji. Wzorzec MVVM i korzyści płynące z jego użycia, przystępnie opisano na stronie MSDN:
Przed omówieniem wzorca, warto zastanowić się, po co utrudniać sobie zadanie poprzez wykorzystywanie MVVM, zamiast pisać aplikację w klasyczny sposób (za pomocą code-behind)? W końcu wdrożenie praktycznie każdego wzorca projektowego wymaga trochę większych początkowych nakładów pracy.
Podejście Code-Behind (autonomous view ? AV) ma poważną wadę ? nie gwarantuje elastyczności oraz testowalności. Podsumowując, wprowadzenie wzorca umożliwia:
- niezależność logiki od sposobu wyświetlania danych,
- niezależność kodu od technologii, w której wykonana jest warstwa prezentacji,
- wykonywanie testów ? za pomocą MVVM czy MVP możliwe jest wykonanie testów zautomatyzowanych (np. jednostkowych),
- łatwą zamianę widoków (brak sztywnych powiązań między widokiem a logiką).
Z perspektywy analizy i projektowania ([[OOAD]]) najistotniejsze są pierwsze dwa punkty, bo umożliwiają hermetyzację (oddzielenie) logiki biznesowej i projektu opisującego interakcje aktor-system czyli UX. Punkt czwarty daje spełnienie jednej z zasad SOLID czyli “łatwość rozszerzenia bez potrzeby modyfikacji”. Ta ostatnia cecha to np. dodawanie nowych interfejsów użytkownika do kolejnych nowych urządzeń (smartfon, tablet, dedykowane urządzenia i wyświetlacze), bez potrzeby ingerowania w kod obsługujący już oprogramowane urządzenia.
Jak to wygląda z perspektywy architektury aplikacji i jej projektanta? Poniżej model:
Co tu mamy? Mamy MVVM i MVC na jednym diagramie. MVVM polega na wstawieniu pomiędzy widok (View) a Model dodatkowe komponentu, który stanowi wersję logiki biznesowej zawierającą ograniczenia “wyświetlacza” i dedykowane (specyfiaczne) tylko dla niego zachowania (to także pozwala unikania bardzo złej praktyki jaką jest umieszczanie logiki biznesowej w komponencie View). Innymi słowy, jeżeli jakieś zachowania systemu są specyficzne dla konkretnego typu wyświetlacza (ale może to być specyfika aktora o czym dalej), logikę tę hermetyzujemy w komponencie ViewModel.
Mając taką abstrakcję aplikacji jak powyżej, łatwo będzie osobno opisać ją przypadkami użycia, uznając je za “usługi systemu (te świadczy komponent Model) oraz osobno szczegółowymi scenariuszami UX zamkniętymi w parze komponentów View-ViewModel. Oba te elementy projektu – UX i Use Case, są więc “ładnie” odseparowane, nie wpływają na siebie nawzajem i pozwalają na łatwą rozbudowę całego systemu, niewymagającą modyfikowania już powstałego kodu (i dokumentacji).
Nawiąże jeszcze do “specyfiki aktora”. Bardzo często w systemach internetowych, mamy potrzebę separacji użytkowników “z poza firmy” (np. klienci sklepu internetowego, interfejsy samoobsługi dla klientów serwisu itp.). Wiąże się to nie raz z bardzo złożonymi zasadami kontroli dostępu do elementów modelu 9czyli dość głęboko w systemie). Potrafi to bardzo skomplikować cały projekt komponentu Model, a nie raz potrzeby jego istotnej przebudowy. Można tego uniknąć, hermetyzując ten obszar. Bardzo często osoba (użytkownik, aktor systemu) z zewnątrz ma bardzo ograniczone możliwości korzystania z logiki całego systemu. Łatwiej jest zaprojektować dedykowany, relatywnie prosty komponent ViewModel i połączyć go z Modelem, niż modyfikować Model Dziedziny systemu by obsługiwał, nowe, nie raz bardzo wyrafinowane, ograniczenia dostępu.
Tak więc przypadkami użycia opisujemy abstrakcję jaką jest [[Model Dziedziny Systemu]]. Są one wtedy proste, zawierają scenariusz, który w skrócie ma postać: aktor inicjuje usługę, system prezentuje formularz do wypełnienia, aktor wypełnia go i potwierdza, system potwierdza odebranie danych i pokazuje wynik swojej pracy (lub komunikaty o błędach). Tu skupiamy się na opisie tego jakie usługi są wymagane od systemu. Kolejny etap to “komplikowanie” każdego scenariusza w postaci projektowania, dla każdego przypadku użycia, który tego wymaga, różnego rodzaju wizardów lub wprowadzamy ograniczenia związane z uprawnieniami użytkowników. Ten etap to praca projektantów UX i grafików, specjalistów od ergonomii itp.