wtorek, 29 grudnia 2009

Symbian S60. Programowanie urządzeń mobilnych

Kupiłem książkę Pawła Gali o Symbianie wydaną przez wydawnictwo Helion. Z dużym zapałem zacząłem ją czytać. Podczas czytania zauważyłem, że styl pisania zaczynał być bardzo akademicki, co zmuszało mnie do przerywania lektury, żeby zastanowić się o co chodziło autorowi. Z wielkim trudem dobrnąłem do końca książki. I mam duże wątpliwości, co do tego kto ją powinien kupować i czytać. Pierwsze skojarzenie to studenci, którzy będą uczyć się programować na Symbiana. Oni są na dobrej drodze żeby kupić tą książkę i razem z wykładowcą na ćwiczeniach przerabiać wiedzę z tej książki. Druga grupa czytelników to ci, którzy już programują na Symbiana. Im bardzo polecam tą książkę ze względu żeby mogli uporządkować sobie wiedzę na temat programowania na Symbiana. Natomiast odradzam kupowanie tej książki ludziom, którzy wcześniej nie programowali na Symbiana, ponieważ w tej książce jest zawarta wiedza teoretyczna, bez praktycznie działających przykładów (czyli przygotowanych projektów z kodem do skompilowania). Są natomiast listingi, które tak naprawdę służą do pokazania jakiejś teoretycznej podstawy w kodzie. To już zmusza czytelnika do dużego wysiłku intelektualnego, żeby sprawdzić tą teorię w praktyce.

