Organizacja projektu – RobotLegs/MVC+

rulersOstatnie miesiące skłoniły mnie do ponownego rozważenia tego wydawałoby się trywialnego problemu, zacząłem doceniać jak dobrze zorganizowany projekt czy przemyślany układ katalogów może ułatwić programiście życie. Już kiedyś poruszałem to zagadnienie w kontekście RobotLegs i projektów realizowanych z jego użyciem – RL jak każdy framework architektoniczny (oparty o wzorzec MVC) narzuca pewien stopień organizacji oraz przynajmniej wstępny układ katalogów. Pisałem również wówczas że to co powinniśmy zapewnić w modelu MVC to daleko za mało aby sprawnie rozwijać projekt. Swoje stanowisko podtrzymuje a ostatnio dostrzegłem w całości nieco głębsze dno – otóż osobiście lubię jak wszystko jest poukładane, klasy nazywają się z sensem i mają ściśle i w oczywisty sposób zdefiniowaną misję a patrząc na pakiet w jakim się znajdują od razu wszystko wiadomo. Takie zaplanowanie całości i to już z góry w momencie zakładania projektu nie jest łatwe i myślę że wymaga pewnej dozy osobistego doświadczenia – bo jak inaczej przewidzieć co komu będzie potrzebne albo jaki stopień poukładania komu odpowiada? Przedstawię całość na własnym przykładzie, wypracowanym przy próbach rozwoju „uniwersalnej bazy projektu” (taki scyzoryk developera ze sprawdzonym kodem i narzędziami).

Pierwszorzędnym jest pytanie gdzie projekt utrzymywać – wiadomo ludzie dzielą się na tych co robią backup i na tych co będą robić:) Dla niektórych (chyba większości nawet) nie ma innej opcji niż github i jemu podobne ale czy jest sens zawracać sobie tym głowę gdy pracuje się w pojedynkę nad relatywnie małymi projektami o których z góry wiadomo że nie będą utrzymywane latami?

Na moim małym podwórku świetnie sprawdza się poczciwy dropbox – w chwili obecnej bez żadnych specjalnych sztuczek mam w nim 5gb przestrzeni co na wszystkie projekty starcza z zawiązką a opcja automatycznego przesyłania plików w tle zwalnia mnie z pamiętania o backupach. Nie wspominając już o dostępności z każdego miejsca na każdym sprzęcie:) Jedną tylko wadę tego rozwiązania odkryłem – nie nadaję się to zupełnie do pracy w grupie zwłaszcza jeśli developerzy korzystają jednocześnie z tych samych plików – wówczas zdarzyć się może że dropbox się zgubi.

Architektura:

  • assets – katalog zawierający wszystkie materiały zewnętrzne do użycia w projekcie – w szególności czcionki które mają zostać osadzone, zestaw ikon do użycia w aplikacji, tła itp.
    • fonts
    • icons
    • backgrounds
  • commands – katalog dla komend z RL – z reguły wszystkie pogrupowane w trzy katalogi:
    • getters – komendy służące pobieraniu danych z modeli ich obróbce i przekazaniu do widoków.
    • opens – komendy modyfikujące widoki, głównie otwierające w ContextView nowe okna (PopUp).
    • services – komendy odpowiadające za komunikacje z serwerem i ogólnie ze światem zewnętrznym aplikacji – wczytywanie danych i plików.
  • contexts – katalog grupujący klasy związane z rozruchem aplikacji oraz jej ustawieniami:
    • MainContext.as  – plik contextu dla aplikacji.
    • Setup.as – klasa której obiekt tworzony jest w MainContext.as – zapisuje wszystkie ważne dla aplikacji ustawienia – np dane serwera MySQL itp.
    • BootstrapCommands.as – klasa której obiekt tworzony jest w MainContext – zawiaduje powiązaniami event – komenda.
    • BootstrapMediators.as – klasa której obiekt tworzony jest w MainContext – zawiaduje powiązaniami widok – mediator.
  • core – katalog na klasy bazowe – lekko zmodyfikowane wersje klas z pakietu mvc RL + klasa bazowa dla eventów, głównie w celu optymalizacji pracy.
    • actor
    • mediator
    • command
    • event
  • events – pakiet z klasami eventów, jak już kiedyś pisałem eventy są wodą na młyn RobotLegs dlatego ich odpowiednie zorganizowanie jest bardzo istotne tym bardziej że w zasadzie w aplikacjach RL każdy powinien mieć swoje ściśle wytyczone zadanie i być unikalny.
    • AppEvents – główne eventy aplikacji – najcięższa liga – są tu eventy dla błędów krytycznych itp na które zareagować ma cała aplikacja.
    • OrderEvents – eventy płynąc do komend – głównie z mediatorów chociaż nie zawsze – główną idę jest odpalanie przez eventy z tej klasy komend z którymi są połączone w klasie „BootstrapCommands.as” (opisana wyżej).
    • ResponseEvents – eventy płynące w odwrotną stronę – z komend do efektorów czyli głównie mediatorów/widoków/modeli itp.
    • ServiceEvents – eventy za pomocą których serwisy porozumiewają się z komendami – głównie ERROR i SUCCESS.
    • ViewEvents – eventy do komunikacji widoków z mediatorami.
  • mediators – katalog z klasami mediatorów dla widoków, podzielony na pod foldery adekwatne do podziały widoków, o tym czemu akurat taki podział patrz poniżej.
    • containers
    • panels
    • windows
    • renderers
  • models – pakiet z klasami przechowującymi dane w aplikacji.
    • vo – vo = ValueObject – czyli obiekty danych – małe klasy służące do przekazywania danych pomiędzy obiektami.
    • SessionManager.as – klasa zarządzająca sesją.
    • Cookies.as – klasa korzystająca z SharedObject pozwala przechowywać dane pomiędzy sesjami.
  • services – pakiet z klasami służącymi do komunikacji  z serwerem i wczytującymi wszelkie dane.
  • skins – katalog ze skórkami dla widoków – podział adekwatny do widoków.
    • app
    • containers
    • panels
    • renderers
    • small
    • windows
  • styles – pliki css z odpowiednimi elementami stylii – osadzonymi czcionkami, ustawieniami skórek dla komponentów itp.
    • Fonts.css
    • Main.css
    • Skins.css
  • views – katalog z widokami, podzielony na odpowiednie elementy – patrz niżej.
    • containers
    • panels
    • renderers
    • small
    • windows
  • Main.mxml – główny plik aplikacji zawierający tag <s:Application>i stanowiący ContextView dla RobotLegs.

