Współczesne WWW to już nie tylko strony HTML a całe – niejednokrotnie mocno rozbudowane – aplikacje internetowe. Prawda ta obowiązuje na rynku Web już od kilku ładnych lat. Obserwując ostatnie zmagania producentów przeglądarek, ciągłą presję na przyśpieszanie przetwarzania Javascript-u, łatwo stwierdzić, iż nieuchronnym trendem w rozwoju WWW są właśnie – bardziej interaktywne, szybsze i stabilniejsze – aplikacje internetowe.  Tym samym, większego znaczenia nabiera to, co dzieje się w przeglądarce użytkownika.

A dzieje się bardzo wiele… Współcześnie nawet proste z pozoru „strony” realizują ogromną ilość funkcjonalności już właśnie w przeglądarce – począwszy od zliczania statystyk, poprzez wyświetlanie reklam, personalizowane elementy, a na rozbudowanych komponentach (np. przeglądarkach map, grach, czy aplikacjach wideo) skończywszy. Jednym z kosztów tego kierunku rozwoju jest szybko rosnąca ilość skryptów wykonywanych w przeglądarce.

Duża ilość kodu to z jednej strony problem dla przeglądarki, która musi go zrealizować w sposób komfortowy dla użytkownika, z drugiej strony źle zorganizowany kod to także problem dla developerów, którzy nieustannie muszą go rozwijać i poprawiać jednocześnie pilnując, by ich aplikacja dała się używać także w starszych przeglądarkach lub na słabszych maszynach. Oba punkty widzenia sprowadzają się do jednej konkluzji – konieczne jest wprowadzenie takiej architektury aplikacji klienta (realizowanego w przeglądarce), by kod był czytelny, prosty i niedublujący się – a to ułatwi dalszy rozwój i optymalizacje najistotniejszych fragmentów aplikacji.

Z powyższą problematyką zmagamy się w Onecie już od jakiegoś czasu i by rozwiązać problemy architektoniczne postanowiliśmy postawić na sprawdzone rozwiązanie, jakim jest PureMVC. Framework ten początkowo powstał na potrzeby platformy Flash i dziś przez wielu uważany jest za bezkonkurencyjny. Jest lekki, zorientowany obiektowo, wprowadza jasną i przejrzystą strukturę aplikacji. Doczekał się wielu portów na różne języki w różnych środowiskach m. in. JavaScript, Java, C#, PHP, Python etc.

PureMVC – rozwiązanie mające wprowadzić porządek i usystematyzować produkcję

PureMVC realizuje koncepcję Model View Controller przy pomocy czterech głównych Aktorów, którymi są:

  • Proxy (Model)
  • Mediator (View)
  • Command (Controller)
  • Facade (interfejs komunikacyjny)

Realizacje powyższych elementów (o nich szerzej za moment) zorganizowane są w następującą strukturę katalogów:

/application/
controller/
model/
vo/
view/
ui/

Za implementację poszczególnego Proxy, Mediator(a) czy Command(y) odpowiada pojedyncza klasa.

W tym miejscu – w ramach dygresji – muszę wspomnieć o problemie obiektowości w Javascript. Jest to problem dość poważny, gdyż sam język nie dostarcza mechanizmów stricte obiektowych i wszelka obiektowość, o jakiej można mówić w tym przypadku jest jedynie symulacją. Problem ten znalazł już wiele rozwiązań i podejść. Sami twórcy portu PureMVC dla JS-a sugerują rozwiązania przyjęte w Mootools.

Wracając do organizacji kodu: każdej klasie odpowiada jeden plik umieszczony w odpowiednim katalogu w zależności od roli, jaką odgrywa (Komendy w Controller, Proxy w Model etc). Sam sposób finalnego wdrożenia aplikacji o tak usystematyzowanym kodzie to bardzo szeroki temat na zupełnie inną notkę.

Kilkanaście słów o architekturze

Spróbujmy przyjrzeć się poszczególnym elementom i komunikacji miedzy nimi.

Fasada i powiadomienia.

Fasada (Facade) jest centralnym punktem aplikacji. Realizuje komunikację pomiędzy wszystkimi Aktorami aplikacji. PureMVC wprowadza w tym miejscu wzorzec Obserwatora (wykorzystujący model nasłuchiwania i publikacji powiadomień), dzięki któremu możliwa jest asynchroniczna, zdarzeniowa komunikacja przy jednoczesnym zachowaniu słabych powiązań pomiędzy wspomnianymi już Aktorami.

Poszczególni Aktorzy wysyłają lub nasłuchują konkretnych Powiadomień (Notification). Fasada odpowiada za przekazanie powiadomienia do wszystkich nasłuchujących Aktorów. W praktyce przekłada się to na wywołanie metody sendNotification obiektu Fasady.