Z pierwszego rozdziału czytelnik dowie się o systemie operacyjnym Symbian i o jego budowie i zrozumie dlaczego jest to jeden z najbardziej restrykcyjnych systemów operacyjnych i jednocześnie bardzo trudnym w zrozumieniu. Istotne jest zrozumienie architektury EKA2. Z drugiego rozdziału można dowiedzieć się że jak trzeba przegotować warsztat programisty. Autor poleca żeby użytkownik instalował SDK S60 3rd FP2 i Carbide.C++. Właściwie to już trochę nie trafiony wybór, bo ja bym zaproponował instalowanie ADT ze stron Fundacji Symbian. Zmartwiło mnie, że to tylko wspomniał o Designerze UI twierdząc, że nie poleca używania tego kreatora bez znajomości teorii o programowaniu. Dzisiaj większość ludzi zaczyna naukę programowania właśnie od takich kreatorów. Zrozumiale jest to, że bez teorii nie ma sensu uczyć programowania, ale przecież można było krok po kroku pokazać gdzie wstawiać odpowiednie fragmentów kodów z listingów. Autor od razu przedstawia w rozdziale 3 architekturę GUI czyli framework AVKON. Podczas tej lektury zauważyłem że celem autora przedstawienie wiedzy niż pomóc czytelnikowi w zrozumieniu jej. Potem spróbowałem wykorzystać listingi do zbudowania sobie aplikacji. Nie udało się, bo listingi nie zawierały wszystkiego co było potrzebne do zbudowania tej aplikacji. Następnie wygenerowałem sobie projekt z Carbide, oraz zacząłem badać jakie są różnice z tym kodem autora, a tym z kreatora. Sęk w tym, że raz autor pisze o standardowym kodzie tj takim który nie uwzględnia wersji językowych, a potem nagle pisze o tworzeniu wersji językowych. Można było się pogubić w lekturze, pomimo że merytorycznie treść jest w porządku. Skończyło się na tym, że zrobiłem 2 wersje raz tylko z wersją angielską a raz z wersją polską. Tylko, że wersja polska nie poprawnie wyświetlała znaki polskie. Poszukałem na Forum Nokia rozwiązania problemu. Wymagało to podania makra CHARACTER_SET UTF8 w pliku lokalizacyjnym. Zadowolony, że uporałem się z problematycznym rozdziałem zacząłem czytać rozdział 4 o platformie bezpieczeństwa. Rozdział ten dość dokładnie omawia o uprawnieniach aplikacji i podpisywaniu aplikacji na Symbiana. Także bardzo dobrze omówił procedurę certyfikacji i sposób uzyskiwania identyfikatorów dla aplikacji w Symbian Signed. Według mnie to najlepiej napisany rozdział w całej książce. Tak zadowolony przeszedłem do czytania 5 rozdziału o emulatorze Symbiana. Jakoś nie darzę szczególną estymą ten emulator z tego powodu, że jest bardzo powolny i trzeba mieć dużo cierpliwości do niego. To co mnie zainteresowało to wykorzystanie narzędzi do diagnostyki czyli zainstalowania ecmtagent_cpp.sis i monitorowanie aktywności aplikacji w komórce z poziomu panelu diagnostycznego Carbide. Wcześniej w tym celu korzystałem tylko z AppTRK. Zawsze można coś dla siebie odkryć ciekawego. Od rozdziału 6 rozpoczyna się wykład o niuansach programowania w Symbianie. Jedyne co mogę uznać za plus to, że autor ustala terminologię w języku polskim dla programistów Symbiana. Rozdział 6 dotyczy konwencji nazewniczych. Tutaj miałem problem z szybkim załapaniem co powoduje ze dana klasa jest na stercie lub na stosie. Czy jest jakiś wyznacznik w kodzie co pozwala na rozróżnienie tego czy daną klasę należy nazwać z przyrostkiem C albo T? Jakoś to rozumiem, ale jeszcze brakuje mi wprawy w tym. Rudział 7 dotyczy obsługi wyjątków w Symbianie. Po prostu podczas tworzenia Symbiana trzeba było wymyślić jakiś sposób obsługi różnych problematycznych sytuacji. W tej sytuacji wymyślono cały unikalny mechanizm oparty na wyjściach, podwójnym konstruktorze, panikach, oraz stosu czyszczącego. Najcenniejszą informację dla mnie była informacja o pliku ErrRd, dzięki któremu programista czy użytkownik może dowiedzieć się o tym jaka panika wystąpiła. Rozdział 8 dotyczy używania deskryptorów. Deskryptory są po to żeby umieć zarządzać danymi w Symbianie. Zarówno tymi tekstowymi i jak binarnym. Szczerze mówiąc zawsze miałem problemy ze zrozumieniem dobrze deskryptorów. Po przeczytaniu tego rozdziału mam jeszcze większy mętlik w głowie - głownie dlatego, że trzeba będzie do każdego listingu zrobić wersję programu który pokazywałby to w działaniu. A tego jest bardzo dużo do przyswojenia i nie da się tego od razu zrozumieć. Czytając te listingi przyszła mi myśl, że skoro takich rzeczy w nauce C++ wystarczy zwykła aplikacja konsolowa to w tym przypadku też można byłoby sobie napisać aplikacje konsolowe i sprawdzać to w trybie debugowania na komórce. Myślę że bardzo to ułatwiłoby naukę. Zrobiłem przerwę w lekturze, czasami polecam przerwanie lektury książki jak okaże się za trudna i wrócić do niej po jakimś czasie. Rozdział 9 traktuje o tablicach dynamicznych. Ten rozdział koncentruje się na klasach typu CArray, o tym że niektóre klasy mają zdolność do wyszukiwania elementów, sortowania. To co mnie zainteresowało to mechanizmy zarządzania pamięcią. Będę musiał przemyśleć jeszcze raz ten rozdział przerabiając do każdego przypadku klasy odpowiedni przykład. to co wyróżnia Symbian od innych systemów operacyjnych to koncepcja aktywnych obiektów. To można potraktować jako pewnego rodzaju AJAX w aplikacji. Kod w aplikacji może zostać wykonany synchronicznie czy w wg odpowiedniej kolejności a także asynchronicznie czyli równolegle. Asynchroniczność zakłada istnienie stanów aplikacji co za tym idzie określanie informacjo o zdarzeniach. Każda klasę która ma być wykonywana w sposób asynchroniczny musi dziedziczyć od klasy CActive i być uruchamiana przez obiekt klasy CActiveScheduler, którzy często jest zwany Zarządcą Aktywności. Ma to sens bo sporo aplikacji na Symbiana, może działać w tle, co tez sprzyja pisaniu aplikacji, które mogą działać długi czas. To jednak trzeba kilka razy czytać ten rozdział. Pomyślałem, że warto by przeczytać cała książkę jeszcze raz pod katem panik różnego rodzaju oraz specjalne napisać takie kody źródłowe które by pokazywały wywołanie określonej paniki a to tak żeby wiedzieć czego unikać. Każdy system operacyjny który ma być wielozadaniowy ma w sobie wątki i procesy o czym omawia rozdział 11 W Symbianie można powiedzieć w dużym uproszczeniu, że proces to załadowana biblioteka bądź uruchomiona aplikacja w której działają różne wątki które wykonują różne zadania. To jak zostaną zadania wykonane zależy też od ustawionych priorytetów. Przynajmniej dzięki tej lekturze lepiej zrozumiałem mechanizmy synchronizacji od strony teoretycznej o semaforach, muteksach i sekcjach krytycznych oraz o klasie Rendezvous. Ponieważ nie miałem okazji do zastanawiania się nad takimi subtelnościami, to w większości ten temat będzie wymagał ode mnie kilkakrotnej lektury. Zauważyłem, że bardzo przyda się zastosowanie klasy RUndertaker w celach diagnostycznych do śledzenia działania wątków w aplikacji. Jak czytam od kilku dni tą książkę to tym coraz bardziej czuję bardzo skomplikowane mechanizmy, których nie da się zrozumieć bez eksperymentowania na listingach i czytania dokumentacji o samym systemie Symbian. Z taką raczej obawą, że nie zrozumiem wszystkiego do końca postanowiłem zrobić przerwę w lekturze. Gdy wróciłem do lektury to uświadomiłem sobie, że autor musiał zrobić pewnego rodzaju kompromis pomiędzy tym żeby w sposób treściwie przedstawić materiał a tym co jest dydaktyką. Kierując z lekturą w stronę bardzo świadomego i samodzielnego czytelnika aspirującego do poziomu wiedzy autora powoduje bardzo zawężenie grupy ludzi, którym ta książka może się przydać. Ja jako czytelnik zacząłem czytać o architekturze klient-serwer i odkryłem fakt, że prawie wszystko w systemie Symbian działa w architekturze klient - serwer. Prawie całą komunikacja w tym systemie od środka polega na tworzeniu sesji i podsesji. Bardzo trafna analogia, że sesja z podsesjami to taki kabel wielożyłowy. Podstawowa klasą odpowiedzialną za tworzenie sesji jest klasa RSessionBase, a za obsługę podsesji odpowiada klasa RSubSessionBase, natomiast serwer i jak klient tworzą instancje obiektów klasy CSession2 aby przesyłać wzajemnie komunikaty, które są obiektami klas TIpcArgs (po stronie klienta) lub RMessage2 (po stronie serwera). Tworząc serwer bazujemy na klasie CServer2. Zauważyłem, że te mechanizmy związane z uprawnianiami i z polityką bezpieczeństwa w tej architekturze mają kluczowa rolę. Po dość długim wprowadzeniu autor zaprezentował to na teoretycznym przykładzie serwera usług kryptograficznych. Znowu autor liczy na samodzielność czytelnika, że sam sprawdzi kod z listingów i przerobi to w kod projektu, a potem sam zaimplementuje klienta. Pomyślałem, że raczej lepiej to zaimplementować w postaci biblioteki dll niż uruchamianego serwera EXE. Ponieważ tworzenie bibliotek dll jest omówione na końcu książki to do tego przykładu warto powracać. Najbardziej zagadkowy okazał się rozdział o właściwościach i repozytoriach. Można przeczytać w nim jak Symbian przechowuje dane globalne o stanach różnych funkcji w komórce. Zaletą właściwości jest to że aplikacja która je zaimplementuje może je rozgłaszać ale już inny program w dowolnym momencie może odebrać tą informację. W architekturze serwer klient obydwie strony wiedzą o sobie nawzajem. Natomiast program który wykorzystuje klasę RProperty nie musi nic wiedzieć o tych klasach które wykorzystują te dane. Repozytoria to już taka specjalna biblioteka która stale przechowuje informacje nawet po restarcie komórki. Dostęp jest możliwy za pomocą obiektów klasy CRepository. W praktyce możliwy jest dostęp do repozytoriów systemowych takie jak stan sieci, profile użytkownika (czyli dostęp do ustawień użytkownika). Tak naprawdę lekturę książki rozpocząłem od rozdziału 14, w którym analizowałem kod z listingów jak tworzyć aplikację wielookienkową. Trochę to różni się od tego co potrafi zrobić kod za pomocą Designera UI z Carbide C++. Jak zwykle autor wymaga od użytkownika zaangażowania, żeby przerobił i uzupełnił kod z listingów w projekt do kompilacji. Czytając na przykład stronę 418 o klasach widoków mam wrażenie, że można pogubić się w tym jak napisać kod brakującej w listingach klasy. Zresztą za pierwszym razem mi nie wyszło. To co mnie zainteresowało też bardzo to aplikacje bez interfejsu użytkownika. I znowu skupiłem swoja uwagę na aplikacji konsolowej. Ten przykład co podał autor jest asynchroniczny co mnie zaskoczyło, że nie mogłem zamknąć tej konsoli w odróżnieniu od aplikacji konsolowej generowanej przez Carbide C++. Największe zdziwienie wywołał u mnie skrypt instalacyjny dla komórki z wyłączoną platformą bezpieczeństwa tak żeby mieć dostęp do plików w folderze !:sys/bin w celu uruchomienia. Potem częściowo to wyjaśniło się jak zacząłem czytać o tworzeniu plików zasobów dla aplikacji, która ma sama się uruchomić. Wyszło na to że aplikacja ma uruchomić się podczas startu systemu. Stosowanie globalnych okien dialogowych nie wymaga przygotowywania specjalnie plików zasobów w interfejsie UI S60 co sprawia że łatwo jest nimi zarządzać z poziomu kodu. Kod z listingów należy przerobić tak żeby działało w aplikacji HelloWorld z trzeciego rozdziału książki albo samodzielnie wstawić do kodu aplikacji GUI wygenerowanej przez Carbide. Autor omawia 5 klas okien dialogowych. Klasa CAknGlobalConfirmationQuery służy do wyświetlania okna dialogowego wyboru logicznego. Klasa CAknGlobalListQuery służy do wyświetlania listy wyboru. Klasa CAknGlobalMsgQuery może wyświetlić długi komunikat bo zawiera pasek przewijania. Klasa CAknGlobalNote wyświetla krótkie komunikaty z odpowiednią kategorią ikon, Natomiast klasa CAknGlobalProgressDialog pokazuje pasek postępu. Aczkolwiek trudno wymyślić sensowną aplikację bazującą na tym to jednak bardzo mogą się przydać przy wyświetlaniu komunikatów wysyłanych przez biblioteki dll, bądź przez aplikacje działające w tle. Najbardziej praktyczny rozdział z tej książki to rozdział o tworzeniu bibliotek dll. Tak naprawdę tworzenie bibliotek dll jest podstawą programowania na Symbianie, do takiego wniosku doszedłem podczas lektury tej całej książki. Są 2 rodzaje bibliotek ładowane statycznie i ładowane dynamicznie. W większości przypadków ładowanie statycznie jest najlepszym rozwiązaniem, ponieważ działa razem z aplikacją. Brak biblioteki powoduje, że aplikacja nie uruchomi się. Przykładem biblioteki statycznej jest Qt. Natomiast gdy istotna jest szybkość i wydajność to warto pomyśleć nad ładowaniem biblioteki polimorficznej do pamięci RAM. Bardzo ciekawie autor pokazał na listingach sposoby tworzenia takich bibliotek i kompilowania tego z linii poleceń. W listingach można zauważyć, że tak naprawdę programowanie na Symbiana w C++ wymaga znajomości wielu makr które w pewien sposób tworzą jakby nakładkę na język C++. Ostatni rozdział opisuje stosowanie podstawowych makr. Właściwie odebrałem wrażenie, że Ci którzy znają się na programowaniu w C++ mogliby rozpocząć od lektury tego rozdziału. Makra _DEBUG wskazują kompilatorowi że ten fragment kodu ma zostać skompilowany dla wersji debugującej. Makro EKA2 ma sens jak tworzy się wersje dla starszych wersji Symbiana. Bardzo użyteczne są __FUNCTION__ czy G_STRLOC makra które służą informowaniu o działaniu programu. Inne użyteczne makra to makra zapobiegające wyciekom pamięci, do których należy grupa makr rozpoczynających się od __UHEAP. Dobrze napisany kod na Symbiana to kod z makrami asercji. Makra które rozpoczynają się od __ASSERT pozawalają już na poziomie kodu sprawdzać wykonanie pewnych założeń i w razie czego wywołać panikę. Obecnie tą rolę zaczynają spełniać testy jednostkowe, które nie są częścią API Symbiana.

1 komentarz:

HARCOWNIK pisze...

Dobra, dokladna recenzja. Niestety większość książek tego typu ma taki schemat i pozostawia czytelnika z podobnym uczuciem zawiedzenia treścią.