Każdy projekt ma swoją architekturę, w tym miejscu chciałbym wytłumaczyć taki a nie inny podział widoków/skórek/mediatorów – sam podział nie jest szczególnie istotny chodzi bardziej oto aby sobie odpowiadał – pozwala to zachować porządek w każdym projekcie.  Osobiście jestem fanem jak najprostszego układu dlatego staram się rozwijać aplikacje w taki sposób aby na ekranie dashbordu użytkownik miał dostęp do wszystkich najważniejszych rzeczy, resztę natomiast udostępniam w postaci okien otwieranych w PopUpManager. Natomiast każdy samodzielny element stanowi u mnie panel, a najmniejsze składowe (w tym często powtarzające się) umieszczam w katalogu „small”. Teraz chyba wszystko jest jasne, jednak podkreślę to raz jeszcze – nie sam układ jest najważniejszy.

Roadmap

question_mark„Co było a nie jest nie pisze się w rejestr” – przyszła wiosna i nastał okres zmian, zakończyłem ostatnio pewną długofalową współpracę i można powiedzieć że znów jestem na swoim:) Nie martwi mnie to szczególnie – programowanie w moim przypadku to przede wszystkim pasja i hobby a w przededniu zawodowych rozterek chciałbym szczególnie aby tak zostało. Po każdym projekcie/zleceniu czy jak w tym przypadku współpracy przychodzi czas na podsumowania, tylko co tu napisać? – może klasycznie że było to ciekawy czas pełen wyzwań i okazji do nauczenia się czegoś nowego? Niewątpliwie tak było  ale czy coś jeszcze? Szczerze powiedziawszy to na razie chyba muszę odpocząć, nabrać dystansu by z powrotem cieszyć się każdą linijką rozwijanego kodu, każdym szkicem zrobionym gdzieś z boku notesu.

Mimo pewnego przemęczania mam za to klarowność a propo tego co chciałbym robić w przyszłości i o tym przede wszystkim jest niniejszy post:) Przede wszystkim chciałbym wrócić do blogowania gdyż sprawiało mi to kiedyś niewypowiedzianą frajdę natomiast co do zainteresowań oto czemu chciałbym się poświęcić:

  • Flex + AS3 – zestaw królów – nie wiem co by mnie zmusiło obecnie aby pisać UI od podstaw w gołym AS3 kiedy możliwości wykorzystania i modyfikacji istniejących zestawów kontrolek są właściwie nieograniczone.
  • Flex + AMF + remote objects – komunikacja flexa z innymi technologiami – głównie serwer side.
  • Flex + bazy danych – aplikacje bazodanowe i przetwarzające dane pozostają w centrum mojego zainteresowania stąd też nie chce się ograniczać do jednej technologii. Wiadomo że opcji jest wiele niestety dla samego flexa sprawa nie wygląda zbyt różowo – oficjalnie wspierany jest jedynie SQLite w Adobe AIR a cała reszta dostępna jest przez różnych „pośredników” (np via php – sic!).
  • Flex + RobotLegs – w tym aplikacje modułowe (miodzio!) – dla długoterminowych/poważnych projektów nie ma chyba alternatywy (sensownej oczywiście).
  • Optymalizacja kodu i wydajności – np przy zastosowaniu Starling’a.
  • Aplikacje mobilne – Flex oczywiście – raczej jako wątek poboczny do powyższych, wiadomo rynek mobilny rośnie i nie można go pominąć.
  • Arduino + Flex – ożywienie aplikacji w świecie rzeczywistym – arduino już do mnie idzie via http://www.dx.com:)
  • Poza tym wszelkiej maści multimedia – odtwarzacze wideo, platformy, streaming audio, odtwarzanie mp3.
  • P2P – wykorzystanie technologii Cirrus wbudowanej w FP i komunikacja bezpośrednia pomiędzy użytkownikami – czaty, streaming audio/wideo.

Są też rzeczy które świadomie mam zamiar omijać szerokim łukiem:

  • Gry! – nie ma w tym nic pociągającego i nikt mnie nie zmusi do pisania pierdół.
  • Social media – nie lubię i nie mam zamiaru zgłębiać jak podłączyć wszystko do facebooka.
Kategorie:Inne Tagi: ,

Embedding fonts – do mxml’a przez css’a od swf… ech.

11 listopada, 2012 Dodaj komentarz