Dodatkową rolą Fasady jest mapowanie powiadomień na konkretne Komendy (Command). Dzięki temu wysłanie danego powiadomienia może skutkować uruchomieniem specyficznego kontrolera. Tym samym nasza aplikacja może asynchronicznie – w zależności od różnych okoliczności – inicjować dodatkowe elementy -  funkcjonalności.

Command – kontroler

Zgodnie ze wzorcem MVC zadaniem kontrolera jest uruchamianie komponentów modelu i widoku. W PureMVC stworzenie controllera (Command) sprowadza się do implementacji klasy dziedziczącej po bazowym SimpleCommandlub MacroCommand i jednej kluczowej metody interfejsu. Komendy rejestrują poszczególne proxy, komponenty widoku i odpowiadające im mediator-y. Co ciekawe – z perspektywy projektanta aplikacji – można łatwo zauważyć, iż w większości przypadków jeden Use Case z diagramu przypadków użycia przekłada się na jedną Komedę w aplikacji. Będziemy zatem mieli do czynienia z komendami: „Zapisz formularz”, „Usuń obiekt”, „Otwórz dialog”. Daje to naturalne przejście od logiki biznesowej aplikacji do jej konkretnej implementacji. Pozwala także na lepsze zarządzanie poszczególnymi funkcjonalnościami (przenoszenie ich do innych aplikacji, zmiany itd.).

W kontekście komunikacyjnym – komenda jest w stanie wysyłać powiadomienia do frameworka, ale ich nie odbiera. Natomiast – jak już wspomniałem – dzięki Fasadzie możliwe jest przypisanie konkretnej Komendy do konkretnego powiadomienia.

Mediator i komponent widoku

Przez „komponent widoku” w ujęciu „stron HTML” powinniśmy rozumieć Klasę obsługującą wybrane elementy DOM. Komponent widoku – zna ich strukturę i umie ją modyfikować – tym samym cała obsługa drzewa DOM zamknięta jest w tym elemencie architektury.

Konkretny komponent z jednej strony udostępnia metody modyfikujące istniejącą strukturę np. dodaj wiersz w tabeli, z drugiej wysyła komunikaty określające zdarzenia wywołane przez użytkownika np. „użytkownik nacisnął przycisk usuń”.
Podstawową cechą Mediator-a jest jego zdolność do „nasłuchiwania” powiadomień, obsługi ich oraz jeśli to konieczne wysłania kolejnych do Framework-a. W podejściu przyjętym w wzorcu Obserwatora Mediator jest Obserwatorem. Jest to jedyny z Aktorów PureMVC pełniący tą rolę.

Z punktu widzenia aplikacji Mediator-a należy rozumieć jako „kontroler” widoku. Tym samym jest on odpowiedzialny za uruchamianie konkretnych metod komponentu widoku oraz przekazywanie przechwyconych „gestów” użytkownika do reszty aplikacji.

Proxy i ValueObject

Zadaniem poszczególnych Proxy jest kompleksowe zarządzanie danymi w aplikacji. Proxy realizują wszelkie operacje na modelu min pobranie, zapis czy usunięcie danych. W nim zatem obsługiwane są wszelkie operacje typu AJAX.
Konkretne Proxy operuje na konkretnym typie Obiektu wartości (ValueObject). Przykładowo: jeśli nasza aplikacja wykorzystuje obiekt typu Rate (ocena) to wszelkie operacje na tym obiekcie będzie realizowało RateProxy, które dostarczy metody getRate, setRate, checkRate. Tym samym będzie pobierać, zapisywać oraz dbać o spójność danych w tej strukturze.

Podsumowanie

Framework PureMVC pozwala usystematyzować problematykę budowy aplikacji klienckich. Wprowadza jasny i przejrzysty podział na składowe elementy w ujęciu wzorca MVC. Pozwala przechodzić z problematyką aplikacji od niskopoziomowych pojęć związanych z środowiskiem przeglądarki internetowej do bardziej abstrakcyjnych pojęć wynikających ze specyfiki produktu. Pozwala także w prosty sposób przejście w drugą stronę: od przypadków użycia do konkretnych klas kontrolerów i elementów przez nie inicjalizowanych. Poszczególne elementy aplikacji bardzo łatwo przenosić i adaptować do innych produktów, tym samym zapewniona zostaje skalowalność i adaptowalność kodu, co z kolei może znacznie poprawić jakość i tempo tworzenia nowych rozwiązań.

Aktualnie w Onecie wykorzystujemy PureMVC od tworzenia aplikacji wewnętrznych, testowaliśmy to rozwiązanie także na aplikacji Pytań do ekspertów w serwisie podatki.onet.pl. Aktualnie wiele toczących się już projektów coraz szerzej wykorzystuje to podejście i wkrótce można się spodziewać obecności PureMVC w coraz większej ilości naszych produktów.

Maciej Jastrzębski
projektant systemów informatycznych