No cóż świat Flexa idzie do przodu, dopiero co wyszedł Flex 4.6 a już za pasem mamy wydanie 4.8 od Apache i co więcej z sieci można pobrać betę FlashBuildera 4.7 którego oficjalne wydanie planowane jest na grudzień 2012. No i w końcu coś się zaczyna dziać, po poprzednim dość kosmetycznym wydaniu Adobe wprowadza cały szereg nowości, z nowym kompilatorem na czele. Tak się też utarło że co nowa wersja to jakieś zmiany w pracy z czcionkami. Czasami mam wrażenie że ktoś w Adobe stawia sobie za punkt honoru namieszanie czegoś w tym temacie za każdym razem gdy ukazuje się nowe sdk lub pakiet CS. Od Flasha CS3 zasadniczo co wersje coś się zmienia i co ciekawe pojawiały się już rozwiązania dobre które można było pozostawić. Rozumiem że za każdą zmianą idą jakieś ulepszenia w wewnętrznej architekturze ale czemu muszą się one tak boleśnie odbijać na programistach?! Nie będzie więc niespodzianką że od wersji 4.7 FB znów wchodzą nowości. Jeśli przywykliście do metatagu [Embed] to niestety o nim zapomnijcie. Od wersji 4.7 nie będzie on potrafił transkodować plików czcionek. Zatem będą one musiały być wstępnie pre-transkodowane i osadzone wewnątrz plików SWF a dopiero z niego w arkuszu stylów lub pliku mxml.

Aby osadzić czcionkę w pliku SWF możemy skorzystać z możliwości Flash Professional ale po co uzależniać się od płatnego oprogramowania? Jest na to prostszy sposób, w skład SDK Flex wchodzi odpowiednie narzędzie – plik „fontswf.bat”.

Plik znajduje się w folderze „bin” wewnątrz folderu z SDK, jeśli twoje SDK jest częścią FlashBuilder’a znajdziesz go w „folder_instalacji_FB/sdks/4.6.0/bin”. Plik pracuje w linii komend, a jego zastosowanie sprowadza się do przekazania odpowiednich parametrów.

  • -a (nazwa), nazwa czcionki po jakiej będziesz się do niej odwoływać w aplikacji;
  • -b, oznacza czcionkę jako pogrubioną;
  • -i, oznacza czcionkę jako pochyloną;
  • -o (nazwa pliku), ścieżka i nazwa pliku swf który ma zostać wygenrowany;
  • -3, jeśli chcesz używać czcionki w czystym AS3 i jego TextField
  • -4, jeśli chcesz używać czcionki w komponentach Flex
  • -u (zakres), zakres znaków które mają zostać osadzone, domyślnie (*) osadza wszystkie znaki.

Wywołujemy więc komendę:

A efekt powinien być mniej więcej taki:

A co zrobić z takim plikiem potem? Osadzamy czcionkę w stylach CSS:

@font-face{
	src: url('./assets/fonts/SansPro.swf');
	fontFamily: "SansPro";
}

.test {
	fontFamily: "SansPro";
	fontSize: 24;
}

 

Kategorie:Flex Tagi: , , , , ,

RobotLegs – IoC (Inversion of Control) i DI (Dependency Injection)

8 listopada, 2012 Dodaj komentarz

Pora na dwa pojęcia które nieodzownie łączą się z RobotLegs a które malują się dużo straszniej niż są w rzeczywistości. Nie ma też co ukrywać z racji rosnącej popularności RL stają się po prostu modne.

IoC – „odwrócenie sterowania” – jest sposobem pracy z frameworkiem w zasadzie wymuszonym kiedy decydujesz się na jego zastosowanie. W zasadzie polega to na tym iż najpierw konfigurujesz framework a potem oddajesz mu kontrolę nad aplikację. Framework zapewnia aplikacji architekturę oraz przejmuje kontrolę nad przepływem zdarzeń a tym samym nad przepływem danych. W RL do konfiguracji frameworka służy generalnie klasa Context z obiektami injectora, commandMap i mediatorMap. Drugim mechanizmem jest natomiast rozszerzanie klas frameworka co też nie jest jakimś niezwykłym fenomenem.

DI – „wstrzyknięcia zależności” – kolejne mylące pojęcie, jeśli napisałeś kiedykolwiek coś w AS3 to pewnie skorzystałeś z DI. Zasadniczo polega to na konfiguracji obiektu z zewnątrz, np: poprzez przekazanie mu jakiś parametrów w konstruktorze czy też poprzez funkcję dostępową. Jak widać jest to sprawa bardziej niż powszechna i wcale nieprzypisana do frameworka. Dzięki takiemu podejściu do programowania możemy wielokrotnie wykorzystać te same obiekty dostosowując ich zachowanie do obecnych potrzeb oraz dostrajając sposób ich pracy dzięki czemu stają się znacznie bardziej użyteczne.

Kategorie:AS3, podstawy, RobotLegs Tagi: , , ,

Testowanie aplikacji mobilnych natywnie w systemie – Android SDK

8 listopada, 2012 Dodaj komentarz

Od wersji 4.5 IDE FlashBuildera jak i Flex SDK Adobe ofiarowało programistom zupełnie nowe możliwość w zakresie tworzenia aplikacji mobilnych. Wystarczy tylko wspomnieć że Flex 4 nie posiadał żadnych zoptymalizowanych w tym kierunku komponentów jak i również samo IDE nie wspierało pisania mobilnych projektów. Wersja 4.5 wniosła w tym temacie pewną świeżość, pojawiło się nagle wsparcie dla testowania (podglądy) oraz debugowania kodu bezpośrednio na urządzeniu. Natomiast Flex SDK wzbogacił się o zestaw mobilnych kontrolek Spark. Nową jakość dało natomiast połączenie obu tych elementów, w FB 4.5 pojawiły się nowe projekty: Flex mobile project i ActionScript mobile project, IDE nagle umiało wygenerować paczkę instalacyjną dla konkretnej platformy (np. apk dla Androida). W śród tych wszystkich ochów i achów pojawiło się jednak kilka zgrzytów. Przede wszystkim ekran, urządzenia mobilne to obecnie co najmniej cztery standardy rozdzielczości dla samych tylko smartfonów o tabletach nie mówiąc. Różne rozdzielczości/różne wielkości ekranów dają nam różne ich gęstości (dpi) a więc wielkość pixela. Stąd też czcionka 10-14 na smartofnie z ekranem 240-320 i dpi 160 będzie doskonale widoczna zaś na ekranie 720×1280 i dpi 320 i wyżej będzie drobnym maczkiem. Jakby tego było mało telefon taki można przecież obrócić co znów zmienia proporcje. Co prawda Flex 4.5 zawiera kilka wbudowanych patentów na te niuanse mobilnych aplikacji lecz nie zawsze działają one tak dobrze jak powinny. Wszystko to prowadzi do potrzeby testowania rozwijanej aplikacji w jakimś miarodajnym środowisku. Najlepiej oczywiście bezpośrednio na smartfonie/tablecie co dzięki nowemu FB jest całkiem łatwe do zrobienia. Mam jednak świadomość że nie każdy developer urządzenie takie posiada a nawet jeśli to z reguły jedno (a wypadałoby przetestować różne scenariusze). Tutaj z pomocą przychodzi Android SDK, pakiet wyposażony został bowiem w system AVD (Android Virtual Device) który pozwala emulować Androida na zasadzie maszyn wirtualnych.

1) Po pierwsze pobieramy instalator SDK – stąd.

2) Następnie uruchamiamy pobrany instalator, do poprawnego przebiegu konieczny jest pakiet JDK (Java Development Kit) do pobrania stąd.

3) W managerze instalacji SDK musimy następnie wybrać wersję systemu której instalacja SDK ma dotyczyć – dopiero wówczas zostaną pobrane niezbędne pakiety.

4) Akceptujemy licencję, najlepiej zbiorczo zaznaczając opcję „Accept All” i klikamy Install.

5) Instalator pobierze dla nas wszystko co jest wymagane co łącznie daje dobrych kilka set MB i chwilę trwa.

6) No i gotowe.

7) Uruchamiamy AVD Manger’a w celu dodania nowego urządzenia.

8) W nowym oknie klikamy „New” po prawej stronie u góry co powinno wywołać widoczne powyżej mniejsze okienko konfiguracji urządzenia.

9) Konfigurujemy: wybieramy architekturę (najlepiej ARM jak na urządzeniach mobilnych), ilość pamięci trwałej, wielkość ekranu, gęstość ekranu oraz ilość pamięci RAM przewidzianej dla urządzenia. Na końcu klikamy „Create AVD”.

10) Wybieramy na liście urządzeń to dodane przez nas i klikamy po prawej stronie „Start”, po uruchomieniu pozostaje nam jedynie działać:)

Książki o Flash i Flex #3

7 listopada, 2012 Dodaj komentarz

Tym razem dodaję do biblioteczki podręcznik niemalże obowiązkowy dla wszystkich zainteresowanych frameworkiem RobotLegs. Niestety jest to pozycja anglojęzyczna ale napisana bardzo przystępnie i co najważniejsza przez samych autorów frameworka. Na około 120 stronach przedstawiony jest zarys pracy, workflow samego RobotLegs, przewodnik po instalacji niezbędnych bibliotek i krótkie wprowadzenie  jak rozpocząć prace. Nie jest to pozycja opisująca dogłębnie klasy i strukturę frameworka, intencją autorów nie jest dokumentowanie kodu lecz przedstawienie korzyści płynących z jego zastosowania w projektach, omówienie architektury oraz opis poszczególnych elementów. Duży nacisk położono na wyjaśnienie schematu pracy frameworka i mimo iż fizycznie schemat w całej publikacji jest jeden to jednak po lekturze rozdziałów charakteryzujących poszczególne składowe RL wyłania się schludny obraz całości. Autorzy bardzo przejrzyście wyjaśniają miejsce w przepływie danych i architekturze przyszłej aplikacji każdego elementu dzięki czemu nie ma wątpliwości o co oprzeć serwisy, modele widoki itp… . Niestety w związku barakiem szerzej dostępnych materiałów a tym bardziej publikacji w języku Polskim przewodnik ten pozostaje na dzień dzisiejszy praktycznie jedynym rzetelnym źródłem informacji o RobotLegs.

Meteo App – Perfect Simplicity

7 listopada, 2012 Dodaj komentarz

Meteo App – to moje najnowsze mobilne dzieło. Appka kierowana jest na urządzenia pracujące pod kontrolą Androida a jej głównym  przeznaczeniem jest monitorowanie warunków pogodowych w czym mam nadzieję sprawdzi się całkiem dobrze. Całość wykonana została w środowisku FlashBuildera 4.6 z użyciem komponentów Flex SDK 4.6, a więc jak przystało w technologii Flash. Do jej uruchomienia niezbędne jest środowisko Adobe AIR (w wersji mobilnej dostępne na android i iOS), zintegrowane w paczce „apk” dla systemy Android. Projekt oparłem o framework RobotLegs celem jego łatwiejszej modernizacji i konserwacji w przyszłości oraz zapewnienia dobrze przetestowanej, wydajnej i zarazem kompaktowej architektury.

SZCZEGÓŁY:

Do pracy aplikacji konieczne jest aktywne połączenie z internetem. W głównym widoku wyświetlane są dane dla obecnej lokalizacji użytkownika która ustalana jest pierwotnie na podstawie adresu IP urządzenia. W przypadku łączności z siecią poprzez 3G ustalenie po IP może być obarczone dużym błędem (w czasie testów często zamiast Wrocławia ustalało mi lokalizacje na Wałbrzych lub nawet Warszawę). Dlatego też w aplikacji zaimplementowałem drugi system ustalania lokalizacji za pomocą GPS. Ustalanie lokalizacji na podstawie IP w przypadku połączenia WiFi jest znacznie dokładniejsze i z reguły nie rodzi nieścisłości. Uzupełnia to idealnie lokalizację poprzez GPS ponieważ z WiFi korzysta się z reguły w budynkach gdzie trudniej o ustalenie pozycji GPS, nie mniej aplikacja podejmie próbę jej pozyskania za każdym razem gdy urządzenie posiada wbudowany odbiornik GPS a dzięki technologi A-GPS najczęściej znajdzie pozycję nawet w budynkach. Poniżej prognozy dla lokalizacji bierzącej wyświetlane są pozycje dodane przez użytkownika – możliwe jest szukanie miejscowości po nazwie na mapie lub otagowanie obecnego miejsca za pomocą GPS. W przypadku tagowania GPS nazwa najbliższej miejscowości dla której prognoza będzie wyświetlana w głównym widoku uzyskiwana jest dzięki „ReverseGeocoding” z serwisów Google. Po kliknięciu na prognozę (dla obecnej lokalizacji jak i zapamiętanych) aplikacja wyświetli pełniejsze dane dla wskazanej pozycji.

Jak wspomniałem we wstępie do posta całą aplikację zrealizowałem w oparciu o RobotLegs dzięki czemu działa on szybko, stabilnie, jest elastyczna i otwarta na dalsza rozbudowę oraz prosta w konserwacji i dalszym utrzymaniu. Mimo iż dopiero co została ukończona jestem świadom iż zawiera pewne niedociągnięcia, narazie skupiłem się na zawarciu w niej podstawowych funkcjonalności. Teraz pora na chwilę oddechu, nabranie dystansu i rozpoczęcie prac nad poprawkami.

RobotLegs – Flash Professional CS4 – CS6

Do tej pory pracowaliśmy z RobotLegs jedynie w środowisku Flash Buildera który zasadnicz0 jest znacznie lepszym narzędziem programistycznym niż Flash Professional nie mniej jego obecności wciąż nie można ignorować. Co prawda osobiście uważam iż do poważnego kodowania Fl się po prostu nie nadaje zwłaszcza w kontekście takich narzędzi jak wspomniany Flash Builder czy genialny Flash Develop. Co więcej sam nie wiem jakie miejsce Fl powinien i do tego jakie realnie zajmuje w świecie AS3, od niego wszystko się zaczeło ale dziś promowany jest jako software dla „projektantów” – cokolwiek to oznacza. Wciąż klasyfikowany jest jako narzędzie graficzne i powszechnie służy do tworzenia banerów, czasem gier i realizacji graficznie rozbudowanych projektów. Ostatnim razem dane mi było pracować w Fl za czasów CS4, natomiast na potrzeby tego wpisu zainstalowałem CS6 w wersji Trial co by się dodatkowo zapoznać z niektórymi nowościami. Tyle słowem wstępu, oto co należy zrobić by móc w środowisku Flash Professional realizować projekty w RobotLegs.

Przede wszystkim ściągamy framework ze strony domowej, i rozpakowujemy paczkę.

Świeżo zainstalowany Flash Professional CS6, tak wyglądał u mnie po pierwszym uruchomieniu (domyślnie w perspektywi „podstawy”)

Perspektywa „programowanie” zdaje się być jednak bardziej odpowiednia dla naszych celów, zalecam zmianę chociażby na potrzeby tego poradnika.

Tworzymy nowy projekt.

Zakładanie nowego projektu – przykład ode mnie.

Taki powinien być efekt poprzedniego kroku.

W tym miejscu musimy się na chwilkę zatrzymać. Fl utworzył dla ciebie projekt we wskazanej lokalizacji natomiast nie zawiera on wszystkich niezbędnych nam elementów a krótko mówiąc nie zawiera on kodu samego frameworka RobotLegs. Musimy się więc cofnąc do kroku pierwszego którym było pobranie i rozpakowanie ze strony twórców RL i rozpakowanie ściągniętej paczki. Potrzebujemy wydobyć z niej w zasadzie dwa elementy – po pierwsze: pakiet „org” zawierający klasy AS3 frameworka oraz jeden plik *.swc: „SwiftSuspenders-v1.6.0″. W ściągniętej paczce pakiet „org” znajduje się w folderze „src”, natomiast plik „swc” w folderze „libs”. Oba elementy należy przenieść do głównego folderu naszego projektu co razem powinno wyglądać jak na zrzucie obok. Możemy teraz przejść do sedna. Mamy utworzony projekt z zaimportowanym frameworkiem, pozostaje jedynie konfiguracja IDE Flasha by chciało z nim współpracować.

Z menu File/Plik wybieramy opcję „Ustawienia ActionScript”, jeśli nie widzisz tej opcji upewnij się że masz otwarty i aktywny w edytorze plik *.fla projektu.

Powinno otworzyć się okno takie jak to. Należy w nim kliknąć wskazaną ikonkę która pozwoli zaimportować do projektu plik swc. Wskazujemy oczywiście plik „SwiftSuspenders-v1.6.0.swc”.

Oto efekt naszego działania, plik swc dodany na liście bibliotek we Fl. Zatwierdzamy przyciskiem „OK”.

Z menu File/Plik wybieramy opcję „Ustawienia publikowania”.

Następnie upewniamy się że przy pozycji SWC jest postawina „fajeczka”, a więc kompilator będzie oprócz wynikowego pliku SWF generował też plik SWC z naszego projektu a skutkiem ubocznym tej operacji bedzie zachowanie wszystkich metadanych w ich miejscu.

Tak sprawa wygląda w starej, poczciwej CS4. Zaznaczamy jedynie pole „export swc”.

To by w zasadzie było na tyle, środowisko jest w pełni skonfigurowane do pracy z RobotLegs, pozostaje natomiast jeszcze jeden haczyk. Rozpoczęcie pracy z frameworkiem we Flashu różni sie nieco od startu w FB czy FD. Różni się dokładnie jedną linijką kodu którą należy dodać w Contex’cie. Mianowicie na samym początku konstruktora twojej klasy Context, jeszcze przed wywołaniem metody super(), należy wstawić taką linijkę:

injector = new SwiftSuspendersInjector();

oraz upewnić się że klasa ta jest zaimportowana:

import org.robotlegs.adapters.SwiftSuspendersInjector;
package com.wordpress.assnippetes {
	
	import org.robotlegs.mvcs.Context;
	import org.robotlegs.adapters.SwiftSuspendersInjector;
	
	import flash.display.DisplayObjectContainer;
	
	public class MainContext extends Context {

		public  function MainContext(contextView:DisplayObjectContainer=null, autoStartup:Boolean=true):void{
			injector = new SwiftSuspendersInjector();
			super(contextView, autoStartup);
		}
		override public function startup():void{
	
		}
	}	
}

Na koniec wstawiam źródła mojego projektu z którego screen zamieściłem we wstępie. Jeśli chcesz sprawdzić czy wszystko zrobiłeś prawidłowo wystarczy że skopiujesz ode mnie do swojego głównego folderu projektu pakiet „com” oraz jako główną klasę dokumentu wksażesz plik: com.wordpress.assnipetes.Main.

Tak jak tutaj, we właściwościach pliku fla.

Jeżeli po kompilacji nie będzie błędów a na panelu wyjściowym (output) pojawi się napis „Hello World!” to znaczy że wszystko działa poprawnie, kod frameworka w pełni funkcjonuje łącznie z jego Metadanymi.

Niestandardowe Eventy – Custom Event.

Niestandardowe klasy Eventów są rozwiązaniem wielu bolączek programistów AS3, przede wszystkim umożliwiają przesłanie razem z Eventem czegoś więcej niż on sam (a więc tylko informacji) a mianowicie również danych. Pozwalają lepiej zoptymalizować zdarzenia aby bardziej odpowiadały faktycznym akcją w aplikacji, a w projektach realizowanych w RobotLegs są wręcz niezbędne i stają się czymś powszechnym i nagminnym tak bardzo że prawie nie zwraca się na nie uwagi, tym bardziej że napisanie własnej klasy Eventów jest bajecznie proste.

W klasycznym systemie Eventów AS3, zdarzenia są sposobem komunikacji obiektów dzięki któremu mogą one przekazywać sobie informacje o (jak nazwa wskazuje) wydarzeniach. Dla przykładu gdy obiekt klasy „A”, skończy wczytywać dane rozgłasza zdarzenie aby inne obiekty się o tym dowiedziały. Przekazywana jest w tym przypadku jedynie informacja o ukończeniu pewnej czynności, co może być istotne dla rozpoczęcia następnej i utrzymania wszystkiego w odpowiednim porządku (najpierw czynność A potem czynność B). Nasłuchując i rozgłaszając zdarzenie obiekty dokonują pewnej ugody – tzn. muszą się zrozumieć a więc obiekt rozgłaszający wysyła to samo czego oczekuje obiekt nasłuchujący. Zgodność ta zapewniana jest przez pojedynczy łańcuch znaków, rozgłaszany jest więc taki sam łańcuch znaków jakiego nasłuchuje odbiorca.

Posłużę się tutaj moim ulubionym przykładem: Studenckie mieszkanie, dwóch studentów zamawia na współę pizzę, a ponieważ jeden z nich ma coś do załatwienia (student_A) to umawiają się w ten sposób iż ten czekający (student_B) zawoła go gdy przyjdzie dostawa. Mamy więc tutaj następującą sytuację: obiekt który rozgłosi zdarzenie (student_B) gdy przyjdzie pizza i obiekt nasłuchujący (student_A) który oczekuje tej informacji, a żeby uniknąć niedomówień studenci muszą dogadać się co do okrzyku – np: PRZYSZŁA_PIZZA. W momencie gdy w mieszkaniu pojawi się dostawca, student_B krzyknie „PRZYSZŁA_PIZZA”, rozgłaszając tym samym konkretny Event, który odbierze nasłuchujący go student_A. Całość nie zadziała zbyt dobrze gdy student_B wykrzyczy inną frazę lub nawet poprawną rozgłosi student_C lub student_D. Konewncja jest taka, że „konkretny obiekt nasłuchuje konkretnego Eventu wygenerowanego przez inny konkretny obiekt”.

Niestandardowe Eventy pomagają uniknąć różnych potencjalnych komplikacji i niedomówień w sytuacji przedstawionej wyżej oraz co więcej umożliwiają dostarczenie razem z wiadomością od razu kawałka pizzy:)

Do dzieła, oto klasa mojego własnego Eventu:


package Events
{
	import flash.events.Event;
	
	public class MyAppEvents extends Event
	{
		public static const PRZYSZLA_PIZZA:String="przyszla_pizza";
		public var data:*;
		public function MyAppEvents(type:String, data:*=null, bubbles:Boolean=false, cancelable:Boolean=false)
		{
			this.data=data;
			super(type, bubbles, cancelable);
		}
		override public function clone():Event{
			return new MyAppEvents(type,data,bubbles,cancelable);
		}
	}
}
import flash.events.Event;
public class MyAppEvents extends Event

jak widać klasa ta importuje podstawową klasę Eventów AS3 oraz ją rozszerza.

public function MyAppEvents(type:String, data:*=null, bubbles:Boolean=false, cancelable:Boolean=false)
	{
		this.data=data;
		super(type, bubbles, cancelable);
	}

w konstruktorze dzieje się już więcej ciekawych rzeczy, po pierwsze należy zwrócić uwagę na drugi argument konstruktora – data:*=null. Umożliwia on przekazanie do obiektu Eventu dowolnych danych (stąd typ *) oraz posiada wartość domyślną „null”, co oznacza iż nie jest on wymagany – można dane przekazać ale nie trzeba.
W pierwszej linii konstruktora:

this.data=data;

dane z argumentu „data:*” przekazywane są do publicznej zmiennej o tej samej nazwie, dzięki czemu będą dostępne dla odbiorcy Eventu. Druga linia konstruktora jest już zupełnie obowiązkowa:

super(type, bubbles, cancelable);

musimy przekazać wartości argumentów z konstruktora naszego niestandardowego Eventu do konstruktora klasy nadrzędnej (poprzez metodę super()) aby nowy Event mógł zostać rozgłoszony i skierowany do systemu przepływu zdarzeń.

override public function clone():Event{
	return new MyAppEvents(type,data,bubbles,cancelable);
}

Każda niestandardowa klasa musi nadpisywać/przesłaniać domyślną metodę clone() – samemu się z niej nie korzysta ale wywołuje ją domyślnie EventDispatcher za każdym razem gdu Event jest przekazywany gdzieś dalej od jednego odbiory do następnego. Metoda ta tworzy dokładną kopię zdarzenia (którym domyślnie jest klasa Event), a więc jeśli się jej nie przysłoni może się okazać że Event dociera gdzieś w zniekształconej (uproszczonej) wersji i np. nie niesie ze sobą żadnych danych. Uwaga! Istotne jest aby metoda clone() zwracała nowy obiekt naszej NIESTANDARDOWEJ klasy wraz ze wszystkimi jego argumentami.

Kategorie:AS3, podstawy, RobotLegs Tagi: , ,

RobotLegs – schemat działania aplikacji.

22 lipca, 2012 1 komentarz

Witam, chciałbym przybliżyć jeszcze jedno ważne zagadnienie związane z pracą w Robotlegs a mianowicie schemat kooperacji elementów składowych aplikacji zrealizowanej w tym frameworku. Jak już wiadomo jest ich kilka:

  1. Context
  2. Views & Mediators
  3. Commands
  4. Models
  5. Services
  6. Events

Chciałbym przedstawić więc miejsce każdego z nich w aplikacji oraz zakres działań i odpowiedzialności. Dla nikogo nie będzie niespodzianką, że tym co widzi użytkownik końcowy jest jedynie View (widok). Klasy widoku są elementami interfejsu (UI – user interface), a to z nim oddziałuje użytkownik dlatego też stanowi on dla punkt wejścia i zarazem wyjścia, ponieważ wszystkie efekty pracy programu (odbywającej się wewnątrz – „w tle”) są prezentowane również poprzez elementy interfejsu. Jest to skrócony i tak naprawdę nieco naciągnięty obraz sytuacji, ponieważ nie wszystkie akcje są inicjalizowane przez użytkownika w wyniku jego interakcji z interfejsem, tak samo jak nie wszystkie efekty pracy aplikacji są zawsze bezpośrednio widoczne (np. zapis do bazy danych czy wysyłanie e-maila).

Raz to już zostało napisane więc nie będę się specjalnie powtarzał, wodą na młyn RobotLegs są Eventy – w głównej mierze niestandardowe pisane przez programistę na potrzeby aplikacji. RL rozwija bardzo mocno myśl aplikacji luźno powiązanych, obiekty które reagują na Event nie musza mieć żadnego bezpośredniego kontaktu z obiektami które Eventy te rozgłaszają. W uproszczeniu wygląda to tak że obiekt rozgłaszając Event wysyła go w „eter” – w bliżej nieokreśloną przestrzeń z której odebrać go może każdy kto chce. W rzeczywistości przestrzenią tą jest klasa Context która dostarcza szynę danych którą płyną wszystkie Eventy – ale jest to wątek poboczny. Najistotniejsze jest to że Event może być wygenerowany gdziekolwiek w aplikacji i gdziekolwiek w aplikacji odebrany (ale i tu są wyjątki, a jakże).

Eventy przekazują pewną informację oraz dane (opcjonalnie), zasadniczo przypominają wiadomość e-mail gdzie cały sens informacji zawarty jest w tytule ale mogą zawierać też załącznik w postaci rozmaitych danych. Ważne jest natomiast co dalej odbiorca (obiekt nasłuchujący) zrobi po otrzymaniu tej informacji (i ewentualnie danych) – aplikacja RL może zareagować dwojako – albo wykonać jakąś pracę w tle np. wczytać/zapisać dane lub zakutalizować/zmienić widok aby dostoswać UI np. przejść na następną stronę. Mamy więc do wyboru dwie możliwości: rekację niewizualną, w tle lub wizualną. Zazwyczaj powstają dość rozbudowane łańcuchy reakcji niewizualnych i wizualnych (prawie zawsze na końcu). Za reakcje niewizualne odpowiadają klasy Komend (Command) za wizualne Mediatory będace dwukierunkowymi pośrednikami pomiędzy widokami a aplikacją.

Modele oraz Serwisy spełniają swoją rolę zgodną ze wzorcem  MVCS bez większych niespodzianek, stanowią one jednak pewien wyjątek w systemie pracy Eventów RL – bowiem mogą tylko rozgłaszać Eventy a nie moga ich nasłuchiwać – jest to w pewien sposób logiczne. Modele i Serwisy mogłyby stanowić co najwyżej niewizualną odpowiedz na Event a za taką odpowiedzialne są już Komendy. Natomiast jeśli odpowidzią na Event ma być np. wczytanie danych to oczywiście niezbędna jest tutaj kooperacja Komendy odbierającej Event i odpowiedniego Serwisu którym Komenda ta mogłaby się posiłkować.

Context natomiast jest najbardziej tajemniczym elementem tej układanki – zawsze omawiany na końcu a tak na prawdę to od niego zaczyna się pisanie aplikacji. Jak pisałem już kiedyś jest to miejsce spojenia w którym łaczy się odpowiednie elementy ze sobą.

Oficjalny diagram korelacji RobotLegs – mniej więcej to co zostało opisane powyżej.

Jak to się teraz wszystko ma do siebie w rzeczywistym projekcie. Na tę okoliczność przygotowałem małą aplikację – jest to projekcik zrealizowany w środowisku FlashBuilder’a 4.6 z użyciem frameworku Flex’a w wersji 4.6 oraz RobotLegs. Aplikacja nie powala ani wyglądem ani funkcjonalnością chciałem za jej pomocą zobrazować jedynie schemat pracy takiej apki. Oto ona:

RobotLegs app – środowisko pracy

RobotLegs app – oto i sama aplikacja.

Aplikacja ta nie robi nic specjalnego wczytuje plik XML (z listą piosenek) wskazany przez użytkownika i wyświetla jego zawartość w postaci listy. Nie ma tu w zasadzie żadnych zautomatyzowanych czynności, wszystko inicjalizowane jest przez użytkownika w momencie kliknięcia przycisku „Wczytaj plik”. Oto plik XML’a którym się posłużyłem:

RobotLegs app – plik xml z listą utworów.

Teraz pora na to co się właściwie dzieje wewnątrz tej apki. Jak wspomniałem wyżej wszystko zaczyna się w momencie kliknięcia przez użytkownika przycisku „Wczytaj plik”. Sam przycisk jak i lista w której zostanie wyświetlona zawartość dokumentu XML oraz okienko w którym się znajdują są komponentami Flex’a oraz w mojej małej aplikacji stanowią razem jej jedyny Widok. Widok ten ma swój mediator który odbiera zdarzenia MouseEvent.CLICK jakim jest naciśnięcie na przycisk „Wczytaj plik”. Mediator spełniając swoja rolę generuje do aplikacji już znacznie konkretniejszy Event pochodzący z niestandardowej klasy Eventów, przygotowanej na potrzeby tej aplikacji, a zgodnie z ideą że generować event może ktokolwiek i ktokolwiek, gdziekolwiek może go odebrać, z eventem tym w Contex’cie zmapowana jest odpowiednia klasa Komendy. Odpowiada ona za stworzenie obiektu klasy File i za wyświetlenie okna przeglądania plików.

RobotLegs app – okno wyboru pliku.

Okno jest wbudowaną metodą klasy File w środowisku AIR, nie jest widokiem więc nie posiada swojego mediatora. Gdy użytkownik wybierze plik Komenda (ta sama co w tekście powyżej obrazka) zawiadująca obiektem klasy File, rozgłosi kolejny Event w którym jako „załącznik” przekaże ścieżkę dostępu do wskazanego pliku XML. I tym razem reakcja na nowy Event ma być niewizualna – bo ma nią być wczytanie wskazanego pliku. Z pewnością da się to zrobić jednoetapowo mnie jednak zależy bardziej na celach dydaktycznych. Nowy Event oznacza więc nową Komendę (a więc już drugą w naszej aplikacji) która wczyta i obrobi plik XMLa, a użyje do tego Serwisu któremu przekaże ścieżkę dostepu do pliku. Tym razem również bez niespodzianek gdy Komenda (ta druga) skończy – rozgłosi kolejny Event i tym razem jako „załącznik” do niego przekaże cały wczytany dokument. Tym razem reakcja ma już być wizualna więc Event odebrac może Mediator i używając odpowiedniej metody Widoku zaktualizować go aby wyświetlał wczytane dane.

RobotLegs app – efekt końcowy.

Ponowne kliknięcie na przycisk uruchomi całą procedurę od nowa. Całość zlepia Context w którym zmapowane pozostają rozgłaszane w aplikacji Eventy z odpowiednimi Komendami, oraz Widok z Mediatorem który również nasłuchuje jednego zdarzenia z aplikacji.