Software Developers Journal PL 03/2009

84

description

Tematy numeru:* Biblioteka Luabind...* Spring Java Configuration Project...* CUDA się zdarzają, czyli programowanie GPGPU...* Facebook dla programistów...* Zabezpieczanie systemów IT...* Praca z zespołem testerów klienta...* Jakość czy jakoś to będzie?...* WebAii – testowanie aplikacji ASP .NET...* Zintegruj się z Internet Explorer 8...* Weryfikacja przez model z narzędziem SPIN...* Aby wielu mogło na raz......* Najpierw cele...

Transcript of Software Developers Journal PL 03/2009

Page 1: Software Developers Journal PL 03/2009
Page 2: Software Developers Journal PL 03/2009
Page 3: Software Developers Journal PL 03/2009
Page 4: Software Developers Journal PL 03/2009

4 5

03/2009

Le périodique hakin9 est publié par Software-Wydawnictwo Sp. z o.o.Bokserska, 02-682 Varsovie, PologneTél. +48 22 887 10 10, Fax. +48 22 887 10 11www.phpsolmag.org

Directeur de la publication : Jarosław Szumski

Imprimerie, photogravure : 101 Studio, Firma Tęgi Ekonomiczna 30/36, 93-426 ŁódźImprimé en Pologne/Printed in Poland

Abonnement (France métropolitaine, DOM/TOM) : 1 an (soit 6 numéros) 38 €

Dépôt légal : à parutionISSN : 1731-7037Distribution : MLP Parc d’activités de Chesnes, 55 bd de la Noirée BP 59 F - 38291 SAINT-QUENTIN-FALLAVIER CEDEX(c) 2005 Software-Wydawnictwo, tous les droits réservés

SPIS TREŚCIwykorzystać kartę graficzną do obliczeń niekoniecznie związanych z grafiką komputerową. Następnie użyjemy typowych rozwiązań mających na celu znaczne przyspieszenie obliczeń.

36 Facebook dla programistów Włodzimierz KozłowskiFacebook jest nie tylko klasycznym serwisem społecznościowym, lecz także platformą umożliwiającą tworzenie własnych aplikacji. W artykule pokażemy jak przygotować i opublikować przykładową aplikację dla Facebooka współpracującą z serwisem aukcyjnym Al-legro.

BEZPIECZEŃSTWO42 Zabezpieczanie systemów ITAleksander JachowiczCoraz więcej słyszymy o ochronie bezpieczeństwa systemów in-formatycznych. Wynika to z tego, że pojawia się coraz więcej do-niesień prasowych o włamaniach na konta klientów banków lub o przypadkach wykradzenia dużej ilości danych osobowych. W ar-tykule Aleksander Jachowicz omawia Adaptive Access Manager fir-my Oracle.

TESTOWANIE OPROGRAMOWANIA46 Praca z zespołem testerów klientaKarolina ZmitrowczKarolina Zmitrowicz w artykule przedstawia studium przypadku do-tyczącego procesu testowania systemu bankowego w środowisku klienta. Zostaną przedstawione problemy wynikłe w trakcie organi-zacji testowania oraz czynności przedsięwzięte w celu ich elimina-cji i osiągnięcia satysfakcjonującego poziomu współpracy pomiędzy dostawcą oprogramowania a klientem.

06 AktualnościRafał Kocisz

35 Opis CDDuży zbiór materiałów od firmy nsoftware

BIBLIOTEKA MIESIĄCA12 Biblioteka LuabindRafał KociszLua oraz C++ bardzo ładnie uzupełniają się jako języki programowa-nia; niestety – ich łączenie przy pomocy podstawowego API oparte-go na czystym C jest delikatnie mówiąc – zniechęcające. Na pomoc przybywa Luabind: nowoczesna biblioteka C++, dzięki której łącze-nie Lua i C++ staje się proste i przyjemne.

PROGRAMOWANIE JAVA20 Spring Java Configuration ProjectHenryk KonsekTwórcy projektu Spring Framework spróbowali zminimalizować ilość konfiguracji XML poprzez przeniesienie źródeł definicji kompo-nentów do plików języka Java. Spring Java Configuration Project to alternatywa dla klasycznego podejścia do zagadnienia konfiguracji aplikacji internetowych, która równocześnie nie narusza wzorca In-version Of Control oraz ogólnej elegancji architektury naszej apli-kacji.

WARSZTATY28 CUDA się zdarzają, czyli programowanie GPGPUJacek PiekarskiW artykule dowiemy się co nieco o CUDA z praktycznego punktu wi-dzenia. Na konkretnym przykładzie zobaczymy, jak w prosty sposób

Miesięcznik Software Developer’s Journal (12 numerów w roku)jest wydawany przez Software-Wydawnictwo Sp. z o.o.

Dyrektor wydawniczy: Anna Adamczyk

Junior Market Manager: Anna Adamczyk

Senior Product Manager: Katarzyna Juszczyńska

Redaktor naczelny: Łukasz Łopuszański [email protected]

Kierownik produkcji: Marta Kurpiewska [email protected]

Projekt okładki: Agnieszka Marchocka

Skład i łamanie: Monika Grotkowska [email protected]

Wyróżnieni betatesterzy: R. Zacharczyk

Nakład: 6 000 egz.

03/2009

Adres korespondencyjny:Software-Wydawnictwo Sp. z o.o., ul. Bokserska 1, 02-682 Warszawa, Polskatel. +48 22 427 36 91, fax +48 22 224 24 59www.phpsolmag.org [email protected]

Dział reklamy: [email protected]

Obsługa prenumeraty: EuroPress Polska [email protected]

Dołączoną do magazynu płytę CD przetestowano programem AntiVirenKit firmy G DATA Software Sp. z o.o.

Redakcja dokłada wszelkich starań, by publikowane w piśmie i na towarzyszących mu nośnikach informacje i programy były poprawne, jednakże nie bierze odpowiedzialności za efekty wykorzystania ich; nie gwarantuje także poprawnego działania programów shareware, freeware i public domain.

Page 5: Software Developers Journal PL 03/2009

4 5

Rédacteur en chef : Marek Bettman [email protected]édacteurs : Aneta Cejmańska [email protected] Dudzic [email protected]éparation du CD : Aurox Core TeamMaquette : Anna Osiecka [email protected] : Agnieszka MarchockaTraduction : Iwona Czarnota, Aneta Lasota, Marie-Laure Perrotey, Grazyna WełnaBêta-testeurs : Thomas Bores, Tony Boucheau, Pascal Foulon, Pascal Miquet, Romain Lévy, Augustin Pascual, Julien Poulalion, Alain Ribault

Les personnes intéressées par la coopération sont priées de nous contacter : [email protected]

Abonnement : [email protected] : Marta Kurpiewska [email protected] : Monika Godlewska [email protected]é : [email protected]

Si vous êtes intéressé par l’achat de licence de publication de revues merci de contacter : Monika Godlewska [email protected] , tél : +48 (22) 887 12 66 fax : +48 (22) 887 10 11

nym wykonaniu jest zadaniem wyjątkowo kłopotliwym. Formalna weryfikacja przez model jest jedną z metod mających na celu wyka-zanie poprawności oraz niezawodności takich systemów.

FELIETON74 Aby wielu mogło na raz...Arkadiusz Merta

77 Najpierw celeArkadiusz Merta

www.sdjournal.org

Uszkodzone podczas wysyłki płyty wymienia redakcja.

Wszystkie znaki firmowe zawarte w piśmie są własności odpowiednich firm.Zostały użyte wyłącznie w celach informacyjnych.

Redakcja używa systemu automatycznego składu

Osoby zainteresowane współpracą prosimy o kontakt:[email protected]

Druk: ArtDruk

Wysokość nakładu obejmuje również dodruki. Redakcja nie udziela pomocy technicznej w instalowaniu i użytkowaniu programów zamieszczonych na płycie CD-ROM dostarczonej razem z pismem.

Sprzedaż aktualnych lub archiwalnych numerów pisma po innej cenie niż wydrukowana na okładce – bez zgody wydawcy – jest działaniem na jego szkodę i skutkuje odpowiedzialnością sądową.

54 Jakość czy jakoś to będzie?Zbigniew ZarzyckiOdpowiedź na pytanie czy tworzone oprogramowanie jest wystar-czająco dobre do uruchomienia produkcyjnego wymaga złożone-go procesu decyzyjnego. IBM Rational Quality Manager jest rozwią-zaniem, które może podjąć tę odpowiedzialną decyzję w oparciu o wiarygodne dane, dostarczane w czasie rzeczywistym.

58 WebAii – testowanie aplikacji ASP .NETPaweł WilkoszPrzyszłość należy do serwisów internetowych. Ogólna powszech-ność Internetu, świadczenie usług na odległość czy też rozwój urzą-dzeń mobilnych są argumentami umacniającymi Pawła w przekona-niu, iż to właśnie aplikacje webowe będą najbardziej kojarzone z in-żynierią oprogramowania za parę lat.

TECHNOLOGIE INTERNETOWE62 Zintegruj się z Internet Explorer 8Bartłomiej ZassJuż niedługo premiera kolejnej wersji przeglądarki firmy Microsoft, któ-ra otworzy przed programistami zupełnie nowe możliwości tworzenia rozszerzeń. W artykule przedstawione zostały podstawy programowa-nia tzw. akceleratorów, web slice’ów oraz search provider’ów, które po-zwalają zintegrować nasze strony z przeglądarką Internet Explorer 8.

NARZĘDZIA68 Weryfikacja przez model z narzędziem SPINSławomir MaludzińskiWspółczesne programy wykorzystują więcej niż jeden wątek prze-twarzania w celu zmniejszenia opóźnień bądź zwiększenia szybko-ści działania. Niestety, zapewnienie o ich bezbłędnym oraz efektyw-

Page 6: Software Developers Journal PL 03/2009

03/2009

Aktualności

6 www.sdjournal.org

Aktualności

7

Mniej telefonów z Windows MobileMicrosoft przewiduje, że w przyszło-ści coraz mniej telefonów komórkowych będzie wyposażonych w system operacyj-ny Windows Mobile. W związku z rosnącą konkurencją Microsoft chce przebudować i ulepszyć swój system. Będzie się to wiąza-ło z umieszczaniem WM na mniejszej licz-bie telefonów po to, aby móc skupić wysił-ki programistów i lepiej dostosować system do wymagań konkretnych urządzeń. Obec-nie Windows Mobile można spotkać na 140 modelach telefonów. System ten ma coraz liczniejszą konkurencję. Oprócz Symbiana jest jeszcze Android. Nowy system opera-cyjny przeznaczony do zastosowań mobil-nych, o nazwie WebOS, opracowuje rów-nież firma Palm.http://www.nytimes.com/

Microsoft-Yahoo!: reaktywacja?Temat przejęcia Yahoo! przez Microsoft wydawał się być sprawą zamkniętą, a tym-czasem okazuje się, że Microsoft poważ-nie myśli o dokończeniu transakcji, a przy-najmniej o zakupie części firmy związanej z wyszukiwaniem informacji w Internecie. Steve Ballmer powiedział w wywiadzie dla Financial Times, że właśnie teraz jest najlep-szy moment na sfinalizowanie tej sprawy. Obie firmy są bowiem w fazie ważnych zmian jeśli chodzi o kadrę zarządzającą. Qi Lu, były szef działu wyszukiwania w Yahoo! pracuje teraz jako dyrektor działań on-line w firmie Microsoft. Yahoo! szuka również nowego dyrektora zarządzającego; główne kandydatki to wywodząca się z Autodesk Carol Barz oraz Susan Decker, aktualna pre-zydent Yahoo!. Wypowiedź Ballmera może dziwić, zwłaszcza biorąc pod uwagę fakt, że jeszcze całkiem niedawno stanowczo odci-nał się on od pomysłów wznawiania oferty przejęcia Yahoo!.http://vnunet.com/

Rok 2009 pod znakiem phishinguJak zapowiada serwis ITPro powołując się na raport firmy McAfee, w 2009 roku wzrośnie ilość botnetów zbierających dane wykorzy-stywane do szantażowania lub sprzeda-ży na czarnym rynku. Z raportu wynika, że coraz częściej celem ataku stawać się będą przeglądarki jako element najsłabiej zabez-pieczony. Praktyki takie jak kradzież wła-sności intelektualnej lub dostęp do danych klientów stają się celem włamywaczy, nie tylko w firmach, ale także w gospodar-stwach domowych. Z tego powodu wiele instytucji zmuszonych będzie do zmiany polityk bezpieczeństwa wynikających z naruszania poufnych danych, których kra-dzieże zwykle bywają próbą zarobku albo ataków. Raport przewiduje ponadto wzrost wyłudzeń wywołany wykorzystywaniem bezrobocia w postaci różnego rodzaju wia-domości z fałszywymi programami szkole-niowymi i certyfikacyjnymi. Podobnie sytu-acja ma się w przypadku ofert rekrutacji z prośbami o CV i dane osobowe, rzekomych pożyczek czy pracy w domu.http://www.itpro.co.uk/

25 najniebezpieczniejszych błędów programistycznych

Ponad 30 organizacji związanych z rynkiem IT połączyło siły, aby pod kierownictwem ekspertów z Agen-

cji Bezpieczeństwa Narodowego USA (U.S. National Security Agency), Departamentu Bezpieczeństwa Krajowego Stanów Zjedno-czonych (Department of Homeland Securi-ty), firm Microsoft i Symantec, opracować dokument zawierający listę najbardziej nie-bezpiecznych błędów, jakie popełniają pro-gramiści. Na liście znajdziemy takie błę-dy jak: zostawianie „otwartych drzwi” dla różnych ataków, wysyłanie kluczowych in-formacji w postaci łatwego do odczytania czystego tekstu, zapisywanie haseł w ko-dzie programu. Dwa z wymienionych błę-dów, zdaniem SANS Institute, spowodo-wały, że ponad 1,5 miliona stron interneto-wych było wrażliwych na ataki. Celem, któ-ry przyświecał twórcom dokumentu, było

dostarczenie minimalnego zestawu wyma-gań, jakie powinno spełniać oprogramowa-nie, zanim trafi w ręce użytkowników. Nie-którzy widzą w nim również kartę przetar-gową, której można użyć przy negocjacjach między producentem oprogramowania a na-bywcą. Jest to też część większego zestawu dokumentów, który być może będzie uży-wany przez agencje stanowe do certyfikacji oprogramowania. Niestety, na chwilę obec-ną, perspektywy certyfikacji ograniczają się do projektów wykonywanych na zamówie-nie i prawdopodobnie oprogramowanie z certyfikatem bezpieczeństwa będzie przy-wilejem organizacji rządowych. Nie ma na razie mowy o przyznawaniu takich certy-fikatów szeroko dostępnym produktom, na przykład systemom Microsoft Windows.http://www.sans.org/

Słabość MD5 poważnym zagrożeniem dla SSL

Podczas odbywającej się w Niemczech 25 edycji Chaos Communication Con-gress, Alex Sotirov i Jacob Appelbaum

zaprezentowali sposób na stworzenie fałszywe-go certyfikatu SSL wykorzystując słabość al-gorytmu kryptograficznego MD5. W tym ce-lu wykorzystali moc klastra składającego się z 200 konsol PlayStation 3. Pomyślne wykona-nie ataku jest możliwe poprzez wykorzystanie tak zwanej kolizji MD5, która pozwala na iden-tyfikowanie różnych danych przez tą samą su-mę kontrolną. Grupa była w stanie wygenero-wać certyfikat imitujący jeden z tak zwanych root CA - głównych urzędów certyfikacji, któ-rych certyfikaty służące do podpisywania in-nych certyfikatów znajdują się na listach za-ufania wszystkich przeglądarek. Umożliwia to wygenerowanie i podpisanie certyfikatu wi-tryny, który będzie nieodróżnialny od orygi-nalnego. Po wejściu na tak spreparowaną stro-nę, przeglądarka automatycznie uzna ją za bez-pieczną - dane przesyłane będą poprzez połą-czenie szyfrowane (https), a na pasku stanu wyświetlana zostanie budząca zaufanie kłód-ka potwierdzająca autentyczność certyfika-tu. Według badaczy, połączenie kolizji MD5 z odkrytą parę miesięcy temu luką w systemie nazw DNS może mieć poważne konsekwen-cje. Użytkownicy będą mogli być przekierowy-wani na podrobione witryny banków, podczas

gdy przeglądarki nie zwrócą uwagi na ten fakt, gdyż witryny te identyfikować się będą rze-komo prawdziwymi certyfikatami SSL. Zda-niem Sotirova, urzędy certyfikacyjne muszą natychmiast zaprzestać wykorzystywać MD5 na rzecz SHA-1. Szczegóły ataku dostępne są na stronie autorów (http://www.win.tue.nl/hashclash/rogue-ca/). Bardziej szczegółowe in-formacje przesłane zostały producentom prze-glądarek internetowych. Również Microsoft w odpowiedzi na doniesienia o ataku opubli-kował biuletyn bezpieczeństwa. Póki co nie odnotowano prób wykorzystania luki, nale-ży mieć jednak na uwadze, że połączenie jej ze wspomnianą luką w systemie DNS mo-że stworzyć bardzo realne i poważne zagroże-nie. Na reakcje firm nie trzeba było długo cze-kać. Dla przykładu, VeriSign, jeden z najwięk-szych wystawców certyfikatów, ogłosił zaprze-stanie korzystania z podważonego przez Soti-rova i Appelbauma algorytmu hashującego w swoich certyfikatach na rzecz SHA-1. MD5 był jak dotąd wykorzystywany w certyfikatach RapidSSL. Jak zapewnia VeriSign, były to jedy-ne certyfikaty tej firmy podatne na atak. Wy-stawca obiecuje dodatkowo, że certyfikaty wy-stawione z hashem MD5 zostaną wszystkim klientom RapidSSL nieodpłatnie wymienione na nowe, wykorzystujące algorytm SHA-1.http://www.techit.pl/

Page 7: Software Developers Journal PL 03/2009

03/2009

Aktualności

6 www.sdjournal.org

Aktualności

7

Co drugi Polak korzysta z InternetuJak wskazują wyniki badań opubliko-wanych przez NetTrack przeprowadzo-nych przez MillwardBrown SMG/KRC, już prawie połowa Polaków (47,1%) posia-da dostęp do Internetu. Według badań za okres wrzesień - listopad 2008, 71,9 proc. osób mających dostęp do Interne-tu korzysta z niego codziennie, 17,5 proc. kilka razy w tygodniu, 5,2 proc. raz na tydzień, a 3,4 proc. kilka razy w miesiącu. Równy 1% badanych korzysta z Internetu raz na miesiąc lub rzadziej. Zdecydowa-na większość badanych (88 proc.) korzy-sta z Internetu w domu, jedna czwar-ta (23,7 proc.) w pracy, 9 proc. w szkole lub na uczelni, 6 proc. u znajomych, a 1 proc. w kawiarence internetowej lub w sklepie komputerowym. Najsilniejszą grupę internautów stanowią niezmiennie osoby w wieku pomiędzy 25 i 39 rokiem życia (36 proc.). Ponad połowa użytkow-ników (51 proc.) to mężczyźni korzysta-jący z Internetu na ogół powyżej 5 lat poprzez stałe łącze. Najczęściej odwie-dzana strona to Google. Ilość osób korzy-stających z Internetu w badanym okresie wzrosła o nieco ponad cztery punkty pro-centowe w stosunku do początku 2008 roku, kiedy liczba ta oscylowała w okoli-cach 45%. Oznacza to, że dynamika wzro-stu popularności Internetu spadła, w ciągu 2007 roku wzrosła o ok. 10%.http://www.millwardbrown.com/pl

Jak bardzo Google zanieczyszcza środowisko?Do ciekawych wniosków doszli auto-rzy wydanego jakiś czas temu rapor-tu, który dowodził, że Google uwalnia do atmosfery taką samą ilość dwutlenku węgla w dwóch wynikach wyszukiwania, ile jest potrzebne do zagotowania czaj-nika wody. Jak wyjaśnia Google, zanie-czyszczenie środowiska wynika z rosną-cego zapotrzebowania na energię elek-tryczną potrzebną do zasilenia centrów danych. Te są wymagane, aby odpowie-dzi na zapytania użytkowników pojawiały się w możliwie jak najkrótszym czasie. W ten sposób przez każdą sekundę połącze-nia z Internetem produkowanych zosta-je 0,2 grama dwutlenku węgla. Typowe wyszukiwanie trwa 0,2 sekundy, zapyta-nie jest wysyłane i przetwarzane przez serwery w kilka tysięcznych sekundy. Pojedyncze wyszukiwanie zużywa 1kJ (0,0003 kWh), średnia dzienna dla doro-słego człowieka to 8000 kJ. Dla przykła-du, ilość dwutlenku węgla emitowana przez samochód pokonujący trasę jed-nego kilometra - odpowiada tysiącowi zapytań. W 2008 roku Google zainwesto-wało 45 milionów dolarów na technolo-gie energetyczne, zaś rok wcześniej zaini-cjowała grupę Climate Savers Computing Initiative zajmującą się cięciem kosztów energii. Na przyszły rok gigant z Mounta-in View planuje redukcję emisji CO2 o 54 milionów ton rocznie.http://neowin.net/

Windows 7 i 2008 R2 Beta dostępne publicznie

Zgodnie z zapowiedziami Micro-soft udostępnił publicznie do po-brania wersję beta systemu Win-

dows 7 oraz jego serwerowego odpowiedni-ka: Windows Server 2008 R2. Od 8 stycznia 2009 roku obie bety mogli pobierać posiada-cze płatnych subskrypcji TechNet i MSDN oraz zaproszeni przez Microsoft uczestni-cy technicznego programu beta. Aktualnie Windows 7 i Windows Server 2008 R2 mo-gą pobrać wszyscy zainteresowani. Udostęp-niona kompilacja oznaczona jest numerem 7000.0.081212-1400. Warto więc zauwa-żyć, że jest to identyczny build, który wy-ciekł jeszcze przed świętami do sieci torren-towych, skompilowany 12 grudnia. Plik ob-razu płyty ISO z systemem Windows 7 w wersji 32-bitowej zajmuje 2,43 GB, wersja 64-bitowa jest nieco „cięższa” - waży 3,15 GB. Windows Server 2008 R2 występuje je-dynie w wersji 64-bitowej, jego obraz w edy-cji Standard zajmuje 2,78 GB, w edycji En-teprise 2,45 GB, zaś w edycji Web 2,66 GB. Klucze produktów do aktywacji wersji beta udostępniono na stronie pobierania. Pozwa-lają one na użytkowanie systemu do 1 sierp-nia 2009. W tym miejscu należy podkreślić, że jest to wczesna wersja beta z licznymi, czę-ściowo już znanymi, problemami. W rezulta-cie nie jest zalecana jej instalacja na kompu-terach wykorzystywanych do codziennej pra-cy. Przy okazji wypuszczenia bety Windows 7 pojawiły się nowe informacje odnośnie pre-miery nowego systemu rodem z Redmont. Microsoft jak dotąd stanowczo zapewniał, że premiera nowych Okienek odbędzie się jesz-cze w 2009 roku. Okazuje się jednak, że pro-ducent po cichu przygotowuje producentów

sprzętu na to, że wydanie nowego systemu może nastąpić nieco później. Podczas targów CES w Las Vegas Bill Veghte, jeden z mene-dżerów działu Windows w firmie Microsoft, mówił w wywiadzie dla CNET, że producen-ci sprzętu są przygotowywani na termin tego-roczny i przyszłoroczny. Wydamy system do-piero wtedy, gdy jego jakość będzie zadowalają-ca - tłumaczył Veghte. Dał również do zrozu-mienia, że na moment premiery może mieć wpływ sytuacja ekonomiczna, a konkretnie konieczność zaciskania pasa przez Microsoft i cięcia finansowe w marketingu. Co prawda, jak na razie są to tylko spekulacje i być mo-że żadnych opóźnień nie będzie, aczkolwiek – jeśli takowe się pojawią, to mogą być fa-talne w skutkach dla Microsoftu; zwłaszcza rozmowy z producentami sprzętu są w tym przypadku krytyczne. To między innymi na skutek wielokrotnego przekładania premiery Visty producenci sprzętu nie zdążyli na czas z przygotowaniem wielu sterowników, co wy-wołało falę niezadowolenia ze strony pierw-szych użytkowników.http://www.microsoft.com/poland;http://www.cnet.com/

Samsung będzie tworzył oprogramowanie w Warszawie

Ministerstwo Gospodarki i Sam-sung Electronics Polska infor-mują o rozpoczęciu wieloletnie-

go programu inwestycyjnego w naszym kra-ju. Program zakłada powstanie w Warsza-wie Telekomunikacyjnego Centrum Badań i Rozwoju. Centrum będzie największym i głównym ośrodkiem rozwoju oprogramowa-nia telekomunikacyjnego Samsung Group. Firma zainwestuje w Polsce blisko 25 milio-nów złotych i zatrudni 250 osób. Prace pro-wadzone będą głównie z myślą o oprogra-

mowaniu dla telefonów komórkowych typu smartphone i featurephone - znajdzie ono zastosowanie na platformach Windows, Li-nux i Symbian. Budżet państwa dodatkowo udzieli wsparcia finansowego w wysokości 3,7 mln złotych; Samsung łącznie wyda po-nad 42 mln złotych. Szacuje się, iż do koń-ca 2016 roku dzięki realizacji tej inwesty-cji do polskiego budżetu wpłynie około 23 mln złotych.http://www.mg.gov.pl/

Page 8: Software Developers Journal PL 03/2009

03/2009

Aktualności

8 www.sdjournal.org

Aktualności

9

Microsoft Tag zamieni długie linki na obrazkiPodczas targów CES 2009 Microsoft ogło-sił dostępność nowej usługi (na razie dzia-łającej w fazie beta): Microsoft Tag. Usługa ta umożliwia dostęp do zawartości on-line nie na podstawie tradycyjnych, długich linków, a specjalnych kodów graficznych. Kod (tag) to niewielki kwadrat z koloro-wym wypełnieniem tworzącym unikalny wzór. Sama technika nie jest nowa, a idea funkcjonowania tej technologii jest bardzo prosta - wystarczy uruchomić aplikację ska-nującą w telefonie lub urządzeniu przeno-śnym wyposażonym w kamerę i skierować obiektyw na kod. W odpowiedzi, po rozpo-znaniu kodu przez aplikację, od razu uru-chamiana jest przeglądarka i strona przy-pisana do zeskanowanego wzoru. Micro-soft Tag to jednak coś więcej niż tylko klon już istniejących usług tego typu, na przy-kład czarno-białych kodów QR. Propo-nowane przez Microsoft tagi korzystają z kolorowych wzorów i opierają się o bar-dziej nowoczesną technologię High Capa-city Color Barcode, opracowaną notabene przez badaczy z Microsoft Research. Dzięki zastosowaniu kolorów przestrzeń potrzeb-na do przechowania tej samej informacji jest mniejsza, więc tag można łatwiej zmie-ścić na stronach gazet, plakatach czy nawet koszulkach lub samochodach. Microsoft Tag może wypróbować każdy; aplikacja na telefon dostępna jest do pobrania bez-płatnie, na tej samej stronie można zna-leźć również testowy wzór do zeskanowa-nia. Możliwe jest również stworzenie wła-snego tagu. W fazie beta komercyjne wyko-rzystanie tagów jest dozwolone bez żad-nych opłat. http://www.microsoft.com/poland

ICANN podsumowuje rok 2008Organizacja ICANN (Internet Corporation for Assigned Names and Numbers), zaj-mująca się między innymi przyznawa-niem domen internetowych, opublikowa-ła raport na temat swojej działalności w roku 2008. Przygotowany raport koncen-truje się na osiągnięciach i postępie orga-nizacji w 2008 roku. Czołowe miejsce zaj-muje proces uwalniania domen najwyższe-go poziomu (TLD) i umożliwienie ich reje-stracji. Na dalszych pozycjach uplasowa-ły się: wprowadzenie międzynarodowych nazw domen oraz prace nad zorganizowa-niem konsultacji w sprawie mechanizmów zaufania pomiędzy podmiotami. Pozosta-ła część przedstawia szczegóły biograficz-ne każdego zarządu spółki i najważniej-sze plany organizacji. Prócz tego, dołączo-no raporty z działania departamentów kor-poracji, zawarto też krótką historię orga-nizacji z podziałem na ponad trzydzieści międzynarodowych publicznych spotkań, jako że ICANN obchodził w ubiegłym roku dziesięciolecie istnienia. Pełna treść rapor-tu jest dostępna na stronach ICANN (http://icann.org/en/annualreport/annual-report-2008-en.pdf) i liczy 133 strony.http://www.icann.org/

Plany Apple na 2009 rok

Phil Schiller na konferencji MacWorld Expo wygłosił keynote, w którym na-kreślił plany Apple na rok 2009. Głów-

ną nowością, o której głośno było w Interne-cie, jest nowy, 17-calowy MacBook Pro. Nie będzie on co prawda posiadał wymienialne-go akumulatora, ale jego wbudowana bateria ma wystarczać na 8 godzin pracy, tudzież na 7 - jeśli wykorzystywany będzie układ graficz-ny 9600GT zamiast 9400M. Niemożliwość samodzielnej wymiany baterii będzie rekom-pensowana przez opcję wymiany przez ser-wis. Nowy MacBook ma posiadać dysk twar-dy o pojemności 320 GB, 4 GB RAM i proce-sor 2,66 GHz. Cenę urządzenia ustalono na 2799$. Dostępna jest także wersja z matową matrycą, ostatnimi czasy bardzo rzadko spoty-kaną w notebookach, a dla wielu osób (szcze-gólnie dla programistów) wygodniejszą od matrycy błyszczących. Kolejna ważna wiado-mość to stopniowa rezygnacja z DRM w iTu-nes. Obecnie już 8 milionów utworów jest do-stępnych bez tego zabezpieczenia, do końca marca będzie to ponad 10 milionów. W od-powiedzi na żądania koncernów fonograficz-

nych zdecydowano się też na elastyczne ce-ny, najtańsze utwory będą dostępne już od 69 centów. Najnowsze utwory mają koszto-wać 1,29 dolara. Apple ogłosiło także betę ser-wisu iWork.com, wzorowany na Google Docs. Będzie on dostępny w ramach pakietu iWork 2009 za opłatą, której wysokość zostanie usta-lona później. Obecnie iWork 2009 dostępny jest w Apple Store za 79$ oraz w opcji „family pack” za 99$, gdzie nabywa się 5 licencji jed-nocześnie. Pakiet można też kupić za promo-cyjną cenę 49$ przy zakupie dowolnego kom-putera Mac.http://www.apple.com/

Renaissance – nowy interfejs OpenOffice.org

Pod koniec 2008 roku Frank Loeh-mann, lider projektu OOo User Expe-rience, publicznie ogłosił zainicjo-

wanie projektu „Renaissance”, którego ce-lem jest przeprojektowanie interfejsu pakie-tu OpenOffice.org. W rzeczywistości projekt ten jest nieco starszy, gdyż jego początki sięga-ją czasów OOoCon’u 2008, które miało miej-sce w Pekinie, we wrześniu. Do grupy OO.o UX dołączyli pracownicy firmy RedFlag, ci sa-mi, którzy zaprojektowali interfejs RedOffice-’a 4.0. Renaissance jest projektem długotermi-nowym i raczej niemożliwe jest, aby jakiekol-wiek zmiany zauważono w zbliżających się wydaniach. Projekt został podzielony na trzy fazy: badania, projekt i ocena. Aktualnie prace skupione są na pierwszym etapie. By móc le-piej zrozumieć potrzeby użytkowników, Ope-nOffice.org 3.1 będzie dostarczany wraz z rozszerzeniem „User Feedback”, którego zada-niem jest zapisywanie danych na temat użyt-kowania aplikacji OO i przesyłanie ich w ano-nimowej formie do zespołu projektowego. Na razie użytkownicy mogą swoje opinie wyra-zić za pośrednictwem internetowej ankiety. Wspomniane rozszerzenie będzie dostępne również dla OpenOffice.org w wersji 3.0.1,

jednak trzeba będzie je doinstalować ręcz-nie. Od momentu aktywacji dodatek zapisu-je wszelkie interakcje użytkownika z progra-mem, takie jak np. wywołania okien dialogo-wych, opcji menu, a także stosowanie skrótów klawiszowych. W drugim etapie drużyna Lo-ehmanna zajmie się modelowaniem struktury menu, tak by najczęściej używane opcje były bardziej dostępne. Loehmann przy okazji po-informował, iż projekt nie będzie ograniczać się do możliwości technicznych obecnego to-olkitu, a że zajmą się stworzeniem listy z wy-maganiami (technicznymi i użytkowników), a drużyna odpowiedzialna za rozwój progra-mu od strony wewnętrznej weźmie się za na-pisanie nowego szkieletu, który powinien w pełni sprostać oczekiwaniom. Misją projektu jest stworzenie takiego interfejsu użytkowni-ka, aby Openoffice.org stał się wyborem użyt-kownika nie tylko z potrzeby, ale i z pożąda-nia. Wszystkie informacje o postępach pro-jektu mają być udokumentowane na oficjal-nym blogu (http://ux.openoffice.org/blog/). Oso-by niezadowolone z obecnego interfejsu Ope-nOffice.org zaproszone są do partycypowania w tym przedsięwzięciu.http://linuxnews.pl/

Page 9: Software Developers Journal PL 03/2009

03/2009

Aktualności

8 www.sdjournal.org

Aktualności

9

Windows 7 wydajniejszy niż Vista oraz XPMimo że licencja dostępnych obecnie wersji beta Windows 7 zabrania wykony-wania testów wydajności, pierwsze porów-nania zaczynają się już pojawiać. Jedno z nich przygotował Adrian Kingsley-Hughes z ZDNet. Na dwóch platformach sprzęto-wych (AMD Phenom 9700 2.4GHz z kartą ATI Radeon 3850 i 4 GB RAM oraz Intel Dual Core E2200 2.2GHz z kartą GeForce 8400 GS i 1 GB RAM) przeprowadził on dwa-dzieścia trzy testy wydajności Windows XP, Visty oraz najnowszego biulda Windows 7 o numerze kompilacji 7000. Testy obejmo-wały typowe scenariusze - od instalacji sys-temu, przez jego uruchomienie, zamknię-cie, przeniesienie różnej wielkości plików między dyskami oraz przez sieć, kompreso-wanie danych, instalację Office 2007, ope-racje na dokumentach Word i Excel, wypa-lanie płyt oraz otwieranie dużych doku-mentów PDF. Wynik każdej operacji był mierzony i zestawiany wynikami osiągnię-tymi na tej samej platformie sprzętowej przez inne systemy. Rezultaty tych testów wypadły bardzo pomyślnie dla Siódem-ki - niemal w każdej kategorii jej wydaj-ność była większa niż Visty oraz Windows XP. Należy pamiętać że jest to nadal kom-pilacja testowa, której wydajność niemal zawsze (w przypadku produktów Micro-soft) jest gorsza od wydajności finalnego produktu.http://neowin.net/

Microsoft Boku zmieniony na KoduPierwsze informacje o projekcie Boku firmy Microsoft pojawiły się w zeszłym roku. Ten język programowania wizualnego przy-gotowywany przez giganta z Redmond zmienia teraz oficjalnie nazwę na Kodu. Jak ogłasza Microsoft, Kodu wystartuje na kanale Xbox LIVE Community Channel i (w skrócie) da zainteresowanym posiada-czom Xboksów 360 możliwość składania z gotowych klocków (jest ich ponad 200) własnych gier, wszystko przy użyciu stan-dardowego kontrolera do konsoli. Projekt zadebiutować ma na wiosnę bieżącego roku. Kodu określane jest jako gra o spo-rych możliwościach kreacyjnych. W minut kilka da się przy jego pomocy złożyć cał-kiem zaawansowany, wyjątkowy świat, a to wszystko przy pomocy ikonkowego interfejsu. Wszystko opiera się na zasa-dzie akcji i reakcji. Dla bardziej leniwych użytkowników Kodu oferuje możliwość modyfikacji dostępnych poziomów. „Zro-biliśmy wszystko, co możliwe, aby upew-nić się, że zabawa z Kodu jest nie tylko łatwa, ale również daje masę frajdy i wcią-gnie różnych odbiorców, w każdym wieku” - powiedział Matt MacLaurin, w głównej mierze odpowiedzialny za ten projekt. „Po-przez to, że interfejs Kodu jest tak intuicyj-ny i zapobiega najczęstszym błędom pro-gramistycznym, ułatwiamy wszystkim roz-koszowanie się magią tworzenia gier.”http://www.gamikaze.pl/

Ruby on Rails 3 = RoR 2 + Merb

Miły prezent przygotowali progra-mistom deweloperzy framewor-ków Ruby on Rails oraz Merb. Pro-

jekty te połączą się w jeden twór, wraz z wy-daniem RoR 3.0 w 2009 roku. Optymaliza-cje i rozszerzenia Merba zostaną przeporto-wane do Rails. Warto przypomnieć, iż frame-work Merb został stworzony przez Ezrę Zyg-muntowicza mniej więcej dwa lata temu, ja-ko lekka alternatywa dla Rails. Z czasem pro-jekt zaczął się rozrastać, a oba projekty zaczę-ły dzielić ze sobą coraz więcej kodu. Dewelo-perzy obu szkieletów programistycznych do-szli do wniosku, że razem zdziałają więcej niż osobno i że nie ma sensu powielać prac, gdy można działać razem. Istotą połączenia będzie przeniesienie części funkcji z Merba do Rails. Nie będzie całkowitego przepisania kodu, a ra-czej spokojne wdrażanie zmian i ulepszanie te-go, co w Rails nie jest idealne. Rdzeń Rails po-zostanie, jednak programiści połączonych pro-jektów postarają się umożliwić uruchamianie go w uszczuplonej wersji, bez zbędnej funk-cjonalności. Również optymalizacje wydajno-

ści z Merb zostaną przeniesione do Rails. Rails stanie się bardziej agnostyczne pod względem wyboru (narzucania użytkownikowi) techno-logii. Aktualnie stosowane rozwiązania będą wykorzystywane domyślnie (np. Active Re-cord), ale łatwe będzie wymienienie ich na al-ternatywne odpowiedniki preferowane przez programistę (np. Sequel/Data do mapowa-nia obiektowo-relacyjnego, Mapper czy jQu-ery dla Ajaksa). Nastąpi też powrót do idei ry-gorystycznego API. Zbyt wiele wtyczek prze-staje działać po aktualizacji, co jest wynikiem słabego zaakcentowania, które części API Ra-ils są stabilne, a które mogą być w najbliższej przyszłości modyfikowane. Samo Rails 3 nie będzie kompatybilne wstecz, aczkolwiek de-weloperzy postarają się w miarę możliwości (i rozsądku) ułatwić migrację projektów zbu-dowanych na straszych wersjach RoR. Bardziej szczegółowe informacje na temat połączenia obydwu frameworków można znaleźć na de-dykowanej stronie http://rubyonrails.org/merb.http://linuxnews.pl

Emotikona zastrzeżonym znakiem towarowym

Oleg Teterin, rosyjski biznesmen i prezes firmy telekomunikacyjnej Superfone, zarejestrował w rosyj-

skim urzędzie patentowym znak towarowy w postaci... emotikony uśmiechu, czyli se-kwencji znaków dwukropka, łącznika i za-mykającego nawiasu: :-). Dlaczego Teteri-nowi zależało na zastrzeżeniu emotikony? Biznesmen zapewnia, iż nie zamierza ści-gać nadawców SMSów i e-maili, czy też użyt-kowników komunikatorów. Będzie jednak zwracał uwagę, czy firmy nie wykorzystują jego zastrzeżonego znaku do celów komer-cyjnych. Aby móc posługiwać się emotiko-ną będzie trzeba zapłacić i nabyć od Teteri-na roczną licencję. Ile konkretnie będzie ta-ka licencja kosztować - tej informacji nieste-ty biznesmen nie chce jeszcze zdradzić, jak mówi, kwota będzie liczona w dziesiątkach tysięcy dolarów. Warto nadmienić, że za-strzeżone są również znaki pochodne two-rzone na podstawie oryginału, czyli takie jak na przykład :) czy ;). Jak nietrudno się domy-ślić, większość internautów na wiadomość o „przywłaszczeniu” przez Teterina emotiko-ny reaguje z oburzeniem. Podstawy prawne

decyzji urzędu patentowego w tej sprawie są bardzo szeroko podważane przez świa-towych komentatorów. Faktycznie, trudno uwierzyć, że wykorzystywana od lat przez miliony ludzi na całym świecie sekwencja znaków została teraz własnością jednej oso-by. Niektórzy zwracają uwagę, że to niebez-pieczny precedens, inni mówią po prostu: absurd. Czas pokaże, czy Teterin będzie w stanie zarobić cokolwiek na swoim kontro-wersyjnym pomyśle. Bez względu jednak na to, czy znak emotikony faktycznie należy do rosyjskiego biznesmena, czy nie - za pionie-ra uśmieszków nadal uważa się Scotta Fahl-mana, amerykańskiego naukowca z Carnegie Mellon University, który w 1982 roku po raz pierwszy użył znaku :-) w wysłanej przez sie-bie wiadomości.http://news.bbc.co.uk/

Page 10: Software Developers Journal PL 03/2009

03/2009

Aktualności

10 www.sdjournal.org

Aktualności

11

Android na netbookachWygląda na to, że opracowany przez Google dla telefonów komórkowych system opera-cyjny Android sprawdzi się także na netbo-okach. Dwóch współpracowników serwisu VentureBeat spędziło cztery godziny kom-pilując Androida na netbooka Asus EEEPC 1000H. Wynik ich eksperymentu był bardzo dobry. Działały prawie wszystkie urządze-nia, w tym karta graficzna, dźwiękowa oraz WiFi. Było to możliwe dzięki temu, że Andro-id jest oparty na Linuksie, który posiada ste-rowniki do wielu urządzeń. Niedawno także Dima Zavin, programista z Google, ogłosił, że udało mu się przeportować Androida na urządzenie Asus EeePC 701. Doniesienia te spowodowały, że zaczęto głośno mówić o wejściu Androida na rynek nie tylko netbo-oków, ale także notebooków, a nawet desk-topów. Netbooki z Androidem mogłyby się pojawić nawet w ciągu trzech miesię-cy. Przewiduje się jednak, że Android zyska większą popularność dopiero w 2010 roku. Pomóc ma mu w tym przeglądarka Google Chrome, mogąca stanowić platformę do uruchamiania wielu aplikacji.http://venturebeat.com/

Microsoft planuje redukcję zatrudnieniaWygląda na to, że plotki o tym, jakoby w obliczu globalnego kryzysu Microsoft miał zacząć redukować zatrudnienie, przestają być plotkami - serwis Fudzilla powołując się na wewnętrzne źródła w korporacji infor-muje, że pracownicy Microsoftu zostali już poinformowani o planowanych na począt-ku 2009 roku zwolnieniach na stosunkowo dużą skalę. Obecnie Microsoft zatrudnia mniej więcej 90 tys. ludzi na całym świecie i z tego co ustalił serwis Fudzilla, zwolnienia mogą objąć aż 15 tys. stanowisk - to niemal 17% całego stanu zatrudnienia, więc zde-cydowanie niemało. Póki co nie wiadomo jeszcze, które jednostki organizacyjne lub regiony zostaną najmocniej dotknięte, nie-oficjalnie wskazuje się na dział MSN oraz struktury regionu EMEA (Europe, Middle East and Africa), w skład których wchodzi także polski oddział.http://neowin.net/

30 lat więzienia dla ukraińskiego hakeraTurecki sąd skazał ukraińskiego hakera na 30 lat pozbawienia wolności i grzywnę w wyso-kości ok. 23 tysięcy dolarów. Maksym Jastrem-ski został skazany za dokonanie serii ataków na dwanaście tureckich banków i liczne mal-wersacje finansowe. Haker został aresztowa-ny 17 miesięcy temu w Antalii, śródziemno-morskiej prowincji Turcji. Wyrok jest surowy, choć dotyczył wyłącznie czynów popełnio-nych na terenie Turcji. Jastremski jest jednak dobrze znany nie tylko tamtejszym władzom. Stany Zjednoczone podejrzewają, że to wła-śnie on stał w 2007 roku za głośnymi atakami na TJX, operatora sieci sklepów w USA, które doprowadziły do ujawnienia danych kart kre-dytowych klientów. Śledztwo w tej sprawie nadal trwa.http://www.cnet.com/

Microsoft zapłaci 1,5 mld USD za Vista Capable?

Półtora miliarda dolarów, tyle może wy-nosić kara, jaką zapłacić będzie musiał Microsoft w wyniku głośnego procesu

dotyczącego kampanii marketingowej Win-dows Vista Capable. W skierowanym do sądu apelacyjnego wnioskowi przeciwko Microsoft, konsumenci zarzucają, że w ramach rzekome-go wprowadzania w błąd klientów dzięki za-niżaniu wymagań sprzętowych systemu certy-fikowane były komputery, które raczej nie po-winny posiadać loga świadczącego o zgodności sprzętu z najnowszym systemem. Nie umożli-wiło to obsługi pozostałych edycji Visty z wy-jątkiem Home Basic, między innymi graficz-nego interfejsu użytkownika Aero. To z ko-lei Microsoftowi pozwoliło wzbogacić się po-

przez zwiększenie popytu na słabsze konfigu-racje. O orientacyjne oszacowanie wysokości dochodów uzyskanych przez Microsoft wsku-tek wyniku sprzedaży Windows XP na kom-puterach z logiem Vista Capable zamiast Vi-sta Premium poproszony został Leffler Ke-ith. Uznał, że zysk ten wyniósł 1,505 miliarda USD. Jeśli powodom uda się przekonać sąd, że Microsoft faktycznie wyrządził szkodę w wy-niku akcji, może podjąć decyzję o ocenie rze-czywistej szkody współmiernie do wspomnia-nej kwoty. Inny scenariusz przewiduje nałoże-nie na firmę kary w wysokości trzykrotności ocenianej kwoty szkód.http://www.theinquirer.net/

Nokia wyda Qt 4.5 na licencji LGPL

Nokia podjęła decyzję o złagodzeniu licencjonowania biblioteki Qt. Naj-bliższe wydanie oznaczone nume-

rem 4.5 będzie dostępne między innymi na licencji LGPL. Rok temu, kiedy Nokia kupi-ła Trolltech, firmę rozwijającą Qt i czerpią-cą zyski z jej wolno-komercyjnej licencji (Qt dostępne było za darmo na GPL, ale tylko dla niekomercyjnych projektów udostępnio-nych na tej samej licencji, firmy sprzedające software musiały zakupić komercyjną licen-cję biblioteki), wszyscy zastanawiali się, w ja-kim kierunku nowy właściciel pokieruje roz-wojem Qt. Teraz widać już, że ten kierunek to

otwartość. Nokia planuje wydanie Qt 4.5 na licencji LGPL, w celu zwiększenia zaintereso-wania tą biblioteką zarówno świata open sour-ce, jak i komercyjnego. Licencja LGPL umoż-liwia używanie kodu do komercyjnych celów bez opłat licencyjnych (choć zastosowanie do-datkowo biblioteki na GPL wymusza stosowa-nie dla projektu licencji GPL). Krok taki wy-nika z faktu, iż Nokia nie musi zarabiać na Qt tak, jak musiał robić to Trolltech. W jej inte-resie leży raczej zwiększenie popularności tej platformy, a zmiana licencji na pewno otwo-rzy dla Qt nowe segmenty rynku.http://linuxnews.pl

Szwedzka Partia Piratów w Europarlamencie?

Kiedy ponad trzy lata temu startowa-ła Szwedzka Partia Piratów, więk-szość ludzi traktowała ją jako żart

w stylu Polskiej Partii Przyjaciół Piwa. Oka-zuje się jednak, że czasy się zmieniły - ostat-nie badania opinii publicznej pokazują, że 21% Szwedów rozważa głosowanie na Par-tię Piratów w nadchodzących wyborach do Parlamentu Europejskiego. Wśród młodych ludzi (18-29) wynik ten jest bezprecedenso-wy - aż 55%. Partia rośnie też w siłę - w cią-gu ostatniego kwartału liczba jej członków wzrosła o 50% i przekroczyła liczebność Par-tii Zielonych, która ma obecnie 19 miejsc w

szwedzkim parlamencie. Bardzo dynamicz-nie rośnie też zainteresowanie i poparcie dla jej działań, w czym kluczową rolę odgrywa naturalnie Internet. Jak twierdzi lider Partii Piratów, Rick Falkvinge, miejsce w Europar-lamencie jest obecnie jak najbardziej w za-sięgu - potrzeba do tego 100 tys. szwedzkich głosów. Czy się uda – okaże się w czerwcu 2009 roku. Jeśli tak, będzie to wydarzenie całkowicie bezprecedensowe - po raz pierw-szy realna siła polityczna ukształtowałaby się w odpowiedzi na potrzeby społeczności in-ternetowej.http://torrentfreak.com/

Page 11: Software Developers Journal PL 03/2009

03/2009

Aktualności

10 www.sdjournal.org

Aktualności

11

Porządki w licencjonowaniu dla organizacji non-profitKoniec roku, czas więc na podsumowania i porządki - również w firmie Microsoft, która przeprowadza audyt wykorzystania licencji grupowych w obniżonej cenie dla organiza-cji non-profit, czyli w ramach programu Aca-demic Volume. O skali tych porządków bole-śnie przekonały się... domy spokojnej sta-rości w Australii. Microsoft zakwestionował prawo do korzystania z programów licen-cjonowania Academic przez 1300 instytu-cji prowadzących 2900 placówek w Austra-lii. Korporacja twierdzi, że tego typu insty-tucje nie mieszczą się w definicji organiza-cji uprawnionych do korzystania z progra-mu. Sprawa jest o tyle poważna, że instytu-cje te z rozwiązań Microsoftu korzystają od lat, nic dziwnego więc, że cała infrastruktu-ra zbudowana jest w oparciu o takie produk-ty jak Office, SharePoint i SQL Server. Teraz, by dalej z nich korzystać, trzeba zapłacić za licencje komercyjne - cztery razy więcej, niż dotychczas. Jest również dobra wiadomość - Microsoft przygotowuje specjalny program licencjonowania dla organizacji charytatyw-nych i non-profit, więc jeśli firma stanie na wysokości zadania i upora się szybko z przygotowaniami, być może w przypadku australijskich domów spokojnej starości i innych tego typu instytucji skończy się tylko na dyskusjach. Poza programami licencjono-wania grupowego Microsoft systematycznie przekazuje podmiotom non-profit opro-gramowanie również w formie zwyczajnej darowizny - w mijającym roku jego wartość wyniosła ponad 22 miliony dolarów.http://www.australianit.news.com.au/

22 korporacje pozwane o naruszenie patentu22 korporacje, głównie wydawcy opro-gramowania chroniącego przed wirusa-mi i złośliwym oprogramowaniem, zosta-ły pozwane przez Information Protection and Authentication of Texas (IPAT). Według IPAT, produkty pozwanych firm naruszają patenty, których jest właścicielem. Wśród pozwanych znaleźli się tacy giganci jak: Microsoft, Symantec, CA, Kaspersky, Novell, AVG czy Trend Micro. Konkretnie chodzi o dwa patenty: 5311591 zarejestrowany w maju 1994 oraz 5412717 zarejestrowany w maju 1995, oba zgłoszone przez Addi-sona M. Fischera i następnie kupione przez IPAT. Pierwszy z wymienionych patentów to innowacja dająca użytkownikowi kon-trolę nad zachowaniem aplikacji przy neu-tralizowaniu działania złośliwych progra-mów (malicious software). Drugi dotyczy zastosowania unikalnych identyfikatorów numerycznych (hash) do upewniania się, że działanie aplikacji (na przykład tarczy anty-wirusowej) nie zostało zablokowane. Jak na razie żadna z pozwanych firm nie odpowie-działa na oskarżenia. Nie wiadomo też, czy IPAT domaga się, poza prawnym nakazem zakończenia działań naruszających patent, odszkodowania lub rekompensaty.http://www.arstechnica.com/

Internet lepszym źródłem aktualności niż prasa

Amerykańska organizacja The Pew Re-search Center for the People & the Press przeprowadzając ostatnie ba-

dania dotyczące czytelnictwa odkryła, że po raz pierwszy Internet wyprzedził prasę dru-kowaną jeśli chodzi o źródła pozyskiwania ak-tualności. Badania przeprowadzono między 3 a 7 grudnia 2008 roku na grupie 1489 doro-słych Amerykanów. Większość pytań dotyczy-ła reakcji na najważniejsze wydarzenia roku, część jednak sprawdzała, skąd respondenci do-wiedzieli się o nich. Okazało się, że 40% ludzi aktualności krajowe i światowe czerpała z In-ternetu - to znaczny skok względem analogicz-nego badania w roku 2007, kiedy podobnie odpowiedziało jedynie 24% badanych. Nie-kwestionowanym liderem okazała się nadal te-lewizja, jednak i dla niej zapaliło się już ostrze-gawcze światło - w badaniu ograniczającym grupę respondentów wyłącznie do młodych

ludzi, telewizja znacznie traci już na swoim znaczeniu i jako źródło pozyskiwania infor-macji pozycjonowana jest już na równi z Inter-netem. Warto zauważyć, że niektóre komen-tarze do tych badań ostrzegają, że nie ma z cze-go się cieszyć. O ile bowiem w oczach wielu ludzi Internet jest idealnym medium szybko i sprawnie identyfikującym najważniejsze wy-darzenia, o tyle mało które witryny webowe mają zasoby niezbędne do przeprowadzania wnikliwych dziennikarskich analiz i śledztw, jakie wykonywanie są codziennie przez do-świadczonych redaktorów dużych gazet - to, że treści internetowe są za darmo, odbija się niestety na ich jakości. Bez wątpienia jednak media internetowe bardzo szybko uczą się i dzięki rosnącemu znaczeniu jako atrakcyjny nośnik reklamy zyskują odpowiednie środki, by tą jakość poprawiać.http://people-press.org/

Apple, Google i Microsoft pozwani za naruszanie patentu

Trzej giganci rynku IT, Apple, Google i Microsoft zostali podani do sądu za złamanie patentu firmy Cygnus Sys-

tems. Chroniona patentem technologia znaj-duje się w produktach takich jak: Windows Vista, Internet Explorer 8, Google Chrome, Mac OS X czy iPhone. Firma Cygnus Systems uważa, że wspomniane systemy i aplikacje używają chronionej funkcji podglądu plików, która pozwala użytkownikowi na podgląd za-wartości dokumentu bez otwierania go. Spół-ka obrała sobie za cel liderów rynku informa-

tycznego, sprawdza jednak możliwe narusza-nie patentu w produktach innych firm i roz-waża skierowanie pozwu także przeciwko nim. Sporny patent został pierwotnie zgło-szony w 2001 roku, ale dopiero teraz Ame-rykańskie Biuro Patentowe przyznało go fir-mie. Jeśli sprawa zostanie rozstrzygnięta ne-gatywnie dla Apple, Google i Microsoft, zo-bowiązani będą zapłacić odszkodowanie i opłaty licencyjne.http://www.edibleapple.com/

Rok 2009 rokiem Linuksa na biurkach?

Jak donosi serwis Bankier.pl, rok 2009 może się stać rokiem Linuksa. Ktoś mo-że zapytać – a co dziennikarze takiego

serwisu jak Bankier.pl mogą wiedzieć o tech-nologii? Na technologii być może się nie zna-ją, ale liczyć potrafią bardzo dobrze. Przyczy-ną sukcesu Linuksa w 2009 roku mają być netbooki – te małe, nieużyteczne i niedoce-niane komputerki sprzedawane w milionach egzemplarzy, na których producenci bardzo często instalują Linuksa. Bankier.pl powołuje się na prognozy sprzedaży netbooków w 2009

roku, które mówią o sprzedaży do 8 milionów sztuk a w roku 2012 ma być sprzedanych po-nad 50 milionów netbooków. Sprzedaż netbo-oków niewątpliwie przyczyni się do populary-zacji Linuksa, ale czy użytkownicy będą chcie-li go używać, i czy będą z niego zadowoleni? Z danych udostępnionych niedawno przez firmę MSI wynika, że ma ona czterokrotnie więcej zwrotów netbooków z Linuksem niż z Windows.http://www.bankier.pl

Page 12: Software Developers Journal PL 03/2009

03/200912

Biblioteka miesiącaBiblioteka Luabind

www.sdjournal.org 13

Język C++ jest to niewątpliwie potężny język programowania, aczkolwiek – posiada pew-ne ograniczenia. Przekonał się o tym zapew-

ne niejeden programista C++, któremu przyszło popracować z bardziej dynamicznymi językami programowania (np. Perl, Python czy Ruby). C++, który oferuje niezwykle bogaty wachlarz mechani-zmów abstrakcji operujących na etapie kompilacji (chociażby potężny mechanizm szablonów), po-zostawia swoim użytkownikom wyraźny niedo-syt w zakresie bardziej zaawansowanych mechani-zmów działających w czasie wykonania programu. Brakuje chociażby mechanizmu refleksji czy moż-liwości wygenerowania i wykonania w locie frag-mentu kodu. Trudno powiedzieć, że są to wady C++. Taki stan rzeczy wynika z filozofii języka, a w zamian użytkownicy C++ otrzymują inne, potęż-ne możliwości. Na szczęście, siła języka C++ pole-ga również na tym, iż brak niektórych jego właści-wości można sobie zrekompensować korzystając z dedykowanych rozwiązań bibliotecznych.

W niniejszym artykule przedstawię w jaki spo-sób można łączyć C++ ze skryptowym językiem Lua wykorzystując bibliotekę Luabind. Dzięki ta-kiemu zabiegowi przed programistą C++ otwie-ra się ocean nowych możliwości: może on na eta-pie wykonania programu uruchamiać skrypty za-

pisane w zewnętrznych plikach, a także generować i wykonywać skrypty zapisane w pamięci. Co wię-cej, w przypadku Lua istnieje możliwość ekspono-wania konstrukcji (np. zmiennych, funkcji, czy klas) opisanych w C++ i odwoływanie się do nich z poziomu skryptów. Ogólny zarys tego jakie moż-liwości i zarazem, jakie zagrożenia wiążą się z wy-korzystaniem skryptów przedstawiłem w ramce Skrypty: zastosowania.

Struktura niniejszego artykułu jest następują-ca: na początku zaprezentuję podstawowe mecha-nizmy integracji obydwu języków (uruchamianie skryptów, eksponowanie konstrukcji) w oparciu o podstawowe API udostępnione w czystym C. W dalszej kolejności zaprezentuję możliwości bi-blioteki Luabind. Podejście takie zastosowałem z dwóch powodów: po pierwsze – przedstawienie możliwości Luabind na tle mechanizmów pod-stawowych pozwala wyraźnie wyeksponować si-łę tej biblioteki, a po drugie – daje ono pełniejszy obraz tematu, szczególnie dla Czytelników nie-obeznanych z tym zagadnieniem. Osoby, które dobrze znają podstawowe mechanizmy integracji Lua i C++, a chciałyby zapoznać się z możliwościa-mi prezentowanej biblioteki, mogą rozpocząć lek-turę niniejszego artykułu od podpunktu Luabind nadciąga z odsieczą!

Pierwszy skryptZgodnie z tradycją, nasze rozważania rozpocznie-my klasycznym przykładem typu Witaj Świecie! Tym razem postaramy się jednak, aby powitalny komunikat został wyświetlony z poziomu skryp-

tu Lua, który z kolei uruchomimy z programu na-pisanego w C++.

Pierwszą czynnością, którą należy wykonać, to konfiguracja środowiska pracy. Osoby korzysta-jące z pakietu Visual Studio C++ zapraszam do przestudiowania zawartości ramki Szybki Start: Lua. Użytkownicy alternatywnych środowisk de-weloperskich w ramce W sieci znajdą odnośniki do stron, na których można znaleźć odpowiednie in-strukcje postępowania odnośnie konfiguracji.

Gdy środowisko pracy jest już gotowe, należy wpisać i skompilować program przedstawiony na Listingu 1.

Rozważmy krok po kroku, co się dzieje we wspomnianym programie. Na początek, dołącza-my odpowiednie nagłówki. Z punktu widzenia in-tegracji naszego programu ze skryptami Lua, uwa-gę należy zwrócić na nagłówek lua.hpp. Kolejna, interesująca nas instrukcja znajduje się wewnątrz funkcji main():

lua_State* pL = lua_open();

W powyższym wywołaniu tworzony jest obiekt reprezentujący kontekst wywołania naszego skryptu (bądź skryptów), będziemy ją przeka-zywać do wszystkich funkcji wywoływanych z

Biblioteka Luabind

Lua oraz C++ bardzo dobrze uzupełniają się jako języki programowania; niestety – ich łączenie przy pomocy podstawowego API opartego na czystym C jest delikatnie mówiąc – zniechęcające. Na pomoc przybywa Luabind: nowoczesna biblioteka C++, dzięki której łączenie Lua i C++ staje się proste i przyjemne.

Dowiesz się:• W jaki sposób odbywa się łączenie języków

Lua i C++ na bazie podstawowego API oparte-go na czystym C;

• W jaki sposób można usprawnić ten proces przy pomocy biblioteki Luabind;

• W jaki sposób języka Lua może stanowić do-pełnienie języka C++.

Powinieneś wiedzieć:• Jak programować w języku C++.

Poziom trudności

Wygodne łączenie języków Lua i C++

Rysunek 1. Koncepcja indeksowania wirtualnego stosu biblioteki Lua

���

���

���

���

���

�����������������

��

��

��

��

��

Page 13: Software Developers Journal PL 03/2009

03/200912

Biblioteka miesiącaBiblioteka Luabind

www.sdjournal.org 13

biblioteki Lua. W kolejnych pięciu instrukcjach (luaopen _ *) aktywujemy dostęp do standardo-wych bibliotek języka Lua. Sercem omawianego przykładu jest instrukcja if, w której wywołuje-

my funkcję luaL_dofile(), przekazując do niej dwa parametry: kontekst oraz nazwę pliku, w którym zapisany jest skrypt do uruchomienia. Je-śli wartość zwrócona ze wspomnianej funkcji jest

różna od zera, to oznacza, że uruchomienie skryp-tu z jakiegoś powodu nie powidło się; w takim przypadku nasz program wypisuje odpowiedni komunikat o błędzie.

To czego jeszcze nam brakuje to zawartość skryptu hello.lua., która wygląda następująco:

print( "Hello from Lua!" )

Po uruchomieniu opisanego wyżej przykładu, program powita nas przyjaznym komunikatem: Hello from Lua!

W tym miejscu należałoby opisać nieco szerzej możliwości języka Lua. Dogłębne przedstawianie tego tematu wykracza poza ramy niniejszego arty-kułu. Żądnych wiedzy Czytelników zapraszam do przestudiowania treści ramki Lua: przegląd możli-wości języka (tutaj można znaleźć podstawowe in-formacje o składni i konstrukcjach stosowanych w Lua), oraz W sieci – gdzie umieściłem odnośniki do bardziej szczegółowych materiałów edukacyj-nych w tym temacie.

Gorąco zachęcam Czytelników do poekspery-mentowania z językiem Lua; można do tego wy-korzystać lekko zmodyfikowaną wersję programu z Listingu 1. Zamiast oryginalnej instrukcji if, na-leży wpisać:

if ( int error = luaL_dofile( pL, argv[ 1 ] )

!= 0 )

Pozwoli to wczytywać dowolne skrypty przez podawanie odpowiednich ścieżek w postaci argu-mentów wiersza poleceń przy kolejnych wywoła-niach programu.

Skrypty: zastosowaniaSkryptowanie (ang. scripting) jest dość modnym tematem wśród programistów C++; szczególnie często słyszy się o nim w kontekście produkcji gier. Czytelnicy, którzy mieli okazję grać w takie tytuły jak Far Cry, Crysis, Grim Fandango, Escape from Monkey Island, Heroes of Might and Magic V, World of Warcraft czy Wit-cher – chcąc nie chcąc mieli do czynienia ze skryptami Lua. Lista gier wykorzystujących ten, bądź alterna-tywne języki skryptowe jest bardzo długa. Ze skryptów korzysta też wiele aplikacji użytkowych (np. Ado-be Photoshop Lightroom, Celestia, Monotone). W tym miejscu postaram się odpowiedzieć w skrócie na py-tanie: dlaczego warto rozważyć wykorzystywanie skryptów w programach – szczególnie w tych, któ-re powstają na bazie kompilowanych języków programowania (takich jak C++)? Kluczem do odnalezie-nia odpowiedzi na przedstawione wyżej pytanie może być hasło data driven developemnt. Idea tworzenia programowania sterowanego danymi zakłada, iż oprogramowanie powinno być tworzone w taki spo-sób, aby jego konfiguracja odbywała się możliwie jak najczęściej na bazie danych zapisanych w zewnętrz-nych, łatwo dostępnych repozytoriach (np. w plikach tekstowych). W myśl tej zasady, wszelkie stałe kon-trolujące zachowanie programu oraz wybrane elementy logiki powinny być zdefiniowane poza progra-mem, w taki sposób aby było je można łatwo modyfikować. Podstawowe zalety takiego podejścia to:

• Oszczędność czasu (łatwiej jest modyfikować zachowanie programu; nie trzeba za każdym razem przebudowywać źródeł),

• Zwiększenie wydajności pracy,• Obniżenie kosztów pracy (wyeksponowane aspekty działania programu mogą być dostrajane

przez mniej wykwalifikowanych pracowników, np. testerów),• Zwiększenie kreatywności (łatwiej i szybciej możne wdrażać i testować nowe pomysły),• Zwiększenie rozszerzalności i elastyczności tworzonego oprogramowania,

Języki skryptowe pokroju Lua nadają się bardzo dobrze do opisanych wyżej celów; można je w relatywnie prosty sposób łączyć z językami kompilowanymi, są stosunkowo nietrudne do nauki (np. Lua można bez problemu użyć do tworzenia prostych plików konfiguracyjnych), a jednocześnie – gdy zachodzi taka po-trzeba – oferują pełną moc języka programowania. Kluczowe jest również tworzenie dwustronnych wią-zań pomiędzy językami. Chodzi o to, aby mieć zarówno możliwość wywoływania funkcji zdefiniowanych w skrypcie z poziomu języka kompilowanego, jak i odwrotnie. Np. częstą praktyką przy tworzeniu gier jest eksponowania interfejsów wybranych modułów, tak aby zachowanie rozgrywki można było łatwo kon-trolować z zewnątrz. Jak wszystkie narzędzia, również mechanizm skryptowania może być nadużywa-ny. Przy projektowaniu systemu korzystającego ze skryptów trzeba bardzo dokładnie przemyśleć, któ-ra część logiki zostanie wyeksponowana. Niestety, często zdarzają się przypadki, kiedy rozentuzjazmo-wani programiści idą na przysłowiową całość i w rezultacie prawie cała aplikacja tworzona jest w języ-ku skryptowym. To z kolei może odbić się negatywnie na wydajności; skrypty też w większości przypad-ków o wiele trudniej jest debugować (chociażby w porównaniu do programu pisanego w C++).

Szybki start: LuaAby rozpocząć pracę z biblioteką Lua należy wykonać następujące czynności (uwaga: poniższa instrukcja odnosi się do użytkowników pakietu Visual Studio w wersji 7 oraz wyższych):

• Pobrać binarną dystrybucję biblioteki Lua (patrz: ramka W Sieci) i rozpakować ją do wybra-nego katalogu (LUA_ROOT),

• Stworzyć w Visual Studio nowy projekt C++• W ustawieniach projektu (C/C++ -> General) ustawić dodatkowy katalog do wyszukiwania

plików nagłówkowych: LUA_ROOT/include,• W ustawieniach projektu (Linker -> General) ustawić dodatkowy katalog do wyszukiwania bi-

bliotek: LUA_ROOT.• W ustawieniach projektu (Linker -> Input) dodać bibliotekę lua5.1.lib,• Skopiować plik LUA_ROOT/lua5.1.dll w miejsce rozpoznawane przez aplikację (np. C:\

Windows\System32).

Szybki start: LuabindAby rozpocząć pracę z biblioteką Luabind należy wykonać następujące czynności (uwaga: po-niższa instrukcja odnosi się do użytkowników pakietu Visual Studio w wersji 7 oraz wyższych):

• Wykonać kroki opisane w ramce Szybki start: Lua,• Pobrać dystrybucję biblioteki (patrz: ramka W Sieci) i rozpakować ją do wybranego katalogu

(LUABIND_ROOT),• W ustawieniach projektu (C/C++ -> General) ustawić dodatkowy katalog do wyszukiwania

plików nagłówkowych: LUABIND_ROOT,• Dodać pliki źródłowe z katalogu LUABIND_ROOT/src do projektu.

Listing 1. Uruchomienie zewnętrznego skryptu Lua z programu C++

#include <iostream>

#include <lua.hpp>

using namespace std;

int main()

{

lua_State* pL = lua_open();

luaopen_base( pL );

luaopen_string( pL );

luaopen_table( pL );

luaopen_math( pL );

luaopen_io( pL );

if ( int error = luaL_dofile( pL,

"hello.lua" )

!= 0 )

{

cout << "\n[C++]: ERROR("

<< error

<< "): Problem with lua

script file!\n\n"

<< endl;

return 0;

}

return 1;

}

Page 14: Software Developers Journal PL 03/2009

03/200914

Biblioteka miesiącaBiblioteka Luabind

www.sdjournal.org 15

Wirtualny stos, czyli rozmowy kontrolowaneLua i C++ jako języki programowania są diametral-nie różne, zarówno na poziomie konstrukcji jak i wykorzystywanych typów danych (patrz: ram-ki Lua: przegląd możliwości języka). W tej sytuacji oczywiste jest, że trudno byłoby zrealizować bezpo-średni mechanizm komunikacji pomiędzy nimi. Aby rozwiązać ten problem autorzy biblioteki Lua

wprowadzili dodatkowy poziom abstrakcji w po-staci wirtualnego stosu, który służy do komunika-cji pomiędzy obydwoma językami. Koncepcja ko-munikacji jest bardzo prosta. Dla przykładu – je-śli z poziomu języka C++ chcielibyśmy wywołać funkcję Lua, to na stos powędruje najpierw obiekt tę funkcję reprezentujący, a później – argumenty. W dalszej kolejności program C++ daje sygnał do biblioteki, że chciałby wywołać funkcję. W tym

momencie po stronie Lua ze stosu zdejmowane są parametry i obiekt reprezentujący funkcję, po czym następuje wywołanie. Opisany tu pokrótce proces będzie opisany bardziej szczegółowo w ko-lejnych podpunktach niniejszego tekstu.

Wirtualny stos Lua ma dość ciekawą właści-wość. Oprócz standardowych operacji (włożenie nowego elementu na wierzchołek i zdjęcie ele-mentu z wierzchołka) użytkownik ma możliwość odwoływania się do konkretnych elementów stosu przy pomocy indeksów. Co więcej – oprócz zwy-czajnego indeksowania liczbami dodatnimi, do elementów stosu można odwoływać się przy po-mocy liczb ujemnych (np. liczba -1 reprezentuje wierzchołek stosu). Koncepcja ta jest przedstawio-na w sposób wizualny na Rysunku 1.

Dostęp do zmiennych Lua z poziomu programu C++Na początek przeanalizujmy najprostszy z moż-liwych scenariuszy: dostęp do globalnych zmien-nych skryptu Lua z poziomu programu napisa-nego w języku C++. Rozważmy następujący, pro-sty skrypt:

url = "http://www.sdjournal.org/"

id = 17

Na Listingu 2 pokazany jest przykładowy pro-gram, który pobiera wartości zmiennych zdefi-niowanych w powyższym skrypcie. Na początek warto zwrócić uwagę na deklarację funkcji:

int run_lua_script( lua_State* pL, const

char* name )

Funkcja ta opakowuje kod odpowiedzialny za uruchomienie skryptu Lua i wyświetlenie komu-nikatu o błędzie; będziemy ją jeszcze wielokrot-nie wykorzystywać w kolejnych przykładach. De-finicję funkcji umieściłem na Listingu 3.

Rozważmy teraz po kolei co dzieje się w funkcji main() przedstawionej na Listingu 2. Na początku tworzony jest kontekst Lua, dalej – wczytywane są biblioteki (tym razem robimy to przy pomocy po-jedynczej funkcji luaL_openlibs()). Następnie wykorzystujemy funkcję run_lua_script() w celu uruchomienia skryptu. Warto w tym miej-scu zauważyć, iż tym razem działanie skryptu jest niewidoczne – dzieje się tak, ponieważ rozważany skrypt nie zawiera żadnych operacji wyjścia; w za-mian za to, w obiekcie reprezentującym stan poja-wiają się dwie zmienne globalne, te do których po-staramy się uzyskać dostęp.

Aby odwołać się do wspomnianych zmien-nych z poziomu języka C++, musimy załadować je na wirtualny stos. Służy do tego funkcja lua_getglobal(). Zanim to jednak uczynimy, stos powinien być wyczyszczony za pomocą operacji lua_settop( pL, 0 ); dopiero po tym lądują na nim po kolei zmienne: url oraz id.

Zanim pobierzemy wartości zmiennych ze sto-su, warto upewnić się, czy mają one rzeczywiście taki typ, którego się spodziewamy. Służy to tego

Lua: przegląd możliwości jezykaJęzyk Lua dość diametralnie różni się do C++. Przede wszystkim jest on dynamicznie typowany. Dzięki temu w skrypcie Lua możemy zapisać następującą sekwencję instrukcji:

name = "Ola"

x = 44

x = name

Lua oferuje 8 typów podstawowych: Nil (oznacza, że dana zmienna nie ma żadnego typu), Number (liczba; warto zauważyć, iż wszystkie wartości liczbowe w Lua reprezentowane są jako wartości zmien-noprzecinkowe), String (napis), Boolean (typ logiczny), Function (w Lua funkcja traktowana jest jako peł-noprawny typ; np. można ją przypisać do zmiennej i przekazać ją do innej funkcji), Table (tablica), User-Data (pomocnicy typ wspomagający integrację Lua z językami C/C++) oraz Thread (wątek). Oprócz te-go Lua oferuje podstawowe operatory oraz instrukcje sterujące. Język ten pozwala również definio-wać klasy. Przykładowe, proste skrypty Lua można znaleźć w dołączonych Listingach, aczkolwiek peł-ne przedstawienie możliwości tego języka zdecydowanie wykracza poza ramy niniejszego artykułu. Czytelników, którzy chcieliby nauczyć się języka Lua zapraszam do zapoznania się z dokumentacją oraz samouczkami wskazanymi w ramce W Sieci.

Listing 2. Dostęp do zmiennych Lua z poziomu programu C++

#include <cassert>

#include <iostream>

#include <string>

#include <lua.hpp>

using namespace std;

int run_lua_script( lua_State* pL, const char* name );

int main()

{

lua_State* pL = lua_open();

luaL_openlibs( pL );

if ( run_lua_script( pL, "vars.lua" ) )

{

return 1;

}

lua_settop( pL, 0 );

lua_getglobal( pL, "url" );

lua_getglobal( pL, "id" );

if ( !lua_isstring( pL, 1 ) )

{

cout << "[C++]: ERROR: Invalid type! (number expected)\n";

return 1;

}

string url = lua_tostring( pL, 1 );

cout << url << endl;

if ( !lua_isnumber( pL, 2 ) )

{

cout << "[C++]: ERROR: Invalid type! (number expected)\n";

return 1;

}

int id = ( int )lua_tonumber( pL, 2 );

cout << id << endl;

return 0;

}

Page 15: Software Developers Journal PL 03/2009

03/200914

Biblioteka miesiącaBiblioteka Luabind

www.sdjournal.org 15

specjalny zestaw operacji (patrz Listing 4). Ope-racje te odpowiadają poszczególnym typom języ-ka Lua. Na Listingu pokazane jest w jaki sposób można jest wykorzystać w celu weryfikacji ty-pu obiektów umieszczonych na stosie. Wreszcie, przy pomocy funkcji z rodziny lua_to* (patrz Listing 5) można pobrać interesującą nas wartość ze stosu i zachować w zmiennej zdefiniowanej w programie C++. W rozpatrywanym przykładzie wykorzystujemy funkcje lua_tostring() oraz lua_tonumber(). W przypadku tej ostatniej ko-nieczne jest dodatkowe rzutowanie na interesują-cy nas typ; w Lua wszystkie wartości numeryczne reprezentowane są przy pomocy zmiennych typu double (reprezentację tę można zmienić, w tym celu należy przebudować bibliotekę).

Dostęp do tablicy Lua z poziomu programu C++Jako kolejny przykład interakcji pomiędzy Lua i C++ rozważymy proces uzyskania dostępu do ta-blicy Lua z poziomu programu C++. Na począ-tek zapraszam Czytelników do zapoznania się z Listingiem 6. W tym przypadku sprawa jest odro-binę bardziej skomplikowana. Kłopot w tym, że ta-blice Lua są w rzeczywistości kontenerami asocja-cyjnymi (patrz: ramka Lua: przegląd możliwości ję-zyka) i aby dostać się do określonego elementu musimy podać właściwy klucz. Na dodatek wspo-mniany klucz może być dowolnego typu. Na po-trzeby rozważanego przykładu, zakładamy iż za-wartość skryptu table.lua jest następująca:

user_data = { name="Monika", age=4 }

Zadaniem programu przedstawionego na Listin-gu 6 jest odczytanie zawartości komórki tabli-cy identyfikowanej przez klucz name. W tym ce-lu najpierw należy umieścić wspomnianą tabli-cę na stosie:

lua_getglobal( pL, "user_data" );

Po upewnieniu się iż mamy rzeczywiście do czy-nienia z tablicą, wrzucamy na stos nazwę intere-sującego nas klucza przy pomocy funkcji lua _

pushstring(). Warto zauważyć, iż tym razem stos został wykorzystany jako kanał komunika-cyjny w drugą stronę: dane zostały wysyłane z programu C++ do skryptu Lua. Dalej mamy na-stępujące wywołanie:

lua_gettable( pL, -2 );

W tym miejscu dzieje się dość sporo interesują-cych rzeczy. Wewnątrz funkcji z wierzchołka stosu zdejmowana jest komórka reprezentują-ca klucz, a następnie z tablicy określonej indek-sem przekazanym jako drugi argument funkcji (w naszym przypadku: -2) pobierana jest wartość dla wspomnianego klucza i po czym ląduje ona na wierzchołku stosu. Po wywołaniu tej funkcji warto sprawdzić czy typ pobranego obiektu od-powiada naszym oczekiwaniom, po czym – przy

pomocy znajomej funkcji lua _ tostring() – pobrać interesującą nas wartość.

Dostęp do funkcji Lua z poziomu programu C++Idąc o krok dalej – sprawdzimy teraz w jaki sposób można wywołać funkcję zdefioniowaną w skryp-cie Lua z poziomu programu C++. Na początek zdefiniujmy sobie prostą funkcję w Lua, która su-muje wartości z przedziału <a, b> (Listing 7).

Program C++ wywołujący tę funkcję przedsta-wiony jest na Listingu 8.

Początek rozważanego przykładu jest identycz-ny w stosunku do swoich poprzedników, do mo-mentu kiedy umieszczamy na stosie obiekt glo-balny, reprezentujący interesującą nas funkcję. W dalszej kolejności musimy umieścić na stosie argu-menty funkcji:

lua_pushnumber( pL, 1 );

lua_pushnumber( pL, 100 );

Kluczowym elementem w tym przykładzie jest wywołanie funkcji lua _ call(). Funkcja ta przyjmuje trzy argumenty: stan, ilość argumen-tów wywoływanej funkcji oraz ilość zwracanych przez nią elementów. Po jej wywołaniu na wierz-chołku stosu pojawiają się wspomniane elementy.

Dostęp do funkcji C++ z poziomu programu LuaW niniejszym podpunkcie opiszemy przypa-dek odwrotny do tego, który omówiony został wcześniej: rozważymy eksponowanie funkcji zapisanych w języku C++ dla skryptów Lua. Aby uzyskać tego rodzaju efekt, programista zmuszony jest dostosować eksponowaną funk-cję do następującego interfejsu:

int (lua_CFunction*) (lua_State*)

Najprostszą techniką pozwalającą uzyskać tego rodzaju efekt jest opakowywanie (ang. wrapping). Przykład udostępnienia funk-cji C++ dla skryptu Lua pokazany jest na Li-stingu 9.

Funkcja, którą eksponujemy w tym przykładzie ma następującą sygnaturę:

void print_ntimes( const string& str, int n )

Jej zadanie jest banalne: n razy wyświetla zadany napis. Aby zrealizować postawione zadanie, defi-niujemy funkcję opakowującą o następującej sy-gnaturze:

int print_ntimes( lua_State* pL )

Listing 3. Definicja funkcji run_lua_script()

int run_lua_script( lua_State* pL, const char* name )

{

if ( int error = luaL_dofile( pL, name ) != 0 )

{

cout << "\n[C++]: ERROR( "

<< error

<< " ): Problem with lua script file!"

<< endl;

return 1;

}

return 0;

}

Listing 4. Funkcje sprawdzające typ wartości przechowywanej w określonej komórce stosu

int lua_type( lua_State *pL, int index );

int lua_isnil( lua_State *pL, int index );

int lua_isboolean( lua_State *pL, int index );

int lua_isnumber( lua_State *pL, int index );

int lua_isstring( lua_State *pL, int index );

int lua_istable( lua_State *pL, int index );

int lua_isfunction( lua_State *pL, int index );

int lua_iscfunction( lua_State *pL, int index );

int lua_isuserdata( lua_State *pL, int index );

Listing 5. Funkcje sprawdzające typ wartości przechowywanej w określonej komórce stosu

int lua_toboolean( lua_State *pL, int index );

lua_Number lua_tonumber( lua_State *pL, int index );

const char* lua_tostring( lua_State *pL, int index );

lua_CFunction lua_tocfunction( lua_State *pL, int index );

void* lua_touserdata( lua_State *pL, int index );

lua_State* lua_tothread( lua_State *pL, int index );

void* lua_topointer( lua_State *pL, int index );

Page 16: Software Developers Journal PL 03/2009

03/200916

Biblioteka miesiącaBiblioteka Luabind

www.sdjournal.org 17

Proces definiowania tej funkcji można opisać pro-stym algorytmem:

• Na początku pobieramy rozmiar stosu przy pomocy funkcji lua _ gettop() i sprawdza-my, czy zgadza się ona z wymaganą liczbą ar-gumentów eksponowanej funkcji.

• Następnie sprawdzamy czy typy poszczegól-nych elementów umieszczonych na stosie zgadzają się z typami argumentów funkcji.

• Pobieramy argumenty ze stosu i wywołuje-my właściwą funkcję.

• Jeśli funkcja zwraca jakąś wartość, bądź mo-dyfikuje swoje argumenty to wyniki tako-wych działań należy umieścić na stosie. Funkcja opakowująca powinna zwracać war-tość całkowitą określającą ilość elementów zwróconych z funkcji.

W funkcji main() pokazane jest w jaki sposób można zarejestrować funkcję opakowującą w kontekście Lua co w rezultacie czyni ją widocz-ną dla wszystkich skryptów uruchamianych w tym kontekście:

lua_register( pL, "cxx_print_ntimes", print_

ntimes );

Drugi argument przekazywany do funkcji lua _

register() określa symbol reprezentujący za-rejestrowaną funkcję w skrypcie. W kontekście rozpatrywanego przykładu skrypt cxx.lua mógł-by wyglądać następująco:

print("Hello from Lua");

cxx_print_ntimes("Hello from C++", 3);

print("Hello from Lua again");

Wyniki działania przykładu zaprezentowanego na Listingu 9 byłyby następujące:

Hello from LuaHello from C++Hello from C++Hello from C++Hello from Lua again

Dostęp do klas C++ z poziomu LuaPrzedstawione powyżej przykłady pokazały, że łą-czenie języków Lua i C++ nie jest trudne, aczkol-wiek wiąże się ze sporym nakładem pracy, która w dużej mierze ma charakter powtarzalny. O ile w przypadku prostych typów danych (zmiennych, tablic czy funkcji) proces ten jest jeszcze znośny, o tyle w przypadku typów złożonych (klas) manual-ne ich eksponowanie może być prawdziwą kator-gą dla programisty. W tym miejscu nie będę nawet pokazywał przykładu takiego procesu – w zamian za to przedstawię rozwiązanie, które znacznie uła-twi nam pracę w tym zakresie. Uwaga, uwaga...

Luabind nadciąga z odsieczą!Mam nadzieję, że w pierwszej części artykułu uda-ło mi się w klarowny sposób zaprezentować pod-

stawowe mechanizmy integracji języków C++ oraz... skutecznie zniechęcić Czytelników do ich wykorzystywania. Trzeba powiedzieć to wprost: stosowanie wspomnianych mechanizmów zmu-szają programistę to wykonywania żmudnej, po-wtarzalnej i podatnej na błędy pracy. Na dodatek większość z potencjalnych błędów manifestuje się dopiero na etapie działania programu, co dodatko-wo utrudnia odpluskwianie programów. Tutaj na pomoc przychodzi nam biblioteka Luabind, która – wydawało by się – w magiczny sposób rozwiązu-je wymienione wyżej problemy. Na początek roz-ważmy podobne przypadki, do tych, które zostały przedstawione w pierwszej części artykułu – tyle, że tym razem - z wykorzystaniem Luabind.

Luabind: zaczynamy pracęW niniejszym punkcie rozważymy w jaki sposób można rozpocząć pracę z biblioteką Luabind. Je-śli chodzi o konfigurację biblioteki, to zapraszam Czytelników do zapoznania się z treścią ramki Lu-abind: szybki start. W tym miejscu zakładam, że bi-blioteka jest pomyślnie zainstalowana oraz skonfi-gurowana i możemy skupić się na programowa-niu. Na Listingu 10 przedstawiłem krótki pro-gram, który pokazuje jak niewiele pracy potrzeba aby rozpocząć korzystanie z Luabind.

Na początek należy dołączyć dwa nagłów-ki: lua.hpp oraz luabind.hpp. Dalej, tworzymy kontekst Lua przy pomocy znajomej nam lua_open(), po czym przekazujemy utworzony obiekt do funkcji luabind::open(). I na tym w zasadzie kończy się inicjacja biblioteki. W miejscu zazna-czonym komentarzem z trzema kropkami moż-na już wstawić kod korzystający z dobrodziejstw Luabind. Rozważmy pierwszy scenariusz wyko-rzystania biblioteki.

Luabind: Dostęp do funkcji Lua z poziomu programu C++Do przeanalizowania tego przypadku wykorzysta-my zdefiniowaną wcześniej funkcję sum_range() (patrz: Listing 7). Na Listingu 11 pokazane jest, w jaki sposób można uzyskać dostęp do tej funk-cji z poziomu programu C++, przy wykorzysta-niu Luabind.

Zanim przejdziemy do szczegółowej analizy wspomnianego Listingu, warto porównać go z za-wartością Listingu 8, w ramach którego realizowa-liśmy podobne zadanie – tyle, że z wykorzysta-niem podstawowego API do integracji Lua i C++. Z miejsca rzuca się w oczy fakt, iż w przypadku ko-rzystania z Luabind programista nie musi borykać się z takimi niskopoziomowymi szczegółami jak obsługa wirtualnego stosu Lua. Cała procedura wywołania funkcji zdefiniowanej w skrypcie spro-wadza się do jednej linijki kodu:

luabind::call_function< int >( pL, "sum_

range", 1, 100 )

Konstrukcja call _ function< int > jest in-stancją funkcji szablonowej; wywołując ja musi-my przekazać parametr szablonu określający typ

Listing 6. Dostęp do tablicy Lua z poziomu programu C++

#include <cassert>

#include <iostream>

#include <string>

#include <lua.hpp>

using namespace std;

int run_lua_script( lua_State* pL,

const char* name

);

int main()

{

lua_State* pL = lua_open();

luaL_openlibs( pL );

if ( run_lua_script( pL,

"table.lua" ) )

{

return 1;

}

lua_settop( pL, 0 );

lua_getglobal( pL, "user_data" );

if ( !lua_istable( pL, 1 ) )

{

cout << "\n[C++]: ERROR:

Invalid

type! (table

expected)\n";

return 1;

}

lua_pushstring( pL, "name" );

lua_gettable( pL, -2 );

if ( !lua_isstring( pL, -1 ) )

{

cout << "\n[C++]: ERROR:

invalid

type! (string

expected)\n";

return 1;

}

string name = lua_tostring( pL,

-1 );

cout << "[C++]: name = " << name <<

endl;

lua_pop( pL, 1 );

return 0;

}

Listing 7. Prosta funkcja zdefiniowana w języku Lua

function sum_range(a, b)

sum = 0

for i = a, b, 1 do

sum = sum + i

end

return sum

end;

Page 17: Software Developers Journal PL 03/2009

03/200916

Biblioteka miesiącaBiblioteka Luabind

www.sdjournal.org 17

zwracany z funkcji wywoływanej ze skryptu Lua (w naszym przypadku jest to int). Pierwszy pa-rametr przekazywany do call _ function() to stan Lua, drugi to nazwa docelowej funkcji, na-stępnie – argumenty tej funkcji. W naszym przy-padku wywołujemy funkcję sum _ range() z pa-rametrami 1 i 100; w wyniku otrzymujemy ko-munikat: sum_range( 1, 100 ) = 5050przy czym wartość 5050 została obliczona i zwrócona z funkcji zdefiniowanej w skryp-cie Lua. W sytuacji gdyby wywołanie funk-cji nie powiodło się z jakiegoś powodu, call_function() zgłosiłoby wyjątek luabind::

error.

Luabind: Dostęp do funkcji C++ z poziomu programu LuaRozważmy teraz przypadek, w którym chcieliby-śmy udostępnić zadaną funkcję zdefiniowaną w programie C++ do skryptu Lua. Jako przykład wy-korzystajmy ponownie funkcję print_ntimes(), zdefiniowaną na Listingu 9. Listing 12 zawiera program realizujący to zadanie przy pomocy Lu-abind.

W tym przypadku przewaga Luabind nad ma-nualnym mechanizmem eksponowania funk-cji C++ do Lua jest wręcz porażająca. Wierzę, iż pierwsza myśl pojawiająca się w głowie niejed-nego Czytelnika brzmi: jak to działa? Magia Lu-abind opiera się na ciekawym paradygmacie pro-gramistycznym, tzw. metaprogramowaniu na ba-zie szablonów języka C++ (ang. template metapro-gramming). Mówiąc w dużym uproszczeniu – kod podobny do tego, który tworzony jest manualnie w przypadku budowania funkcji opakowującej (patrz: Listing 9) – w przypadku Luabind genero-wany jest w trakcie kompilacji przy pomocy dedy-kowanego mechanizmu opartego na szablonach C++. Wszystko to dzieje się w linii:

luabind::module( pL )[ luabind::def( "print_

ntimes", print_ntimes

) ];

W tym miejscu, w globalnej przestrzeni nazw umieszczona jest funkcja print _ ntimes(), przy czym jest ona związana (ang. bind) z funk-cją o takiej samej nazwie – zdefiniowanej w na-szym przykładowym programie. Voila! Zanim przejdziemy do kolejnego podpunktu, warto zwrócić uwagę, iż tym razem – dla odmiany – do uruchomienia testowego skryptu wykorzy-stałem funkcję luaL _ dostring(). Funkcja ta interpretuje skrypt zapisany w pamięci progra-mu (w naszym przypadku jest to zwyczajna sta-ła tekstowa).

Luabind: Eksponowanie klas C++ dla skryptów LuaWidząc jak łatwo przy pomocy Luabind można zrealizować podstawowe zadania związane z łącze-niem języków Lua i C++, większość Czytelników domyśla się zapewne, iż wiązanie klas będzie rów-nie proste. I tak właśnie jest w rzeczywistości.

Listing 8. Dostęp do funkcji Lua z poziomu języka C++

#include <cassert>

#include <iostream>

#include <string>

#include <lua.hpp>

using namespace std;

int run_lua_script( lua_State* pL, const char* name );

int main()

{

lua_State* pL = lua_open();

luaL_openlibs( pL );

if ( run_lua_script( pL, "func.lua" ) )

{

return 1;

}

lua_getglobal( pL, "sum_range" );

if ( !lua_isfunction( pL, -1 ) )

{

cout << "\n[C++]: ERROR: Invalid type! (function expected)\n";

return 1;

}

lua_pushnumber( pL, 1 );

lua_pushnumber( pL, 100 );

lua_call( pL, 2, 1 );

int result = static_cast< int >( lua_tonumber( pL, -1 ) );

cout << "[C++]: sum_range( 1, 100 ) = " << result << endl;

lua_pop( pL, 1 );

return 0;

}

Listing 9a. Eksponowanie funkcji C++ dla skryptu Lua

#include <iostream>

#include <string>

#include <lua.hpp>

using namespace std;

void print_ntimes( const string& str, int n )

{

while ( n-- )

{

cout << str << endl;

}

}

int print_ntimes( lua_State* pL )

{

int argc = lua_gettop( pL );

if ( argc != 2 )

{

cout << "[C++]: print_ntimes: wrong number of parameters\n";

return 0;

}

if ( !lua_isstring( pL, 1 ) && !lua_isnumber( pL, 2 ) )

{

cout << "[C++]: print_ntimes: invalid types passed\n";

return 0;

}

string str = lua_tostring( pL, 1 );

int n = static_cast< int >( lua_tonumber( pL, 2 ) );

print_ntimes( str, n );

return 0;

}

int run_lua_script( lua_State* pL, const char* name );

Page 18: Software Developers Journal PL 03/2009

03/200918

Biblioteka miesiącaBiblioteka Luabind

www.sdjournal.org 19

Na Listingu 13 przedstawiona jest przykładowa klasa (point2d) reprezentująca punkt.

Z kolei na Listingu 14 pokazane jest jak można uczynić tę klasę widoczną dla skryptów Lua. Roz-ważmy zawartość tych dwóch Listingów.

Szkielet programu przedstawionego na wspo-mnianym Listingu jest bardzo podobny do te-go, który zastosowaliśmy w przykładzie wiązania funkcji. Podstawową różnicą jest zastosowanie sza-blonu luabind::class_, który służy do ekspono-wania klas. W kolejnych liniach zawarte są instruk-cje odpowiedzialne za generowanie kodu ekspo-nującego dla poszczególnych składników klasy: na początku dwa konstruktory, następnie funkcja print oraz składowe. Przy tych ostatnich warto się na moment zatrzymać. Dla przykładu, linia

.property( "x", &point2d::get_x, &point2d::

set_x )

definiuje tzw. właściwość klasy (ang. property) z możliwością jego odczytu za pomocą funkcji składowej get_x() oraz zapisu – przy pomoc set_x(). Dzięki temu w kodzie skryptu możemy napi-sać następującą instrukcję:

p2.x = p1.y

Na wyjściu przykładowego programu przedsta-wionego na Listingu 14 otrzymamy następuja-cy wynik:

[2,4][3,3][4,10]

Zaawansowane możliwości LuabindPrzedstawione wyżej przykłady pokazują moc prostoty i elegancji drzemiącą w bibliotece Lu-abind, aczkolwiek stanowią one jedynie zalą-żek możliwości tej biblioteki. Języki C++ i Lua różnią się mocno od siebie i przy łączeniu ich razem pojawia się wiele wyzwań (podejrze-wam, że co bardziej uważni i dociekliwi Czy-telnicy sami zauważyli niektóre z nich, ana-lizując zawartość prezentowanych wyżej Li-stingów). Luabind dokłada starań aby zaofe-rować wygodne mechanizmy wspomagające tę niełatwą integrację. Przedstawione powy-żej udogodnienia będą zapewne wystarczają-ce dla większości standardowych zastosowań, aczkolwiek prędzej czy później przyjdzie nam sięgnąć do arsenału bardziej zaawansowanych możliwości Luabind. Poniżej zaprezentowana jest pełna lista możliwości tej biblioteki:

• Wiązanie wolnych funkcji (włącznie z prze-ciążaniem)

• Eksponowanie klas C++ dla skryptów Lua,• Eksponowanie składowych klas dla skryp-

tów Lua,• Eksponowanie właściwości (ang. properties)

klas C++ dla skryptów Lua,

Listing 9b. Eksponowanie funkcji C++ dla skryptu Lua

int main()

{

lua_State* pL = lua_open();

luaL_openlibs( pL );

lua_register( pL, "cxx_print_ntimes", print_ntimes );

if ( run_lua_script( pL, "cxx.lua" ) )

{

return 1;

}

return 0;

}

Listing 10. Rozpoczynamy pracę z Luabind

#include <lua.hpp>

#include <luabind/luabind.hpp>

int main()

{

lua_State *pL = lua_open();

luabind::open( pL );

// ...

return 0;

}

Listing 11. Dostęp do funkcji Lua z poziomu języka C++, zrealizowany przy pomocy Luabind

#include <lua.hpp>

#include <luabind/luabind.hpp>

#include <iostream>

using namespace std;

int run_lua_script( lua_State* pL, const char* name );

int main()

{

lua_State *pL = lua_open();

luabind::open( pL );

if ( run_lua_script( pL, "func.lua" ) == 1 )

{

return 1;

}

cout << "sum_range( 1, 100 ) = "

<< luabind::call_function< int >( pL, "sum_range", 1, 100 )

<< endl;

return 0;

}

Listing 12. Dostęp do funkcji C++ z poziomu języka Lua, zrealizowany przy pomocy Luabind

#include <lua.hpp>

#include <luabind/luabind.hpp>

#include <iostream>

using namespace std;

void print_ntimes( const string& str, int n ) { /* ... */ }

int main()

{

lua_State *pL = lua_open();

luabind::open( pL );

luabind::module( pL )

[

luabind::def( "print_ntimes", print_ntimes )

];

luaL_dostring( pL, "print_ntimes( \"Hello from Lua!\", 5 )\n" );

return 0;

}

Page 19: Software Developers Journal PL 03/2009

03/200918

Biblioteka miesiącaBiblioteka Luabind

www.sdjournal.org 19

• Eksponowanie enumeracji C++ dla skryp-tów Lua,

• Eksponowanie funkcji Lua dla programów C++,

• Eksponowanie klas Lua dla programów C++,• Dziedziczenie klas (mechanizm ten dzia-

ła zarówno z Lua do C++ jak i z C++ do Lua),

• Przeciążanie funkcji wirtualnych z klas C++ w skryptach Lua,

• Rozdzielne rejestrowanie modułów• Polityki wartości zwracanych i parametrów• Obsługa błędów• Obsługa wątków Lua

Istota działania większość z wymienionych wy-żej mechanizmów jest dość oczywista; w przy-padku niektórych warto by pokusić się o dodat-kowy opis – niestety, ze względu na ogranicze-nie długości niniejszego artykułu zmuszony by-łem pominąć wspomniane opisy. W zamian za to – zapraszam zainteresowanych Czytelników do lektury materiałów odnoszących się do tych tematów, a dostępnych bezpłatnie w Internecie (patrz: ramka W sieci).

Luabind: ograniczeniaNie ma róży bez kolców: Luabind również posiada pewne ograniczenia. Choć jest to nieco paradok-salne, podstawową wadą biblioteki jest jednocze-śnie to co stanowi o jej olbrzymiej mocy i użytecz-ności – mowa tu oczywiście o mechanizmie meta-programowania bazującego na szablonach. Korzy-stanie z Luabind powoduje znaczący wzrost czasu kompilacji – zwłaszcza w przypadku projektów, w których rejestracja modułów odbywa się w wielu plikach źródłowych. Sami autorzy biblioteki zale-cają zresztą aby (w miarę możliwości) wspomnia-na rejestracja odbywała się w ograniczonej liczbie plików (najlepiej w jednym). Niestety – problem ten dotyka praktycznie wszystkich bibliotek, które intensywnie korzystają z mechanizmów metapro-gramowania opartego na szablonach języka C++.

PodsumowanieW powyższym artykule przedstawiłem mecha-nizm integrowania języków Lua i C++ na bazie prostego API opartego na czystym C, pokazałem wady i ograniczenia takiego podejścia oraz za-proponowałem alternatywę w postaci bibliote-ki Luabind. Rozważając kolejne przykłady poka-załem jak wspomniane rozwiązanie pozwala ła-two i wygodnie łączyć dwa pięknie dopełniają-ce się języki programowania. Gorąco zachęcam Czytelników do wypróbowania tego koktajlu – dzięki Luabind jest on zdecydowanie łatwiej-szy do przełknięcia.

Listing 13. Przykładowa, prosta klasa reprezentująca punkt

class point2d

{

public:

point2d( int x, int y ) : x_( x ), y_( y ) {}

point2d( int x ) : x_( x ), y_( x ) {}

int get_x() const { return x_; }

void set_x( int x ) { x_ = x; }

int get_y() const { return y_; }

void set_y( int y ) { y_ = y; }

void print()

{

cout << '[' << x_ << ',' << y_ << ']' << endl;

}

private:

int x_;

int y_;

};

Listing 14. Eksponowanie klasy C++ dla skryptu Lua przy pomocy Luabind

#include <lua.hpp>

#include <luabind/luabind.hpp>

int main()

{

lua_State *pL = lua_open();

luabind::open( pL );

luabind::module( pL )

[

luabind::class_< point2d >( "point2d" )

.def( luabind::constructor< int, int >() )

.def( luabind::constructor< int >() )

.def( "print", &point2d::print )

.property( "x", &point2d::get_x, &point2d::set_x )

.property( "y", &point2d::get_y, &point2d::set_y )

];

luaL_dostring( pL,

"p1 = point2d( 2, 4 )\n"

"p1:print()\n"

"p2 = point2d( 3 )\n"

"p2:print()\n"

"p2.x = p1.y\n"

"p2.y = 10\n"

"p2:print()" );

return 0;

} RAFAŁ KOCISZPracuje na stanowisku Dyrektora Technicznego w firmie Gamelion, wchodzącej w skład Grupy BLStre-am. Rafał specjalizuje się w technologiach zwią-zanych z produkcją oprogramowania na platfor-my mobilne, ze szczególnym naciskiem na tworze-nie gier. Grupa BLStream powstała, by efektywniej wykorzystywać potencjał dwóch szybko rozwijają-cych się producentów oprogramowania – BLStre-am i Gamelion. Firmy wchodzące w skład grupy specjalizują się w wytwarzaniu oprogramowania dla klientów korporacyjnych, w rozwiązaniach mo-bilnych oraz produkcji i testowaniu gier. Kontakt z autorem: [email protected]

W Sieci

• http://www.lua.org/ – strona domowa języka Lua;• http://luabinaries.luaforge.net/ – stąd można pobrać binarną dystrybucję interpretera i bi-

blioteka języka Lua;• http://en.wikipedia.org/wiki/Lua_(programming_language) – podstawowe informacje na te-

mat języka Lua;• http://lua-users.org/wiki/TutorialDirectory – samouczki poświęcone językowi Lua;• http://www.rasterbar.com/products/luabind.html – strona domowa biblioteki Luabind• http://www.rasterbar.com/products/luabind/docs.html – rozbudowany opis możliwości biblio-

teki Luabind.

Page 20: Software Developers Journal PL 03/2009

03/200920

Programowanie JavaSpring Java Configuration Project

www.sdjournal.org 21

Trudno znaleźć użytkownika szkieletu aplikacyjnego Spring Framework, który nie wiedziałby, czym jest XML. Sądzę

również, że żaden z takowych nie uniknął w swo-jej karierze edycji dokumentu XML rozpoczyna-jącego się elementem <beans>. Oczywiście twór-cy Springa udostępnili nam na tyle ogólny mecha-nizm programowej obsługi kontenera IoC (Inver-sion Of Control), że bez większych problemów możemy dodawać do niego definicje ziaren sprin-gowych (znanych również jako beany) zbudowa-nych w języku Java lub zawartych w plikach pro-perties. Mało tego, możemy nawet przy nadmia-rze wolnego czasu napisać samodzielnie imple-mentację interfejsu org.springframework.beans.fac-tory.BeanFactory, który będzie odczytywać defi-nicje naszych komponentów z najbardziej nawet niecodziennych źródeł (bazy danych, dokumen-tów w formacie JSON, hierarchii systemu pli-ków, etc.). Niezależnie od chwały należnej auto-rom Springa za elegancję jego architektury, fak-tem jest, że de facto standardem konfiguracji apli-

kacji internetowych jest XML. Co za tym idzie, wśród projektów opartych na Spring Framework funkcjonują w zasadzie tylko konteksty aplikacji analizujące dokumenty w tym formacie. Czytając dokumentację Springa lub artykuły na jego temat można wręcz odnieść wrażenie, że nie ma innego sposobu na konfigurację aplikacji napisanych z je-go użyciem.

MotywacjaXML jest bardzo wygodnym formatem konfi-guracji – z tym stwierdzeniem zapewne zgo-dzi się większość z nas. Niemniej jednak wraz ze wzrostem złożoności projektu nietrudno po-czuć subtelne uczucie przytłoczenia rozmiarem dokumentu applicationContext.xml, który na po-czątku wydawał się nam tak zgrabny, minimali-styczny i czytelny. Postanawiamy zatem go od-chudzić. Zaczynamy wydzielać wspólne części konfiguracji i tworzymy abstrakcyjne definicje beanów. Decydujemy się na rezygnację z pełnej kontroli nad zależnościami na rzecz automatycz-nego wiązania (autowiring). Dzielimy plik konfi-guracyjny na logiczne moduły, które następnie umieszczamy w osobnych plikach i importuje-my do głównej konfiguracji. Wreszcie, zdespe-rowani, piszemy własny schemat XML i za po-mocą własnej przestrzeni nazw redukujemy roz-

miar części konfiguracji charakterystycznej dla naszego projektu.

Załóżmy, że kiedy powyższe techniki nie dają nam satysfakcjonującego poziomu zredukowania konfiguracji, decydujemy się na użycie adnotacji. Dla przykładu, zastępujemy konfigurację transak-cji dokonywaną za pomocą przestrzeni nazw tx, na adnotacje @Transactional. I to właśnie jest klu-czowy moment w naszej opowieści – coś w nas pękło. Po raz pierwszy przełamaliśmy tabu kon-figuracji XML i przenieśliśmy część tej odpowie-dzialności do kodu aplikacji. Co prawda są to tyl-ko metadane, bo adnotacje to w końcu żaden kod. Załóżmy, że adnotacje nie kłócą się z naszym poj-mowaniem wzorca Inversion Of Control. Nieste-ty dalsze przenoszenie odpowiedzialności za kon-figurację z XML-a do kodu jakiejkolwiek warstwy aplikacji spowoduje powolną regresję do stanu, któremu Spring wraz ze swoim kontenerem IoC właśnie zapobiegają.

Może zatem wypracujemy jakiś kompromis pomiędzy unikaniem XML-a a przenoszeniem konfiguracji do kodu? A gdybyśmy tak np. stwo-rzyli osobny plik języka Java, który pozwoliłby nam na przeniesienie części konfiguracji z do-kumentu XML? Taki plik logicznie znajdowałby się poza wszystkimi warstwami aplikacji (zatem nie mieszamy logiki aplikacji z logiką konfigura-cji), a jedyną częścią systemu, która byłaby zależ-na od niego, to kontener IoC (zatem i ten wzo-rzec pozostanie nienaruszony). Wspominałem wcześniej, że twórcy Springa pozwolili nam na eleganckie rozszerzanie mechanizmu rozpozna-wania źródeł definicji komponentów. Kuszącą perspektywą wydaję się więc odczytywanie de-finicji beanów z odpowiednio napisanej, prostej klasy języka Java. Taką skompilowaną klasę mo-glibyśmy analizować za pomocą mechanizmu refleksji oraz poprzez rozpoznawanie określo-

Spring Java Configuration Project

Twórcy projektu Spring Framework spróbowali zminimalizować ilość konfiguracji XML poprzez przeniesienie źródeł definicji komponentów do plików języka Java. Spring Java Configuration Project to alternatywa dla klasycznego podejścia do zagadnienia konfiguracji aplikacji internetowych, która równocześnie nie narusza wzorca Inversion Of Control oraz ogólnej elegancji architektury naszej aplikacji.

Dowiesz się:• Jak można konfigurować kontener IOC (Inver-

sion Of Control) Springa za pomocą klas języka Java;

• Dlaczego warto posiąść taką umiejętność;• Jak połączyć klasyczną konfigurację XML z in-

nowacyjnym podejściem do tematu oferowa-nym przez Java Configuration Project.

Powinieneś wiedzieć:• Podstawowa znajomość języka Java oraz kon-

figuracji kontenera Inversion Of Control dla Spring Framework 2.x za pomocą plików XML.

Poziom trudności

Alternatywa dla tradycyjnej konfiguracji XML

Page 21: Software Developers Journal PL 03/2009

03/200920

Programowanie JavaSpring Java Configuration Project

www.sdjournal.org 21

nych adnotacji naniesionych na nią lub na jej me-tody. Fizycznie plik języka Java stanowiłby źró-dło konfiguracji, ale z punktu widzenia architek-tury byłby on logicznie tożsamy z plikiem XML (Rysunek 1.).

Wizja ciekawa, ale ktoś już nas uprzedził. Twórcy Springa już w 2005 roku rozpoczęli pracę nad projektem Java Configuration (w skrócie JavaConfig) realizującym ten pomysł.

Konfiguracyjny flamewarZanim przejdziemy dalej, pragnąłbym zwrócić uwagę na fakt, że zarówno podejście lansowa-ne przez np. Google Guice, Spring Java Confi-guration Project, jak i jakiekolwiek inne odej-ście od XML-a na rzecz konfigurowania aplika-cji poprzez chociażby adnotacje lub XDoclety (a już w szczególności kod języka Java, analizowany na poziomie wykonywania programu) mają pra-wo budzić kontrowersje. Kierunek redukowania tzw. XML hell na rzecz czegokolwiek bliższego językowi aplikacji nie jest standardem w świecie aplikacji zdominowanych przez XML. Dla wielu podejście reprezentowane przez Java Configura-tion jest nie do zaakceptowania i w ich opinii na-rusza realizację wzorca IoC.

Celem tego artykułu nie jest stwierdzenie, że przedstawiona w nim technika konfiguracji jest lepsza lub gorsza od jakiejkolwiek innej. Unikałbym zbędnego wartościowania konfi-guracji XML oraz nowszych technik, używa-nych do jej redukcji. JavaConfiguration to po prostu alternatywa. A już do architekta kon-kretnego projektu należy decyzja (i związana z nią odpowiedzialność), czy taka opcja wyj-dzie na lepsze.

JavaConfigSpring Java Configuration Project (w skrócie na-zywany po prostu Spring JavaConfig) to jeden z podprojektów Springa. Dostarcza on nowe źró-dło konfiguracji dla kontenera IoC, zatem wśród jego zależności możemy znaleźć głównie powią-zania ze Spring Core. Java Configuration oferu-je m.in.: zbiór adnotacji (używanych do ozna-czania klas i ich poszczególnych elementów ja-ko konfiguracji kontenera), nowe implementa-cje kontekstu aplikacji (rozbudowane o świado-

mość możliwości analizowania odpowiednich klas języka Java) oraz post processor służący do zintegrowania istniejących konfiguracji XML z nową konfiguracja JavaConfig.

O możliwościach rozwoju tego projektu może świadczyć osobiste zaangażowanie Ro-da Johnsona (głównego architekta Springa) w rozwój oraz promowanie Java Configuration Project. Jeżeli uznamy intuicję Pana Johnsona za wyznacznik pewnych trendów w programo-waniu, to możemy spodziewać się wzrostu zna-czenia tej nowej techniki konfiguracji w aplika-cjach internetowych.

Hello World, Bye XMLChcielibyśmy móc z czystym sumieniem powie-dzieć, że kiedyś napisaliśmy coś w Java Configura-tion. Skonfigurujemy zatem kontener IoC Springa bez jednej linijki XML-a, wyłącznie w czystej Javie.

Załóżmy, że chcemy napisać aplikację kon-solową, której klasa jest równocześnie konfi-

guracją swojego kontenera IoC. Nasz kontener mógłby zawierać jeden komponent springowy – niech to będzie zwykły string. Kod potrzeb-ny do uruchomienia tej przykładowej aplikacji znajduje się na Listingu 1.

W stosunku do konfiguracji kontenera IoC za pomocą XML-a pojawiły się trzy nowości:

• oznaczenie klasy, zawierającej konfigura-cję adnotacją @Configuration,

• oznaczenie adnotacją @Bean metody, któ-rej wynik ma zostać zarejestrowany w kontenerze jako bean,

• użycie kontekstu aplikacji świadomego klas zgodnych z Java Configuration.

Hello World z wiązaniemOd kontenera IoC oczekujemy najczęściej, że bę-dzie w stanie wstrzykiwać zależności. Aby udo-wodnić, że i Java Configuration nie jest pozbawio-ny tej funkcjonalności, spróbujmy rozszerzyć nasz

Rysunek 1. Uproszczony schemat zależności między aplikacją, kontenerem IoC Springa oraz źródłami jego konfiguracji

���������

������������������

����������������������������

����������������������

�����������

����� �����

Listing 1. Najprostszy przykład użycia JavaConfig

package pl.hekonsek;

import org.springframework.config.java.annotation.Bean;

import org.springframework.config.java.annotation.Configuration;

import org.springframework.config.java.context.JavaConfigApplicationContext;

import org.springframework.context.ApplicationContext;

// To jest konfiguracja Java Configuration

@Configuration

public class Application {

/** Tożsame z...

* <bean id="myBean" class="java.lang.String">

* <constructor-arg value="foo"/>

* </bean>

*/

@Bean

public String myBean() {

return "foo";

}

public static void main(String[] args) {

// Stwórz kontekst świadomy analizy plików Java Configuration

// i dodaj do niego klasę zawierającą taką konfigurację.

ApplicationContext ac = new JavaConfigApplicationContext(

Application.class);

System.out.println(ac.getBean("myBean"));

}

}

Listing 2. Najprostsze wiązanie w XML

<bean id="wireSth" class"java.lang.String">

<constructor-arg ref="wireMe" />

</bean>

<bean id="wireMe" class"java.lang.String">

<constructor-arg value="foo />

</bean>

Page 22: Software Developers Journal PL 03/2009

03/200922

Programowanie JavaSpring Java Configuration Project

www.sdjournal.org 23

przykład o najprostsze wiązanie. Chcielibyśmy za pomocą JavaConfig uzyskać konfigurację XML, analogiczną do tej z Listingu 2. Odpowiedni wy-cinek w Java Configuration widać na Listingu 3. – wiązanie odbywa się po prostu przez wywoła-nie metody oznaczonej adnotacją @Bean.

Szczegółowe przykłady konfiguracji

A czy w Java Configuration tak mogę?Zapewne niektórzy z was zadają sobie już py-tanie, czy w JavaConfig można uzyskać każ-

dą funkcjonalność konfiguracji XML? Czy nie jest to tylko zabawka oferująca najprost-szy podzbiór możliwości kontenera konfigu-rowanego za pomocą XML-a? Otóż nie, nie jest to tylko zabawka, ale w pełni funkcjo-nalna alternatywa dla tradycyjnej konfigura-cji. Na poparcie tych słów pozwolę sobie na rozwianie typowych wątpliwości, pojawiają-cych się na początku przygody z Java Confi-guration.

Cykl życia ziarna springowego w kontenerzeSpring oferuje pokaźną listę możliwych wywo-łań zwrotnych, które pozwalają nam na wstrze-lenie się z naszym kodem w różne momenty ży-cia naszej instancji, np. poprzez interfejsy z se-rii *aware (np. BeanNameAware) lub Initiali-zingBean (Listing 4.). Mam dobra wiadomość – wszystkie one są obsługiwane przez JavaCon-fig. Wynika to z faktu, że implementacje inter-face'u ApplicationContext, dostarczane przez Java Configuration, rozszerzają bazowe wersje, istniejące w Spring Core, tak więc mechanika związana z analizą cyklu życia jest realizowana przez oryginalny kod Springa.

Cykl życia – przekazywanie nazwy metodyA co, gdy chcemy użyć odpowiedników metod wskazanych przez atrybuty init-method lub destroy-method z konfiguracji XML (Listing 5.)? W końcu musimy wpisać je w pliku XML. Oczywiście i tutaj Java Configuration pozwa-la nam na podanie odpowiedniej nazwy meto-dy, tyle że nie w XML-u. Java Configuration pozwala nam na podanie odpowiedniej nazwy metody w ramach atrybutu initMethodName lub destroyMethodName adnotacji @Bean (Li-sting 6.).

Cykl życia – BeanPostProcessorsCo z implementacjami interface'u BeanPost-Processor? Oczywiście spełniają swoją funk-cję, jak powinny – ponownie kod, rozszerza-ny przez implementacje interface'u Appli-cationContext deleguje sterowanie do kodu Spring Core odpowiedzialnego za tą funkcjo-nalność. Zatem PostProcessory zostaną odpa-lone na zawartości kontenera, nie wnikając w to, czy źródłem zawartych w nim instancji jest plik XML, czy klasa zgodna z Java Con-figuration.

Zasięg instancjiDomyślnie instancje, zarejestrowane za po-mocą Java Configuration, mają (podobnie jak w konfiguracji XML) zasięg singleton. Aby wybrać inny zasięg, należy podać go ja-ko parametr adnotacji. Parametr scope jest typu string, tak więc możemy podawać rów-nież własne zasięgi, o ile zarejestrujemy tako-we w kontenerze. Przykłady znajdują się na Listingu 7.

Listing 3. Najprostsze wiązanie w Java Configuration

package pl.hekonsek;

import org.springframework.config.java.annotation.Bean;

import org.springframework.config.java.annotation.Configuration;

import org.springframework.config.java.context.JavaConfigApplicationContext;

import org.springframework.context.ApplicationContext;

@Configuration

public class Application {

@Bean

public String wireMe() {

return "foo";

}

@Bean

public String wireSth() {

// wywołanie metody oznaczonej jako @Bean

return new String( wireMe() );

}

public static void main(String[] args) {

ApplicationContext ac = new JavaConfigApplicationContext(

Application.class);

System.out.println(ac.getBean("wireSth"));

}

}

Listing 4. Przykład klasy świadomej swojego cyklu życia w kontenerze

package pl.hekonsek;

import org.springframework.beans.factory.BeanNameAware;

import org.springframework.beans.factory.InitializingBean;

public class LifeCycleBean implements InitializingBean, BeanNameAware {

@Override

public void afterPropertiesSet() throws Exception {

}

@Override

public void setBeanName(String name) {

}

}

Listing 5. Deklaracja metod init-method oraz destroy-method w XML-u

<bean class="com.Foo" init-method="start" destroy-method="close"/>

Listing 6. Deklaracja metod init oraz destroy w JavaConfig

@Bean(initMethodName="start",destroyMethodName="close")

public Foo foo() {

return new Foo();

}

Page 23: Software Developers Journal PL 03/2009

03/200922

Programowanie JavaSpring Java Configuration Project

www.sdjournal.org 23

Wstrzykiwanie nietypowych zasięgów przez Scoped ProxyJeżeli w konfiguracji XML chcemy wstrzyknąć do beana typu singleton zależność o zasięgu ty-pu np. session lub request, to musimy od-powiadającą jej definicję oznaczyć jako <aop:scoped-proxy/>.

Wynika to z węższego zakresu działania singletona w porównaniu z przekazywanymi (wstrzykiwanymi) obiektami. A ponieważ se-sje oraz żądania HTTP zwykły żyć krócej niż aplikacja (wraz ze swoimi singletonami), tak więc naprawdę Spring musi wstrzyknąć do takiego singletona pośrednika, który będzie żył tak długo, jak obiekt, do którego wstrzy-kuje się zależność (i przekierowywało żąda-nia do odpowiedniej instancji o krótszym za-sięgu życia).

Oczywiście Java Configuration również udo-stępnia taką funkcjonalność. Wystarczy spoj-rzeć na porównanie Listingów 8 oraz 9.

Zmiana domyślnych polityk rejestracji instancjiKonfiguracja XML pozwala nam na globalne określenie polityki tworzenia instancji zdefi-niowanych w pliku XML (patrz Listing 10.). Podobny efekt możemy osiągnąć za pomocą parametryzowania adnotacji @Configuration (patrz Listing 11.).

Method injectionPoza najbardziej popularnymi sposobami wstrzykiwania zależności tzn. wstrzykiwa-niu przez metodę ustawiającą (setter injection) oraz konstruktor (constructor injection) Spring oferuje tzw. metodę wstrzykującą (method in-jection). Technika ta jest przydatna zwłaszcza w scenariuszu, w którym potrzebujemy, aby bean typu singleton mógł uzyskać nowy eg-zemplarz beana o zasięgu prototype, zarządza-nego przez kontener IoC, za każdym razem, kiedy ów singleton odwołuje się do swojej za-leżności. Tradycyjne wstrzyknięcie zależno-ści przez konstruktor lub metodę ustawiają-cą będzie tutaj niewystarczające, gdyż proto-typy są tworzone i wstrzykiwane do singleto-nów tylko w momencie ustawiania zależności tych drugich.

Metoda wstrzykująca jest dostępna w Java Configuration w bardzo intuicyjny sposób – poprzez implementację lub nadpisanie żą-danej metody w klasie wewnętrznej (najczę-ściej anonimowej) i odwołanie się do meto-dy tworzącej prototyp. Style użycia metody wstrzykującej klasy z Listingu 12. w XML-u oraz Java Configuration porównują Listingi 13 oraz 14.

Ukrywanie definicji beanówNieco mniej oczywistą, a bardzo ciekawą opcją, oferowaną przez Java Configuration, jest moż-liwość ukrywania swoich instancji przed inny-mi kontekstami w hierarchii. Jeżeli zdefinio-

wana przez nas metoda @Bean będzie miała wi-doczność domyślną lub chronioną (w starszych wersjach JavaConfig również prywatną), to da-

na definicja beana będzie umieszczona w po-mocniczym kontekście-potomku i będzie nie-widoczna dla innych kontekstów w hierarchii

Listing 7. Przykłady zmiany domyślnego zasięgu instancji w kontenerze

@Bean(scope = DefaultScopes.SINGLETON)

public String wireMe() {

return "foo";

}

@Bean(scope = DefaultScopes.PROTOTYPE)

public String wireMe() {

return "foo";

}

@Bean(scope = "myCustomScope")

public String wireMe() {

return "foo";

}

Listing 8. Scoped Proxy w XML-u

<bean id="cart" class="pl.hekonsek.Cart" scope="session">

<aop:scoped-proxy/>

</bean>

<bean id="cartVerifier" class="pl.hekonsek.CartVerifier">

<property name="cart" ref="cart"/>

</bean>

Listing 9. Scoped Proxy w Java Configuration

@Bean(scope = DefaultScopes.SESSION)

@ScopedProxy

public Cart cart() {

return new Cart();

}

@Bean

public CartVerifier cartVerifier() {

CartVerifier cv = new CartVerifier();

cv.setCart(cart());

return cv;

}

Listing 10. Konfigurowanie domyślnej polityki tworzenia i wiązania instancji w XML

<beans default-autowire="byName" default-lazy-init="false" ... ></beans>

Listing 11. Konfigurowanie domyślnej polityki tworzenia i wiązania instancji w Java Configuration

package pl.hekonsek;

import org.springframework.beans.factory.annotation.Autowire;

import org.springframework.config.java.annotation.Bean;

import org.springframework.config.java.annotation.Configuration;

import org.springframework.config.java.annotation.Lazy;

@Configuration(defaultAutowire=Autowire.BY_NAME,defaultLazy=Lazy.FALSE)

public class Application {

@Bean(autowire=Autowire.BY_TYPE)

public String wireMe() {

return "foo";

}

}

Page 24: Software Developers Journal PL 03/2009

03/200924

Programowanie JavaSpring Java Configuration Project

www.sdjournal.org 25

niż ten, który ją definiuje. Możemy dzięki temu tworzyć pomocnicze instancje, które nie będą widoczne dla innych poziomów aplikacji.

Integracja konfiguracji XML oraz JavaConfig

Dodatek do XML-aOczywiście Java Configuration nie wymu-sza od nas całkowitej rezygnacji z konfigura-

cji XML. Możemy np. dodać do naszej apli-kacji skonfigurowanej w XML PostProcessor org.springframework.config.java.process.Con-figurationPostProcessor. Następnie należy do-dać definicje naszych klas konfiguracyjnych do kontenera (Listing 15.). Wspomniany przez nas PostProcessor wykryje, że są one oznaczone adnotacją @Configuration i do-da znajdujące się w nich definicje do kon-tenera.

Tą metodą możemy cieszyć się możliwościa-mi JavaConfig tylko dla wybranych przez nas fragmentów konfiguracji, podczas gdy więk-szość definicji dalej będziemy trzymać w for-macie XML. Co ważne, ConfigurationPostPro-cessor pozwala nam na płynną migrację konfi-guracji z XML-a do JavaConfig. Dzięki temu nie jesteśmy stawiani przed wyborem, którego konsekwencją może być poważna zmiana w ar-chitekturze konfiguracji naszej aplikacji.

Nadpisywanie definicjiCiekawą opcją oferowaną przez JavaConfig (a przydatną zwłaszcza w kontekście integracji z XML-em) jest możliwość oznaczenia defini-cji beana parametrem allowOverriding. Dzię-ki temu zarejestrowanie w konfiguracji XML instancji o tej samej nazwie przesłoni tą zdefi-niowaną w JavaConfig. Jest to funkcjonalność przydatna zwłaszcza wtedy, gdy JavaConfig planujemy używać do bardziej ogólnych (a za-razem domyślnych) fragmentów konfiguracji, podczas gdy XML-owi pozostawiamy rolę kon-figuracji szczegółowej. Przykład takiego podej-ścia demonstrują Listingi 16 oraz 17.

JavaConfig w aplikacjach internetowychJedną technikę integracji Java Configuration z aplikacjami webowymi już poznaliśmy. Jest to dodanie do pliku XML naszej konfiguracji Post-Processora org.springframework.config.java.pro-cess.ConfigurationPostProcessor. Niezależnie od tej możliwości możemy użyć kontekstu apli-kacji dedykowanego JavaConfig i aplikacjom internetowym. Implementacja org.springfra-mework.config.java.JavaConfigWebApplication-Context w zasadzie niewiele różni się od np. tra-dycyjnego org.springframework.web.context.sup-port.XmlWebApplicationContext. O ile ten dru-gi jako wartość contextConfigLocation pobiera li-stę lokalizacji plików XML, to pierwszy wczy-tuje listę klas języka Java. Przykład użycia kon-tekstu aplikacji oferowanego przez Java Confi-guration znajduje się na Listingu 18.

Modularyzacja konfiguracji

Wszystko można zapchaćOczywiście konfiguracja w klasach JavaConfig może być po pewnym czasie, wraz z rozrostem aplikacji, równie uciążliwa w utrzymaniu i kontroli, co monolityczny plik XML. Java Con-figuration oferuje na szczęście szereg mechani-zmów służących do podziału klas konfiguracyj-nych na mniejsze elementy.

Dostęp do instancji z innych klas i źródełPodstawowym zagadnieniem pojawiającym się podczas modularyzacji klas JavaConfig jest dostęp do metod definiujących instancje z in-nych klas lub źródeł danych. Jeżeli np. inte-grujemy Java Configuration z aplikacją zarzą-dzaną za pomocą XML-a (poprzez Configura-tionPostProcessor) to tracimy możliwość od-

Listing 12. Klasy służące do demonstracji metody wstrzykującej

package pl.hekonsek;

public abstract class StringHolder {

public abstract String getString();

}

package pl.hekonsek;

import java.util.Date;

class DateString {

public Date date = new Date();

}

Listing 13. Metoda wstrzykująca w XML-u

<bean id="prototype" class="pl.hekonsek.DateString"/>

<bean id="holder" class="pl.hekonsek.StringHolder>

<lookup-method name="getString" bean="prototype"/>

</bean>

Listing 14. Metoda wstrzykująca w Java Configuration

@Bean(scope = DefaultScopes.PROTOTYPE)

public DateString prototype() {

return new DateString();

}

@Bean

public StringHolder holder() {

return new StringHolder() {

@Override

public String getString() {

return prototype().date.getTime() + "";

}

};

}

Listing 15. Integracja konfiguracji XML i JavaConfig

<beans ... >

<!-- Dodaj konfigurację do kontenera -->

<bean class="pl.hekonsek.MyConfigurationClass"/>

<!-- Lub dodaj do kontenera wszystkie konfiguracje oznaczone jako @Component -->

<context:component-scan base-package="pl.hekonsek.*"/>

<bean class="org.springframework.config.java.process.ConfigurationPostProcessor"/>

</beans>

Page 25: Software Developers Journal PL 03/2009

03/200924

Programowanie JavaSpring Java Configuration Project

www.sdjournal.org 25

wołania się z poziomu klasy oznaczonej adno-tacją @Configuration do instancji zdefiniowa-nej w pliku XML. Dzieje się tak z prozaiczne-go powodu – Java jest językiem statycznie ty-powanym i nie pozwoli nam na wywoływanie w ramach klasy metody o arbitralnej nazwie. Logicznie wiemy, że np. definicja beana o na-zwie notDefinedHere znajduje się w kontene-rze, ale składnia języka Java nie pozwoli nam na odwołanie się do metody o takiej nazwie (a jak wiadomo, jest to sposób na odnoszenie się in-nych obiektów w kontenerze za pomocą Java-Config). Problem ten obrazuje Listing 19. Mu-simy zatem zdefiniować metodę pomocniczą, która pozwoli nam na odwołanie się do instan-cji zdefiniowanej poza daną klasą. Metoda ta-ka może być abstrakcyjna (notabene stąd wnio-sek, że i klasy JavaConfig mogą być abstrakcyj-ne, oraz że są one proxowane za pomocą biblio-teki służącej do dynamicznej generacji kodu) lub konkretna (zostanie ona nadpisana przez JavaConfig) oraz musi być oznaczona adnota-cją @ExternalBean. Rozwiązanie problemu z Listingu 19. za pomocą takiej właśnie metody demonstruje listing 20.

Analogiczny problem wystąpi podczas roz-dzielania klasy konfiguracyjnej na mniejsze, ale bardziej spójne logicznie. Ponownie z pomocą przybywa adnotacja @ExternalBean.

Rozbijanie konfiguracji na wiele klasNajprostszą techniką rozbijania konfigura-cji jest przeniesienie części metod z klasy kon-figuracyjnej do drugiej klasy i dodanie oby-dwu do kontekstu. Listing 21. pokazuje przy-kład podziału klasy na dwie mniejsze z zacho-waniem wzajemnych referencji za pomocą @ExternalBean.

Adnotacja @ImportPodobnie jak w przypadku XML-a i jego ele-mentu <import/>, konfiguracja JavaConfig również może importować inne klasy oznaczo-ne adnotacją @Configuration. Aby tego doko-nać, wystarczy oznaczyć klasę konfiguracyjną adnotacją @Import({foo.Config1.class,foo

.Config2.class}).

Wewnętrzne klasy konfiguracyjne oraz zasięg widoczności obiektuZastosowanie klasy wewnętrznej w JavaCon-fig spowoduje utworzenie dla niej osobnego kontekstu aplikacji, będącego potomkiem kla-sy zewnętrznej. Konteksty te podlegają oczywi-ście zasadom hierarchii kontenerów IoC Sprin-ga (co demonstruje Listing 22.).

Specjalnie nie piszę o...

Wsparciu w Spring IDESpring IDE to znakomity plugin do Eclipse IDE, wspomagający pracę ze Springiem. Ma już opcjo-nalne wsparcie dla JavaConfig. Szczegóły jego użycia są poza zasięgiem tematycznym tego ar-

Listing 16. Definicja domyślna komponentu w JavaConfig

package pl.hekonsek;

import org.springframework.config.java.annotation.Bean;

import org.springframework.config.java.annotation.Configuration;

@Configuration

public class Application {

@Bean(allowOverriding = true)

public String username() {

return "root";

}

}

Listing 17. Nadpisywanie domyślnej wartości za pomocą XML-a

<beans ... >

<!-- Dodaj konfigurację do kontenera -->

<bean class="pl.hekonsek.Application"/>

<!-- Nadpisz instancję reprezentującą domyślną nazwę użytkownika -->

<bean id="username" class="java.lang.String">

<constructor-arg value="hekonsek"/>

</bean>

<bean class="org.springframework.config.java.process.ConfigurationPostProcessor"/>

</beans>

Listing 18. Konfiguracja internetowego kontekstu aplikacji świadomego javaConfig

<web-app>

<!-- Główny kontekst aplikacji. -->

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</

listener-class>

</listener>

<context-param>

<param-name>contextClass</param-name>

<param-value>org.springframework.config.java.JavaConfigWebApplicationContext</

param-value>

</context-param>

<!-- Lokalizacje klas zamiast plików XML -->

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>pl.hekonsek.ApplicationContext</param-value>

</context-param>

<!-- Główny servlet aplikacji... -->

<!-- ...konfigurowany tak samo, jak kontekst powyżej. -->

<servlet>

<servlet-name>app</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-

class>

<init-param>

<param-name>contextClass</param-name>

<param-value>org.springframework.config.java.JavaConfigWebApplicationContex

t</param-value>

</init-param>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>pl.hekonsek.AppServletConf,pl.hekonsek.AppServletDaoConf</

param-value>

</init-param>

</servlet>

</web-app>

Page 26: Software Developers Journal PL 03/2009

03/200926

Programowanie JavaSpring Java Configuration Project

www.sdjournal.org 27

tykułu (jakkolwiek jest ono na tyle intuicyjne, że nikt nie powinien mieć z nim problemów).

Kwestii stabilnościAktualna wersja JavaConfig to 1.0.0.m3. Ze względu na fakt, że Java Configuration znaj-

duje się wciąż w fazie rozwojowej, pewne funk-cjonalności oferowane przez projekt mogą ulec gruntownej zmianie. Takie newralgiczne frag-menty API zostały przeze mnie umyślnie po-mięte, jakkolwiek myślę, że warto o nich wspo-mnieć w dużym skrócie.

@ResourceBundles oraz @ExternalValue@ResourceBundles oraz @ExternalValue to pa-ra adnotacji pozwalających na uzyskanie funkcjo-nalności podobnej do tej oferowanej przez Pro-pertyPlaceholderConfigurer. Pierwsza z nich ła-duje pliki z właściwościami, druga zaś pozwala

Listing 19. Problem z kompilacją klasy JavaConfig odnoszącej się do zewnętrznej definicji

Listing 20. Rozwiązanie problemu z kompilacją klasy JavaConfig odnoszącej się do zewnętrznej definicji

Listing 21. Rozbicie dużej konfiguracji na dwie mniejsze klasy

package pl.hekonsek;

import org.springframework.config.java.annotation.Bean;

import org.springframework.config.java.annotation.Configuration;

@Configuration

public class Application {

@Bean

public StringHolder referencer() {

// Wstrzyknij referencję do beana 'notDefinedHere'

// Compilation error:

// The method notDefinedHere() is undefined for the type

Application

return new StringHolder(notDefinedHere());

}

}

package pl.hekonsek;

import org.springframework.config.java.annotation.Bean;

import org.springframework.config.java.annotation.Configuration;

import org.springframework.config.java.annotation.ExternalBean;

@Configuration

public class Application {

@ExternalBean

public String notDefinedHere() {

throw new RuntimeException("Assertion - this line must

not be executed.");

}

@Bean

public StringHolder referencer() {

// Wstrzyknij referencję do beana 'notDefinedHere'

return new StringHolder(notDefinedHere());

}

}

Większa klasa

package pl.hekonsek;

import org.springframework.config.java.annotation.Bean;

import org.springframework.config.java.annotation.Configuration;

@Configuration

public class BigConf {

@Bean

public String foo() {

return "foo";

}

@Bean

public StringHolder fooHolder() {

return new StringHolder(foo());

}

}

Mniejsza klasa nr 1

package pl.hekonsek;

import org.springframework.config.java.annotation.Bean;

import org.springframework.config.java.annotation.Configuration;

import org.springframework.config.java.annotation.ExternalBean;

@Configuration

public class SmallConf1 {

@ExternalBean

public String foo() {

throw new RuntimeException("This line should never be

executed.");

}

@Bean

public StringHolder fooHolder() {

return new StringHolder(foo());

}

}

Mniejsza klasa nr 2

package pl.hekonsek;

import org.springframework.config.java.annotation.Bean;

import org.springframework.config.java.annotation.Configuration;

@Configuration

class SmallConf2 {

@Bean

public String foo() {

return "foo";

}

}

Przykład uruchomienia kontekstu mniejszych klas

new JavaConfigApplicationContext(SmallConf1.class,

SmallConf2.class);

Page 27: Software Developers Journal PL 03/2009

03/200926

Programowanie JavaSpring Java Configuration Project

www.sdjournal.org 27

na oznaczenie metody na podobnej zasadzie, co @ExternalBean (tyle że wartość zostanie odczyta-na z pliku właściwości).

Konfiguracjach aspektowychJavaConfig oferuje możliwość oznaczenia klasy konfiguracyjnej jako aspektu AOP (ang. Aspect-Oriented Programming) oraz jej konstrukcję umożliwiającą zastosowanie go do określonych in-stancji w kontenerze. Dzięki temu możemy np. przechwytywać za pomocą metody zdefiniowa-nej w pliku konfiguracyjnym określony wyjątek dla wszystkich instancji naszej aplikacji (lub dla wybra-nych obiektów i metod - jest to jedynie kwestia od-powiedniego zadeklarowania punktu przecięcia).

Podsumowanie Java Configuration oferuje nam nowatorskie podejście do konfiguracji aplikacji. Twórcy

Springa starają się balansować pomiędzy za-chowaniem spójności wzorca Inversion Of Control i równocześnie pozwalają nam na bar-dziej intuicyjny (przynajmniej dla programi-stów języka Java) format konfiguracji. Jak na razie starania zespołu Roda Johnsona dają bar-dzo satysfakcjonujące rezultaty – JavaConfig może być z powodzeniem stosowany nie tylko jako wsparcie dla konfiguracji XML, ale rów-nież jako samodzielna metoda konfiguracji kontenera IoC.

Jak wspominałem wcześniej, łatwo jest po-paść w pułapkę klasyfikowania tego typu roz-wiązań binarnie – jako lepszych lub gorszych od konfiguracji poprzez XML. Sądzę jednak, że każdy rozsądny architekt nie będzie sta-rał się forsować na siłę jednej techniki kon-figuracyjnej do wszystkich nadzorowanych przez siebie aplikacji i raczej będzie skłon-

ny do spokojnego zastanowienia się co mo-że uzyskać projekt po ewentualnej relaksacji klasycznego podejścia do konfiguracji XML. Wykorzystanie drzemiących w Java Configu-ration możliwości jest szczególnie wygodne ze względu na możliwość drobnoziarnistej i płynnej migracji definicji zwartych XML na rzecz klas konfiguracyjnych.

Listing 22. Konfiguracje wewnętrzne oraz zależności rodzic-dziecko między nimi

Referencje

• Strona projektu Spring Framework – http://springframework.org/javaconfig• Strona projektu JavaConfig – http://springframework.org/javaconfig• Inne projekty poboczne Springa – http://springframework.org/projects• Artykuł Martina Fowlera nt. IoC – http://martinfowler.com/articles/injection.html• JavaConfig Reference Documentation – http://static.springframework.org/spring-javaconfig/docs/1.0.0.m3/reference/html• JavaConfig API – http://static.springframework.org/spring-javaconfig/docs/1.0.0.m3/apidocs/• Artykuł Roda Johnsona nt. JavaConfig – http://blog.springsource.com/2006/11/28/a-java-configuration-option-for-spring/• Klasyczna konfiguracja XML Springa – http://static.springframework.org/spring/docs/2.5.x/reference/beans.html

package pl.hekonsek;

import org.springframework.beans.factory.NoSuchBeanDefinitionE

xception;

import org.springframework.config.java.annotation.Bean;

import org.springframework.config.java.annotation.Configuration;

import org.springframework.config.java.context.JavaConfigApplica

tionContext;

import org.springframework.context.ApplicationContext;

@Configuration

public class Parent {

@Bean

public String foo() {

return "parent";

}

@Bean

public String fromParent() {

return "from parent";

}

@Configuration

public static class Child {

@Bean

public String foo() {

return "child";

}

@Bean

public String fromChild() {

return "from child";

}

}

public static void main(String[] args) {

ApplicationContext ac = new JavaConfigApplicationContex

t(Child.class);

// Pobierz obiekt z kontekstu dziecka

System.out.println(ac.getBean("foo"));

// Mamy dostęp do obiektów rodzica i potomka

System.out.println(ac.getBean("fromParent"));

System.out.println(ac.getBean("fromChild"));

ac = new JavaConfigApplicationContext(Parent.class);

// Pobierz obiekt z kontekstu rodzica

System.out.println(ac.getBean("foo"));

// Mamy dostęp do obiektów rodzica

System.out.println(ac.getBean("fromParent"));

try {

System.out.println(ac.getBean("fromChild"));

assert false;

} catch (NoSuchBeanDefinitionException e) {

assert true;

// Nie mamy dostępu do obiektów potomka

}

}

}

HENRYK KONSEKAutor pracuje na stanowisku projektanta JEE w warszawskiej firmie Artegence. Udziela się rów-nież jako administrator serwisu javablackbelt.com. W wolnym czasie interesuje się swoją Anią oraz m.in. psychiatrią oraz dobrymi technologiami. Kontakt z autorem: http://www.hekonsek.pl lub [email protected].

Page 28: Software Developers Journal PL 03/2009

03/200928

WarsztatyCUDA się zdarzają, czyli programowanie GPGPU

www.sdjournal.org 29

Ostatnio coraz częściej mówi się o GPG-PU, czyli o obliczeniach dowolnego za-stosowania przy użyciu kart graficz-

nych. Temat stał się jeszcze bardziej popularny po pojawieniu się CUDA (ang. Compute Unified Device Architecture) – rozwiązania w znacznym stopniu ułatwiającego tego typu obliczenia. Ni-niejszy artykuł jest czysto praktycznym wprowa-dzeniem do tej technologii. Czytelników, którzy chcieliby dowiedzieć się troszkę więcej o GPGPU oraz CUDA, zapraszamy do lektury Ramek Kilka słów o GPGPU , Co to właściwie jest CUDA oraz do materiałów poleconych w Ramce W Sieci. Ja-ko że zawsze dobrze tłumaczy się na przykładzie, to na początku dobierzemy sobie problem nume-ryczny najlepiej nadający się do takiego wprowa-dzenia: na tyle prosty, żeby nie zaciemniał szcze-gółów, ale zarazem na tyle wredny ( a więc typowy ), żeby pozwolił poruszyć najistotniejsze aspekty programowania w CUDA.

Wszystkie obliczenia były wykonane na GeFor-ce GTX280 oraz na jednym rdzeniu QuadCora taktowanego zegarem 2.66 Ghz. Często niefor-malnie będziemy używać zwrotów w stylu: ko-piowanie pamięci ze strony CPU na stronę GPU,

mając na myśli pamięć RAM komputera dostęp-ną bezpośrednio dla części kodu wykonywanej na CPU oraz pamięć RAM karty graficznej.

Opis przykładu numerycznegoNa wstępie dobierzemy sobie przykładowy pro-blem do eksperymentów, by na jego bazie eta-powo poznawać kolejne techniki programowa-nia przy użyciu CUDA. Idealne do tego wyda-je się być różniczkowanie numeryczne z formu-łą pięciopunktową: mając na wejściu funkcję (sy-gnał), daną jako tablicę N liczb rzeczywistych roz-mieszczonych ze stałym krokiem h, w celu obli-czenia przybliżonej pochodnej tej funkcji stosuje-my wzór przedstawiony na Rysunku 1. Wzory z Rysunku 2. stosujemy dla dwóch pierwszych oraz dwóch ostatnich punktów z tablicy.

Na Listingu 1. widzimy implementację te-go dość prostego problemu w języku C. W kon-wencji nazewnictwa CUDA Host odnosi się za-wsze do kodu wykonywanego po stronie CPU, stąd też nazwa naszej funkcji. Znaczenie para-metrów in, out , oraz data_size jest oczywiste, natomiast den pochodzi od denominator, czyli mianownik 1/h.

Rysunek 3. przedstawia zależność danych wyjściowych od wejściowych

Zarządzanie pamięciąZanim zaczniemy obliczenia, po stronie GPU mu-simy w pierwszej kolejności zaalokować oraz sko-piować pamięć na naszą kartę graficzną. Alokacja oraz dealokacja są analogiczne do klasycznych mal-loców w C (Listing 2.) , przy czym używamy do te-go oczywiście funkcji z API CUDA.

W Listingu 2., jak i w dalszej części artyku-łu, została przyjęta konwencja dodawania przed-rostka h_ dla wskaźników do pamięci dostęp-nej z poziomu CPU (host) oraz przedrostka d_ dla pamięci GPU (device). Kopiowanie pamię-ci odbywa się również podobnie jak w języku C (patrz: Listing 3.)

CUDA się zdarzają, czyli programowanie GPGPU

W artykule dowiemy się co nieco o CUDA z praktycznego punktu widzenia. Na konkretnym przykładzie zobaczymy, jak w prosty sposób wykorzystać kartę graficzną do obliczeń niekoniecznie związanych z grafiką komputerową. Następnie użyjemy typowych rozwiązań mających na celu znaczne przyspieszenie obliczeń.

Dowiesz się:• Jak napisać i wykonać obliczenia na GPU;• Jak wykorzystać pamięć współdzieloną i nie-

stronicowaną a także asynchroniczne API.

Powinieneś wiedzieć:• Średnio zaawansowana wiedza ogólna z za-

kresu programowania w języku C;• Podstawowa wiedza z zakresu programowa-

nia równoległego.

Poziom trudności

Wprowadzenie do programowania przy użyciu technologii CUDA

Szybki startOczywiście na początek musimy ściągnąć ze strony Nvidii SDK toolkit oraz drivery dla CUDA. Wszystko znajdziemy np. tu: http://www.nvidia.pl/object/cuda_get_pl.html Rekomendowanym środowiskiem dla programowania CUDA pod Windowsem jest MS Visual C++ 2005. Głównie chodzi o dostarczany w tym pakiecie kompilator. Fragmenty kodu dla części GPU są kompilowa-ne przez Nvidiowe narzędzie, zaś część dla CPU przez zewnętrzny kompilator i niestety nowsza wersja Microsoftowego kompilatora nie jest kompatybilna z Nvidiową. W katalogu, w którym zainstalowaliśmy CUDA SDK, w podkatalogu \doc\syntax_highlighting znajdziemy mały plik readme opisujący, jak włączyć kolorowanie w Visualu dla plików .cu. Takie właśnie rozszerzenie mają pliki z kodem dla CUDA.Pozostaje jeszcze jedna niezbędna rzecz, a mianowicie CUDA Visual Wizard, czyli plugin dla MS Visuala pozwalający nam na łatwą obsługę projektów CUDA. Pakiet instalacyjny znajduje się na http://sourceforge.net/projects/cudavswizard.

Page 29: Software Developers Journal PL 03/2009

03/200928

WarsztatyCUDA się zdarzają, czyli programowanie GPGPU

www.sdjournal.org 29

Argumentami funckji cudaMemcpy są kolej-no: wskaźnik pamięci docelowej, wskaźnik pa-mięci źródłowej, wielkość kopiowanej pamię-ci oraz kierunek kopiowania. W tym ostatnim mamy dostępne jeszcze dodatkowo dwie opcje: cudaMemcpyHostToHost oraz cudaMemcpyDeviceToDevice. Ich znaczenie wynika z samych nazw.

Pierwszy kernelNadszedł moment na zaimplementowanie funkcji wykonywanej po stronie GPU (tzw. ją-dra, ang. kernel). Na Listingu 4. przedstawia-my pierwszą wersję, bez użycia pamięci współ-dzielonej. Jest to dość prosta modyfikacja funk-cji dla CPU.

Pierwsze rzuca się w oczy słowo kluczowe __global__. Funkcje nim poprzedzone będą skompilowane i wykonywane na GPU wielowąt-kowo, a dokładniej każdy wątek raz wykona taką funkcję. Fakt ten tłumaczy nieobecność pętli w kodzie jądra, w porównaniu z kodem

przeznaczonym do wykonywania na CPU. Taki właśnie był nasz cel: zamiast robić obli-czenia sekwencyjnie w pętli, chcieliśmy wyko-nać je wszystkie jednocześnie w sposób równo-legły. Index idx identyfikuje wątek, a do zna-czenia parametrów blockIdx.x, blockDim.x, threadIdx.x zaraz wrócimy. Zwróćmy uwa-gę, że wątki o indeksie większym niż liczba da-nych nie będą wykonywać obliczeń: if(idx >= data_size) return;, zaś wątki o dwóch naj-mniejszych i dwóch największych indeksach wykonają obliczenia na podstawie formuły dwupunktowej.

Rozważmy teraz sposób wywołania takiej funkcji (patrz: Listing 5.).

Dość ciekawie wygląda składnia: . Tutaj są podawane parametry dla konfiguracji wywoła-nia jądra: rozmiar siatki bloków (grid) oraz roz-miar każdego bloku. Następnie jest miejsce na podanie argumentów funkcji. Zwróćmy uwa-gę na użycie typu dim3. Jest to struktura trzech liczb całkowitych ( x, y, z ), używana do określa-nia rozmiarów. Nasz przykład jest jednowymia-rowy, więc nie definiowaliśmy pozostałych pól. W tym przypadku zostały one automatycznie zainicjalizowane jako 1.

Z eksperymentów wynikło, że najlepsza ze względu na wydajność wartość dla BLOCK_

WIDTH to 256 (w przypadku karty Nvidia Ge-Force GTX280). Ponieważ wielkość bloku i tak jest dość mocno ograniczona ( w przy-padku tej karty to 512), bloki te grupuje-my jeszcze w siatkę ( tutaj maksymalny roz-miar wynosi już 65535). Mamy zatem skon-figurowane uruchomienie jądra na dokładnie numBlocks * numThreadsPerBlock wątkach. Nietrudno wyliczyć, że występuje tu pewien nadmiar w stosunku do DATA_SIZE, wynikają-cy oczywiście ze sposobu wyliczenia ilości blo-ków numBlocks. Istotniejszym jednak parame-trem, z punktu widzenia szybkości, jest tu-taj wielkość bloku numThreadsPerBlock, na-

wet gdyby miało być nieznacznie więcej wąt-ków ogółem.

Wróćmy teraz do sposobu indeksowania wątków w kodzie jądra:

int idx = blockIdx.x*blockDim.x +

threadIdx.x; W momencie wykonania ko-du jądra mamy dostęp do wartości określa-jących:

• rozmiar bloku – blockDim – jest to zmienna typu dim3 i jak już wcześniej wspomnieliśmy, w naszym przykła-dzie interesuje nas blockDim.x. War-tość ta jest równa dokładnie skonfigu-

Kilka słów o GPGPUGPGPU (ang. General-purpose computing on graphics processing units) to po prostu wyko-nywanie obliczeń przy użyciu karty graficznej, zamiast procesora komputera. Początkowo technika ta była wykorzystywana głównie do wspierania procesu tworzenia grafiki kompu-terowej, jak np. proste obliczenia fizyczne. Z czasem karty graficzne zaczęto wyposażać w coraz to większą liczbę coraz szybszych procesorów (obecnie niektóre urządzenia mają ich grubo ponad 100). Dodatkowo rozmiar pamięci zainstalowanej na karcie graficznej zaczął dorównywać rozmiarom standardowego RAMU. W naturalny więc sposób GPGPU wykro-czyło poza ramy grafiki komputerowej i znajduje olbrzymią liczbę zastosowań w zasadzie wszędzie tam, gdzie do tej pory CPU było bezkonkurencyjne. W przypadku masowych ob-liczeń równoległych można nawet śmiało powiedzieć, że obliczenia na CPU już zwyczjanie się nie opłacają, gdyż na GPGPU możemy uzyskać czasem nawet kilkusetkrotne przyspiesze-nie. Użytkownicy domowi na pewną będą odczuwać coraz więcej korzyści z rozwoju techno-logii GPGPU. Nawet bardzo tanie karty graficzne już są w stanie wspierać np. obróbkę zdjęć, kodeki audio/wideo, itd. Natomiast wymagający naukowcy mogą sobie zafundować syste-my oparte na kilku mega wydajnych kartach uzyskując superkomputer za stosunkowo nie-wielkie pieniądze.

Co to właściwie jest CUDA?CUDA (ang. Compute Unified Device Architecture) jest stworzoną przez firmę NVidia architek-turą dla obliczeń równoległych z wykorzystaniem karty graficznej. Dzięki API CUDA technika GPGPU jest jeszcze prostsza, nie musimy bowiem odwoływać się do API typowo graficzne-go, jak np. Shading Language. Dostępne są także gotowe biblioteki dla algebry liniowej, czy transformaty Fouriera. Jako nowość pojawia się szybka pamięć współdzielona, co jeszcze bardziej uatrakcyjnia GPGPU z CUDA. Językiem programowania dla CUDA jest język C, ale ist-nieją także nakładki dla Fortrana, Pythona czy Javy. Oczywiście technologia ta jest dostęp-na tylko dla urządzeń wyporodukowanych przez NVidię, a pełną ich listę znajdziemy w lin-ku podanym w ramce W Sieci. Konkurencja też nie śpi i np. AMD rozwija alternatywną tech-nologię o nazwie FireStream. Niedawno powstał nowy standard OpenCL, który jest niezależ-nym od urządzenia sposobem pisania programów dla obliczeń równoległych, podobnie jak OpenGL dla grafiki 3D.

Rysunek 1. Formuła pięciopunktowa dla przybliżonej pochodnej funkcji

����������� ������������� � ������������������������������������

���

Rysunek 2. Formuły dwupunktowe dla przybliżonej pochodnej funkcji

����������� ������������������

����������� ������ � ���������

Listing 1. Implementacja przykładu numerycznego

void HostFunction(float* in, float* out, float den, int data_size){

int idx;

for(idx = 0; idx<2; idx++);

out[idx] = ( in[idx+1] - in[idx] ) * den;

for(idx=2; idx<data_size-2; idx++){

out[idx] = ( in[idx-2] - 8*in[idx-1] + 8*in[idx+1]

-in[idx+2] )*den*0.083333333f; //1/12h;

}

for(idx = data_size - 2; idx< data_size; idx++)

out[idx] = ( in[idx] - in[idx-1] ) * den;

}

Page 30: Software Developers Journal PL 03/2009

03/200930

WarsztatyCUDA się zdarzają, czyli programowanie GPGPU

www.sdjournal.org 31

rowanej przez nas uprzednio wartości numThreadsPerBlock;

• indeks bloku dla aktualnego wątku – blockIdx.x;

• indeks aktualnego wątku w obrębie bloku, do którego przynależy – threadIdx.x.

W naszym przykładzie threadIdx.x przyjmu-je wartości od 0 do 256 maksymalnie i jest of-fsetem, podszas gdy blockIdx.x*blockDim.x jest segmentem.

Z punktu widzenia CPU jądro jest wykony-wane asynchronicznie. Chcąc na nie poczekać użyliśmy cudaThreadSynchronize();

Debuggowanie i emulacjaW trybie Debug mamy możliwość debugowania tylko części kodu dla CPU. Niestety nie jest moż-liwe śledzenie kodu bezpośrednio wykonywane-go w GPU. Na szczęście istnieją tryby emulacji, w których kod napisany dla GPU wykonuje się na CPU, dając nam możliwość pełnego debuggowa-nia (tryb EmuDebug). Przeważnie chcemy w ten sposób sprawdzić poprawność zaimplementowa-nego przez nas algorytmu, zwłaszcza gdy stosuje-my kolejne optymalizacje. W trybie emulacji wąt-ki (a w tym wypadku raczej pojedyncze urucho-mienia kodu jądra ) wykonają się sekwencyjnie, jednak w losowej kolejności. Należy pamiętać, że w tym trybie kod może się wykonywać o wiele dłużej, dlatego na potrzeby takiego debuggowania warto czasem zmniejszyć znacznie rozmiar da-nych, wielkość bloku czy też siatki bloków. Nawet jeśli mamy tablice o milionowych rozmiarach do przetworzenia, często warto najpierw uzyskać po-prawny algorytm w trybie emulacji nawet na ta-blicach kilkunasto elementowych.

Obsługa błędów i specyfikacja urządzeniaOczywiście błędy były, są i będą, więc CUDA również dostarcza nam mechanizm ich obsłu-gi. Prosty sposób jego wykorzystania przedsta-wiony jest na Listingu 6.

Wspomnieliśmy wcześniej, że w przypadku karty GTX280 maksymalna wartość dla roz-miaru bloku to 512. W niektórych modelach nawet 256 może być nieosiągalne. Aby nasz kod był bardziej przenośny (z punktu widze-nia karty graficznej obsługującej CUDA), po-winniśmy parametr BLOCK_WIDTH uzależnić od urządzenia. Na Listingu 7. pokazujemy spo-sób odczytania maksymalnej wartości rozmia-ru bloku (zakładamy tutaj, że jeśli w ogóle, to zainstalowana jest tylko jedna karta graficzna z CUDA).

Nazwy użytych tutaj funkcji są dość opiso-we, więc nie będziemy wchodzić w szczegóły. Dostępny jest też cały szereg innych informa-cji o naszym urządzeniu, jak. np. rozmiar pa-mięci globalnej czy współdzielonej, maksy-malne rozmiary dla siatki bloków itd.; wszyst-kie te wartości można uzyskać w analogicz-ny sposób.

Listing 2. Alokacja i zwalnianie pamięci poprzez funkcje C oraz CUDA

size_t mem_size = DATA_SIZE * sizeof(float);

//host memory allocation

float* h_in;

h_in = (float *) malloc (mem_size);

//device memory allocation

float* d_in;

cudaMalloc( (void **) &d_in, mem_size );

free(h_in);

cudaFree(d_in);

Listing 3. Kopiowanie pamięci w CUDA

cudaMemcpy(d_in, h_in, mem_size, cudaMemcpyHostToDevice);

cudaMemcpy(h_out, d_out, mem_size, cudaMemcpyDeviceToHost);

Listing 4. Implementacja funkcji uruchamianej na GPU

__global__ void CudaKernel(float* d_in,

float* d_out,

float den, int

data_size){

int idx = blockIdx.x*blockDim.x + threadIdx.x;

if(idx >= data_size) return;

if( idx < 2 ){

d_out[idx] = ( d_in[idx+1] - d_in[idx] ) * den;

return;

}

if( idx >= (data_size – 2)){

d_out[idx] = ( d_in[idx] - d_in[idx-1] ) * den;

return;

}

d_out[idx] = ( d_in[idx-2]-8*d_in[idx-1];

+ 8*d_in[idx+1] - d_in[idx+2] );

*den*0.083333333f; // 1/12h;

}

Listing 5. Konfiguracja i uruchomienie jądra

#define BLOCK_WIDTH 256

#define DATA_SIZE 10000000

#define DATA_STEP 0.0001f

int numBlocks = DATA_SIZE/BLOCK_WIDTH + 1;

int numThreadsPerBlock = BLOCK_WIDTH;

dim3 dimGrid(numBlocks);

dim3 dimBlock(numThreadsPerBlock);

float denominator = 1.0/DATA_STEP;

CudaKernel<<< dimGrid, dimBlock >>>

(d_in, d_out, denominator, DATA_SIZE);

cudaThreadSynchronize();

Page 31: Software Developers Journal PL 03/2009

03/200930

WarsztatyCUDA się zdarzają, czyli programowanie GPGPU

www.sdjournal.org 31

Optymalizacja jądra poprzez użycie pamięci współdzielonejPomimo że już na tym etapie uzyskaliśmy nie-złą prędkość obliczeń, to nadal istnieje możli-wość zwiększenia wydajności jądra. Każde od-wołanie do tablicy d_in kosztuje od 400 do 600 cykli, gdyż tablica ta jest ulokowana w pamię-ci globalnej GPU, a pamięć ta nie jest w żaden sposób buforowana. Co więcej, łatwo zauwa-żyć, że kilka wątków będzie czytać naraz z tej samej lokalizacji. Jest to konsekwencją natury naszego zadania numerycznego: dla wykonania obliczeń dla bieżącego indeksu odczytujemy dwie poprzednie i dwie następne wartości w ta-blicy. Idealna sytuacja występuje, gdy mamy do czynienia z odczytem jednorodnym (ang. coale-sced ), kiedy to na jeden wątek przypada jeden i dokładnie jeden adres tablicy. Niestety nie za-wsze możemy zmodyfikować nasz algorytm, aby spełniał ten warunek. Możemy wtedy użyć pamięci współdzielonej, z której to odczyt wy-nosi tylko 4 cykle. Pamięć ta jest wspólna w ob-rębie jednego bloku, więc jeśli każdy wątek z bloku wczyta jedną wartość z pamięci global-nej do pamięci współdzielonej, to potem war-tości te będą dostępne dla wszystkich wątków w bloku już z poziomu pamięci współdzielo-nej. Zaimplementujmy jeszcze raz nasze jądro (patrz Listing 8.).

Znaczenie pierwszej linijki kodu jądra za-raz omówimy. Zwróćmy uwagę, że teraz ją-dro jest podzielone na dwie sekcje. W pierw-szej odbywa się kopiowanie pamięci z global-nej do współdzielonej. Zanim jednak przejdzie-my do obliczeń, a tym samym do odczytu war-tości, musimy mieć pewność, że wszystkie wąt-ki zakończyły już to kopiowanie. Właśnie do tej synchronizacji służy __syncthreads(). W dru-giej sekcji wykonywane są obliczenia tak jak w pierwszej wersji jądra, z tym, że odczytujemy wartości już z tablicy shared[]. Tablica z dany-mi wejściowymi jest teraz rozdzielona między fragmenty (Rysunek 4.).

Każdemu fragmentowi odpowiada blok wąt-ków, a więc i każdy taki fragment jest wczytywa-ny do odpowiadającej pamięci współdzielonej. Ponieważ jednak nasz wzór numeryczny wy-maga dwóch poprzednich oraz dwóch następ-nych punktów w stosunku do aktualnego, to do tablicy shared[] wczytujemy również dwa po-przedzające fragment danych punkty, jak i dwa następujące po fragmencie (patrz Rysunek 5.). Punkty poprzedzające są wczytywane przez dwa pierwsze wątki w bloku, pod warunkiem, że nie są pierwszymi globalnie. Analogicznie punk-ty następujące są wczytywane przez dwa ostat-nie wątki w bloku, pod warunkiem też, że nie są ostatnimi globalnie. Wpłynęło to też na przesu-nięcie indeksów w sekcji obliczeniowej w porów-naniu z pierwszą wersją jądra.

Na Listingu 9. widzimy, jak zmieni się nie-znacznie sposób wywołania takiego jądra.

Pojawił się trzeci parametr konfiguracji i oznacza on wielkość pamięci współdzielo-

nej na każdy blok. Wyjaśnia się teraz znacze-nie pierwszej linii w kodzie jądra: rozmiar ta-

blicy shared[] w pamięci współdzielonej jest ustalany w momencie uruchamiania jądra, co

Listing 6. Obsługa błędów w CUDA

cudaError_t error = cudaGetLastError();

if( cudaSuccess != error)

{

fprintf(stderr, "Cuda error: %s.\n",

cudaGetErrorString( error ) );

exit(-1);

}

Listing 7. Przykład odczytania specyfikacji karty graficznej

int maxThreadsPerBlock;

int deviceCount;

if ( deviceCount > 0 )

{

cudaDeviceProp deviceProp;

cudaGetDeviceProperties(&deviceProp, 0);

maxThreadsPerBlock = deviceProp.maxThreadsPerBlock;

}

Listing 8. Implementacja funkcji uruchamianej na GPU z użyciem pamięci współdzielonej

__global__ void CudaKernel_sharedmem( float* d_in,

float* d_out, float den, int data_size)

{

extern __shared__ float shared[];

int idx = blockIdx.x * blockDim.x + threadIdx.x;

if(idx >= (data_size))

return;

if( (threadIdx.x < 2) && (idx >= 2) ) {

shared[threadIdx.x] = d_in[idx – 2];

}

if( (threadIdx.x>=(blockDim.x-2))&&(idx<(data_size-2))){

shared[threadIdx.x + 4] =d_in[idx + 2];

}

shared[threadIdx.x + 2] = d_in[idx];

__syncthreads();

if(idx<2){

d_out[idx] =(shared[threadIdx.x+3]

return;

}

else if( idx >= (data_size – 2)){

d_out[idx] =(shared[threadIdx.x+2]

- shared[threadIdx.x+1] )*den;

return;

}

d_out[idx] =(shared[threadIdx.x]

- 8*shared[threadIdx.x+1]

+ 8*shared[threadIdx.x+3]

- shared[threadIdx.x+4])

*den*0.083333333f;

}

Page 32: Software Developers Journal PL 03/2009

03/200932

WarsztatyCUDA się zdarzają, czyli programowanie GPGPU

www.sdjournal.org 33

uzyskujemy poprzez użycie słowa kluczowego extern. Oczywiście, można też ręcznie usta-lić wielkość tablicy w pamięci współdzielo-nej, należy jednak pamiętać o ograniczeniach jej wielkości.

Profilowanie i porównanie czasów wykonaniaChcielibyśmy teraz zobaczyć różnicę między dwiema wersjami naszego jądra ze względu na prędkość wykonania, najlepiej przy uży-ciu jakiegoś profilera. Na stronie Nvidii do-stępny jest CUDA Visual Profiler, posiadający proste GUI, którego nie będziemy tu jednak-że opisywać. Jego działanie jest podobne do metody, którą użyjemy bezpośrednio. Mia-nowicie, po pierwsze musimy włączyć pro-filowanie.

Otwieramy w tym celu właściwości projek-tu w MS Visualu i w sekcji Debugging w po-lu Environment wpisujemy CUDA_PROFILE=1;. Dzięki temu, po uruchomieniu naszego pro-gramu, powinien pojawić się plik cuda_pro-file.log o treści przypominającej tę z Listin-gu 10.

W nawiasach kwadratowych podane są cza-sy w mikrosekundach. Łatwo zauważyć (para-metr gputime), iż rzeczywiście zoptymalizo-wane jądro wykonuje się mniej więcej dwa ra-zy szybciej. Widać również, że raczej wąskim gardłem jest tutaj kopiowanie pamięci do i z GPU (gputime dla metod memcopy). Profiler posiada cały szereg dodatkowych opcji i para-metrów. Zainteresowanych odsyłamy do do-kumentacji CUDA, do pliku CUDA_Profi-ler_2.0.txt.

Podobne wnioski można wyciągnąć, gdy ręcznie zmierzymy w naszym programie czasy wykonania. I tak, czas wykonania al-gorytmu na CPU wyniósł 0.15160 sekun-dy, pierwsza wersja jądra: 0.04360, zaś wer-sja zoptymalizowana: 0.04062, przy czym w dwóch ostatnich przypadkach jest sumo-wany czas skopiowania danych na GPU, wy-konanie kodu jądra oraz ponowne skopio-wanie danych wynikowych na stronę CPU. Pomiary te są bliższe stanu faktycznego, gdyż wynik profilera nie uwzględnił czasu CPU poświęconego kopiowaniu danych. W obu przypadkach ustawiliśmy DATA_SIZE = 10000000.

Rysunek 4. Fragment danych. Odczyt może być spoza fragmentu

������� ������� ����� ������� ������� ��������� ��������� ��������� ��������� ������� ���������

�����������������������

��� ��� ���

�������� ������ ����������� ��� ���������� ���������� ������������� ���

Listing 9. Konfiguracja uruchomienia jądra z pamięcia współdzieloną

int sharedMemSize = (numThreadsPerBlock+4)*sizeof(float);;

CudaKernel_sharedmem<<< dimGrid, dimBlock, sharedMemSize>>>;

(d_in_1, d_out_1, den, DATA_SIZE);

Listing 10. Treść pliku cuda_profile.log

method,gputime,cputime,occupancy;

method=[ memcopy ] gputime=[ 11782.849 ] ;

method=[ __globfunc__Z10CudaKernelPfS_fi ] gputime=[ 2552.960 ] cputime=[ 6.681 ];

occupancy=[ 1.000 ];

method=[ memcopy ] gputime=[ 12483.425 ] ;

method=[ memcopy ] gputime=[ 11782.017 ] ;

method=[ __globfunc__Z20CudaKernel_sharedmemPfS_fi ] gputime=[ 1292.928 ]; cputime=[

6.459 ] occupancy=[ 1.000 ];

method=[ memcopy ] gputime=[ 11780.385 ]

Listing 11. Alokacja i dealokacja w pamięci niestronicowanej

//host memory allocation

cudaMallocHost( (void**) &h_in, mem_size);

cudaFreeHost(h_in);

Listing 12. W funkcji HostFunction dodajemy pętlę aby zasymulować więcej obliczeń

for(idx=2; idx<data_size-2; idx++);

for(int i=0; i<200; i++);

out[idx] =(in[idx-2]-8*in[idx-1];

+8*in[idx+1]–in[idx+2];

Rysunek 3. Zależność danych wyjściowych od wejściowych

�����

������

��������������������

������ ������

������� ������� ����� ������� �������

�������� ������ ��������

���

���

��� ����

��� ���

Page 33: Software Developers Journal PL 03/2009

03/200932

WarsztatyCUDA się zdarzają, czyli programowanie GPGPU

www.sdjournal.org 33

Nasz problem numeryczny nie był zbyt skomplikowany obliczeniowo w tym sensie, że jeden wątek (jedno przekręcenie pętli) nie wy-konywał zbyt wielu operacji. Z otrzymanych tutaj wyników można wysnuć śmiało wnio-sek, iż wysiłek włożony w optymalizację ją-dra może nie zawsze się opłacać. Oczywiście o wiele łatwiej jest napisać kod jądra nie uży-wając pamięci współdzielonej i może to czasa-mi być wystarczające. Nietrudno jednak wy-obrazić sobie sytuację, gdy obliczenia są o wie-le bardziej skomplikowane lub gdy kod jądra jest intensywnie wykonywany bez kopiowania danych (np. generacja tekstury, złożone symu-lacje w pętli).

Pamięć niestronicowanaCUDA posiada bardzo ciekawy mechanizm pozwalający na użycie pamięci niestronico-wanej (ang. page-locked). Z grubsza wystar-czy nam tutaj takie rozróżnienie, że pamięć zaalokowana w pamięci stronicowanej, czy-li przy użyciu standardowego malloc'a, w pierwszej kolejnośći jest kopiowana do pa-mięci niestronicowanej, a dopiero w drugiej kolejności poprzez DMA, do pamięci GPU. W przypadku pamięci niestronicowanej ma-my do czynienia tylko z tym drugim etapem. Aby zastosować tę dogodność, zmodyfiku-jemy część kodu z Listingu 2. do kodu z Li-stingu 11.

Po tej modyfikacji mierzymy ponownie cza-sy wykonania i otrzymujemy odpowiednio dla obu wersji jądra: 0.02628 oraz 0.02526 sekun-dy. Zatem wąskie gardło dało się trochę rozsze-rzyć. Trzeba jednak pamiętać, że pula pamięci niestronicowanej jest o wiele mniejsza niż stro-nicowanej i nie należy przesadzać z tego typu alokacjami.

Obliczenia asynchroniczneWspomnieliśmy wcześniej, że jądro jest wyko-nywane asynchronicznie z punktu widzenia CPU. Dodatkowo kopiowanie z pamięci nie-stronicowanej nie obciąża CPU. CUDA korzy-sta z tych faktów udostępniając asynchronicz-ne API, dzięki któremu da się wykonać nastę-pujący scenariusz:

• dane są kopiowane do pamięci GPU;• następnie na tych danych jest wykonywa-

ny kod jądra, a w tym samym czasie trwa kopiowanie kolejnych danych;

• dane wynikowe z 1. są kopiowane z GPU, a w tym czasie na drugich danych wykonuje się kod (być może innego) ją-dra;

• powrót do kroku 1.

Co więcej, w tym samym czasie da się jesz-cze czasami wcisnąć jakieś obliczenia na CPU, gdyż operacje na CPU, GPU oraz kopiowanie pomiędzy nimi wykonywane są niezależnie względem siebie.

Na bazie naszego przykładu zrealizujemy po-wyższy scenariusz i wykonamy kolejne ekspery-menty, porównując z czasem wykonania na CPU. Aby zasymulować większą złożoność obliczenio-wą, formuły wynikowe powtórzymy, powiedzmy, ze 200 razy w HostFunction (patrz Listing 12.).

i analogicznie w kodzie jądra CudaKernel_sharedmem. Na Listingu 13. widzimy kod, jaki wykonamy po stronie CPU, zaś na Listingu 14. odpowiadającą mu adaptację dla GPU z uży-ciem asynchronicznego API.

Najpierw tworzymy identyfikatory dla dwóch strumieni. Strumień jest ciągiem se-kwencyjncyh operacji, ale dwa strumienie są wobec siebie asynchroniczne. Do utworzenia i zamknięcia strumienia służą odpowiednio: cudaStreamCreate oraz cudaStreamDestroy, zaś funkcja cudaStreamSynchronize wstrzy-muje program, aż wszystkie operacje w stru-mieniu się nie zakończą. Aby kopiowanie danych było asynchroniczne, musimy po pierwsze użyć funkcji cudaMemcpyAsync za-

Rysunek 5. Schemat bloków wątków i odpowiadających im pamięci współdzielonych

����������������������������

� � � � � � ��� ��� ���

� � � ��� ���

������� ������� ����� ������� ������� ������ ��������� ��������� ������� ���������

����� ����� ����� ����� �����

������

������������������������������

� � � � � � ��� ��� ���

��������� ��������� ������� ��������� ���������

� � � ��� ���

����� ����� ����� ����� �����

������

������

������ �������������

�������� �������������

Listing 13. Dziesięciokrotne wywokonanie HostFunction dla dwóch tablic

for(int i=0;i<10;i++){;

if(i%2 == 0);

HostFunction(h_in_1,h_out_1,den,DATA_SIZE);;

else;

HostFunction(h_in_2,h_out_2,den,DATA_SIZE);;

}

Page 34: Software Developers Journal PL 03/2009

03/200934

Warsztaty

miast cudaMemcpy, podając dodatkowo jako ostatni argument identyfikator strumienia, a po drugie pamięć po stronie CPU musi być zaalokowana w pamięci niestronicowanej. Jeśli o tym zapomnimy, to niestety kompila-tor tego nie wykryje i błąd pojawi się dopie-ro w trakcie wykonania programu – i to za-kładając, że sami przechwytujemy te błędy. Czyli najbezpieczniej jest po prostu po każ-

dej operacji przy użyciu API CUDA spraw-dzić ostatni błąd. Jest to dość żmudne i ra-czej psuje czytelność kodu, dlatego też we wszystkich listingach pomijaliśmy obsłu-gę błędów.

Za to w tym momencie dajemy przykład na to, że lekceważenie tego problemu może spra-wić przykre niespodzianki. Wracając do Li-stingu 13. zwracamy jeszcze uwagę, że iden-

tyfikatory strumieni pojawiają się także jako ostatni parametr konfiguracji jądra.

PodsumowanieW podsumowaniu podajemy rezultaty cza-sowe ostatniego eksperymentu: dla CPU było to 62.86327 sekund, zaś dla GPU 1.29735. Można by rzec, że wyniki mówią same za siebie. Czy są imponujące, pozosta-wiamy do subiektywnej oceny. Panuje opi-nia, że GPU liczy coś tam, coś tam setki ra-zy szybciej niż CPU. W niektórych zastoso-waniach, a zwłaszcza w takich, gdzie nie ma-my do czynienia z kopiowaniem dużej ilości danych pomiędzy CPU i GPU, takie wyniki są jak najbardziej osiągalne. Jeśli jednak mó-wimy o GPGPU w pełni tego słowa znacze-niu, to nie możemy zapominać o wąskim gardle. Co więcej, operacje dzielenia i mno-żenia na liczbach całkowitych jak na razie są beznadziejnie wolne w porównaniu z ich od-powiednikami dla liczb zmiennoprzecinko-wych, a te z kolei kosztem szybkości są po-zbawione czasami należytej dokładności. No cóż, w końcu karty graficzne zostały stwo-rzone do grafiki. Na pewno jednak GPU wraz z CUDA jest świetnym poszerzeniem możliwości obliczeniowych oferowanych przez CPU. Najlepiej jednak wykorzystywać oba równocześnie, gdyż nie zawsze CUDA będzie w stanie czynić cuda.

Listing 14. Adaptacja do wersji CUDA kodu z Listingu 13

cudaStream_t stream_one, stream_two;

cudaStreamCreate(&stream_one);

cudaStreamCreate(&stream_two);

for(int i=0;i<10;i++)

{

if(i%2 == 0){

cudaMemcpyHostToDevice,stream_one);

CudaKernel_sharedmem<<< dimGrid, dimBlock,

sharedMemSize, stream_one >>>

(d_in_1, d_out_1, den, DATA_SIZE);

cudaMemcpyAsync(h_out_1,d_out_1,mem_size,

cudaMemcpyDeviceToHost,stream_one);

}

else{

cudaMemcpyAsync(d_in_2,h_in_2,mem_size,

cudaMemcpyHostToDevice,stream_two);

CudaKernel_sharedmem<<< dimGrid, dimBlock,

sharedMemSize, stream_two >>>

(d_in_2, d_out_2, den, DATA_SIZE);

cudaMemcpyAsync(h_out_2,d_out_2,mem_size,

cudaMemcpyDeviceToHost,stream_two);

}

}

cudaStreamSynchronize(stream_one);

cudaStreamSynchronize(stream_two);

cudaStreamDestroy(stream_one);

cudaStreamDestroy(stream_two);

W Sieci

• http://www.nvidia.pl/object/cuda_what_is_pl.html – strona firmowa CUDA;• http://www.nvidia.pl/object/cuda_learn_products_pl.html – lista urządzeń wspierających CUDA;• http://sarathc.wordpress.com/2008/09/26/how-to-integrate-cuda-with-visual-c/ – alternatywny sposób integracji CUDA z Visualem C++;• http://en.wikipedia.org/wiki/CUDA – ogólnie o CUDA;• http://www.ddj.com/architect/207200659 – cykl świetnych artykułów wprowadzających do programowania z CUDA;• http://heim.ifi.uio.no/~knutm/geilo2008/seland.pdf – wprowadzenie do CUDA w formie prezentacji;• http://www.gpgpu.org/ - strona poświęcona GPGPU nie tylko z CUDA.

JACEK PIEKARSKIPracuje na stanowisku programisty w firmie BLStre-am wchodzącej w skład Grupy BLStream. Grupa BLStream powstała, by efektywniej wykorzystywać potencjał dwóch, szybko rozwijających się produ-centów oprogramowania – BLStream i Gamelion. Firmy wchodzące w skład grupy specjalizują się w wytwarzaniu oprogramowania dla klientów kor-poracyjnych, w rozwiązaniach mobilnych oraz pro-dukcji i testowaniu gier. Kontakt z autorem: [email protected]

BibliografiaW zasadzie literatura papierowa do CUDA jeszcze nie istnieje, ale zachęcamy do lektury następujących:

• NVIDIA_CUDA_Programming_Guide_1.1.pdf – po zainstalowaniu CUDA dokument dostępny w katalogu docs/;• http://sites.google.com/site/cudaiap2009/materials-1/cuda-textbook – panowie David Kirk oraz Prof. Wen-mei Hwu udostępnili nam fragmenty

książki, którą przygotowują.

Page 35: Software Developers Journal PL 03/2009

www.sdjournal.org

Opis CD

Jeśli nie możesz odczytać zawartości płyty CD, a nie jest ona uszkodzona mechanicznie, sprawdź ją na co najmniej dwóch napędach CD. W razie problemów z płytą, prosimy pisać pod adres: [email protected]

Redakcja nie udziela pomocy technicznej w instalowaniu i użytkowaniu programów

zamieszczonych na płytach CD-ROM dostarczonych razem z pismem.

35

UIQ 3.3 Beta SDKUIQ SDK to zestaw narzędzi UIQ, Symbiana i innych. SDK to ze-staw narzędzi kontrolowanych przez skrypty Perl. Nowości w in-terfejsie to: pełne wykorzystanie możliwości Opery Mobile 9 (szyb-kie ładowanie stron, usprawnienie Zoomu), wprowadzenie obsłu-gi usługi Widget za pomocą specjalnie przygotowanego pulpitu, usprawnienie obsługi Opery za pomocą szybko dostępnych funkcji, ujednolicony system wiadomości oraz obsługa Java JSR 248 MSA.

IP*Works! SSLDo IP*Works! dodano bezpieczeństwo SSL i zarządzanie certy-fikatami cyfrowymi. IP*Works! SSL – to wszechstronny zestaw komponentów ze wsparciem SSL w celu zapewnienia bezpiecznej pracy wszystkich protokołów internetowych.

IP*Works! Secure SNMPIP*Works! Secure SNMP to wszechstronne narzędzie do two-rzenia bezpiecznych agentów SNMP i menadżerów aplika-

cji. IP*Works! Secure SNMP wspiera pełny zakres możliwo-ści zarządzania siecią, łącznie z rozszerzonymi właściwościa-mi bezpieczeństwa SNMPv3, opracowanie pułapek, i kompi-lację ASN-1 MIB.

IP*Works! ZipZestaw łatwych, szybkich i efektywnych komponentów, któ-ry daje informatykom możliwość dodawania funkcji kompresji do swoich aplikacji. IP*Works! Zip umożlwia szybka integrację funkcji kompresji i rozpakowywania do aplikacji, wykorzystując do tego standardy kompresji Zip, Tar, Gzip lub Jar.

Inne Trialowe wersje kilkunastu produktów firmy nsoftware

Page 36: Software Developers Journal PL 03/2009

03/200936

WarsztatyFacebook dla programistów

www.sdjournal.org 37

Facebook (www.facebook.com) jest ser-wisem społecznościowym, dzięki któ-remu, jak piszą o nim jego autorzy, mi-

liony użytkowników na całym świecie każ-dego dnia mogą odszukiwać swoich znajo-mych, przesyłać nieograniczoną liczbę zdjęć, udostępniać linki i pliki wideo i dowiadywać się coraz więcej o poznanych tam ludziach, a wszystko po to, żeby świat był coraz bardziej otwarty i połączony. Projekt został urucho-miony 4 lutego 2004 roku przez studenta Uniwersytetu Harvard – Marka Zuckerber-ga i obecnie posiada ponad 120 mln aktyw-nych użytkowników na całym świecie. We-dług rankingu Forbes Magazine z 2008 ro-ku Zuckerberg został najmłodszym miliar-derem świata.

Z punktu widzenia programisty Facebook jest tym bardziej interesujący, że umożliwia tworzenie i publikowanie własnych aplikacji dla tej platformy.

Dzięki temu możemy zrealizować zasa-dę: jeśli brakuje Ci funkcjonalności dostar-czonej przez twórców serwisu, rozbuduj go o to, co potrzebujesz i jeśli masz taką ochotę,

udostępnij efekty swojej pracy innym człon-kom społeczności. Katalog aplikacji podzie-lony jest na kilkadziesiąt kategorii, w któ-rych można znaleźć zarówno eksperymen-talną aplikację do weryfikacji teorii o sze-ściu stopniach separacji – Six Degrees, jak i aplikację umożliwiającą komponowanie no-wych potraw i ocenę ich smaku przez wła-snych znajomych.

Jak działają aplikacje FacebookaSchemat działania każdej zewnętrznej apli-kacji Facebooka przedstawiony jest na Rysun-ku 1.

Za każdym razem, kiedy użytkownik do-konuje interakcji z naszą aplikacją (1) je-go żądanie poprzez jeden z serwerów ser-wisu społecznościowego przekazywane jest do serwera, na którym hostowana jest na-sza aplikacja (2). W odpowiedzi na to żąda-nie aplikacja przygotowuje odpowiedź w for-macie FBML, którą przekazuje do serwera Facebooka (5). Jednym z kroków przygoto-wania takiej odpowiedzi może być dodatko-wa komunikacja z serwerami platformy po-przez wywołanie jednej z metod API lub za-pytanie FQL.

W kolejnym kroku nasza odpowiedź FBML tłumaczona jest do HTML i w takiej posta-ci przesyłana jest do przeglądarki użytkowni-ka (6).

Rozpoczynamy pracęTworzenie każdej aplikacji dla platformy Face-book należy rozpocząć od jej zarejestrowania i wygenerowania kluczy. Służy do tego dostępna dla każdego zarejestrowanego w serwisie użyt-kownika aplikacja o nazwie Twórca aplikacji (ang. Developer). Po wybraniu przycisku Set Up New Application zostaniemy przeniesieni do okna tworzenia nowej aplikacji.

Mimo iż jedynymi wymaganymi polami są nazwa aplikacji (ang. Application Name) oraz po-twierdzenie zapoznania się z regulaminem usłu-gi, warto w tym miejscu od razu skonfigurować pola Callback URL oraz Canvas Page URL, które umożliwią nam szybkie uruchomienie testowej aplikacji. Pierwsze z nich jest adresem, pod któ-rym fizycznie będzie dostępna nasza aplikacja (np. http://www.kozlowscy.org/facebook/

allegro), drugi parametr określa unikalną na-zwę, która posłuży do konstrukcji adresu, pod którym będzie widoczna nasza aplikacja (np. http://apps.facebook.com/allegro). Oczy-wiście wszystkie ustawienia aplikacji możemy później edytować. Do pierwszego uruchomie-nia naszej aplikacji pozostało nam tylko kilka kroków.

Po pierwsze do katalogu aplikacji na naszym serwerze musimy skopiować pliki oficjalnego klienta Facebooka (ang. official PHP Client Li-brary) oraz plik index.php, który możemy wyge-nerować automatycznie, korzystając z linka Get started quickly with some example code! Jeśli wy-wołamy teraz naszą aplikację, powinniśmy uj-rzeć listę naszych znajomych w serwisie (do-kładniej listę ich identyfikatorów).

Nasza aplikacja nie musi być oczywiście tworzona z wykorzystaniem wyżej wspo-mnianej biblioteki i języka PHP. Facebook API jest interfejsem opartym o wywołania REST zwracającym wyniki w formacie XML

Facebook dla programistów

Facebook jest nie tylko klasycznym serwisem społecznościowym, lecz także platformą umożliwiającą tworzenie własnych aplikacji. W artykule pokażemy jak przygotować i opublikować przykładową aplikację dla Facebooka współpracującą z serwisem aukcyjnym Allegro.

Dowiesz się:• jak stworzyć i opublikować aplikację dla plat-

formy Facebook,• w jaki sposób wykorzystać Facebook API,

FBML i FQL,• jak wykorzystać metody Allegro WebAPI.

Powinieneś wiedzieć:• znać podstawy tworzenia aplikacji webowych

(PHP, HTML, CSS),• znać podstawy programowania obiektowego,• znać podstawy języka SQL,• wiedzieć czym jest WebService i protokół SOAP.

Poziom trudności

Przygotuj własną aplikację dla użytkowników serwisu Facebook

Page 37: Software Developers Journal PL 03/2009

03/200936

WarsztatyFacebook dla programistów

www.sdjournal.org 37

lub JSON, a wynikiem wywołania naszej apli-kacji zwracanym do serwerów Facebook jest kod FBML. Możemy więc wykorzystać bi-blioteki dostępne dla innych języków (choć-by facebook-java-api http://code.google.com/p/facebook-java-api/) lub zdać się na własną im-plementację.

Wykorzystane technologie i narzędzia

Facebook APIFacebook API jest sieciową usługą opartą o REST udostępniającą kilkadziesiąt metod w kil-ku grupach tematycznych.

Facebook Markup Language (FBML)FBML jest zbiorem znaczników umożliwiają-cym integrację aplikację z platformą Facebooka. Składa się z podzbioru znaczników HTML oraz znaczników specyficznych dla Facebooka, np. fb:photo czy fb:dialog. Zwróćmy uwagę, że w zbiorze znaczników FBML nie ma np. znacznika body. Próba jego użycia w naszej aplikacji spowo-duje wystąpienie błędu ładowania strony i wy-świetlenie komunikatu w rodzaju:

Wystąpiły błędy podczas ładowania strony

aplikacji

Błędy składniowe:

FBML Error (line 184): illegal tag "body"

under "fb:canvas".

Komunikat taki pojawi się tylko w przypad-ku używania aplikacji przez jej programistów, dla pozostałych użytkowników niedozwolone znaczniki zostaną po prostu zignorowane. Pod-glądając źródła stron prezentowanych w przeglą-darce przez naszą aplikację, możemy zobaczyć, w jaki sposób tłumaczone są strony FBML do HTML. Jeśli jesteś programistą używanej aplika-cji, w komentarzach możesz także zobaczyć źró-dłowy FBML, który może okazać się przydatny w procesie debugowania.

Facebook Query Language (FQL)FQL umożliwia dostęp do tych samych danych, które możemy uzyskać za pomocą wywołań me-tod API, ale w stylu podobnym do zapytań języ-ka SQL. Tak naprawdę użycie sporej części metod API sprowadza się do wykonania określonych za-

Listing 1. Przykładowy szkielet naszej aplikacji wygenerowany automatycznie z Twórcy aplikacji

<?php

// Copyright 2007 Facebook Corp. All Rights Reserved.

//

// Application: test

// File: 'index.php'

// This is a sample skeleton for your application.

//

require_once 'facebook.php';

$appapikey = '0f88cc125f2c08e351541ae2ecabc985';

$appsecret = 'e7ada359998797e35f9422b2b960a2da';

$facebook = new Facebook($appapikey, $appsecret);

$user_id = $facebook->require_login();

// Greet the currently logged-in user!

echo "<p>Hello, <fb:name uid=\"$user_id\" useyou=\"false\" />!</p>";

// Print out at most 25 of the logged-in user's friends,

// using the friends.get API method

echo "<p>Friends:";

$friends = $facebook->api_client->friends_get();

$friends = array_slice($friends, 0, 25);

foreach ($friends as $friend) {

echo "<br>$friend";

}

echo "</p>";

?>

Rysunek 1. Schemat działania aplikacji Facebooka Rysunek 2. Struktura i lista plików aplikacji

������ ������� ���������

��������������������

����������������� ������

�������� ��� ���������� ������� ���������

���� ������������� �� ������

�������������������

���� �� �����

���������������������������

������������������

���� ������������� �����

��������������������������

�������������������

������������� �����

���������������� ������������������

����������������� �����

�������� ��� ���������������������

������������������

�����������������������

Page 38: Software Developers Journal PL 03/2009

03/200938

WarsztatyFacebook dla programistów

www.sdjournal.org 39

pytań FQL. Wykorzystując zapytania FQL, może-my zarówno ograniczyć liczbę niezbędnych żą-dań w porównaniu z wykorzystaniem tradycyj-nego API, jak i stosować złożone kryteria wyszu-kiwania. Poniżej przykładowe zapytanie zwraca-jące nam identyfikator, nazwę oraz datę urodzin wszystkich naszych znajomych.

SELECT uid, name, birthday FROM user WHERE

uid IN (SELECT uid2 FROM friend WHERE

uid1 = $fb_uid).

Typowe wywołanie zapytania FQL będzie wy-glądać następująco:

$query = "...";

$result = $facebook->api_client->fql_

query($query);

Narzędzia dla programistówStrona dla programistów Facebooka udostęp-nia między innymi narzędzia API Test Console i FBML Test Console. Z ich wykorzystaniem może-my przeprowadzać eksperymenty z parametra-

mi wywołań metod API i zwracanymi formata-mi danych, zapytań FQL i poprawnością wyko-rzystania znaczników FBML w poszczególnych elementach aplikacji.

Allegro WebAPIJak piszą sami autorzy, Allegro WebAPI to usłu-ga umożliwiająca wymianę informacji między ze-wnętrznymi aplikacjami a serwisem. Dzięki niej moż-na tworzyć programy ułatwiające m.in. zarządzanie transakcjami. Aby rozpocząć pracę z usługą, nale-ży być użytkownikiem Allegro i wystąpić o klucz aktywacji WebAPI-Key. Obecnie korzystanie z pakietu podstawowego, który zawiera około 70 metod jest bezpłatne, nie są także naliczane żad-ne opłaty za poszczególne wywołania. Szczegóło-wy opis usługi udostępniany jest za pomocą pli-ku WSDL (ang. Web Services Description Language) dzięki czemu możemy ją wykorzystać w każdym języku wspierającym obsługę protokołu SOAP.

Budujemy naszą aplikacjęGłównym plikiem aplikacji jest index.php, przez który przechodzą wszystkie wywołania i do które-

go w zależności od wartości parametru menu do-łączane są funkcją include odpowiednie skrypty. Struktura i lista wszystkich plików pokazana jest na Rysunku 2.

Kilka słów o bezpieczeństwieMusimy pamiętać, że zgodnie z architektu-rą przedstawioną na Rysunku 1. skrypty apli-kacji wykonywane są na naszym serwerze, i to na nas spoczywa zapewnienie jej bezpieczeń-stwa. Z tego też względu wprowadzona jest kontrola wartości parametru menu, żeby zapo-biec próbie nieuprawnionego dostępu lub wy-konania plików spoza naszej aplikacji, dodatko-wo w katalogu include umieściliśmy plik .htac-cess z wpisem

<FILES ~ ".php$">

Deny from all

</FILES>

dzięki czemu próba bezpośredniego wywoła-nia dowolnego pliku PHP z tego katalogu za-kończy się błędem.

Listing 2. Główny plik aplikacji index.php

<?php

// plik konfiguracyjny

require_once 'config.php';

// klient Facebooka

require_once 'facebook.php';

// klasa Allegro

require_once 'allegro.php';

// zestaw funkcji pomocniczych

require_once 'functions.php';

// utworzenie instancji klienta Facebooka

$facebook = new Facebook($config['facebook']['api-key'],

$config['facebook']['secret']);

// korzystanie z naszej aplikacji wymaga wcześniejszego

zalogowania

$fb_uid = $facebook->require_login();

// utworzenie instancji pomocniczej klasy obsługi serwisu

Allegro

$allegro = new Allegro($config);

?>

<style>

<?php echo htmlentities(file_get_contents('css/styles.css',

true)); ?>

</style>

<!-- dashboard -->

<fb:dashboard>

<?php

$menu = nvl($_REQUEST['menu'], 'my_auctions');

$items = array(

array('my_auctions', 'Moje aukcje', true),

array('friends_auctions', 'Aukcje znajomych', true),

array('search', 'Szukaj', true),

array('friends', 'Znajomi', true),

array('login', 'Zaloguj', true),

array('about', 'Informacja', true),

array('auction', 'Aukcja', false),

array('watch', 'Dodaj do obserwowanych', false),

array('test', '@Test', false)

);

for($i = 0; $i < count($items); $i++) {

if($items[$i][2]) {

$selected = ($menu == $items[$i][0]);

echo "<fb:action href=\"?menu={$items[$i][0]}\

">{$items[$i][1]}</fb:action>";

}

}

?>

<fb:create-button href="?menu=friends">Powiadom znajomych</

fb:create-button>

</fb:dashboard>

<!-- include -->

<div>

<?php

$step = nvl($_REQUEST['step'], 1);

foreach($items as $item)

$pages[] = $item[0];

/*

* kontrola czy wartość parametru

* jest jedną z dopuszczalnych

*/

if(!in_array($menu, $pages))

die('Próba wywołania niepoprawnej opcji!');

try {

include('./include/' . basename($menu) . '.php');

} catch(Exception $e) {

echo '<fb:error><fb:message>Błąd</fb:message>' . $e-

>getMessage() . '</fb:error>';

}

?>

</div>

Page 39: Software Developers Journal PL 03/2009

03/200938

WarsztatyFacebook dla programistów

www.sdjournal.org 39

Konsumowanie usługi AllegroUżycie zdecydowanej większości metod Allegro WebAPI wymaga wcześniejszego zalogowania się do serwisu. Służą do tego metody doLogin lub doLoginEnc. W naszej aplikacji wybraliśmy tę drugą ze względu na sposób przesyłania hasła użytkownika. Porównanie danych przesyłanych do serwera w wyniku wywołania metody logo-wania dla użytkownika pwgdrk, który podał ha-sło ngtrx znajduje się na Listingu 5.

Oprócz oczywistych parametrów, jakimi są nazwa user-login i hasło użytkownika user-password metody wymagają podania kodu kra-ju użytkownika country-code (1 – dla Polski), wartości klucza WebAPI webapi-key oraz ak-tualnego numeru wersji komponentów local-version. Numer ten zmienia się wraz ze zmia-nami dokonywanymi w udostępnianej przez Allegro usłudze i może być wykorzystywany do weryfikacji zgodności wersji aplikacji klienckiej z interfejsem WebAPI.

Jeśli podana przez nas wartość tego parame-tru będzie różnić się od aktualnej wersji serwisu, to próba logowania zakończy się błędem i zwró-ceniem komunikatu Niepoprawna wersja katego-rii lub pól sprzedaży. Proszę sprawdzić lokalne wer-sje i uaktualnić oprogramowanie! Aktualną wartość tego parametru możemy uzyskać, wykorzystując panel użytkownika serwisu Allegro (opcja Alle-gro> Moje Allegro>Ustawienia>WebAPI>Informa-cje) lub wywołując metodę doQuerySysStatus, doQueryAllSysStatus lub doGetSitesInfo. Do komunikacji z usługą wykorzystamy w naszej aplikacji pomocniczą klasę Allegro pokazaną na Listingu 3. Klasa zawiera pole api będące instan-cją klasy SoapClient, za pomocą którego będzie-my odwoływać się poszczególnych metod API.

W wyniku poprawnego zalogowania do serwi-su zwracany jest uchwyt (identyfikator) sesji, któ-ry jest parametrem wejściowym do wszystkich me-tod wymagających wcześniejszego zalogowania.

Każdy użytkownik może mieć równocześnie otwartych do pięciu sesji, a ważność trwania se-sji wynosi 3 godziny. Dla celów demonstracyj-nych wartość tego identyfikatora zapisujemy w cookies z wykorzystaniem metody Facebook API data.setCookie:

$facebook->api_client->data_setCookie($fb_

uid,

'AllegroSession', $session, (time() + 3

* HOUR), null);

a kontrolę aktualności logowania wykorzystu-jąc zapytanie FQL:

$cookies = $facebook->api_client->fql_query

("SELECT name, value, expires FROM cookies

WHERE uid = $fb_uid AND name =

'AllegroSession' AND expires > " .

time());.

Każde pomyślne logowanie skutkuje także zapi-saniem w bazie danych pary identyfikator użyt-

kownika Facebook fb _ uid ,identyfikator użyt-kownika Allegro a _ uid, dzięki czemu będzie-my mogli zrealizować funkcjonalność prezenta-cji wystawionych aukcji naszych znajomych.

Funkcjonalność naszej aplikacjiPrzykładowy widok naszej aplikacji w działa-niu wraz z jej menu głównym pokazany jest na Rysunku 3.

Opcja Moje aukcje (my_auctions.php) odpo-wiada części funkcjonalności dostępnej w pa-nelu użytkownika serwisu Allegro w opcji Mo-je Allegro>Aukcje. Do realizacji zakładek wyko-rzystaliśmy znacznik fb:tab-item.

Aukcje znajomych (friends_auctions.php) to li-sta sprzedawanych przedmiotów w serwisie au-kcyjnym przez naszych znajomych z serwisu społecznościowego. W pierwszym kroku zapy-

Rysunek 3. Przykładowy widok naszej aplikacji prezentujący informacje o wybranej aukcji

Rysunek 4. Wyślij zaproszenie do znajomych jako przykład wykorzystania znaczników FBML

Rysunek 5. Przykładowy efekt wykorzystania funkcjonalności Udostępnij

Page 40: Software Developers Journal PL 03/2009

03/200940

WarsztatyFacebook dla programistów

www.sdjournal.org 41

Listing 3. Klasa Allegro

<?php

class Allegro{

private $config;

/*

* pole będące instancją klienta SOAP,

* które umożliwia nam dostęp do metod interfejsu Allegro

WebAPI

* (http://webapi.allegro.pl)

*/

public $api;

function __construct($config) {

$this->config = $config;

// utworzenie instancji klienta SOAP

$this->api = new SoapClient("http://webapi.allegro.pl/

uploader.php?wsdl");

}

/*

* nawiązanie połączenia z bazą danych

*/

private function connect() {

mysql_connect($this->config['database']['host'],

$this->config['database']['user'],

$this->config['database']['password']);

mysql_select_db($this->config['database']['name']);

}

/*

* zalogowanie do serwisu Allegro

*/

public function doLogin($login, $password) {

// pobranie aktualnej wartości local-version

$doGetSitesInfoResponse = $this->api->doGetSitesInfo(1,

$this->config['allegro']['webapi-key']);

// szyfrowane logowanie

$doLoginEncResponse = $this->api->doLoginEnc(

$login, $this->enc($password), 1,

$this->config['allegro']['webapi-key'],

$doGetSitesInfoResponse['ver-key']);

// identyfikator (uchwyt) sesji

$session = $doLoginEncResponse['session-handle-part'];

return $session;

}

/*

* metoda kodowania hasła

*/

private function enc($password) {

return base64_encode(hash('sha256',$password,true));

}

/*

* zapisuje powiązanie między kontami Facebook i Allegro

* (identyfikatory użytkowników w obu serwisach)

*/

public function doSaveUser($fb_uid, $a_uid) {

$this->connect();

$query = "REPLACE INTO fba_users SET fb_uid = $fb_uid,

a_uid = $a_uid";

mysql_query($query)

or die(mysql_error());

}

public function doGetUsers($fb_uids){

$query = 'SELECT * FROM fba_users WHERE fb_uid in (' .

implode(',', $fb_uids) . ')';

$this->connect();

$result = mysql_query($query);

while($row = mysql_fetch_assoc($result)) {

$users[] = $row;

}

return $users;

}

}

?>

Metody Allegro WebAPIPrzykładowe metody usługi Allegro WebAPI wykorzystane w naszej aplikacji:

• doShowItemInfo – pozwala uzyskać informacje o aukcji o określonym identyfikatorze,• doGetBidItem2 – pozwala uzyskać informacje o ofertach kupna złożonych w danej aukcji,• doGetUserID – pozwala uzyskać unikalny identyfikator użytkownika na podstawie jego nazwy (login) lub adresu email,• doMyAccount2 – pozwala uzyskać informacje o aukcjach użytkownika (Licytuję, Sprzedaję, Wygrałem itp.),• doSearch – pozwala na wyszukiwanie aukcji o zadanych parametrach,• doAddWatchList – pozwala dodać określoną aukcję do listy aukcji obserwowanych,• doGetSitesInfo – pozwala uzyskać podstawowe informacje o dostępnych serwisach aukcyjnych,• doLoginEnc – metoda szyfrowanego logowania do serwisu.

Świat jest małyW 1967 r. Stanley Milgram – amerykański socjolog z uniwersytetu Yale przeprowadził ciekawy eksperyment. Poprosił losowo wybrane osoby z Nebra-ski o przesłanie listu do pewnego maklera giełdowego w Bostonie. Oczywiście jego adres pocztowy nie został ujawniony, a uczestnicy doświadcze-nia musieli dotrzeć do adresata, wykorzystując jedynie sieć swoich znajomych. Część listów dotarła i okazało się, że średnia liczba ogniw w łańcuchu drogi listu wyniosła sześć. Stąd wzięła się nazwa paradygmatu o sześciu stopniach separacji (and. six degrees of separation) i teorii tzw. małych świa-tów (ang. small world). Okazuje się, że własność tę posiadają także modele innych sieci rzeczywistych. Powstające serwisy społecznościowe stały się naturalnym polem do ponownej weryfikacji wspomnianej teorii.

Page 41: Software Developers Journal PL 03/2009

03/200940

WarsztatyFacebook dla programistów

www.sdjournal.org 41

taniem FQL pobieramy listę znajomych, którzy już dodali naszą aplikację:

SELECT uid FROM user WHERE is_app_user =

1 AND uid IN (SELECT uid2 FROM friend

WHERE uid1 = $fb_uid)

a następnie z wykorzystaniem metody doGetUsers klasy Allegro pobieramy po-wiązanie pomiędzy kontami użytkownika w obu serwisach. Mając te dane, możemy już uzyskać listę aukcji każdego użytkow-nika. Zamiast jego nazwy wykorzystaliśmy znacznik fb:profile-pic wyświetlający jego profilowe zdjęcie.

Szukaj (search.php) to prosta wyszukiwarka z formularzem opartym na znaczniku fb:editor.

W opcji Znajomi (friends.php) wykorzystu-jąc znaczniki fb:request-form i fb:multi-friend-selector możemy wysłać zaprosze-nie do znajomych, którzy nie używają jeszcze naszej aplikacji.

Nasza aplikacja nie musi ograniczać się je-dynie do swojego głównego okna (ang. Ca-nvas Page). W widoku aukcji (auction.php) zastosowaliśmy znacznik fb:share-button, który umożliwia nam współdzielenie zaso-bów z innymi użytkownikami poprzez wy-słanie do nich wiadomości lub publikację in-formacji na stronie naszego profilu. Przykła-dowy efekt wykorzystania znacznika pokaza-ny jest na Rysunku 5. Dodatkowo wykorzy-staliśmy metodę API profile.setFBML, za pomocą której ustawiamy informację o ostat-

nio oglądanej przez nas aukcji w widoku Pola naszego profilu.

Katalog aplikacjiKiedy uznamy, że nasza aplikacja jest już goto-wa i posiada co najmniej pięciu użytkowników, możemy wysłać ją do Katalogu aplikacji wyko-rzystując opcję w Twórcy aplikacji.

Cały proces sprowadza się do wypełnienia krótkiego formularza. Aby nasza aplikacja nie została odrzucona, musimy pamiętać o tym, że jej nazwa nie może zawierać słów fb i face (np. nasza przykładowa aplikacja otrzymała nazwę Yaama jako akronim od słów Yet Another Alle-gro Manager), a opis musi być w języku angiel-skim. Po pozytywnym przejściu weryfikacji na-sza aplikacja stanie się łatwo dostępna dla mi-lionów użytkowników serwisu.

PodsumowaniePokazaliśmy w jaki sposób utworzyć przykła-dową aplikację działającą na platformie Facebo-ok. Oczywiście wykorzystaliśmy tylko wycinek możliwości zarówno mechanizmów oferowa-nych przez tę platformę, jak i interfejsu serwi-su aukcyjnego. Mamy jednak nadzieję, że spoj-rzenie na serwis społecznościowy nie od strony użytkownika, lecz od strony programisty, uczy-ni go atrakcyjnym polem eksperymentów dla tych drugich.

WŁODZIMIERZ KOZŁOWSKIAbsolwent Wydziału Elektrycznego Politechniki Po-znańskiej, obecnie doktorant na Wydziale Matema-tyki i Informatyki Uniwersytetu im. Adama Mickie-wicza. Pracuje jako projektant i programista w fir-mie ABG S.A. (Grupa Asseco). Jest laureatem Truveo Developers Challenge 2008 (za aplikację 3Styler for Facebook) oraz konkursu na przygotowanie doku-mentacji z przykładami dla usługi Allegro WebAPI.Kontakt z autorem: [email protected]

W Sieci

• Strona dla programistów Facebooka http://developers.facebook.com/• Dokumentacja usługi Allegro WebAPI http://webapi.allegro.pl/

Rysunek 6. Przykładowy widok aplikacji w zakładce Pola naszego profilu

Listing 4. Skrypt tworzący tabelę przechowującą powiązanie kont użytkowników Facebooka i Allegro

CREATE TABLE IF NOT EXISTS `fba_users` (

`fb_uid` bigint(20) NOT NULL COMMENT 'identyfikator użytkownika Facebook',

`a_uid` bigint(20) NOT NULL COMMENT 'identyfikator użytkownika Allegro.pl',

PRIMARY KEY (`fb_uid`)

);

Listing 5. Porównanie przesyłanych danych dla obu metod logowania

<!-- fragment koperty SOAP dla wywołania metody doLogin -->

<ns1:doLogin soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:AllegroWebApi">

<user-login xsi:type="xsd:string">pwgdrk</user-login>

<user-password xsi:type="xsd:string">ngtrx</user-password>

...

</ns1:doLogin>

<!-- oraz analogiczny fragment dla tych samych danych użytkownika przesyłanych w wyniku wywołania metody doLoginEnc -->

<ns1:doLoginEnc soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:AllegroWebApi">

<user-login xsi:type="xsd:string">pwgdrk</user-login>

<user-hash-password xsi:type="xsd:string">tKa+M+Ur0WT4ggDq5cOUQfmqt3+Wo+7eGDTQL2/LR0Y=</user-hash-password>

...

</ns1:doLoginEnc>

Page 42: Software Developers Journal PL 03/2009

03/200942

BezpieczeństwoZabezpieczanie systemów IT

www.sdjournal.org 43

Nie są to jednak w większości przypad-ków takie włamania, jakie znamy z hi-storii o hakerach, gdzie wykorzysty-

wane są luki, czy może techniczne niedocią-gnięcia systemów IT. Obecnie największym za-grożeniem są ataki typu phishing czy pharming. Niepowołane osoby nie łamią zabezpieczeń sys-temu, one po prostu zdobywają w nielegalny sposób informacje potrzebne do prawidłowego logowania i je wykorzystują. Większość insty-tucji posiada już zabezpieczenia typu firewall, które chronią systemy IT przed niepowołanym dostępem, ale takie zabezpieczenia w dzisiej-szych czasach nie wystarczają.

Jak w takim razie radzić sobie z nowym rodza-jem przestępczości komputerowej? Odpowiedzią na to jest nowa generacja systemów ochrony. Jed-nym z wiodących produktów w tej kategorii jest Oracle Adaptive Access Manager (OAAM). W ar-tykule opiszemy zasadę działania tego rozwiąza-nia. Trzeba zwrócić uwagę na dwa aspekty korzy-stania przez użytkownika z aplikacji webowych: uwierzytelnienie użytkownika w aplikacji, ale też uwierzytelnienie systemu IT u użytkownika, a także zachowanie użytkownika w systemie.

UwierzytelnianieUwierzytelnianie użytkownika w systemie IT jest obecnie całkiem dobrze rozwinięte – po-cząwszy od konta i hasła, przez hasła jednora-

zowe i tokeny, a skończywszy na certyfikatach i smartkartach. Nieco gorzej wygląda sytuacja je-śli chodzi o zapewnienie użytkownika, że stro-ny, które wyświetlają się w jego przeglądarce, pochodzą rzeczywiście z tych źródeł, z których sądzi on, że powinny pochodzić. Fakt uwierzy-telnienia sprowadza się w tym przypadku do zmiany małej ikonki w dolnym rogu ekranu (w nowszych wersjach przeglądarek jest to już do-syć wyraźnie wyszczególnione).

Doświadczona i świadoma zagrożenia osoba zauważy próbę wyłudzenia danych (phishing), ale przeciętny Kowalski może zostać łatwo oszu-kany, co widać zresztą w treści publikacji praso-wych. Dużym krokiem w kierunku zwiększenia bezpieczeństwa jest w tym przypadku personali-zacja. OAAM rozdziela stronę wpisywania iden-tyfikatora użytkownika i hasła. Najpierw zosta-niemy poproszeni o podanie naszego identyfika-tora. Hasło wpisujemy na kolejnej stronie, która będzie już spersonalizowana przez system, bo on już wie, kto się loguje. Personalizacja polega na wybraniu przez użytkownika dedykowanego dla niego obrazka, który zawsze będzie tłem modu-łu wpisywania danych typu hasło, czy odpowie-dzi na pytania kontrolne.

Takiego wyboru użytkownik dokonuje w trak-cie rejestracji. Jednocześnie, dla ochrony przez key-loggerami, użytkownik może wybrać bezpiecz-niejszy moduł wpisywania danych, za pomocą któ-rego dane wprowadzane są nie z klawiatury, ale za pomocą myszki, a więc nie mogą zostać przechwy-cone. Również w trakcie rejestracji użytkownik podaje odpowiedzi na kilka pytań kontrolnych. Taka dodatkowa weryfikacja może zostać użyta przez system w momencie zwiększonego ryzyka

transakcji. To zabezpiecza użytkownika i znacznie utrudnia utratę przez niego danych pozwalających na zalogowanie się niepowołanej osobie i dokona-nie nieautoryzowanych transakcji.

A co, jeśli jednak dojdzie do takiej utraty da-nych? System musi rozpoznać, że osoba zalogo-wana do aplikacji i wykonująca pewne akcje nie jest prawdziwym użytkownikiem, ale włamy-waczem. To zadanie jest podstawową funkcją systemu OAAM. Jak jest ona realizowana?

Przede wszystkim realizowany jest tak zwany device fingerprinting gdzie przez device rozumie się urządzenie, z którego loguje się użytkownik. Chodzi tu jednak nie tylko o komputer w sen-sie dosłownym, ale także o daną instancję prze-glądarki. OAAM korzysta z wielu dostępnych atrybutów w celu tworzenia odcisku urządzenia – są to między innymi dedykowane pojedyncze cookies, obiekty flash oraz zaawansowane tech-niki samo-uczenia się.

Zbieranie odcisku urządzeniaTzw. fingerprinting odbywa się przy pierwszym kontakcie użytkownika z systemem, zanim jeszcze przeprowadzane są jakiekolwiek działa-nia autoryzacyjne. Dzięki temu informacje ze-brane w ten sposób są dostępne do określenia ryzyka w dowolnym momencie – np.: przed autoryzacją, po autoryzacji, czy w trakcie sesji przed wykonaniem transakcji.

Pierwsza strona do logowania zawiera kil-ka linijek statycznego html’a. Ten kod zawie-ra obiekt flash’owy i tag <IMG>, które służą do zbierania szczegółowych danych o urządzeniu. Kod flash’owy odwołuje się do serwera aplika-cyjnego wysyłając do niego zebrane dane.

OAAM generuje unikalne szyfrowane ciastecz-ka (cookies) dla każdej sesji i sprawdza, czy kon-kretny cookie istnieje przy kolejnym logowaniu użytkownika z tego urządzenia. Oczywiście, ten cookie jest ważny tylko podczas danej sesji z da-nego urządzenia. Cookies są pobierane od użyt-kownika za pośrednictwem różnych metod:

Zabezpieczanie systemów IT Coraz więcej słyszymy o ochronie bezpieczeństwa systemów informatycznych. Wynika to z tego, że pojawia się coraz więcej doniesień prasowych o włamaniach na konta klientów banków lub o przypadkach wykradzenia dużej ilości danych osobowych.

Dowiesz się:• Jak można zabezpieczyć aplikację WWW;• Jak można chronić użytkownika przed „phi-

shingiem”.

Powinieneś wiedzieć:• Jak działa protokół HTTP;• Wskazana znajomość działania JavaScript.

Poziom trudności

Adaptive Access Manager firmy Oracle

Page 43: Software Developers Journal PL 03/2009

03/200942

BezpieczeństwoZabezpieczanie systemów IT

www.sdjournal.org 43

• Tag <IMG> – specjalny tag jest umieszcza-ny na stronie i przeglądarka wysyła żąda-nie w celu jego pobrania. W trakcie tego zadania plik cookie jest przesyłany do sys-temu. Takie tagi mogą być również wyko-rzystane do badania przepustowości sieci urządzenia oraz prędkości działania same-go urządzenia. Te informacje również mo-gą być użyte do tworzenia odcisku;

• Request HTTP – w przypadku blokady znaczników <IMG>, OAAM może pobrać cookie z pierwszego żądania o stronę do logowania. Stosowanie różnych technik ma na celu zapewnienie zebrania jak naj-większej ilości danych w różnych konfigu-racjach urządzenia użytkownika.

Biblioteki, które przetwarzają te dane, są udo-stępniane z kodem źródłowym, więc istnieje możliwość ich modyfikacji w trakcie wdrożenia.

Dane dla cookiesJak wspomniałem, pliki cookie są generowane dla każdej sesji i system sprawdza, czy istnie-

ją już jakieś z sesji poprzedniej. W czasie takie-go przetwarzania zbierane są również inne do-stępne dane:

• System operacyjny wraz z wersją i wgrany-mi patchami;

• Przeglądarka z jej wersją;• Możliwość uruchamiania JavaScript.

W trakcie zbierania informacji przez obiekty flashowe można uzyskać dalsze dane o środo-wisku użytkownika:

• Rozdzielczość ekranu;• Dane o kolorach;• Czy jest zainstalowana karta dźwiękowa;• Czy jest zainstalowana drukarka;• Czy jest mikrofon;• Czy są jakieś kodeki audio i video;• Czy jest wsparcie dla MP3.

Informacje o IPKolejną grupą informacji, jaki zbiera OAAM, są dane związane z IP i protokołem. To wszystko ma na celu uniemożliwienie podszycia się pod użytkownika. Dane zbierane na temat protoko-łu IP o użytkowniku to:

• Sam adres IP;• Lokalizacja geograficzna wyliczona na

podstawie danych geolokacyjnych (dane o mapowaniu IP na lokalizacje geograficzne kupuje się od firm zewnętrznych);

• Typ i prędkość połączenia;• Typ routingu IP;• Flaga ISP;• ASN;• Nazwa ISP;• Nazwy domen poszczególnych poziomów;• Lista proxy anonimizujących;• Rutery i nazwy maszyn.

ModelePosiadając już odpowiednią ilość informacji, mo-żemy zacząć je przetwarzać. Głównym zadaniem systemu jest wygenerowanie liczby (risk score) określającej ryzyko związane z aktualnie wyko-nywaną przez użytkownika akcją. Takie oblicze-nia odbywają się oczywiście on-line w wybranych w trakcie instalacji miejscach w chronionej aplika-cji (np. przed wygenerowaniem zlecenia przele-wu). Na podstawie wartości risk score mogą zostać wykonane akcje (blokada konta, email do admini-stratora, dodatkowa weryfikacja klienta pytania-mi kontrolnymi) lub wartość ta może być przeka-zana do chronionej aplikacji, aby ona sama podję-ła dalsze kroki.

Generowanie risk score odbywa się na pod-stawie reguł zebranych w modele, które z ko-lei zgrupowane są w polityki. Standardowo sys-tem posiada ponad 200 szablonów reguł. Poli-tyki podzielone są ze względu na zastosowanie:

• Polityka bezpieczeństwa – używa standar-dów do wykrywania fraudowego zacho-wania. Typowe reguły bezpieczeństwa to: blokowanie użytkowników z listy zabro-nionych urządzeń, blokowanie użytkow-nika działającego z różnych krajów w usta-lonej jednostce czasu, blokowanie dostę-pu z urządzenia, z którego nastąpiło kil-ka błędnych logowań, blokowanie dostę-pu z urządzenia, z którego nastąpił dostęp ustalonej liczby użytkowników w tym sa-mym czasie, blokowanie logowania użyt-kownika, który zalogował się z miejsc od-ległych geograficznie w czasie krótkiego czasu, itd.

• Polityki transakcji – zawierają reguły bazu-jące na parametrach biznesowych, używa-ne do zmniejszenia ryzyka operacji. Uży-wane do monitorowania działań w trakcie sesji.

Rysunek 1. Moduły wpisywania danych Rysunek 2. „Odcisk palca” urządzenia

������������������������

����������������

���������

����������

���������������

�����������

��������

�����������

�������

�����������������������

��������������������

���������������������

����������������������� �����������������������

Page 44: Software Developers Journal PL 03/2009

03/200944

Bezpieczeństwo

• Polityki workflow – używają znanych wzor-ców zachowania użytkownika do wykrywa-nia transakcji, w których to zachowanie jest inne niż zapamiętane. Wykorzystują metody analizy behawioralnej, wykrywania wzorców, analizy temporalnej i danych historycznych.

• Dane zewnętrzne – Możliwa jest także in-tegracja z danymi dostarczanymi przez systemy zewnętrzne.

Generowanie risk score jest stosunkowo proste. Kiedy pojawia się żądanie, system uruchamia po-

szczególne modele, skonfigurowane do działania dla danej transakcji. Każda z reguł zwróci risk score (przykładowo, jeśli użytkownik łączy się ze znanego urządzenia, wówczas wynikiem jest 0 -, w przeciwnym przypadku 100). Dla modelu wy-licza się wynik biorąc pod uwagę wagi. Następnie taki sam algorytm stosuje się na poziomie wyżej aż do osiągnięcia wartości końcowej.

Na podstawie tak wygenerowanego wyni-ku można podejmować już pewne konkretne działania biznesowe, jak np. wydanie pozwo-lenia na przelew lub nie. Zaletą OAAM jest możliwość zastosowania dodatkowej weryfika-cji użytkownika za pomocą pytań kontrolnych. Logika rozmyta stosowana przy ewaluacji od-powiedzi może być tematem na oddzielny ar-tykuł i pozwala na zaawansowaną autoryzację przy jednoczesnym niewielkim obciążeniu sa-mego użytkownika. Nie musi on dokładnie pa-miętać odpowiedzi na pytania kontrolne. Sto-pień dokładności zależy od nas samych.

Na zakończenie prezentuję całościowy przy-kład działania systemu OAAM: (Rysunek 4)

ALEKSANDER JACHOWICZEnterprise Solution Architect w obszarze Identity Management, Oracle PolskaRysunek 3. Obliczanie „Risk Score”

�������������������������������������������������������������������������������������������������

����������������

�����������������������������������������������������������������������������������������������������������

������������������������������������������������������������������������������������������������������������

�������������������������������������������������������������������������������

�����������������

�����������������

����������������� �����������������

����� ����� ����������

Rysunek 4. Działanie pakietu Adaptive Access Manager

������������������������

��������������

�����������

����������

��������������������

���������

������������

�����������

����������������

����������������

������������

���������������

�����������

���������

�������

���������

���������

�������

���������

����������

�������

���������

�����������������������

����������������������

�������������������

������������������������

�����������������������

���������������

������������������

������������������������

��������������������������

����������������������

�������������������������

�����������������������������

��� ���

��� ��� ���

������������������������

��������������������������

���������������������

��������������

����������

��������������������

���������

������������

�����������

��������������������������

����������������������������

������

��������������

������������������

���������

�����������

���������

������������������������

����������������

�������������������������

���������������

�������������������������

���������������

������������������������

������������������������

��������������������

�������������������������

���������������������

�������������������������

��������������������

������������������������

����������������� ������������������ ��������������

Page 45: Software Developers Journal PL 03/2009
Page 46: Software Developers Journal PL 03/2009

03/200946

Testowanie oprogramowania Praca z zespołem testerów klienta

www.sdjournal.org 47

Pierwsza część artykułu opisuje podsta-wowe rodzaje testów zwykle przepro-wadzanych przez klienta. W następnej

kolejności zostaną przedstawione zalety i wa-dy udostępnienia aplikacji zespołowi klien-ta z punktu widzenia dostawcy oprogramo-wania. Trzeci rozdział artykułu jest subiek-tywną próbą stworzenia pewnego ogólnego schematu postępowania podczas organizacji testowania w środowisku klienta – przedsta-wia pewne zasady, które powinny być prze-strzegane zarówno przez dostawcę, jak i klienta, aby uniknąć w przyszłości potencjal-nych problemów.

Ostatnia część artykułu to studium przy-padku opisujące, w jaki sposób zorganizowa-no proces testowy w projekcie realizowanym dla zagranicznej instytucji bankowej.

Po zapoznaniu się z treścią artykułu, czy-telnicy zdobędą wiedzę, w jaki sposób moż-na czerpać korzyści z udostępnienia systemu klientowi oraz zwiększyć efektywność testo-wania, a także zaufanie klienta zarówno do produktu, jak i samego producenta oprogra-mowania.

Podejmując się realizacji usługi wytwo-rzenia systemu informatycznego, dostawca IT zobowiązuje się do wypełnienia pewnych określonych czynności. Nie tylko musi do-starczyć gotowy produkt w założonym ter-minie i w ramach określonego budżetu, za-gwarantować niezbędne wsparcie przy wdro-żeniu systemu i przeszkoleniu użytkowni-ków, ale i powinien przedstawić gwarancję niezawodności i poprawnego działania sys-temu. Warunkami spełnienia takiej gwaran-cji są na ogół kryteria wejścia / wyjścia sto-sowane dla poszczególnych etapów testowa-nia wytwarzanej aplikacji. Dla każdego eta-pu testowania powinny zostać spełnione nie-co inne kryteria. Zapewniają one, iż pewien etap implementacji systemu został ukończo-ny, a jego rezultat zweryfikowany z pozytyw-nymi wynikami.

Mimo obaw i sprzeciwów, związanych z ujawnieniem kondycji aplikacji przed cza-sem jej oddania do oficjalnych testów akcep-tacyjnych, wytwórcy oprogramowania coraz częściej godzą się na przeprowadzanie testów aplikacji przez zespół klienta. Zwykle dzieje się tak na życzenie klienta, który pragnie mieć stały wgląd w postęp prac deweloperskich i stan ukończenia systemu. Informacja taka uła-twia planowanie i podejmowanie decyzji doty-czących np. budżetu, daty oddania systemu na produkcję itd. Czasem rozstrzyga też o kwestii

być albo nie być – kontynuować projekt, czy go zawiesić ze względu na mniejsze niż zakłada-no postępy prac.

Niniejszy artykuł przedstawia przykładowy proces testowania przez klienta oraz pokazuje trudności, które można napotkać wspomaga-jąc taki proces. Z drugiej strony zostaną uka-zane korzyści takiego podejścia i jego możli-wy pozytywny wpływ na powodzenie przed-sięwzięcia IT.

Z punktu widzenia dostawcy oprogramowania…Nierzadko pierwszą reakcją wytwórcy opro-gramowania na prośbę umożliwienia testo-wania aplikacji przez testerów klienta jest gwałtowny sprzeciw i wynajdywanie mnó-stwa przeciwwskazań. Wynika to głównie z obawy przed ujawnieniem przed przyszłym nabywcą oprogramowania błędów i usterek systemu. Często też pragnie się ukryć mniej-szy niż zakładano postęp w pracach dewelo-perskich lub testowych. Producent oprogra-mowania wychodzi z założenia, iż dopie-ro w pełni zaimplementowany i gruntow-nie przetestowany system może zostać pod-dany testom klienta. Udostępnienie nie w pełni zaimplementowanego i nieprzetesto-wanego przez zespół wewnętrzny systemu może w oczach dostawcy wpłynąć negatyw-nie na opinię klienta o postępach w pracach projektowych.

Takie podejście ma często realne uzasadnie-nie. Klient, zobaczywszy część systemu, jest rozczarowany słabymi w jego pojęciu postępa-mi i niespokojny o możliwość ukończenia ca-łej aplikacji w zakładanym czasie. Pojawia się napięcie i naciski ze strony udziałowców pro-jektu – bądź to, aby położyć większy nacisk

Praca z zespołem testerów klienta

Niniejszy artykuł przedstawia studium przypadku dotyczącego procesu testowania systemu bankowego w środowisku klienta. Zostaną przedstawione problemy wynikłe w trakcie organizacji testowania oraz czynności przedsięwzięte w celu ich eliminacji i osiągnięcia satysfakcjonującego poziomu współpracy pomiędzy dostawcą oprogramowania a klientem.

Dowiesz się:• Jakich reguł przestrzegać, aby testowanie nie

doprowadziło do katastrofy;• Jak poprawić proces testowy, gdy jest już w trak-

cie realizacji a rezultaty są dalekie od ideału.

Powinieneś wiedzieć:• Podstawowa wiedza z zakresu testowania

funkcjonalnego;• Podstawowa wiedza z zakresu zarządzania

projektem informatycznym.

Poziom trudności

Zwiększanie efektywności testów przeprowadzanych przez klienta

Page 47: Software Developers Journal PL 03/2009

03/200946

Testowanie oprogramowania Praca z zespołem testerów klienta

www.sdjournal.org 47

na testowanie systemu, bądź by przyspieszyć prace deweloperskie. Często bywa też tak, iż testerzy klienta nie są wystarczająco zaznajo-mieni z funkcjonowaniem aplikacji by dać po-prawne wyobrażenie o jakości działania syste-mu. Wprowadza to nieporozumienia i kon-flikt – ponieważ dostawca pewny jest swoich racji, a klient swoich. W takiej sytuacji łatwo może dojść do pogorszenia stosunków pomię-dzy udziałowcami projektu ze strony dostaw-cy i klienta.

Są jednak – i to wcale nierzadko – pozy-tywne aspekty oddania systemu do testowa-nia klientowi. Najistotniejszym z nich jest fakt, iż testerzy klienta – zwykle pracowni-cy danej instytucji tymczasowo oddelego-wani do prac testerskich – najlepiej wiedzą, jak powinien działać system, aby w pełni re-alizował swoją rolę i usprawniał pracę ludzi. Testerzy ci mogą bardzo pomóc programi-stom i analitykom dostarczając wskazówek i sugestii pozwalających usprawnić funk-cjonowanie aplikacji. Mogą też, co równie ważne, sprawdzić, czy zaprojektowany sys-tem sprawdza się w kategoriach użyteczno-ści – czy praca z nim jest wystarczająco intu-icyjna, jak szybko zwykły użytkownik może nauczyć się jego obsługi itp. Informacje tego typu, uzyskane jeszcze w fazie implementa-cji mogą być bardzo przydatne – ponieważ w razie konieczności można jeszcze dokonać pewnych zmian w projekcie i zaimplemento-wać je znacznie mniejszym kosztem i przy mniejszym ryzyku niż jakby to miało miej-sce w fazie np. wdrożenia lub końcowych te-stów akceptacyjnych.

Inną zaletą testowania przez zespół klien-ta jest możliwość wykrycia błędów pominię-tych przy testowaniu wewnętrznym – po-nieważ takie testowanie jest bliższe rzeczy-wistemu użytkowaniu systemu i realnych in-terakcjach z użytkownikiem.

Rodzaje testów przeprowadzanych przez klientaW zależności od przyjętego podejścia i wy-magań projektu klient wykonuje testy na kil-ku poziomach. Zazwyczaj testowanie takie obejmuje testy funkcjonalne, użyteczności i testy akceptacyjne.

Testy funkcjonalne Zwykle aplikacja oddawana jest klientowi do testów funkcjonalnych po zaimplementowa-niu i wstępnym przetestowaniu przez we-wnętrzny zespół testerów pewnego modułu lub zbioru funkcjonalności. Testy takie ma-ją na celu sprawdzenie czy aplikacja spełnia założone wymagania – innymi słowy, czy umożliwia poprawne wykonanie wszystkich pożądanych i ujętych w ramach kontraktu operacji i funkcji. Testy takie mogą się od-bywać równocześnie z dalszym rozwijaniem aplikacji przez zespół deweloperski – wtedy

wsparcie ze strony zespołu klienta może być szczególnie istotne dla dalszych prac progra-mistycznych. Często podczas testów funk-cjonalnych przeprowadzanych przez klienta wynajdywane są braki lub nieścisłości w pro-jekcie aplikacji – takie jak błędne lub pomi-nięte wymagania biznesowe.

Jako przykład niech służy projekt przed-sięwzięty na zlecenie instytucji bankowej, w którym testerzy klienta (pracownicy banku) przeprowadzali testy funkcjonalne równo-legle z testami wewnętrznymi. Podczas pra-cy z systemem testerzy wykryli wiele błędów wynikających z niekompletnej analizy bizne-sowej – np. dokumentacja analityczna nie przewidywała i nie opisała scenariusza inte-rakcji użytkownika (kasjera w banku) z kasą w przypadku używania monet. Udokumen-towane i zaprojektowane było jedynie opero-wanie na banknotach. W rezultacie system błędnie przetwarzał operacje finansowe do-konywane w małych kwotach (poniżej war-tości najmniejszego nominału banknotu) lub kwotach obejmujących część ‘groszową’. Transakcje takie były poprawnie zapisywane w systemie, lecz nie w rejestrze kasy – urzą-dzenia bankowego połączonego z aplikacją. Urządzenie takie nie operuje na monetach, więc transakcje monetarne były obsługiwane niepoprawnie – np. w przypadku wypłaty go-tówkowej na kwotę 20,50 zł urządzenie wy-płacało 20 zł, po czym system wyświetlał ko-munikat o błędzie – ponieważ nie ‘wiedział’ jak interpretować 0,50 zł.

Testy użytecznościTesty użyteczności pozwalają ocenić stopień zadowolenia użytkownika końcowego z pra-cy z aplikacją. Na użyteczność składa się pro-stota nauki obsługi systemu, wygoda i szyb-kość użytkowania, wydajność. Zwykle te-stowana jest ergonomia układu strony, roz-mieszczenie pól, sekcji, przycisków, intuicyj-ność położenia elementów na stronie oraz szybkość i efektywność przepływu procesu biznesowego. Użytkownik pragnie, aby apli-kacja umożliwiała mu jak najprostsze i naj-bardziej wydajne przeprowadzanie operacji. Nie ma tu miejsca na czasochłonne szkolenia i naukę obsługi systemu – aplikacja powinna dać się poznać w najkrótszym możliwym cza-sie. Optymistyczny wariant zakłada, iż krót-ka demonstracja oraz niezbyt rozbudowany podręcznik użytkownika powinien wystar-czyć do zapoznania się z działaniem i założe-niami aplikacji. Możliwe jest to tylko wów-

czas, gdy system został zaprojektowany tak, by być nieskomplikowany w użytku i jak naj-bardziej intuicyjny.

Podczas testów użyteczności użytkowni-cy weryfikują, czy projekt aplikacji odpowia-da ich potrzebom, preferencjom i nawykom oraz czy system sprawdzi się podczas pracy na produkcji. Testy użyteczności – jeśli prze-prowadzane są odpowiednio – mogą pomóc ulepszyć aplikację skłaniając do modyfikacji UI zgodnie z sugestiami użytkowników, co z kolei zwiększa komfort pracy z systemem i satysfakcję odbiorcy oprogramowania. Po-nadto, przyjazny i intuicyjny interfejs użyt-kownika umożliwia minimalizację nakła-dów przeznaczonych na zapewnienie szkoleń i usług help desk, ponieważ system jest prosty w obsłudze i nauka nie wymaga szczególne-go treningu.

Testy akceptacyjneTesty akceptacyjne przeprowadza się w celu ostatecznej weryfikacji funkcjonalności sys-temu przed wdrożeniem na produkcję. Te-sty te z reguły wykonuje wybrana grupa użyt-kowników końcowych na podstawie opraco-wanych scenariuszy end to end. Celem jest stwierdzenie, czy dany system działa w po-żądany sposób oraz czy poprawnie i bez uste-rek współpracuje z zależnymi systemami lub urządzeniami. Często w testach akceptacyj-nych uczestniczą również specjaliści z bran-ży danego biznesu (np. analitycy biznesowi) – celem ostatecznego potwierdzenia popraw-ności systemu. W związku z powyższym, te-stowanie akceptacyjne często rozdziela się na dwa rodzaje – FAT (ang. Functional Acceptan-ce Testing) i BAT (ang. Business Acceptance Te-sting). Testy FAT przeprowadzane są zazwy-czaj przez wybraną reprezentację użytkowni-ków końcowych (lub testerów klienta wypo-sażonych w specjalnie opracowane scenariu-sze testowe); testy BAT wykonywane są przez przedstawicieli biznesu – analityków, specja-listów branżowych.

Testy akceptacyjne muszą być przeprowa-dzane w oficjalny sposób – zgodnie z założe-niami i planem. Konieczne jest sporządzenie raportu końcowego, który jest podstawą do podjęcia decyzji o wdrożeniu oprogramowa-nia na produkcję.

Zalety i wady testowania przez zespół klientaWyobraźmy sobie, że jesteśmy producentem oprogramowania. Otrzymujemy zlecenie wy-

Rysunek 1. Struktura testów wewnętrznych

Page 48: Software Developers Journal PL 03/2009

03/200948

Testowanie oprogramowania Praca z zespołem testerów klienta

www.sdjournal.org 49

tworzenia aplikacji dla instytucji bankowej zajmującej się obsługą klienta indywidualne-go i firm (transakcje, kredyty itp.). Załóżmy, że nasza firma zajmuje się nie tylko usługa-mi programistycznymi, ale i oferuje komplek-sowe usługi Quality Assurance. Jak w takim przypadku odnieść się do życzenia klienta, który żąda umożliwienia mu wglądu w stan aplikacji i możliwości przeprowadzenia swo-ich własnych testów po każdej fazie imple-mentacji? Jakie korzyści możemy z tego uzy-skać, a jakie straty ponieść?

W pierwszej kolejności rozpatrzmy wady i niedogodności takiego podejścia.

Wady

• Dodatkowa infrastruktura testów

Planując testy klienta często pojawia się ko-nieczność stworzenia odpowiedniej infra-struktury dla potrzeb testów klienta. Nale-ży zorganizować środowisko testowe, odpo-wiednie oprogramowanie wspierające testo-wanie i raportowanie. Zwykle środowisko testowe dla testów klienta jest organizowa-ne w jego siedzibie – i zazwyczaj to dostaw-ca oprogramowania proszony jest o przygo-towanie i skonfigurowanie sprzętu, integra-cji itp. Czynności te wymagają zaplanowa-nia i zaalokowania odpowiedniej ilości zaso-bów – ludzkich, czasowych, czasem sprzę-towych. Dostawca systemu czasem traktu-je to jako niepotrzebną stratę czasu i pienię-dzy i z niechęcią pomaga w realizacji zada-

nia, mocno akcentując, że czyni to ze szko-dą dla planowanego przebiegu projektu.

• Większe wymagania odnośnie zasobów ludzkich

Organizacja i zarządzanie testami klienta wymaga zapewnienia dostępności dodatko-wych zasobów ludzkich wspierających in-stalację i konfigurację systemu, testowanie i wykonywanie poprawek błędów w środo-wisku klienta.

Instalacja testowego systemu, konfigura-cja jego ustawień, sprawdzenia, czy system startuje itp. zwykle wymaga poświęcenia jej trochę czasu. W dodatku, środowisko klien-ta często różni się od środowiska testów we-wnętrznych, co również powoduje nieco komplikacji i potrzebę uprzedniego pozna-nia środowiska.

Zainstalowaną aplikację należy poddać te-stom dymnym, aby upewnić się, że dalsze te-stowanie jest możliwe i system odpowiednio stabilny. To również oznacza konieczność alo-kacji pewnej liczby zasobów ludzkich (o ile do testów dymnych nie stosuje się narzędzi auto-matycznych, co jednak nie należy do częstych praktyk).

• Zmiany w planowaniu

Zachodzą zmiany w planie projektu. Harmo-nogram dewelopmentu i testowania należy przeanalizować pod kątem wymagań zwią-zanych z testami klienta – czasem oznacza

to potrzebę zmiany planu, aby dostosować się do preferencji klienta (np. kolejność imple-mentacji modułów itp.)

• Dodatkowe szkolenia

Zgoda na przeprowadzenie testów przez ze-spół klienta oznacza dodatkową pracę nie-zbędną dla przeszkolenia testerów klienta w zakresie funkcjonalności systemu oraz pro-cedur i narzędzi służących do wykonywania i zarządzania testami. Odpowiedzialność ta zwykle spada na dostawcę oprogramowania – niezbyt często zdarza się, aby zespół klien-ta potrafił w odpowiedni sposób przygotować się do przeprowadzania testów, raportowa-nia ich wyników oraz zarządzania zgłoszony-mi defektami. Nie wynika to ze złej woli, ale raczej z braku profesjonalnego przygotowania i kwalifikacji testerskich. Wyjątkiem są sytu-acje, w których klient zleca całość testowania zewnętrznemu zespołowi, wynajętemu od pro-fesjonalnej firmy IT. Jednak nawet i w takim przypadku może zaistnieć konieczność prze-szkolenia testerów z zakresu funkcjonalności systemu oraz obsługi specyficznych narzędzi wspierających testowanie.

• Różna specyfika pracy i kultura

Dość często jedną z najważniejszych prze-szkód dla testowania klienta jest perspekty-wa problemów wynikających z różnej specyfi-ki i kultury pracy – np. odmienny sposób roz-wiązywania problemów czy informowania o wynikach pracy, inne podejście do organiza-cji pracy. Częstym przypadkiem jest zgłasza-nie przez testerów klienta rzeczywistych lub 'urojonych' problemów bezpośrednio kierow-nictwu projektu i podnoszenie stosunkowo drobnych kwestii jako wysokie ryzyko projek-towe – co w efekcie powoduje konflikty i nie-porozumienia. Innym przykładem jest organi-zacja pracy – problem szczególnie widoczny w przypadku projektów międzynarodowych – np. przeprowadzanie testów przez tydzień czy dwa, notowanie defektów niezależnie od systemu śledzenia błędów, po czym zgłasza-nie ich dopiero po ukończeniu cyklu testów. W praktyce oznacza to, że:

• programiści przez tydzień są bezczyn-ni, nie mając żadnych defektów do na-prawy;

• czas przeznaczony na poprawki dra-stycznie się zmniejsza – ponieważ obejmuje tylko czas od zakończenia cyklu testów do wydania następnej wersji systemu, a nie np. od momentu znalezienia pierwszych defektów – co z kolei budzi frustrację i sprzeciwy ze-społu deweloperskiego;

• często zgłaszane są defekty niepraw-dziwe lub nieodtwarzalne – znalezio-Rysunek 2. Środowiska testowe i podział zadań testowych i odpowiedzialności

���������������

���������������

������������������

����������������

�������

�����������������

����������

����������

����������

����������������������������������������

�������

��������

������

������

������

������ ������ ������

Page 49: Software Developers Journal PL 03/2009

03/200948

Testowanie oprogramowania Praca z zespołem testerów klienta

www.sdjournal.org 49

ne tuż po instalacji nowego systemu, kiedy aplikacja bądź środowisko nie są jeszcze w pełni stabilne.

• Niskie kwalifikacje zespołu klienta.

Dość częstym problemem w testowaniu przez zespół klienta jest brak wymaganych kwalifi-kacji i umiejętności testerskich. Sytuacja ta-ka ma miejsce zwłaszcza wtedy, kiedy testerzy są po prostu pracownikami danej instytucji, tymczasowo alokowanymi do wykonywania testów. Rodzi to nieporozumienia wynikające z braku profesjonalnego przygotowania teste-rów – niewłaściwego podejścia do testowania, zgłaszania nieprawdziwych defektów – co wy-nika z niezrozumienia funkcjonowania apli-kacji, braku wystarczającego opisu problemu (zbyt ogólne opisywanie błędów, brak wszyst-kich danych koniecznych do reprodukcji i na-prawy problemu) etc.

Innego rodzaju czynnikiem powodującym niechęć do testów klienta jest ujawnienie przed klientem kondycji aplikacji przed ukoń-czeniem jej rozwijania.

Czasami dostawca oprogramowania nie chce pokazywać klientowi aplikacji, która nie jest jeszcze w pełni ukończona i przetestowa-na obawiając się paniki w przypadku odkrycia krytycznych błędów i wzbudzenia niepokoju o utrzymanie zakładanych terminów

ZaletyUdostępnienie aplikacji testerom klienta to nie tylko problemy i dodatkowa praca. Ko-rzyści są następujące:

• Większe pokrycie testów

Aplikacja poddana testowaniu przez więcej niż jeden zespół jest przetestowana głębiej i staran-niej, wykonanych jest więcej scenariuszy i przy-padków testowych – aplikację testuje zespół we-wnętrzny oraz zewnętrzny (testerzy klienta), co minimalizuje ryzyko pominięcia błędów. Można tu stosować dwa podejścia:

• testerzy dzielą się pracą i zakresem funkcjonalności, skupiając się na mak-symalnie dokładnym przetestowaniu swojej części aplikacji;

• obie grupy testerów pracują równole-gle – celem takiego podejścia jest do-kładne sprawdzenie aplikacji przez dwie grupy testerów, częściowo nie-zależnych od siebie i stosujących róż-ne metody pracy, tak by błędy były znalezione nawet jeśli jedna grupa je pominie.

• Wyższa efektywność testów

Niezaprzeczalną zaletą udostępnienia apli-kacji testom klienta jest zwiększenie efek-

tywności testowania oraz możliwość ulep-szenia systemu na stosunkowo wczesnym etapie.

Testowanie jest bardziej efektywne – po-dzielenie pracy na dwa zespoły pozwala na lepszy podział zadań czy też testowanych aspektów (np. zespół wewnętrzny wykonu-je testy integracyjne i ogólne testy dymne, ze-spół klienta koncentruje się na testach funk-cjonalności, logiki biznesowej i użyteczno-ści). Dobrze zorganizowana współpraca po-między oboma zespołami może przełożyć się na o wiele lepsze pokrycie i głębokość te-stów niż w przypadku wykonywania prac te-stowych tylko przez testerów dostawcy opro-gramowania.

Pracownicy klienta – testerzy i analitycy – mogą dostarczyć cennych wskazówek od-nośnie wytwarzanego oprogramowania. Ja-ko że znają oni specyfikę danej organizacji, wymogi biznesowe jakie muszą być spełnio-ne przez system, nawyki i przyzwyczajenia docelowych użytkowników systemu najle-piej ocenią funkcjonalność aplikacji. Ich te-sty są pod pewnym względem korzystniejsze od testów wewnętrznych, ponieważ symulu-ją pracę z systemem w docelowym środowi-sku i z docelowymi odbiorcami. Zespół we-wnętrzny nie zawsze jest w stanie opracować i zrealizować wszystkie tego typu scenariu-sze testowe.

• Ulepszanie aplikacji

Udostępnienie aplikacji klientowi daje możli-wość dokonywania zmian w projekcie aplika-cji na stosunkowo wczesnym etapie wytwa-rzania systemu, jeśli służy to poprawie uży-teczności, co wiąże się ze znacznie niższymi kosztami niż gdyby to miało miejsce np. na etapie testów akceptacyjnych (przed wdro-żeniem na produkcję). Również modyfika-cje wymagań wynikające ze zmian w bizne-sie (np. zmiana przepisów prawnych) mogą być zaplanowane i wdrożone wcześnie, jako że zarówno testerzy, jak i analitycy bizneso-wi klienta, mają wgląd w aplikację i mogą do-

starczyć wskazówek co do sposobu rozwiąza-nia danej kwestii.

• Lepszy poziom komunikacji

Klient, informowany na bieżąco o postępie prac – lub ewentualnym opóźnieniu – jest w stanie odpowiednio szybko reagować na zaistniałą sytuacje i adaptować swoje plany zgodnie z bieżącym stanem rzeczy. Przej-rzystość ta pozwala zwiększyć komfort pra-cy, efektywność planowania i podejmowa-nia decyzji biznesowych. Minimalizuje też ryzyko konfliktów, które mogłyby się poja-wić w momencie, kiedy klient – przekona-ny o dobrym postępie prac – nagle dowia-duje się o opóźnieniu.

Zasady współpracy z zespołem klienta Godząc się na udostępnienie systemu zespo-łowi klienta, należy uzgodnić plan i organi-zację procesu testowego. W szczególności dotyczy to harmonogramowania oraz zakre-su zadań testowych – ponieważ inne podej-ście należy przyjąć, gdy testy klienta odby-wają się sporadycznie, a inne, kiedy regular-nie. Zespół klienta może przystąpić do pracy równocześnie z testerami producenta opro-gramowania lub też dopiero po ukończeniu pewnego etapu testów wewnętrznych.

Dobrą praktyką jest jednoznaczne określe-nie następujących kwestii:

• Kto jest osobą odpowiedzialną za testo-wanie w środowisku klienta – pracownik klienta, członek zespołu projektowego do-stawcy oprogramowania czy też osoba z całkowicie niezależnej organizacji. Osoba taka będzie stanowić tzw. punkt kontaktu dla wszelkiego typu kwestii związanych z testowaniem klienta – organizacji procesu testowego, planowania i alokacji zasobów, realizacji i raportowania zadań;

• Rodzaj narzędzia stosowanego do rapor-towania wyników testów (system śledze-nia defektów) – ważne jest ustalenie, czy

Rysunek 3. Organizacja testów

Page 50: Software Developers Journal PL 03/2009

03/200950

Testowanie oprogramowania Praca z zespołem testerów klienta

www.sdjournal.org 51

testerzy klienta będą używać tego same-go narzędzia, co zespół dostawcy opro-gramowania, czy też defekty raporto-wane będą we własnym systemie klien-ta. Raportowanie defektów w systemie klienta będzie się wiązać z koniecznością eksportu znalezionych problemów do wewnętrznego narzędzia dostawcy opro-gramowania, a następnie z zarządzaniem owymi defektami – kontrolowaniem, które zostały odrzucone, które przeka-zane do naprawy oraz naprawione. Infor-macje te będą musiały z kolei zostać prze-kazane zespołowi klienta. Wszystkie te czynności wymagają dodatkowych zaso-bów, co należy uwzględnić w planowaniu testów;

• Harmonogram testów – należy określić, kiedy zespół klienta może rozpocząć te-stowanie, czy będzie się ono odbywać równocześnie z testami wewnętrzny-mi, czy też w osobnych fazach. Inne po-dejście stosuje się w przypadku, gdy te-stowanie ma odbywać się regularnie w dłuższym okresie czasu, a inne, kiedy zespół testowy pracuje jedynie od cza-su do czasu, wyrywkowo sprawdzając działanie aplikacji. Testowanie regular-ne oznacza konieczność synchronizacji prac testowych zespołu testerów klienta i dostawcy oprogramowania, tak aby sta-rać się nie duplikować wykonywanej pra-cy i nie wprowadzać chaosu organiza-cyjnego. Dobrym rozwiązaniem jest po-dział zadań lub skupienie się na innych aspektach testowania. Harmonogram testów powinien uwzględniać również prace deweloperskie niezbędne do na-prawienia błędów znalezionych przez te-sterów – ponieważ dopiero po zakończe-niu jednego cyklu testowania i naprawie błędów można rozpocząć kolejny cykl testów;

• Zakres testów – planując testowanie w środowisku klienta należy zdefiniować, co będzie przedmiotem testowania, a co nie. Pozwoli to uniknąć nieporozumień i niepotrzebnych konfliktów – np. jeśli testy dotyczyć będą użyteczności czy logiki biznesowej, testerzy nie powinni zgłaszać defektów związanych z wydaj-nością systemu;

• Zasady raportowania defektów. Ważne jest przyjęcie pewnych wspólnych wy-tycznych i zasad zgłaszania błędów. W or-ganizacji klienta mogą istnieć wewnętrz-ne standardy raportowania, nie odpowia-dające potrzebom i przyzwyczajeniom zespołu deweloperskiego dostawcy opro-gramowania. Z drugiej strony mogą nie istnieć żadne standardy – w przypadku, gdy np. odbiorca systemu nie utrzymu-je własnego działu testów lub korzysta z zewnętrznych usług testerskich. Popraw-

ne zgłaszanie błędu znacznie skraca czas analizy problemu i naprawy usterki – po-nieważ deweloper rozumie opis defektu i wie, jak go zreprodukować.

Studium przypadkuPrzykład procesu organizacji procesu testo-wego, w którym uczestniczy zespół klien-ta, prześledzimy na podstawie międzynaro-dowego projektu IT, mającego na celu wy-produkowanie oprogramowania na potrze-by bankowości. System miał zastąpić do-tychczas używany w oddziałach banku sys-tem, zintegrowany z kilkoma innymi apli-kacjami i bazami danych oraz urządzenia-mi bankowymi.

Bezwzględnym wymogiem klienta (ban-ku) było dopuszczenie jego zespołu do prze-prowadzania testów – i to jeszcze przed roz-poczęciem testów akceptacyjnych, po ukoń-czeniu pewnego etapu rozwijania aplikacji i zbudowaniu wybranych modułów i funk-cjonalności.

Testowanie wewnętrzne, przeprowadzane przez zespół testerów dostawcy oprogramo-wania, odbywało się od momentu stworze-nia pierwszych stabilnych wersji modułów aplikacji. Testy podzielono na etapy:

• Stream – testy polegały na testowa-niu pojedynczych funkcjonalności, bez sprawdzania integracji i poprawności biznesowej przebiegu procesu;

• Build – testowanie obejmowało kilka funkcjonalności zintegrowanych w sta-bilną paczkę. Częściowo testowano inte-grację – na tyle, na ile pozwalał zakres dostarczonej paczki;

• Release – testowanie Release obejmowa-ło większą część aplikacji – kilkanaście modułów i funkcjonalności zintegrowa-nych w aplikację, która mogła już speł-niać wybrane funkcje biznesowe. Testy obejmowały zarówno poprawność funk-cjonalną, jak i integrację pomiędzy mo-dułami aplikacji.

Strukturę testów w ramach jednej ‘iteracji’ przedstawia Rysunek 1.

W ramach jednego podejścia testów Stream oddawano kolejno trzy pakiety funkcjonalno-ści (‘Streamy’ po kilka funkcji), głównie do pod-stawowych testów funkcjonalności i Look & feel. Po zakończeniu tego etapu testów były tworzone paczki funkcjonalności, dostarczane jako Build. Obejmowały one zintegrowane funkcje, dotąd przetestowane w ramach poprzednich testów. Testom poddawano kolejno trzy takie paczki. Końcowym produktem jednej iteracji była wer-sja Release aplikacji, obejmująca wszystkie do-tychczas przetestowane funkcje i moduły zinte-growane w jedną, stabilną aplikację.

Testowanie wewnętrzne obejmowało 3 ite-racje. Następnie – gdy kondycja aplikacji oraz

zakres funkcjonalności umożliwiał włączenie do testów zespołu klienta – organizacja proce-su testowego została zmieniona. Testy wykony-wały równocześnie dwa zespoły – wewnętrzny (wewnętrzne środowisko testowe / SIT) i klien-ta (SIT / UAT). Testowanie dotyczyło już tylko wersji Release aplikacji – przy czym wersja sys-temu, którą testował zespół wewnętrzny była nowszą o 2 wersje od wersji oddanej do testów pracownikom klienta. Takie podejście umożli-wiało zarówno znalezienie poważniejszych błę-dów i ich poprawienie zanim system zostanie przekazany do testowania klientowi, jak i za-gwarantowanie, że testerzy klienta będą praco-wać na aplikacji wolnej od poważnych błędów i skupią się na testowaniu funkcjonalności, logi-ki biznesowej i użyteczności.

Środowiska testowe Zależnie od etapu i celu testów, testowanie przeprowadzano w innych środowiskach. Testy wewnętrzne odbywały się w udostępnionym testerom środowisku dostawcy oprogramowa-nia, ubogim w dane testowe i pozbawionym in-tegracji z zależnymi systemami zewnętrznymi i urządzeniami. Ich celem było znalezienie błę-dów powstałych w trakcie wytwarzania opro-gramowania i przygotowanie aplikacji do ko-lejnego poziomu testów – integracyjnych i ak-ceptacyjnych. W trakcie testów wewnętrznych wszystkie punkty integracji zastąpiono zaślep-kami i sztucznymi danymi testowymi, współ-praca z urządzeniami była natomiast symulo-wana przez oprogramowanie.

Laboratoria SIT oraz UAT były stworzone w siedzibie klienta - i połączone z odpowied-nimi testowymi bazami danych, systemami zewnętrznymi i urządzeniami typu drukar-ki, czytniki kart, kasy. W pierwszej kolejno-ści przygotowano środowisko SIT (System In-tegration Testing) – którego celem było prze-testowanie działania systemu zintegrowane-go z systemami i urządzeniami zewnętrzny-mi, przy użyciu testowych danych, kart ban-kowych, czeków itp. Za tą weryfikację odpo-wiedzialny był zespół testerów klienta, przy wymaganym wsparciu testerów wewnętrz-nych. Po uzyskaniu odpowiedniego stop-nia jakości aplikacji (ocenianej jako ilość otwartych błędów o określonej krytyczno-ści), system zainstalowano w środowisku UAT I. UAT (User Acceptance Testing) było oficjalnym testem akceptacyjnym, wykony-wanym przez testerów klienta. Dwa miesią-ce przed planowanym terminem wdrożenia systemu na produkcję, aplikację poddano testom UAT II – wykonywanym przez pra-cowników placówek banku. Mieli oni spraw-dzić, czy gotowy system wypełnia wszyst-kie pożądane funkcje i jest gotowy by zastą-pić dotychczas używaną w oddziałach ban-ku aplikację.

Schemat organizacji środowisk testowych przedstawia Rysunek 2.

Page 51: Software Developers Journal PL 03/2009

03/200950

Testowanie oprogramowania Praca z zespołem testerów klienta

www.sdjournal.org 51

W organizacji i konfiguracji środowiska testów wewnętrznych przyjęto następujące założenia:

• Dostęp do środowiska ma jedynie ze-spół testerów dostawcy oprogramowa-nia;

• Test dymny (Smoke test) jest pierwszą czynnością po udostępnieniu nowej wer-sji aplikacji. Test ten musi zostać wyko-nany z pozytywnymi rezultatami za-nim rozpocznie się jakiekolwiek testowa-nie. Dopuszczalne jest przyjęcie aplikacji do dalszych, regularnych testów, jedynie gdy:• nie ma defektów krytycznych i blo-

kujących dalsze testowanie;• istnieją defekty krytyczne, lecz mo-

gą zostać szybko naprawione za po-mocą hotfixu lub innego rodzaju szyb-kiej poprawki. W tym przypadku wa-runkiem koniecznym po zastosowa-niu hotfixu jest rozpoczęcie testów od sprawdzenia, czy poprawka dzia-ła i umożliwia dalsze testowanie apli-kacji. Hotfix może dotyczyć zarówno błędów w samej aplikacji, jak i defek-tów środowiska – konfiguracji sprzę-tu, baz danych itp;

• Defekty znalezione w testach we-wnętrznych są zgłaszane w osobnej (we-wnętrznej) bazie danych i nie są udo-stępniane klientowi ani jego testerom;

• Końcową czynnością testów jest spo-rządzenie raportu opisującego kondycję aplikacji, liczbę i ważność znalezionych defektów oraz poprawek, zweryfikowa-nych i potwierdzonych jako działające w pożądany sposób;

• Zakończeniem testowania wewnętrzne-go jest upewnienie się, że aplikacja jest stabilna, działa poprawnie i jest gotowa do testowania zewnętrznego – przez zespół klienta. Decyzja ta jest podjęta na podstawie raportu z testowania oraz dyskusji kierowników zespołów testo-wych i kierownictwa projektu.

Organizacja środowiska SIT przedstawiała się następująco:

• Dostęp do środowiska mają testerzy do-stawcy oprogramowania – w celu przepro-

wadzenia testu dymnego oraz reproduk-cji zgłoszonych defektów – oraz testerzy klienta – dla wykonywania regularnych testów w fazie poprzedzającej testy UAT oraz dla przeprowadzania testów dym-nych w fazie testowania UAT;

• Test dymny (Smoke test) jest pierwszą czynnością po udostępnieniu nowej wersji aplikacji. Test ten musi zostać wykonany z pozytywnymi rezultatami zanim rozpocznie się jakiekolwiek te-stowanie. Podobnie jak w przypadku te-stów wewnętrznych, dopuszczalne jest przyjęcie aplikacji do dalszych, regular-nych testów, jedynie gdy nie ma defek-tów krytycznych i blokujących lub jeśli istnieje co najwyżej jeden defekt kry-tyczny, ale może zostać naprawiony w przeciągu 1 dnia za pomocą hotfixu lub re-instalacji systemu;

• Defekty znalezione w testach SIT są zgła-szane w oddzielnym, udostępnionym klientowi systemie śledzenia błędów (‘ze-wnętrzna’ baza danych błędów). Dostęp do tej bazy danych mają wybrane osoby z zespołu klienta (Test Leader) oraz anali-tycy biznesowi i Test Leader zespołu do-stawcy oprogramowania;

• Końcową czynnością testów jest spo-rządzenie raportu zawierającego liczbę i określenie krytyczności znalezionych defektów oraz liczbę poprawek, zwery-fikowanych i potwierdzonych jako dzia-łające w pożądany sposób;

• Zakończeniem testowania SIT jest upewnienie się, że aplikacja jest stabil-na, działa poprawnie i jest gotowa do testowania UAT – w środowisku bar-dziej zbliżonym do produkcyjnego pod względem danych testowych. Testy UAT wykonują testerzy oraz analitycy klienta. Decyzja ta jest podjęta na pod-stawie raportu z testowania oraz dysku-sji kierowników zespołów testowych i kierownictwa projektu.

Środowiska UAT służyły do oficjalnych te-stów akceptacyjnych. Zorganizowano dwa laboratoria UAT – jedno dla zespołu tester-skiego klienta, drugie dla zespołu pracowni-ków banku z różnych oddziałów, mających sprawdzić funkcjonowanie systemu pod ką-

tem przydatności i poprawności w działa-niu operacyjnym oraz ergonomii. Środowi-ska UAT charakteryzowały się następujący-mi cechami:

• Dostęp mają jedynie zespoły klienta;• Defekty znalezione podczas testo-

wania zgłaszane są w wewnętrznym systemie klienta. Manager QA po stronie dostawcy oprogramowania ma dostęp do tego systemu i jest od-powiedzialny za przetransferowanie defektów dotyczących aplikacji do wewnętrznej bazy defektów produ-centa oprogramowania;

• Zakończenie cyklu testów UAT kończy się sporządzeniem rapor-tu przedstawiającego stan aplikacji – do wglądu Komitetu Sterującego. Pozytywne wyniki testów i subiek-tywna ocena udziałowców projek-tu są podstawą do podjęcia decyzji o wdrożeniu na produkcję.

Organizacja pracy zespołów testerskich W trakcie dewelopmentu i początkowych eta-pów testowania, testy wykonywał tylko zespół wewnętrzny. W tym czasie testerzy klienta za-poznawali się z funkcjonalnością systemu na podstawie dokumentacji projektowej oraz or-ganizowali środowisko pracy.

Po zakończeniu pierwszego etapu testów i upewnieniu się, że dana wersja systemu jest gotowa do testów integracyjnych i udostęp-nienia go zespołowi klienta, aplikację zainsta-lowano w środowisku SIT. SIT było początko-wo środowiskiem dostępnym jedynie zespo-łowi klienta, testerzy wewnętrzni nie mie-li do niego dostępu. Podczas gdy zespół we-wnętrzny kontynuował swoje testy i wery-fikował kolejne wersje aplikacji, pracownicy klienta otrzymali pierwszą – już przetestowa-ną wewnętrznie – wersję systemu do testowa-nia. Swoje pierwsze testy przeprowadzali bez jakiegokolwiek wsparcia ze strony dostawcy oprogramowania, opierając się na własnym rozumieniu systemu i dostępnej dokumen-tacji projektowej. Testy odbywały się w cyklu tygodniowym, przy czym zgłaszanie znalezio-nych defektów następowało dopiero po zakoń-czeniu cyklu. Komunikacja z zespołem produ-centa oprogramowania ograniczała się do roz-

Pojęcia

• UAT (User Acceptance Testing) – Testy akceptacji użytkowników mające na celu sprawdzenie, czy aplikacja spełnia wymagania użytkowników pod względem funkcjonalności oraz użyteczności.

• SIT (System Integration Testing) – Testowanie integracji systemu weryfikujące poprawność działania wszystkich modułów systemu zintegrowa-nych w całość i połączonych z zależnymi systemami zewnętrznymi.

• Smoke test (Sanity test) – Test dymny – podstawowy test wykonywany po instalacji nowej wersji systemu mający na celu stwierdzenie, czy aplika-cja działa i może być poddana dalszym, głębszym testom

• Back end – Aplikacja pośrednio wspierająca pracę systemu frony end – np. przez komunikowanie się w celu pobrania informacji / danych wyko-rzystywanych bezpośrednio przez użytkownika aplikacji front-end

• Front end – Aplikacja, z którą użytkownik pracuje bezpośrednio

Page 52: Software Developers Journal PL 03/2009

03/200952

Testowanie oprogramowania

mów telefonicznych lub e-konferencji (raz w tygodniu) dotyczącej rezultatów testów i ogól-nego postępu prac.

Takie podejście od początku doprowadzi-ło do problemów i sytuacji konfliktowych. Po pierwsze, brak odpowiedniej komunika-cji i wsparcia spowodował, iż zespół testowy skazany był na siebie. Problemy z konfiguracją systemu, integracją z systemami zewnętrzny-mi lub urządzeniami itp. wstrzymywały testo-wanie i powodowały nieprawdziwe wyniki te-stów, ale nie były identyfikowane i komuniko-wane odpowiednim osobom. I tak na przykład awaria połączenia z zewnętrznym systemem, która uniemożliwiała wykonanie transakcji bankowych, została zgłoszona jako krytycz-ny błąd w aplikacji, bez upewnienia się, że in-tegracja z back endem działa. Dalsze testowa-nie wstrzymano odrzucając wersję systemu ja-ko niestabilną, mimo że – jak się okazało póź-niej – przywrócenie połączenia z back endem zajęło 0.5 godziny.

Powtarzające się problemy i konflikty do-prowadziły w końcu do zmiany podejścia do testowania – do siedziby klienta wysłano te-sterów dostawcy oprogramowania oraz pro-gramistów, którzy mieli wspierać testowanie aplikacji i naprawę błędów bezpośrednio ko-rzystając ze środowiska docelowego. Począt-kowo zespół wewnętrzny korzystał ze środo-wiska SIT jedynie w celu przeprowadzania testów dymnych oraz reprodukcji defektów, które nie były reprodukowane w wewnętrz-nym środowisku testowym. W rzeczywistości oznaczało to, że programiści i testerzy dostaw-cy oprogramowania byli zmuszeni czekać, aż zespół klienta zakończy prace, aby mieć do-stęp do SIT i móc rozpocząć analizę zgłoszo-nych błędów.

Aby wyeliminować to ograniczenie i umoż-liwić bezproblemową pracę obu zespołów, klient zorganizował drugie środowisko testo-we – UAT. Testerom dostawcy udostępnio-no środowisko SIT, natomiast testerzy klien-ta rozpoczęli prace w środowisku UAT, przy czym wstępny test dymny realizował zespół dostawcy.

Harmonogram i organizacja testów SIT odbywała się według wspólnego schematu (Rysunek 3.).

Procedura testów przedstawiała się nastę-pująco:

• Po instalacji nowa wersja systemu zosta-wała poddawana testom dymnym. Wy-

konywał je najpierw zespół dostawcy oprogramowania w środowisku SIT. W razie pozytywnych wyników testu, apli-kację instalowano w środowisku UAT i oddawano testerom klienta;

• Test dymny wykonywany przez klien-ta miał na celu stwierdzić, czy aplika-cja jest gotowa do dalszych, głębszych testów. Wszystkie krytyczne przypadki testowe musiały być zakończone z ocze-kiwanym wynikiem;

• W czasie, gdy zespół klienta zajmował się testem dymnym, testerzy wewnętrz-ni wykonywali testy regresji. Pozwala-ło to zweryfikować dokonane poprawki błędów i znaleźć ewentualne nowe błę-dy jeszcze przed rozpoczęciem kolejne-go etapu testów klienta. Tym sposobem programiści otrzymywali szybką infor-mację zwrotną i mogli skupić się na ko-lejnych pracach;

• Po zakończeniu testów dymnych zespół klienta rozpoczynał testy regresji, aby stwierdzić, czy poprawki dla uprzednio zgłoszonych przez nich błędów działa-ją w odpowiedni sposób i nie wywołują dalszych błędów;

• Zespół dostawcy rozpoczynał testowa-nie regularne jeszcze w trakcie testów regresji – przypadki testowe zostały za-projektowane w taki sposób, aby umoż-liwiać jednoczesną weryfikację popra-wek i przeprowadzanie normalnych te-stów. Wyniki testów – błędy – były ra-portowane na bieżąco w wewnętrznym systemie obsługi błędów dostawcy opro-gramowania;

• Zespół klienta rozpoczynał regularne testy po wykonaniu testów regresji, ana-lizie ich wyników oraz przygotowaniu zadań do zrealizowania podczas testo-wania. Testy klienta wykonywane były według procedury obowiązującej w ban-ku, pod nadzorem i przy wsparciu ze-społu dostawcy, który udzielał niezbęd-nych wyjaśnień co do wdrożonych po-prawek oraz zakresu zmian dokonanych w funkcjonalności systemu;

• Po ukończeniu cyklu testów zespół klienta opracowywał wyniki testów (tworzył raporty błędów) i przekazywał je do swojego Kierownika Testów, który po dyskusji z Kierownikiem Testów ze strony dostawcy zgłaszał znalezione błę-dy do systemu obsługi błędów;

• Równocześnie z rozpoczęciem cyklu te-stowania przez zespół klienta, progra-miści przystępowali do naprawy błę-dów: • zgłoszonych w trakcie testów wyko-

nywanych przez testerów dostawcy oprogramowania;

• zgłoszonych przez testerów klienta po ukończeniu ich cyklu testów.

Plusem takiej organizacji pracy było zwięk-szenie interakcji i komunikacji pomiędzy zespołami, co w widoczny sposób polep-szyło efektywność testowania i zmniejszyło ilość popełnianych przez testerów pomyłek. Ponadto testy przeprowadzane podwójnie – przez oba zespoły – pozwalały znaleźć wię-cej błędów i zminimalizować ryzyko pomi-nięcia istotnych błędów.

Poprawiła się także efektywność poprawia-nia błędów, ponieważ nowe błędy zgłaszane były z wystarczającym opisem i już zweryfi-kowane jako prawdziwe błędy – programiści nie musieli więc tracić czasu na analizowa-nie i weryfikację poprawności.

Udostępnienie środowiska UAT oznacza-ło jeszcze większe zwiększenie efektywności testowania z racji tego, że zawierało więcej danych i urządzeń testowych i było bardziej niż SIT zbliżone do środowiska docelowego. Z tego powodu testy umożliwiały symulację pracy w środowisku docelowym.

Kolejnym etapem było udostępnienie apli-kacji pracownikom oddziałów banku w ce-lu ostatecznej weryfikacji funkcjonalności i użyteczności aplikacji. System testowy za-instalowano w osobnym środowisku UAT II będącym niemal dokładną kopią środowi-ska produkcyjnego. Pracownicy banku re-alizowali testy posługując się własnymi me-todami i procedurami, które obowiązywały w oddziałach banku. Operacje wykonywane przez nich symulowały rzeczywiste procesy biznesowe i czynności w banku. Pracę teste-rów z oddziałów banku nadzorowali anality-cy biznesowi klienta oraz Kierownik Testów ze strony dostawcy oprogramowania. Służyli oni wyjaśnieniami w przypadku pytań i nie-jasności dotyczących funkcjonalności sys-temu oraz weryfikowali ewentualne błędy (które następnie zgłaszano do systemu ob-sługi błędów projektu).

Wszelkie uwagi i wnioski pracowników ban-ku były notowane i rozpatrywane na cotygo-dniowych zebraniach kierownictwa projektu,

W Sieci

• http://articles.techrepublic.com.com/5100-10878_11-1044625.html – Krótkie wprowadzenie do pojęcia testów akceptacyjnych;• www.xpuniverse.com/2001/pdfs/Testing05.pdf – Artykuł dotyczący wymagań i przeprowadzania testów akceptacyjnych;• http://www.usability.gov/refine/learnusa.html – Wprowadzenie do testów użyteczności – cele, metody i koszty testów;• www.webcredible.co.uk/user-friendly-resources/web-usability/usabilty.testing.shtml – Osiem wskazówek dotyczących planowania, realizacji i analizy

wyników testów akceptacyjnych.

Page 53: Software Developers Journal PL 03/2009

Praca z zespołem testerów klienta

www.sdjournal.org 53

które następnie decydowało, jakie uwagi i suge-stie rzeczywiście mogą usprawnić działanie apli-kacji i będą wdrażane jako Żądania Zmian.

Analizowano również błędy wykryte pod-czas testów UAT II – stosunkowo często błę-dy te pojawiały się tylko w środowisku UAT II, nie występowały w UAT i SIT. W takich przypadkach naprawa błędów wymagała do-stępu do UAT II – błąd reprodukowano oraz brano odpowiednie logi systemu, aby następ-nie przystąpić do poprawiania błędu na ma-szynie programisty.

Zatrudnienie pracowników banku do testo-wania systemu przed wdrożeniem na produk-cję umożliwiło wykrycie i poprawę istotnych dla poprawnego funkcjonowania systemu błę-dów oraz wdrożenie kilku zmian ułatwiających sprawną i szybką pracę z aplikacją.

WynikiDzięki usprawnionej współpracy z zespoła-mi klienta i kooperacji w prowadzeniu prac testowych osiągnięto wymierne korzyści:

• większa liczba błędów wykrytych i na-prawionych przed wdrożeniem systemu na produkcję;

• większe pokrycie testów dzięki wyko-nywaniu testów przez dwa zespoły, uzu-pełniające się nawzajem;

• lepsza komunikacja w projekcie, szybsze i efektywniejsze rozwiązywanie proble-mów;

• wzrost zaufania klienta do dostawcy oprogramowania.

Oraz oczywiście – sprawdzenie funkcjo-nowania systemu w środowisku docelo-wym (UAT II) i w użytkowaniu przez użyt-kowników końcowych. Dodatkowo połą-czenie sił i wspólna praca nad systemem umożliwiła zespołowi klienta dogłębne po-znanie funkcjonalności tworzonego syste-mu, jak również powiązań z systemami ze-wnętrznymi, co usprawniło pracę organiza-cji klienta.

PodsumowaniePraca z testerami klienta nie zawsze jest pro-sta i przyjemna. Czasami wymaga poświęce-nia stosunkowo dużych nakładów czasu na przeszkolenie zespołu klienta i zorganizo-wania dodatkowego środowiska testowego oraz reorganizacji planu i założeń projektu. Współpraca z klientem wymaga dobrej or-ganizacji pracy i chęci współdziałania, ale re-zultaty mogą być bardzo dobre i mieć zasad-niczy wpływ na sukces projektu. Klient na-biera zaufania do dostawcy oprogramowania i z większym zaangażowaniem podchodzi do

rozwiązywania problemów, jeśli ma wgląd w bieżący stan aplikacji. Niewątpliwym plu-sem jest możliwość maksymalizacji efektyw-ności prac testowych – wykrycie jak najwięk-szej liczby błędów w jak najkrótszym czasie oraz możliwość sprawdzenia działania syste-mu podczas działania z użytkownikami zbli-żonymi do użytkowników końcowych sys-temu. Dlatego też warto rozważyć większe zaangażowanie klienta w prace projektowe – obie strony – i dostawca, i klient – mogą na tym wiele skorzystać.

KAROLINA ZMITROWICZPracuje na stanowisku Analityka biznesowego w firmie BLStream, wchodzącej w skład Grupy BLStre-am. Karolina specjalizuje się obecnie w modelowa-niu wymagań biznesowych. Wcześniej pracowała jako Manager Quality Assurance w projektach in-formatycznych w sektorze finansowo – bankowym. Grupa BLStream powstała by efektywniej wykorzy-stywać potencjał dwóch, szybko rozwijających się producentów oprogramowania – BLStream i Ga-melion. Firmy wchodzące w skład grupy specjali-zują się w wytwarzaniu oprogramowania dla klien-tów korporacyjnych, w rozwiązaniach mobilnych oraz produkcji i testowaniu gier. Kontakt z autorem: [email protected]

�������������� ���������������������

R E K L A M A

Page 54: Software Developers Journal PL 03/2009

03/200954

Testowanie oprogramowaniaJakość czy jakoś to będzie?

www.sdjournal.org 55

Jego zadaniem jest maksymalizacja efektów pracy zespołów projektowych, zmniejsze-nie liczby defektów oraz skrócenie czasu

dostarczania produktów. To ludzie, a nie organizacje, tworzą dobre opro-

gramowanie. Aby proces produkcji oprogramowa-nia był ściśle związany z zapewnieniem jakości, ze-społy muszą współpracować, wykorzystywać au-tomatyzację, która przyspiesza realizację prac, wy-mieniać informacje oraz widzieć wskaźniki postę-pu testów umożliwiające lepsze zarządzanie pro-jektami. Proces produkcji oprogramowania stero-wany jakością rozszerza definicję jakości poza tra-dycyjne testowanie. Obejmuje kluczowe aspek-ty produkcji oprogramowania — od definiowania wymagań i zarządzania projektem, po zarządza-nie defektami.

Jakie zadania może Rational Qu-ality Manager wykonać za Ciebie?Lista funkcji realizowanych przez Rational Quality Manager jest długa. Nie było w ofercie IBM Ratio-nal podobnego produktu do tej pory. Oto krótkie podsumowanie kluczowych cech: Postulaty te są jasne i w każdym projekcie powinny być przestrze-

gane. Praktyka jednak mówi inaczej. Np. współ-dzielenie informacji w zespole. Przecież informa-cje w każdym projekcie są rozsyłane do wszystkich zainteresowanych! Czy na pewno tak jest?

Przestrzeganie wszystkich tych zadań może się wiązać z koniecznością wykonania dodatkowych prac niż konkretne zadania projektowe, a w efek-cie czasem doprowadzamy do drobnych zanie-dbań, które mają tendencje do przekształcania się w poważne problemy projektowe. Np. brak infor-macji o wykorzystaniu laboratorium testowego może spowodować spiętrzenie się testów wyma-gających specyficznych zasobów w pewnych okre-sach czasu (zwykle tuż przed końcem projektu), a bezproduktywne utrzymywanie go w innych. Ta-kie przykłady można mnożyć. Zwykle wytłuma-czeniem jest brak czasu na zadania niezwiązane ściśle z projektem, takie jak raportowanie czy uzu-pełnianie dokumentacji.

Ważne jest więc zapewnienie automatyzacji jak największej ilości czynności, aby postulaty takie jak wgląd w stan realizacji projektu w czasie rze-czywistym mogły być spełnione. Jak więc wygląda praca z Rational Quality Manager i jak rzeczywi-ście wypełnia on postawione przed nim zadania?

Ze strony http://www.ibm.com/developerworks/downloads/r/rqm/ można ściągnąć 60 dniową wersję próbną Rational Quality Manager, aby we własnym środowisku przekonać się o możliwo-ściach tego narzędzia. Aby ułatwić pierwsze kro-ki, kilka przykładów działania użytkowników.

Tworzenie nowego użytkownikaUtworzenie konta dla nowego użytkownika wy-maga następujących czynności:

• Zalogowanie do systemu w roli administra-tora (domyślne konto to user name: AD-MIN; password: ADMIN).

• Następnie z menu aplikacji wybieramy Ad-min i Jazz User Administration (Rysunek 1.)

• Na ekranie User Management wybieramy polecenie Create User.

Niezbędne dane do wprowadzenia to name (na-zwa użytkownika), user ID (login użytkownika i adres e-mail oraz konieczne jest wybranie wła-ściwych uprawnień licencyjnych, przykład na Rysunku 2. Następnie przycisk Save zakończy operację, która będzie potwierdzona komunika-tem (tak jak na Rysunku 3.)

Uwaga: Nowy użytkownik ma nadawane hasło takie same jak nazwa konta (User Id) Po pierwszym zalogowaniu użytkownik powinien ustalić sobie inne hasło.

Planowanie testówPlan testów to jedna z tych cznności, które są klu-czowo ważne dla sprawnego procesu testów, ale bardzo często prowadzona jest tylko na ogólnym poziomie, a typowym wytłumaczeniem jest, że planowanie zabiera dużo czasu, który może być wykorzystany na bardziej konkretną pracę.

Jakość czy jakoś to będzie?

Odpowiedź na pytanie czy tworzone oprogramowanie jest wystaczająco dobre do uruchomienia produkcyjnego wymaga złożonego procesu decyzjnego. IBM Rational® Quality Manager jest rozwiązaniem, które może pomóc podjąć tą odpowiedzialną decyzję w oparciu o wiarygodne dane dostarczane w czasie rzeczywistym.

Dowiesz się:• Jak oprogramowanie wspiera proces zarzą-

dzania testami;• Jak rozpocząć prace z Rational Quality Manager .

Powinieneś wiedzieć:• Jak wygląda proces testów w Twoich projek-

tach.

Poziom trudności

Czyli jak Rational Quality Manager może wesprzeć profesjonalne zarządzanie procesem testów

Rysunek 1. Menu administratora

Page 55: Software Developers Journal PL 03/2009

03/200954

Testowanie oprogramowaniaJakość czy jakoś to będzie?

www.sdjournal.org 55

Dzięki Rational Quality Manager plan te-stów może być stworzony szybko, może wy-korzystywać sprawdzone wcześniej procedu-ry i być aktualizowany na bieżąco, zgodnie ze zmieniającymi się potrzebami projektu. W Ra-tional Quality Manager plan testów obejmu-je co najmniej cel i zakres testów, poszczegól-nych etapów testów oraz kryteria zakończenia. Pozwala to na:

• Śledzenie przeglądów, akceptacji i bieżące-go statusu planu;

• Tworzenie i zarządzanie przypadkami te-stowymi w powiązaniu z zakresem zdefi-niowanym w planie;

• Importowanie i wiązanie wymagań projek-tu z przypadkami testowymi czy bezpo-średnio z planem dla zapewnienia właści-wego pokrycia testami;

• Planowanie i wiązanie z przypadkami i ele-mentami planu środowisk do przeprowa-dzania testów (np. przeglądarki, bazy da-nych, systemy operacyjne), co ułatwia przy-gotowanie właściwych konfiguracji testo-

wych i śledzenie stanu w rozbiciu na istotne cechy konfiguracji;

• Określenie potrzebnych zasobów, czasu i innych wysiłków do zrealizowania właści-wych testów na każdym z etapów projektu;

• Zdefiniowane i komunikowanie w całym ze-spole celów biznesowych, przedmiotów te-stów, kryteriów jakości i innych artefaktów.

Plan składa się zwykle z kilku szablonów, dosto-sowywanych do własnych potrzeb organizacji. Je-śli w standardowych szablonach są elementy nie-przydatne do Twojego procesu, można je usunąć, jeśli jakiś brakuje, można je utworzyć. Tak utwo-rzony szablon może być podstawą w następnym projekcie, pozwalając tym samym na przeniesie-nie sprawdzonych praktyk i przyspieszenie pracy.

Kluczowe kroki przy tworzeniu nowego pla-nu testów ze standardowego szablonu:

• Zaloguj się do Rational Quality Manager ja-ko użytkownik.

• W lewym panelu nawigacyjnym wybierz ikonę Plannig i polecenie Create Test Plan

• Następnie podaj nazwę planu testów, a w po-lu Template wybierz Default Test Plan Template

• Przycisk Save utworzy Twój plan testów, efekt powinien być analogiczny do widocz-nego na Rysunku 4.

Domyślny plan testów składa się z trzech głów-nych sekcji:

• * Nagłówek (pokazy na Rysunku 4.);• * Spis treści (czyli elementy planu);• * Sekcja opisu elementu.

Domyślnie sekcje znajdujące się w szablonie nie są utworzone, tak więc w każdą potrzebną w projekcie należy zainicjować poprzez naciśnię-cie przycisku Work Item Create i wypełnienie danych niezbędnych danej sekcji,

Np. w sekcji Summary musimy wybrać właści-ciela (Owned By) i planowaną datę zakończenia (Due), tak jak to pokazane jest na Rysunku 5.

Jako że zadaniem testów jest sprawdzenie speł-nienia wymagań, najczęściej kolejnym krokiem jest dołączenie opisów wymagań do przetestowa-nia. Jeśli wymagania są zgromadzone w systemie zarządzania wymaganiami takim jak RequistePro możemy je powiązać do Rational Quality Mana-ger. Wymagania zapisane w dokumentach może-my zaimportować przez format XML, a dla na-szego ćwiczenia utworzymy wymaganie wprost w Rational Quality Manager.

Wybieramy z panelu sterowania ikonę Requ-irements i polecanie Create Requirement.

Tabela1. Podsumowanie kluczowych cech Rational Quality Manager

Współdziele-nie informacji w zespole

Wsparcie współpracy w rozproszonych zespołach dzięki interfejsowi Web 2.0;Centralne repozytorium przechowuje wersje zasobów testowych i szablonów do wielokrotnego wykorzystania;Obsługa zespołów małych, średnich i dużych (do 250 osób).

Zarządzanie w cyklu życia projektu

Elastyczne środowisko definiowania procesów pozwalające na włączenie spraw-dzonych praktyk w miarę ich nabywania;Plan testów dla wszystkich etapów projektu określający role uczestników, proces, odpowiedzialnych za efekty i automatyzujący przepływ zasobów i informacji;Współdzielony dostęp i śledzenie stanu zasobów w całym cyklu życia.

Zarządzanie testami ręcz-nymi

Opisywanie kroków testowych z formatowaniem RichText, obrazami i zestawami danych testowych zapewniające precyzję opisu i wykonania;Proceduralizacja tworzonych testów zapewnia przyspieszenie pracy, wielokrotne wykorzystanie tworzonych elementów oraz dostęp dla wszystkich zainteresowa-nych w zespole.

Automatyza-cja skracają-ca czas pro-jektu

Terminarze wykonania testów zapewniają możliwość optymalnego wykorzystania środowisk testowych;Zarządzanie laboratoriami testowymi pomaga użytkownikom śledzić zapotrzebo-wanie i maksymalizować wykorzystanie posiadanych zasobów zarówno tych do-stępnych fizycznie, jak i tworzonych wirtualnie.

Metryki pro-jektu ułatwia-jące podejmo-wanie decyzji

Automatyczne zbieranie danych;Wizualizacja aktualnego statusu projektu dzięki personalnym widokom wskaźni-ków;Stała aktualizacja danych.

Rysunek 2. Tworzenie nowego użytkownika

Rysunek 3. Potwierdzenie utworzenia nowego konta

Rysunek 4. Zapisany plan testów

Rysunek 5. Tworzenie sekcji Summary

Page 56: Software Developers Journal PL 03/2009

03/200956

Testowanie oprogramowaniaJakość czy jakoś to będzie?

www.sdjournal.org 57

W oknie dialogowym, które się pokazuje, wpi-sujemy tytuł (pole summary) i możemy określić in-ne parametry (tylko waga jest obowiązkowa, ale ma wartość domyślną, więc też możemy pozosta-wić bez zmiany). Obowiązkowe jest naciśnięcie Save aby wysłać dane do bazy. Przykładowo wypeł-nione wymaganie jest pokazane na Rysunku 6.

Kolejne dane wprowadzamy do opisu przypad-ku testowego. Wybieramy sekcję przypadków te-stowych (Table of Contents->Test Cases) i z panelu nad tabelą operację Add New Test Case

Przy użyciu domyślnego szablonu (Default Test Case Template) wszystkie pola poza nazwą i wagą są opcjonalne. Ich wypełnienie pozwala łatwo wy-szukiwać potrzebne elementy i zestawy elemen-tów. Warto jest zwrócić uwagę na pole waga (We-ight). Teoretycznie wszystkie przypadki testowe są równie ważne, ale jak wiadomo, niektóre są waż-niejsze. Dobra skala oceny pozwala w krytycznych sytuacjach wybrać kluczowo ważne. Zatwierdze-nie danych przyciskiem OK tworzy szablon i wra-camy do listy przypadków testowych, podobnej do tej z Rysunku 8.

Kliknięcie na elemencie listy przypadków te-stowych otworzy nową kartę z szablonem możli-wych do wprowadzenia danych. W odpowiednich sekcjach możemy utworzyć link do wymagań in-nych przypadków testowych czy dołączyć dowol-ne dokumenty, które powinny być związane z tym przypadkiem testowym. Wszystkie te informacje pomogą nam określić,jak wykonać test na rzecz

wybranego przypadku testowego. Na koniec tego artykułu stworzymy i uruchomimy test.

Tworzenie i wykonywanie przypadków testowychKluczowym elementem przypadku testowego jest opis testu. Znajduje się on w sekcji skryptów (Test Scripts). Sekcja pozwala na stworzenie listy skryptów związanych z przypadkiem testowym.

Skrypty mogą być wpisane do ręcznego wyko-nania w Rational Quality Manager albo też po-wiązane z narzędziami automatyzujące pracę ta-kimi jak:

• IBM® Rational® Functional Tester, • IBM® Rational® Manual Tester, • IBM® Rational® Performance Tester, • IBM® Rational® Service Tester for SOA

Quality, • IBM® Rational® Appscan i innymi.

Interfejs komunikacji jest w pełni udokumento-wany, więc w razie potrzeby można zbudować po-łączenie do innych rozwiązań wspierających pracę testera. W ramach tego artykułu stworzymy naj-prostszy kilkukrokowy skrypt do testów ręcznych.

Wybieramy sekcję Test Scripts i ikonę dodaj no-wy skrypt (Add New Test Script). Podajemy nazwę skryptu i wypełniamy inne opcjonalne pola (pole Type nie może być zmienione, jeśli nie są zainstalo-wane interfejsy do narzędzi automatyzacji). Przy-

cisk OK tworzy skrypt, następnie naciskamy Save i klikamy nazwę skryptu, co otwiera nową kartę, w której możemy wprowadzić kroki skryptu.

Każdy tworzony krok testu jest domyślnie ak-cją do wykonania. W liście wyboru po lewej stro-nie opisu kroku można zmienić rodzaj z akcji na punkt weryfikacji bądź punkt raportowania.

Opisując kroki testu można tekst formatować zgodnie z formatem RFT, dodawać obrazy i listy danych do wykorzystania w trakcie danego kroku.

Przycisk Save kończy edycję i nasz skrypt jest gotowy do wykonania.

Wykonanie skryptuW prawym górnym rogu przypadku testowe-go, niezależnie od wybranej sekcji, jest przycisk uruchomienia skryptu Run Test Case. Po wybra-niu wypełniamy metrykę testu (kto, kiedy, jaki skrypt, jakie środowisko itp.), i otwiera się okno wykonania takie jak na Rysunku 11.

Następnie wykonujemy pokazane kroki te-stu raportując kolejno ich wykonanie oraz spraw-dzając punkty testowe i określając wynik. Przej-ście przez ostatni punkt bądź wybranie negatyw-nego zakończenia testu (Fail) powoduje wyświe-tlenie statusu realizacji takie jak na Rysunku 12. Na tym ekranie mamy do dyspozycji przycisk Sa-ve – zapisanie wyników testu lub też zgłoszenie

Rysunek 6. Wypełnione wymaganie

Rysunek 7. Opisany przypadek testowy

Rysunek 8. Lista przypadków testowych

Rysunek 9. New Test Script dialog

Rysunek 10. Kroki skryptu

Page 57: Software Developers Journal PL 03/2009

03/200956

Testowanie oprogramowaniaJakość czy jakoś to będzie?

www.sdjournal.org 57

błędu. Nie da się ukryć, że tester czuje się usats-fakcjonowany, jeśli błąd znajduje, co w jakimś stop-niu może opóźnić dostarczenie produktu, ale ta-ka jest natura ludzka. Następny krok staje się więc bardzo ważny – zakomunikowanie faktu, że apli-kacja nie jest taka dobra jak się wydawało do tej po-ry w zespole. Nie darmo powstały określenie kryty-ka i krytyka konstruktywna. Ta druga forma wska-zania błędów zakłada, że nie tylko podamy infor-mację, że jest źle, ale również podpowiemy, co trze-ba zrobić/osiągnąć, aby stan uległ poprawie. Dzię-ki Rational Quality Manager wraz z werdyktem te-stu przesyłane są w czasie rzeczywistym wszystkie inne dostępne informacje:

• skrypt testu pokazujący kroki, jakie zostały wykonane;

• dane testowe, które doprowadziły do błędu;• czas wykonania;• opis konfiguracji serwera i klienta;• wymagania, które zostały niespełnione.

Mając takie informacje znacznie łatwiej jest znaleźć i usunąć przyczynę błędu niż tylko na podstawie informacji, że jest źle.

Zebrane w jednym centralnym serwerze wszystkie informacje o testach znacznie ułatwia-ją wielokrotne wykorzystanie tych samych skryp-tów, danych, czy osób, co zapewnia krótszy czas i większą precyzję pracy.

Przy tym dzięki temu, że Rational Quality Ma-nager jest zbudowany w Javie przy użyciu techno-logii Web 2.0, dotarcie i wykorzystanie informacji nie jest trudniejsze niż użycie przeglądarki WWW.

Rational Quality Manager jest środowiskiem zarówno dla testerów, jak i dla osób podejmują-cych decyzje projektowe. Wszystkie dane, jakie wprowadziliśmy w trakcie tworzenia i wykonania testu, mogą posłużyć powzięciu właściwej decyzji czy to o skierowaniu produktu do rzeczywistego działania, czy o dalszych pracach rozwojowych.

Ekran główny (Home) pokazuje (być może trzeba nacisnąć przycisk Refresh) wyniki wła-śnie wykonanych testów, w formie graficznej czy tekstowej. Podejmowanie trafnych decyzji na podstawie twardych danych staje się znacznie ła-twiejsze. Wygląd ekranu głównego i dostępne ra-porty mogą być dowolnie zmieniane i rozszerza-ne o potrzebne organizacji wskaźniki, zestawie-nia czy inne formy raportu. Przykładowy raport można zobaczyć na Rysunku 13.

Zapraszam na stronę ibm.com/developerworks/rational, gdzie w sekcji Rational Quality Manager znajdziesz artykuły na temat tworzenia własnych raportów, wskaźników, integracji z narzędziami automatyzacji. Artykuły są publikowane zarówno w formie tekstów, jak i filmów. Można dołączyć się do forum użytkowników wymieniających infor-macje na temat Rational Quality Manager i innych produktów rodziny Rational poświęconych jako-ści oprogramowania.

ZBIGNIEW ZARZYCKIIBM Rational Technical Consultant

Rysunek 11. Wykonanie testu

Rysunek 12. Podsumowanie wykonania skryptu

Rysunek 13. Przykładowy wykres automatycznie generowany przez Rational Quality Manager

Page 58: Software Developers Journal PL 03/2009

03/200958

Testowanie oprogramowaniaWebAii –Testowanie aplikacji ASP .NET

www.sdjournal.org 59

Jak twierdzi Stephen H. Kan: jakość opro-gramowania przestała być zaletą syste-mów informatycznych. Stała się warun-

kiem koniecznym dla firm poważnie myślą-cych o zakończeniu projektów sukcesem. Dla-tego wychodząc naprzeciw tym problemom, chciałbym zaprezentować czytelnikowi arty-kuł na temat technik testowania systemów webowych opartych na silniku ASP.NET oraz frameworku WebAii.

WebAii – wprowadzenieWebAii jest darmowym zestawem biblio-tek wspierającym tworzenie testów auto-matycznych, uruchamianych dla podstawo-wych przeglądarek internetowych (Micro-soft Internet Explorer, Mozilla Firefox). Ni-niejszy framework dostarcza rozbudowa-nego zestawu narzędzi do tworzenia aser-cji dla stron WWW związanych ze spraw-dzaniem dostępności i widoczności kontro-lek HTML/ASP.NET, śledzenia renderin-gu elementów strony, wsparciem dla testów struktury DOM oraz JavaScript czy też wido-ków zależnych od kaskadowego arkusza sty-lów (CSS). Sercem środowiska WebAii jest obiekt Manager, który odpowiedzialny jest m.in. za uruchomienie przeglądarki, połącze-nie z klientem oraz sterowanie procesem te-

stów. Istnieje możliwość uruchomienia pro-gramu testowego na dwa sposoby: w środo-wisku NUnit bądź we własnej aplikacji typu standalone (błędy wykonania można rapor-tować w pliku zewnętrznym, obsługiwanym przez obiekt Log). Swoje rozważania chciał-bym skupić na pierwszym sposobie.

Po dodaniu referencji do bibliotek zewnętrz-nych, możemy rozpocząć pracę z implementa-cją pierwszego testu. Na początku zdefiniujmy nową klasę. W tym celu w Visual Studio z me-nu Project>Add New Item wybieramy WebAii-NUnitTest (Shared Manager). W tym momen-cie utworzyliśmy gotowy szablon składający się z następujących standardowych metod:

• TestClassInitialize – utworzenie in-stancji obiektu Manager, wykorzystywa-nego podczas testów. Jeżeli nie istnieje obiekt konfiguracyjny (Settings) bądź zo-stał zniszczony, tworzona jest jego nowa instancja. Wszystkie pola ustawiane są na wartości domyślne.

• MyTestInitialize – określenie wartości początkowych, wykonywanych przed każ-dym testem.

• TestClassTearDown (CleanUp) – tzw. me-toda sprzątająca, kończy pracę obiektu Manager oraz zamyka uruchomioną przy starcie przeglądarkę interetową.

W dalszych krokach jedyne co musimy zro-bić to zakodować poszczególne metody, któ-re będą odpowiedzialne za weryfikację po-prawności naszej aplikacji webowej. W tym

miejscu chciałbym się zatrzymać nad meto-dą MyTestInitialize. W niniejszym przy-kładzie wykorzystywane są ustawienia do-myślne – czyli weryfikacja poprawności oce-niania będzie w środowisku Internet Explo-rer. Aby zmienić przeglądarkę na Firefox, wy-starczy jako parametr wywołania metody LaunchNewBrowser podać typ przeglądarki, zgodnie z Listingiem 1.

Pierwszy testZałóżmy, iż przedmiotem naszej weryfikacji będzie prosta strona ASP.NET, która zawiera formularz logowania użytkownika do systemu (Rysunek 1.).

W pierwszym teście będziemy chcieli sprawdzić, czy wszystkie elementy, które zo-stały określone w specyfikacji, znajdują się na podstawowym widoku. Znając ich numery ID metodę testującą można zakodować w nastę-pujący sposób (Listing 2.).

Ponadto framework WebAii pozwala na wy-szukiwanie elementów na stronie po dowol-nym parametrze, według którego będzie w sta-nie odróżnić kontrolki. Wśród nich do bardziej użytecznych można zaliczyć:

• Find.ByName – wyszukiwanie po nazwie pontrolki.

• Find.ByContent /Find.AllByContent – wyszukiwanie kontrolki/zbioru kontrolek wg zawartości np.• Manager.ActiveBrowser.Find.ByCon

tent("<div id=RegionId>"); Opcja ta akceptuje również wyrażenia regu-larne.

• Find.ByAttributes /Find.AllByAttributes – jako parametr wywołania metoda przyj-muje tablicę znaków interpretowaną jako pa-rę [name, value], np. Manager.ActiveBrowser.Find.ByAttributes(new string[] {

"class", "TextArea _ Class" });.

WebAii

Przyszłość należy do serwisów internetowych – tego typu sformułowanie słyszałem już niejednokrotnie i być może jakiś gram prawdy w nim jest. Ogólnodostępność, interaktywność czy też współdzielenie zasobów są argumentami umacniającymi mnie w przekonaniu, iż to właśnie aplikacje webowe będą najbardziej kojarzone z inżynierią oprogramowania za parę lat.

Dowiesz się:• Czym jest WebAii i jaka jest jego rola w proce-

sie testowania stron ASP .NET;• Jak krok po kroku stworzyć szablon testów.

Powinieneś wiedzieć:• Czym są testy jednostkowe;• Posiadać podstawową wiedzę z zakresu biblio-

teki NUnit.

Poziom trudności

Testowanie aplikacji ASP .NET

Page 59: Software Developers Journal PL 03/2009

03/200958

Testowanie oprogramowaniaWebAii –Testowanie aplikacji ASP .NET

www.sdjournal.org 59

• Find.ByXPath/Find.AllByXPath – zwraca kontrolkę/zbiór kontrolek dopasowanych do wyrażenia XPath, np. pobranie wszystkich ele-mentów div ze strony:

IList<Element> allDivs =

Find.AllByXPath("/descendant::

node()[starts-with(@id,'div')]");.

Drugi test – ustawianie wartości dla poszczególnych kontrolekW kolejnym etapie testowania naszego for-mularza spróbujemy sprawdzić zachowa-nie systemu podczas autoryzacji użytkowni-ka. Załóżmy, iż w przypadku udanej próby klient zostanie przekierowany do strony http://localhost/WebAiiTest/StartPage.aspx, na któ-rej będzie znajdowała się tylko jedna etykieta z wartością Hello [login użytkownika]. Na początek spróbujmy wypełnić wartości login i hasło poprawnymi danymi:

loginTxt.Text = "admin";

passwdTxt.Text = "admin";

W następnym kroku odnajdujemy i klikamy przycisk Log In:

HtmlInputSubmit button = Manager.ActiveBro

wser.Find.ById<HtmlIn

putSubmit>("Button");

button.Click();

Na koniec sprawdzamy, czy zostaliśmy prze-kierowani do prawidłowej strony z wymaga-nymi elementami:

string url = Manager.ActiveBrowser.Url;

HtmlSpan label =

Manager.ActiveBrowser.Find.ById<HtmlSpan

>("Hello_Label_id");

string labelValue = label.InnerText;

Pełny zapis metody prezentuje Listing 3.

Pliki cookieProgramowanie WWW nierozerwalnie wiąże się z obsługą plików cookie (ciasteczek). Odno-

sząc się chociażby do naszej przykładowej apli-kacji, jednym ze sposobów przenoszenia nazwy użytkownika pomiędzy stronami, jest umiesz-czenie wartości login właśnie w takim pliku. WebAii dostarcza pełnego wsparcia w dziedzi-nie obsługi plików cookie. Dostęp do niego od-bywa się poprzez obiekt CookieManager. Do podstawowych funkcji malipulacji na obiekcie tego typu można zaliczyć:

• DeleteCookie – usunięcie wszystkich ciasteczek – opcja szczególnie przydatna, gdy podczas testowania aplikacji w środo-wisku produkcyjnym chcemy się uchro-nić przed cache'owaniem niektórych war-tości.

• GetCookies – pobranie zbioru plików Co-okie spod podanego adresu URL.

• SetCookie – utworzenie nowego cia-steczka.

Wywoływanie funkcji JavaScriptW ostatnim etapie testowania naszego przy-kładowego formularza odniesiemy się do procesu integracji strony ze skryptami Ja-vaScript. Za pomocą metody InvokeScript możemy wywołać dowolną funkcję JS, prze-kazując jej nazwę jako parametr. Załóżmy, iż formularz nie zostanie wysłany do serwera, dopóki użytkownik nie wprowadzi wartości w pola wymagane (w naszym przypadku logi-nu oraz hasła). Błąd zostanie zasygnalizowa-ny w formie etykiety zawierającej napis kolo-ru czerwonego Fill all required fields.

Listing 1. Ustawienie domyślnej przeglądarki na Mozilla Firefox

[SetUp]

public void MyTestInitialize()

{

if (Manager.Browsers.Count == 0)

{

Manager.LaunchNewBrowser(BrowserType.FireFox);

}

}

Listing 2. Metoda testująca dostępność elementów wymaganych na formularzu

[Test]

public void ControlVisibility()

{

// Nawigacja do strony podlegającej weryfikacji

Manager.ActiveBrowser.NavigateTo(

"http://localhost/WebAiiTest/Default.aspx");

// Element ogólny

Element loginLabel = Manager.ActiveBrowser.Find.ById("Login_Label");

Element passwordLabel = Manager.ActiveBrowser.Find.ById("Password_Label");

// Korzystając już z konkretnego typu Html Input

HtmlInputText loginTxt = Manager.ActiveBrowser.Find.ById<HtmlInputText>("Logi

n_TextBox");

HtmlInputPassword passwdTxt = Manager.ActiveBrowser.Find.ById<HtmlInputPassword>("

Passwd_TextBox");

HtmlInputSubmit button = Manager.ActiveBrowser.Find.ById<HtmlInputSubmit>("Button

");

Assert.IsNotNull(loginLabel);

Assert.IsNotNull(passwordLabel);

Assert.IsNotNull(loginTxt);

Assert.IsNotNull(passwdTxt);

Assert.IsNotNull(button);

}

Rysunek 1. Przykładowy formularz logowania

Rysunek 2. Widok po poprawnej autoryzacji

Rysunek 3. Walidacja z wykorzystaniem JavaScript

Page 60: Software Developers Journal PL 03/2009

03/200960

Testowanie oprogramowania

Proces walidacji przeprowadzimy w następu-jących krokach:

• Przed kliknięciem: etykieta validate po-siada styl display:none – nie jest widocz-na na stronie. Deklaracja: • <span id="validate" style=

"display:none">Fill all required

fields</span>

• Po kliknięciu przycisku Log In, etykieta validate zmieni kolor na czerwony oraz styl na display:inline. • Deklaracja: <span id="validate"

style="display:inline">Fill all

required fields</span>

Listing 4. prezentuje propozycję przeprowadze-nia testów integracji JavaScript z naszą aplikacją.

Test RegionsStrona www zazwyczaj składa się z wielu czę-ści np. nagłówka, stopki, wydzielonych bloków, paska nawigacyjnego itp. Framework WebAii umożliwia grupowanie elementów wchodzą-cych w skład danego segmentu strony i prze-prowadzenia procesu weryfikacji poprawności dla jej fragmentu. Korzyści płynące z tego za-biegu to m.in.:

• zmniejszenie kosztów i złożoności testów po-przez ich ukierunkowanie na dany obszar,

• oznaczanie fragmentów stałych zmian w kodzie podlegających szczególnej analizie,

• luźne połączenie testów z kodem produktu• w przypadku pracy z praktyką Test Dri-

ven Development – ostrzeganie programi-stów o potencjalnym złamaniu zasad auto-matyzacji testów.

WebAii oferuje pełną elastyczność w przy-padku tworzenia oznaczeń dla regionów. Można zapisać je za pomocą dowolnego ję-zyka znaczników (html, xml, xhtm) za-wierającym tag testregion oraz numer id (np. dla widoku ASP .NET: <testregion id=”regionid”> region content </

testregion>). W kodzie metody testującej odwołanie do wyznaczonego fragmentu uzy-skujemy za pomocą metody Region obiek-tu ActiveBrowser (np. TestRegion reg =

Manager.ActiveBrowser.Regions[„region

id”];)

PodsumowaniePrezentowane w artykule techniki testo-wania dynamicznych stron WWW są jedy-nie kroplą w morzu możliwości framewor-ka WebAii. Pozostałe rozszerzenia odno-szą się również do testowania m.in. aplika-cji Microsoft Silverlight, Ajax, ASP.NET lo-cal server, .NET Page DOM czy też popu-larnego w systemach WEB 2.0 wsparcia dla dynamicznych elementów typu Drag And Drop. Testowanie części FrontEndowej stro-ny jest dość problematyczne, natomiast za-równo rynek komercyjny, jak i opensource-'owy nadal pozostaje ubogi w kwestii dobo-ru narzędzi tworzenia testów automatycz-nych dla witryn internetowych. Dlatego, wg mnie, warto zapoznać się z framewor-kiem WebAii.

PAWEŁ WILKOSZ Pracuje na stanowisku Software Quality Engineer w firmie Making Waves Polska. Ma również doświad-czenie w tworzeniu aplikacji .NET oraz SQL Server. Jest aktywnym członkiem Polish SQL Server User Group w Krakowie. Prywatnie pasjonat muzyki al-ternatywnej z lat ’60 – ’90 oraz squasha. Kontakt z autorem: [email protected]

Bibliografia

• Stephen H. Kan, Metryki i modele w inży-nierii jakości oprogramowania, Wydaw-nictwo Naukowe PWN, 2006

• J. Newkirk, Test Driven Development In .NET, Microsoft Professional 2004

• A. Hunt, D. Thomas, Pragmatic Unit te-sting in C# with NUnit, O’Reilly 2007

• Dokumentacja techniczna framewor-ka WebAii dostępna pod adresem: http://www.artoftest.com/Resources/WebAii/Documentation/topicsindex.aspx

Listing 3. Testowanie procesu uwierzytelniania użytkownika

[Test]

public void ValidFormLogIn()

{

HtmlInputText loginTxt = Manager.ActiveBrowser.Find.ById<HtmlInputText>(

"Login_TextBox");

HtmlInputPassword passwdTxt = Manager.ActiveBrowser.Find.ById<HtmlInputPassword>(

"Password_TextBox");

loginTxt.Text = "admin";

passwdTxt.Text = "admin";

HtmlInputSubmit button = Manager.ActiveBrowser.Find.ById<HtmlInputSubmit>("But

ton");

button.Click();

string url = Manager.ActiveBrowser.Url;

HtmlSpan label =

Manager.ActiveBrowser.Find.ById<HtmlSpan>("Hello_Label_id");

string labelValue = label.InnerText;

Assert.AreEqual(url, “http://localhost/WebAiiTest/StartPage.aspx/”);

Assert.IsNotNull(label);

Assert.AreEqual(labelValue, "Hello admin");

}

Listing 4. Testowanie elementów zależnych od CSS i JavaScript

[Test]

public void RequiredFields()

{

Manager.ActiveBrowser.NavigateTo(

"http://localhost:1293/WebAiiAsp/Default.aspx");

HtmlSpan span = Manager.ActiveBrowser.Find.ById<HtmlSpan>("validate");

Assert.AreEqual("none", span.Styles[0]);

// Wywołanie metody JavaScript CheckForm()

Manager.ActiveBrowser.Actions.InvokeScript("CheckForm(this)");

Assert.AreEqual(Color.Red, span.GetComputedStyle("color").ToColor());

Assert.AreEqual("inline", span.Styles[0]);

}

Page 61: Software Developers Journal PL 03/2009

Soware Development GigaCon– budowanie aplikacji biznesowych

23 - 24 marca 2009Warszawa, Hotel Novotel Airport

Tematyka konferencji:

Blok zarządzanie projektami:- zarządzanie portfelem projektów- zarządzanie wymaganiami- zarządzanie zmianą- outsourcing projektów IT- nowoczesne metodyki projektowania systemów informatycznych- metodyki „lekkie” (agile, xp) w konstrukcji systemów informatycznych- problematyka analizy wymagań w projektach wdrożeniowych

Blok technologiczny:- cloud computing – NOWOŚĆ!- bazy danych- Java- zarządzanie treścią w internecie (narzędzia do tworzenia aplikacji web, oprogramowania portalowe)- RIA - rich internet application- środowiska programistyczne -- pakiety Case i Rad- rozwiązania oparte na technologiach XML i Web Services- platformy integracyjne- budowanie aplikacji mobilnych- budowanie aplikacji BPM- budowanie aplikacji SOA- narzędzia do testowania oprogramowania- narzędzia wspomagające prowadzenie projektów programistycznych

Blok jakości i testowania - jakość systemów informatycznych.- planowanie jakości- zapewnianie jakości- kontrola jakości- normy i standardy dotyczące jakości oprogramowania- jakość w różnych fazach procesu budowy oprogramowania: jakość w wymaganiach, analizie, projektowaniu itp.- konstrukcja i testowanie oprogramowania

Więcej informacji: http://sdevelopment.gigacon.org

Kontakt:Marta PaprowiczSpecjalista ds.organizacji konferencji i szkoleńmail: [email protected]: +48 22/ 427 36 75

WSTĘP BEZPŁATNY

Główny sponsor konferencji:

Page 62: Software Developers Journal PL 03/2009

03/200962

Technologie internetoweZintegruj się z Internet Explorer 8

www.sdjournal.org 63

Wraz z rosnącą popularnością Inter-netu rosną również oczekiwania użytkowników w stosunku do moż-

liwości oferowanych przez przeglądarki interne-towe. Internet Explorer 8 (w chwili pisania arty-kułu wchodzący w fazę RC1) będzie oferował 3 nowe typy rozszerzeń: zintegrowaną wyszu-kiwarkę (o bogatszych możliwościach niż w In-ternet Explorer 7), tzw. Akceleratory (przyspie-szające odnajdowanie informacji w sieci) oraz Web Slice’y (do monitorowania często zmienia-jących się treści stron). Wszystkie mechanizmy bazują na standardach XML oraz HTML – mo-żemy odetchnąć z ulgą, tym razem zintegrowa-nie strony z przeglądarką Microsoftu będzie na-prawdę prostym zadaniem. A kiedy już coś zro-bimy, warto się tym podzielić z innymi użytkow-nikami – każdy może zgłosić swoje rozszerzenie do publicznej galerii polskich dodatków do IE 8 (http://ieaddons.com/pl/).

Zintegrowana wyszukiwarkaZarówno przeglądarka Internet Explorer od wersji 7, jak i Firefox od wersji 2 w prawym gór-nym rogu udostępniają niewielkie pole tekstowe umożliwiające użytkownikom szybkie przesła-

nie zapytania do wybranej wyszukiwarki inter-netowej. W dolnej części okna rozwijającego się po wpisaniu słów kluczowych możemy wybrać silnik, który ma zostać w danym momencie wy-korzystany. Praktycznie każda strona z zaimple-mentowanymi mechanizmami wyszukiwania może zintegrować się w ten sposób z przeglą-darką. Na rynku dostępne są już wyszukiwarki integrujące się np. z Wikipedią, serwisem Ama-zon czy wyszukiwarkami Windows Live oraz Google. W Polsce warto zwrócić uwagę m.in. na rozwiązanie stworzone przez serwis GoldenLi-ne (patrz Rysunek 1.) z uwagi na fakt, iż wyko-rzystuje ono najnowsze mechanizmy zintegro-wanej wyszukiwarki – automatycznie pojawia-jące się sugestie ze zdjęciami i opisami.

Od strony technicznej każdy search provider reprezentowany jest przez niewielki plik XML będący zgodny z tzw. specyfikacją OpenSearch. Została ona zaprojektowana przez firmy Ama-zon.com oraz A9 i wprowadzona na rynek w roku 2005. Obecnie OpenSearch wykorzystu-ją zarówno Firefox 2+, jak i Internet Explorer 7+. Najprostszy provider zgodny z tą specyfika-cją prezentuje Listing 1.

Wystarczy w znaczniku ShortName okre-ślić nazwę wyszukiwarki, w znaczniku Image adres reprezentującej ją ikony oraz w elemen-cie Url szablon adresu, pod który przeglądarka ma wysyłać zapytania. Najistotniejszy w sekcji Url jest parametr {searchTerms} – reprezentu-je on słowo kluczowe wpisane przez użytkow-

nika do wyszukiwarki. Na przykładzie z Listin-gu 1., po wysłaniu słowa test do tak zdefiniowa-nej wyszukiwarki użytkownik trafi na stronę http://example.com/?query=test.

Nieco więcej pracy wymagać będzie od nas dodanie do wyszukiwarki funkcjonalności pod-powiedzi dla wprowadzanych słów kluczowych. Aby były one wspierane, musimy stworzyć stro-nę (np. http://suggestions.example.com/?q=slowo_kluczowe), która będzie wysyłała odpowiednio sformatowane odpowiedzi w formacie XML lub JSON (Javascript Object Notation). Będą one w rzeczywistości interpretowanymi przez przeglą-darkę podpowiedziami do przekazanego w para-metrze slowo_kluczowe zapytania. W zależno-ści od tego czy serwer zwraca odpowiedzi w for-macie JSON, czy XML, do sekcji OpenSearch-Description musimy dodać jedną z dwóch lini-jek prezentowanych na Listingu 2.

Przykład podpowiedzi w formacie JSON, ja-ką mógłby zwracać serwer po wpisaniu przez użytkownika zapytania XBOX, prezentuje Li-sting 3.

Jak widzieliśmy na Rysunku 1., podpowie-dzi mogą również zawierać obrazy oraz opisy. Listing 4. prezentuje przykładową odpowiedź serwera w formacie XML, która spowoduje wy-świetlenie tych elementów.

Opisy zamieszczamy w elementach Description, adresy obrazów w sekcjach Image. Podpowiedzi mogą być również od-dzielone od siebie separatorami definiowany-mi przez elementy Separator. Na podstawie otrzymanej od serwera odpowiedzi z Listin-gu 4., przeglądarka wyświetliłaby jeden sepa-rator o nazwie My Visual Suggestions na samej górze okna.

Po stworzeniu pliku XML definiującego wy-szukiwarkę nie pozostaje nam nic innego, jak dodanie mechanizmów umożliwiających zain-

Zintegruj się z Internet Explorer 8

Już niedługo premiera kolejnej wersji przeglądarki firmy Microsoft, która otworzy przed programistami zupełnie nowe możliwości tworzenia rozszerzeń. W niniejszym artykule przedstawione zostały podstawy programowania tzw. akceleratorów, web slice’ów oraz search provider’ów, które pozwalają zintegrować nasze strony z przeglądarką Internet Explorer 8.

Dowiesz się:• Jakie nowe możliwości rozszerzeń będą do-

stępne w Internet Explorer 8;• Jak zintegrować Twoją stronę z przeglądarką;• Jak stworzyć search provider, akcelerator i web

slice.

Powinieneś wiedzieć:• Znajomość podstawowych pojęć z zakresu

HTML, CSS, RSS, Javascript;• Podstawowe informacje na temat protokołu

HTTP.

Poziom trudności

Czyli jak stworzyć Akcelerator, Web Slice i Search Provider

Page 63: Software Developers Journal PL 03/2009

03/200962

Technologie internetoweZintegruj się z Internet Explorer 8

www.sdjournal.org 63

stalowanie jej przez użytkowników portalu. Ma-my tu do dyspozycji dwie możliwości. Pierwszą z nich jest zamieszczenie na stronie specjalnego linku, który odpowiednim wywołaniem funkcji JavaScript spowoduje zainstalowanie wyszuki-warki. Przykładem może być link:

<a href="#"

onclick="window.external.AddSearch

Provider('http:

//www.example.com/

provider.xml')">

Add Search Provider Example</a>

który zainstaluje wyszukiwarkę zdefiniowaną w pliku provider.xml. Drugim sposobem jest dodanie do strony specjalnych nagłówków np.:

<link title="My Provider" rel="search"

type="application/opensearchdescription

+xml"

href="http://www.example.com/

provider.xml">

które spowodują automatyczne wykrycie wy-szukiwarki. Po wejściu na stronę zawierającą takie znaczniki, Internet Explorer 8 wyświe-tli żółtą strzałkę obok pola wyszukiwarki. Umożliwi ona instalację search provider’a. To wszystko, co musieliśmy zrobić, aby użytkow-nicy mogli cieszyć się zintegrowanym z prze-glądarką mechanizmem wyszukiwania treści na naszym portalu.

Tworzenie akceleratorówCzy nie zdarzyło Ci się nigdy kopiowanie adresu pocztowego do portalu nawigacyjne-go? A ile razy znajdowałeś na stronie inte-resujący zwrot, który kopiowałeś do schow-ka, by wkleić go za chwilę w oknie wyszu-kiwarki internetowej? Akceleratory mają na celu przyspieszyć niektóre operacje, któ-

re robimy w Internecie – wyeliminować ko-nieczność nieustannego kopiowania i wkle-jania, ręcznego przenoszenia interesujących nas słów kluczowych ze strony do strony. Są one dodatkowymi opcjami pojawiającymi się w menu kontekstowym po zaznaczeniu tek-stu i kliknięciu go prawym przyciskiem my-szy (lub wybraniu specjalnej ikony akcelera-tora). Przykładowymi akceleratorami mo-gą być np.: wyślij zaznaczony tekst mailem, znajdź zaznaczony tekst, przetłumacz wybra-ny tekst, znajdź zaznaczone słowo kluczowe w portal.pl, itp. Interesującym przykładem mo-że być korzystający z serwisu Live Maps ak-celerator, prezentujący mapę zaznaczonego adresu pocztowego – bez konieczności ręcz-nego wklejania go na stronach portalu (Ry-sunek 2.).

Rysunek 1. Zintegrowana wyszukiwarka udostępniana przez serwis GoldenLine Rysunek 2. Przykładowy akcelerator – mapa z Live Maps

Listing 1. Najprostszy Search Provider<?xml version="1.0" encoding="UTF-8"?>;

<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">;

<ShortName>My Custom Search</ShortName>;

<Url type="text/html" template="http://example.com/?query={searchTerms}&amp;source=IE"/>;

<Image height="16" width="16" type="image/icon">http://example.com/mycustom.ico</Image>;

</OpenSearchDescription>

Listing 2. Definiowanie adresu zwracającego podpowiedzi

<Url type="application/x-suggestions+json"; template="http://suggestions.example.com/?query={searchTerms}"/>;

<Url type="application/x-suggestions+xml"; template="http://suggestions.example.com/?query={searchTerms}"/>

Listing 3. Przykładowa odpowiedź serwera w formacie JSON

["xbox",;

["Xbox 360", "Xbox cheats", "Xbox 360 games"]]

Page 64: Software Developers Journal PL 03/2009

03/200964

Technologie internetoweZintegruj się z Internet Explorer 8

www.sdjournal.org 65

Jak widać, akcelerator po podświetleniu myszką potrafi wyświetlić niewielkie okno podglądu – możemy w nim znaleźć np. wyni-ki wyszukiwania, tłumaczenie zaznaczonego zwrotu, definicję z wikipedii, itp.

Z technicznego punktu widzenia akcelerator jest po prostu plikiem XML (tzw. OpenService Description Format), podobnie jak search provi-der. Do zrobienia najprostszych akceleratorów (tzw. Codeless Accelerators) wystarczy dosłownie kilka linijek kodu (patrz Listing 5.). Najważniej-szymi elementami formatu OpenService są:

• homePageUrl – określa domenę, w ramach której ma działać akcelerator;

• display – definiuje wygląd akceleratora (nazwa, ikona);

• activity – określa funkcjonalności.

Dodatkowymi parametrami, które możemy zdefiniować są:

• Kategoria (category) – kategoria, w któ-rej akcelerator wyświetlać się będzie użytkownikowi. Można skorzystać z pre-

definiowanych: Add , Blog, Define, Map, Translate lub stworzyć własną;

• Typ treści, dla której działa (context) – może być to cała strona (jeśli wywołujemy akcelerator z menu Page), zaznaczenie (se-lection) lub hiperłącze;

• Szablon adresu strony, do której przekazy-wane są dane kontekstu (execute);

• Informacja o kodowaniu znaków.

Listing 5. prezentuje niektóre z tych parame-trów w praktyce. Jednym z bardziej istotnych elementów akceleratora jest sekcja execute. Określa ona szablon strony, do której zosta-niemy przekierowani po kliknięciu opcji re-prezentującej dany akcelerator. Może on za-wierać określone zmienne – np. na przykła-dzie z Listingu 5. wykorzystujemy parametr {selection}, który definiuje zaznaczony przez użytkownika tekst.

Tabela 1. prezentuje inne parametry, które możemy wykorzystać w naszych szablonach adresów.

Parametr możemy również oznaczyć ja-ko opcjonalny, poprzez dodanie znaku za-pytania po identyfikatorze zmiennej (np. {documentUrl?}). W odróżnieniu od zaprezen-towanego na Listingu 5. przekazywania para-metrów metodą GET, można je również prze-kazywać metodą POST. Listing 6. prezentuje przykład tego drugiego podejścia.

Omawiane dotychczas akceleratory nie ofe-rowały jednak bardzo wygodnej funkcjonalno-ści, jaką jest podgląd wyników (wyświetlany po podświetleniu akceleratora). W praktyce jest to najzwyklejsza strona HTML, osadzona w nie-wielkim okienku podglądu. Musimy zatem ją stworzyć. Listing 7. prezentuje kod akcelerato-ra zaprojektowanego przez serwis Ebay. Dzięki elementowi preview w sekcji activity, po pod-świetleniu akceleratora myszką wyświetli on podgląd (kod HTML zwracany ze strony http://ie8.ebay.com/activities/preview/index.php). Pod-gląd może zawierać kod Javascript (ograniczo-ny do domeny akceleratora) oraz kontrolki Ac-tiveX – o ile zostały przez użytkownika zaak-ceptowane dla danej domeny. Okno podglą-du ma stały rozmiar 320 x 240, wszystko po-za nim jest ucinane. Nie zaleca się stosowania w nich pasków przewijania.

Kiedy nasz akcelerator jest już goto-wy, wystarczy dodać do strony mecha-nizm umożliwiający użytkownikom za-instalowanie go. Podobnie jak w przypad-ku search provider’ów dokonujemy tego z poziomu kodu Javascript, np.: <button onclick=”window.external.AddService(‘htt

p://maps.live.com/GetMap.xml’)”>Dodaj

akcelerator</button>. Dodajmy, że moż-liwe jest również programowe sprawdzenie, czy dany akcelerator nie został wcześniej za-instalowany – kod analogiczny do: window.external.isServiceInstalled(http://

maps.live.com/GetMap.xml, „map”);.

Listing 4. Przykładowa odpowiedź serwera w formacie XML

<?xml version=”1.0”?>;

<SearchSuggestion>;

<Query>xbox</Query>;

<Section>;

<Separator title="My Visual Suggestions" />;

<Item>;

<Text>Xbox 360 Game Consoles</Text>;

<Description>Game console systems and packages at a great deal.</Description>;

<Image source="http://www.example.com/xboxconsole.jpg" alt="Xbox 360 Consoles"

width="75"; height="75"/>;

<Url>http://www.example.com/</Url>;

</Item>;

<Item>;

<Text>Xbox 360 Wireless Controller</Text>;

<Image source="http://www.example.com/xboxcontroller.jpg" alt="Xbox 360 Wireless

Controller" width="75" height="75"/>;

</Item>;

<Item>;

<Text>Xbox 360 Live Games</Text>;

<Image source="http://www.example.com/live.jpg" alt="Xbox 360 Live Games"

width="75"; height="75"/>;

<Url>http://www.example.com/games.aspx?q="Xbox 360"</Url>;

</Item>;

</Section>;

</SearchSuggestion>

Listing 5. Przykładowa implementacja prostego akceleratora

<?xml version="1.0" encoding="UTF-8"?>;

<openServiceDescription;

xmlns="http://www.microsoft.com/schemas/openservicedescription/1.0">;

<homepageUrl>http://www.portal.pl</homepageUrl>;

<display>;

<name>Wyszukaj w Portal.pl</name>;

<icon>http://www.portal.pl/ikonka-act.ico</icon>;

</display>;

<activity category="find">;

<activityAction context="selection">;

<execute action="http://www.portal.pl/search.aspx?string={selection}"

method="get"/>;

</activityAction>;

</activity>;

</openServiceDescription>

Listing 6. Przekazywanie parametrów metodą POST przez akcelerator

<execute method=”post” action=”http://www.portal.pl/search.aspx“>;

<parameter name=”selection” value=”{documentUrl}” />;

<parameter name=”title” value=”{documentTitle}” />;

</execute>

Page 65: Software Developers Journal PL 03/2009

03/200964

Technologie internetoweZintegruj się z Internet Explorer 8

www.sdjournal.org 65

Na koniec warto wspomnieć, iż akcelerato-ry mogą również integrować się z aplikacjami działającymi na komputerze poprzez COM (tzw. Code-based Accelerators), ale nie są one przedmiotem tego artykułu.

Web Slice’yWeb Slice’y są budzącą wśród użytkowników wiele entuzjazmu nową koncepcją, która po-zwala zasubskrybować kawałek strony inter-netowej i monitorować jej zawartość. Można je porównać do wizualnych, HTML-owych in-formacji RSS, do których dostęp mamy zawsze w przeglądarce, pod paskiem adresu. Przykła-dy zastosowań znajdziemy wszędzie tam, gdzie często szukamy aktualizacji – nowe wiadomo-ści e-mail w internetowej skrzynce odbiorczej, najnowsze informacje ze świata, aktualne kur-sy walut, zmiany statusów znajomych na por-talu społecznościowym, itp. Rysunek 3. pre-zentuje Web Slice do monitorowania skrzynki odbiorczej dostępny dla użytkowników porta-lu GoldenLine.

Aby sprawdzić czy mamy nowe wiadomo-ści, nie musimy za każdym razem wchodzić na stronę – wystarczy rozwinąć Web Slice. Ten nowy mechanizm wspiera wszystkie popularne typy zabezpieczeń (w tym SSL, Cookies, Basic Authentication). Użytkownicy po zalogowaniu do portalu i zaznaczeniu opcji zapamiętaj (zo-stawiającej ciasteczko z ticketem uwierzytel-niającym) będą mogli monitorować stan swo-jej skrzynki z poziomu Web Slice’u – korzysta-ją one z tych samych, zapisanych już na dysku, ciasteczek.

Ogromną zaletą Web Slice’ów jest informo-wanie o wszelkich zmianach w monitorowanej części portalu. Kiedy tylko zmieni się część za-subskrybowanej przez nas zawartości, przeglą-darka poinformuje nas o tym wizualnie. Nie bez znaczenia są tu skojarzenia z RSS. Wszyst-kie aktualizacje Web Slice’ów kontroluje Win-dows RSS Platform. Ponadto zasubskrybowa-nie Web Slice’u skutkuje również dodaniem go do wszystkich czytników RSS wykorzystu-jących tę platformę. Przyjrzyjmy się, jakim mo-dyfikacjom należy poddać portal, aby pozwalał

użytkownikom na monitorowanie jego zawar-tości poprzez Web Slice.

Aby Web Slice był wykrywany na stronie, musimy jej fragment oznakować specjalnymi znacznikami:

• Klasa hslice. Przypisanie klasy hslice nie wyklucza wykorzystania również innych klas CSS;

• Atrybut id – dla tego samego elemetu, do którego przypisana jest klasa hslice. Musi być unikalny w obrębie całej strony;

• Klasa entry-title – określa tytuł Web Slice’u. Jeśli zostanie przypisana do kilku elementów (np. div oraz span), tytuł po-wstanie ze złączenia ich. Element można ukryć stosując np. style=”visibility: hidden;”.

Tabela 1. Parametry wykorzystywane w akceleratorach

Parametr Kontekst Opis

{documentUrl} Dowolny Adres dokumentu

{documentTitle} Dowolny Tytuł dokumentu

{documentDomain} Dowolny Domena dokumentu

{documentHost} Dowolny W pełni kwalifikowana nazwa hosta

{selection} selection Aktualnie zaznaczony tekst

{link} link href zaznaczonego linku

{linkText} link Inner Text zaznaczonego linku

{linkRel} link Rel zaznaczonego linku

{linkType} link Typ zaznaczonego linku (jeśli dostępny)

{linkDomain} link Domena wybranego linku

{linkHost} link W pełni kwalifikowana nazwa hosta linku

Listing 7. Akcelerator oferujący podgląd aukcji Ebay

<?xml version="1.0" encoding="UTF-8" ?>;

<openServiceDescription xmlns="http://www.microsoft.com/schemas/

openservicedescription/1.0">

<homepageUrl>http://ie8.ebay.com</homepageUrl>;

<display>;

<name>Find with eBay Search</name>;

<icon>http://ie8.ebay.com/resources/images/favicon.ico</icon>;

</display>;

<activity category="Find"> <activityAction context="selection">;

<preview action="http://ie8.ebay.com/activities/preview/index.php?query={select

ion}" />;

<execute method="get" action="http://ie8.ebay.com/index.php?query={selection}"

/>;

</activityAction>;

</activity>;

</openServiceDescription>

Listing 8. Najprostszy Web Slice

<div class="hslice" id="1">;

<div class="entry-title">Slice Title</div>;

<div class="entry-content">Content</div>;

</div>

Listing 9. Strona Basic.htm (dodawanie Web Slice’u)

<div class="hslice" id="auction">;

<span class="entry-title">Web Slice Test</span>;

<a rel="feedurl" href="update.htm#slice-test" style="display:none;"></a>;

</div>

Listing 10. Strona Update.htm (aktualizowanie Web Slice’u)

<div class="hslice" id="slice-test">;

<h2 class="entry-title">Web Slice Test</h2>;

<div class="entry-content">Web Slice content</div> ;

</div>

Page 66: Software Developers Journal PL 03/2009

03/200966

Technologie internetowe

Wszystkie powyższe znaczniki możemy przypisać do dowolnych elementów HTML (np. div, span, tabela). Listing 8. prezen-tuje fragment strony, który zostanie rozpo-znany jako Web Slice. Przeglądarka umożli-wi zasubskrybowanie go poprzez specjalną opcję w menu (patrz Rysunek 4.) lub ikonę pojawiającą się po najechaniu myszką na tak oznaczony element div. Web Slice będzie au-tomatycznie aktualizowany przez Windows RSS Platform. Kiedy tylko zmieni się jego zawartość, użytkownik zostanie o tym po-wiadomiony.

Opcjonalnymi elementami istotnymi dla tworzenia Web Slice’ów są:

• Klasa entry-content – oznacza zawartość Web Slice’u. Może być łączona z kilkoma innymi tak oznaczonymi elementami (jak

w przypadku klasy entry-title). Wielkość Web Slice’u określa rozmiar tego elemen-tu;

• rel=”feedurl” – adres strony, z której ak-tualizowana będzie zawartość Web Sli-ce’u. Może to być feed RSS lub inna stro-na zawierająca znaczniki hslice (w takim wypadku na końcu adresu powinniśmy dodać znak hash oraz identyfikator Web Slice’u – np. http://test.com/slice-

update.htm#Slice1);• Klasa ttl – pozwala określić, jak często (w

minutach) Internet Explorer 8 ma odświe-żać zawartość Web Slice’u. Może on być przypisany do dowolnego elementu strony (np. <span class=”ttl”>5</span> ;

• Klasa endtime – data ważności Web Slice-’u. Po jej upływie Web Slice będzie uzna-wany za nieaktywny. Przestanie być aktu-

alizowany i zostanie specjalnie oznaczony przez przeglądarkę.

Bardzo często dochodzi do sytuacji, w której chcielibyśmy po dodaniu Web Slice’u aktuali-zować go z innych źródeł niż strona, na któ-rej został wykryty. Jest to korzystne, jeśli za-leży nam np. na odciążeniu strony głównej portalu od zapytań wysyłanych automatycz-nie przez przeglądarkę. Aby to zrobić, określa-my tzw. Alternative Update Source, wykorzy-stując konstrukcję rel=”feedurl” (Listing 9.). Listing 10. prezentuje stronę, która będzie wy-korzystywana do pobierania aktualizacji.

Do projektowania zawartości Web Slice-’ów można wykorzystywać style CSS (zarów-no zagnieżdżone w kodzie, jak i zawarte w zewnętrznych plikach). Istnieje także moż-liwość korzystania z kodu JavaScript, Flash czy Silverlight – takie Web Slice’y muszą być jednak odpowiednio zaprojektowane (z wy-korzystaniem tzw. Alternative Display So-urce). Strona zawierająca interaktywne ele-menty powinna zostać wydzielona ze stron odpowiedzialnych za aktualizowanie zawar-tości Web Slice’u i wskazana konstrukcją <a rel="entry-content" href="Display.htm"

style="display:none;"></a>, zamiast trady-cyjnego elementu entry-content.

Na koniec warto dodać, że Web Slice-’y mogą być również dodawane z poziomu kodu JavaScript. Konstrukcja analogiczna do: <button onclick="javascript:windo

w.external.addToFavoritesBar('http:/

/auction.microsoft.com/item#1', 'Item

- $66.00', 'slice')">Add WebSlice</

button> spowoduje zasubskrybowanie ele-mentu.

PodsumowaniePrzeglądarka Internet Explorer nigdy dotąd nie umożliwiała tak prostego pisania rozsze-rzeń integrujących ją ze stronami internetowy-mi. O ich przydatności może świadczyć fakt, iż przenikają stopniowo także do innych przeglą-darek. Najnowszy Firefox wspiera już nie tylko standard OpenSearch, ale również Web Slice’y (na razie w postaci add-inu). Nie pozostaje nic innego, jak tylko stworzyć własne rozszerze-nie – a kiedy już to zrobimy, zgłośmy je do pol-skiej galerii dodatków Internet Explorer 8 (http://www.ieaddons.com/pl/), aby inni użytkownicy mogli je zobaczyć!

Rysunek 3. Web Slice prezentujący aktualny stan skrzynki odbiorczej GoldenLine

BARTŁOMIEJ ZASSBartłomiej Zass pracuje w dziale Developer & Plat-form Group polskiego oddziału Microsoft. Zajmu-je się współpracą z producentami oprogramowa-nia w zakresie najnowszych technologii dla progra-mistów. Szczególnie interesuje się technologiami internetowymi, programowaniem urządzeń mo-bilnych oraz zagadnieniami konstrukcji interfejsu użytkownika.Kontakt z autorem: [email protected]

Rysunek 4. Dodawanie wykrytego Web Slice’u

W Sieci

• Polska galeria dodatków do Internet Explorer 8 http://ieaddons.com/pl/;• Specyfikacje OpenSearch http://www.opensearch.org;• Szczegóły specyfikacji OpenService Accelerators http://msdn.microsoft.com/en-us/library/

cc287851(VS.85).aspx;• Dokumentacja Web Slice’ów http://msdn.microsoft.com/en-us/library/cc196992(VS.85).aspx#_

preview

Page 67: Software Developers Journal PL 03/2009
Page 68: Software Developers Journal PL 03/2009

03/200968

NarzędziaWeryfikacja przez model z narzędziem SPIN

www.sdjournal.org 69

Wytwarzanie programów współ-bieżnych jest zadaniem wyjątko-wo trudnym. Co więcej, zauwa-

żenie możliwych błędów w projekcie lub implementacji jest niejednokrotnie czynno-ścią bardzo pracochłonną i wymagającą wie-le uwagi. Formalna weryfikacja przez mo-del jest techniką, która umożliwia zbada-nie wszystkich wykonań systemu współbież-nego. W przypadku wykrycia sekwencji in-strukcji, które prowadzą do niepoprawne-go stanu, pozwala na wygenerowanie kontr-przykładu świadczącego o takiej sytuacji. Dodatkowo możliwe jest badanie systemów, których wykonanie nigdy się nie kończy. Ję-zyk PROMELA pozwala na specyfikację sys-temów, w których dochodzi do komunikacji kilku wątków wykonania programu współ-bieżnego. Komunikację możemy przedsta-wiać przy pomocy wymiany wiadomości oraz zmiennych dzielonych, a przez to badać wła-sności takich programów. Informację tą uzy-skuje się przy pomocy narzędzia SPIN inter-

pretującego język PROMELA. Jego w pełni automatyczne działanie oraz zwiększające się zastosowania tej metody weryfikacji sprawia-ją, iż warto przyjrzeć im się bliżej.

Wzajemne wykluczenieWykonanie nawet najprostszego programu współbieżnego może prowadzić do powsta-nia nietrywialnych, trudnych do wykrycia błędów. W tym celu przedstawiamy pro-sty problem pokazujący, w jaki sposób mo-że dojść do błędnego zachowania. Przez ów przykład wprowadzamy Czytelnika w pod-stawy języka PROMELA służącego do opi-su modelu systemów współbieżnych oraz własności poprawności, jakie mają być speł-nione.

Model ten jest następnie poddawany weryfi-kacji przy użyciu narzędzia SPIN, które może pokazać, w jaki sposób dana własność popraw-ności zostaje złamana. W poniższym przykła-dzie przedstawiono dwa procesy dokonujące współbieżnej modyfikacji zmiennej dzielonej. Ich równoczesne działanie prowadzi do niepo-prawnego stanu systemu.

Na Listingu 1. prezentujemy przykład sys-temu, w którym dostęp do zmiennej dzielo-nej total jest realizowany przez dwa procesy credit oraz debit. Ich inicjalizacji dokonuje-

my w specjalnym procesie init, wykonywa-nym zawsze na początku działania systemu. Wspomniane procesy dokonują odpowied-nio zwiększenia oraz zmniejszenia warto-ści zmiennej określającej wysokość środków na pewnym koncie bankowym. Czynności te realizowane są z użyciem zmiennej tym-czasowej temp. Powoduje to, że w przypadku przeplotu instrukcji może dojść do sytuacji, gdzie po zakończeniu wspomnianych proce-sów stan konta nie będzie odpowiadał wy-sokości zdeponowanych oraz wypłaconych środków. Zapewnienie o ich poprawnej wy-sokości realizujemy przez instrukcję assert. Ze względu na współbieżne działanie proce-su init wraz z procesami credit oraz debit, koniecznie jest poczekanie na ich zakończe-nie. Stąd w specyfikacji systemu wprowa-dzamy dodatkową zmienną pc. Po przyjęciu przez nią wartości 0, proces init wykona in-strukcję assert.

Na podstawie utworzonego modelu wery-fikator SPIN generuje program, który podda-je analizie wszystkie możliwe wykonania sys-temu. Aby uzyskać taki weryfikator, wywołu-jemy program SPIN z odpowiednimi opcjami oraz kompilujemy otrzymany kod. W następ-nym kroku uruchamiamy weryfikator i po za-uważeniu komunikatu o złamaniu assercji, do-konujemy analizy kontrprzykładu. Komendy, które służą do wykonania tych czynności, znaj-dują się poniżej.

spin -a bankaccount.pml

gcc -w -DSAFETY -o pan pan.c

./pan

spin -t -p bankaccount.pml

Na Listingu 2. możemy prześledzić typowy wynik działania weryfikatora. Najważniej-

Weryfikacja przez model z narzędziem SPINWspółczesne programy wykorzystują więcej niż jeden wątek przetwarzania w celu zmniejszenia opóźnień bądź zwiększenia szybkości działania. Niestety, zapewnienie o ich bezbłędnym oraz efektywnym wykonaniu jest zadaniem wyjątkowo kłopotliwym. Formalna weryfikacja przez model jest jedną z metod mających na celu wykazanie poprawności oraz niezawodności takich systemów.

Dowiesz się:• Czym jest weryfikacja przez model;• W jaki sposób modelować systemy w języku

PROMELA;• Jak specyfikować własności poprawności;• Jak przeprowadzić weryfikację oraz interpre-

tować otrzymane wyniki;• Jakie są zalety oraz wady przedstawionej metody.

Powinieneś wiedzieć:• Co to jest wątek;• Jakie problemy występują podczas przetwa-

rzania współbieżnego.

Poziom trudności

Wprowadzenie do języka PROMELA oraz narzędzia SPIN

Page 69: Software Developers Journal PL 03/2009

03/200968

NarzędziaWeryfikacja przez model z narzędziem SPIN

www.sdjournal.org 69

szą informacją jest ta o złamaniu własności poprawności, którą specyfikowaliśmy przy pomocy instrukcji assert. Pozostałe linie informują nas o wersji programu, zastoso-wanych optymalizacjach, rodzajach spraw-dzanych własności poprawności oraz o wiel-kości przestrzeni stanów, jaka została rozpa-trzona.

Przyjrzyjmy się teraz Listingowi 3., przedsta-wiającemu wygenerowany kontrprzykład. In-formuje nas o sekwencji instrukcji, które do-prowadziły do błędu. Jego uważne prześledze-nie wskazuje, iż problem ten pojawia się w przy-padku dokonania jednoczesnych obliczeń przy pomocy zmiennej tymczasowej temp przez oba procesy (linie 3-4 oraz 5-6). Przypisanie wyni-ku obliczeń (linie 7 i 10) do zmiennej dzielo-nej powoduje, iż tak obliczona wartość jest nie-poprawna.

Aby uniknąć tego błędu, należy wykonać obliczenia niepodzielnie przez obydwa pro-cesy. Język PROMELA dostarcza takie roz-wiązanie. Na Listingu 1. została zakomento-wana instrukcja atomic. Lista instrukcji we-wnątrz bloku opatrzonego tym słowem klu-czowym zostanie wykonana niepodzielnie, bez przeplotu z innymi procesami. W ten sposób unikniemy przedstawionego proble-mu. Po usunięciu komentarzy i powtórnym wykonaniu komend, nie zostanie wygenero-wana informacja o błędzie. Oznacza to, iż dla wszystkich możliwych wykonań procesów assercja będzie spełniona.

Przedstawiony przykład prezentuje kilka elementów potrzebnych do weryfikacji sys-temów. Po pierwsze, sam model systemu podlegającego weryfikacji. Jest on uprosz-czeniem i abstrakcją prawdziwego systemu – pominięto w nim wszystkie zbędne ele-menty. Składa się on jednak z najważniej-szych procesów oraz akcji w weryfikowa-nym systemie.

Następnym składnikiem jest specyfikacja własności poprawności, jakie mają zacho-dzić. W tym przypadku własność taka zosta-ła określona przez słowo kluczowe assert. Kolejnymi czynnościami jest weryfikacja systemu oraz analiza otrzymanych rezulta-tów, zaś w przypadku wykrycia błędu – je-go usunięcie oraz powtórne sprawdzenie po-prawności.

Weryfikacja przez modelWykorzystanie możliwości współczesnych procesorów w programach komputerowych odbywa się poprzez wprowadzenie kilku wątków wykonania. Dzięki ich współbieżne-mu działaniu możliwe jest osiągnięcie trzech podstawowych celów. Pierwszym z nich jest zredukowanie opóźnień podczas przetwarza-nia, dzięki zwiększeniu szybkości wykonania pewnych obliczeń. Drugim celem jest ukry-cie samego faktu wykonywania długotrwa-łych obliczeń poprzez pozwolenie na konty-nuację pracy całego systemu. Wreszcie ostat-nim jest podwyższenie przepustowości syste-mu przez zwiększenie ilości obliczeń, które mogą być wykonanie w jednostce czasu. Nie-stety pozytywne efekty, jakie przynosi wpro-wadzenie kilku wątków przetwarzania, oku-pione są większym stopniem skomplikowa-nia takich programów. W ogólności poja-wiają się problemy związane z dostępem do wspólnych zasobów. Musi następować od-powiednie ograniczenie kolejności wykona-nia wątków podczas ich odczytu oraz zapi-su. Kolejnymi jest nadwyrężenie zasobów w trakcie pracy kilku wątków. Wynika stąd ko-nieczność przypisania odpowiednich priory-tetów wątkom oraz zapewnienie ich uszere-gowania w dostępie do procesora. Wreszcie okazuje się, iż sekwencyjne algorytmy, które dobrze działają z jednym wątkiem wykona-nia, są bardzo trudne do stworzenia dla kil-ku wątków. Często nie uzyskuje się oczekiwa-nych rezultatów związanych z przyspiesze-niem działania.

Weryfikacja przez model jest w pełni auto-matyczną metodą, pozwalającą na stwierdze-nie poprawności wykonania systemów współ-bieżnych. Wykorzystuje się ją do weryfika-cji urządzeń elektronicznych, protokołów, a ostatnio nawet programów komputerowych. Jej głównym zadaniem jest udzielenie odpo-wiedzi na temat bezpieczeństwa oraz żywot-ności takich systemów. Są to dwie duże kla-sy własności poprawności, których spełnie-nie świadczy o poprawnym działaniu. W ra-mach własności bezpieczeństwa weryfiku-je się zachodzenie niezmienników, brak za-kleszczeń oraz występowanie sekwencji in-strukcji prowadzących do niepoprawnego za-chowania. Żywotność z kolei oznacza spraw-

dzanie zakończenia wykonywania procesów, możliwość odpowiedzi na nadchodzącą wia-domość oraz brak nieskończonych pętli in-strukcji, które prowadzą do niepoprawnego zachowania. Specyfikacji tych własności doko-nuje się przy pomocy instrukcji assert, odpo-wiednich etykiet oraz formuł logicznych. Na-rzędzia do weryfikacji przez model analizują wszystkie możliwe wykonania systemu współ-bieżnego. W przypadku zauważenia sekwen-cji zdarzeń, które prowadzą do złamania wła-sności poprawności, generowany jest kontr-przykład. Umożliwia on prześledzenie, w ja-ki sposób dochodzi do jej złamania.

W kolejnym przykładzie prezentujemy moż-liwości specyfikacji oraz badania klasyczne-go problemu czytelników i pisarzy. Posłuży nam on do dokładniejszego zapoznania się z elementami języka PROMELA oraz sposobu sprawdzania poprawności rozwiązania. Przed-stawiona jest również weryfikacja własności bezpieczeństwa oraz żywotności.

Czytelnicy i pisarzeW problemie czytelników i pisarzy dwie grupy procesów (wątków) posiadają dostęp do wspól-

Listing 1. Przeplot instrukcji prowadzący do błędu

int total = 1500; /* stan rachunku */

byte pc = 2; /* bariera */

proctype credit(int amount) {

int temp;

//atomic {

temp = total;

temp = temp + amount;

total = temp;

//}

pc = pc – 1

}

proctype debit(int amount) {

int temp;

// atomic {

temp = total;

temp = temp - amount;

total = temp;

// }

pc = pc – 1

}

init {

run credit(1000);

run debit (1000);

/* czekamy na zakonczenie procesow

*/

do

:: pc > 0 -> skip;

:: pc == 0 -> break;

od;

assert (total == 1500);

printf ("bank account total %d\n",

total);

}

SemaforSemafor jest nieujemną zmienną naturalną, dla której określono dwie operacje: P oraz V. Dla da-nego semafora s, operacja P(s) jest blokowana aż s > 0, a następnie zostaje wykonane s = s – 1. Sprawdzenie wartości zmiennej s oraz jej zmniejszenie jest wykonywane niepodzielnie. Z kolei V(s) wykonuje s = s + 1 jako niepodzielną instrukcję.Pojęcie semafora zostało przedstawione przez Holendra Edsgera Dijkstrę. Stąd też wzięły się na-zwy operacji P i V. P jest pierwszą literą słowa passeren, które oznacza mijać, przechodzić. V po-chodzi od słowa vrygeven oznaczającego zwolnienie lub uwolnienie. W toku dalszych badań uświadomiono sobie, iż lepszym określeniem dla P będzie prolagen, powstałe z połączenia słów roberen (próbować) oraz verlagen (zmniejszać). Uznano również, że bardziej odpowiednim sło-wem dla V, jest verhogen oznaczające zwiększanie. W literaturze angielskojęzycznej operacja P oznaczana jest przez słowo wait, a operacja V – przez signal.

Page 70: Software Developers Journal PL 03/2009

03/200970

NarzędziaWeryfikacja przez model z narzędziem SPIN

www.sdjournal.org 71

nego zasobu. Zasobem tym może być baza da-nych, plik, zmienna lub też czytelnia w biblio-tece. Czytelnicy oraz pisarze wykonują różne czynności względem zasobu. W ogólności w tym samym czasie dostęp do niego może posia-dać wielu czytelników. W przypadku zaś pisa-rzy, dostęp do zasobu może mieć tylko jeden z nich. Problem ten można rozszerzać o kolejne założenia dotyczące działania tych procesów, na przykład wykluczenia czytelników, gdy pi-sarz zechce modyfikować zasób.

Na Listingu 4. znajduje się kompleksowe roz-wiązanie omawianego problemu z użyciem se-

maforów. Oprócz realizacji odpowiedniego do-stępu czytelników i pisarzy, zapewnia ono wy-kluczenie czytelników, gdy pisarz próbuje uzy-skać dostęp do czytelni. W następnych paragra-fach postaramy się w kolejnych krokach przed-stawić zastosowane podejście jak i sam język specyfikacji.

Specyfikacja w języku PROMELA składa się z kilku elementów: deklaracji stałych, zmien-nych dzielonych, kanałów komunikacyjnych oraz procesów. Dodatkowo określane są za-strzeżenia stanowiące o poprawności takiego modelu.

W rozpatrywanym przykładzie zostały zdefiniowane dwie stałe wait oraz signal. Posłużą one do realizacji semafora binarne-go poprzez kanały komunikacyjne mutex, roomEmpty oraz turnstile. Kanały te, za-deklarowane w kolejnych liniach, mają ze-rową pojemność. Oznacza to, iż może po-przez nie dochodzić do synchronizacji pro-cesu wysyłającego oraz odbierającego wiado-mość. Proces wysyłający jest wstrzymywany do czasu odbioru wiadomości i na odwrót - proces odbierający wiadomość jest zatrzy-mywany do czasu nadania komunikatu. W ten sposób określa się spotkanie procesów (rendez-vous).

W prezentowanym przykładzie proces semaphor będzie kolejno oczekiwał na wia-domości zawierające stałą wait lub signal. W ten sposób procesy wysyłające wiado-mości wait i signal będą miały wyłącz-ny dostęp do fragmentów kodu. Po wysła-niu komunikatu wait, inne procesy zosta-ną wstrzymane do czasu nadania wiadomo-ści signal. W ten sposób specyfikuje się se-mafor binarny. Posłuży on nam w kolejnych liniach modelu.

Procesy deklarowane są przy pomocy sło-wa kluczowego proctype. Uruchomienie in-stancji procesu następuje przy pomocy sło-wa kluczowego run. W obrębie danego pro-cesu mogą zostać zadeklarowane zmienne lo-kalne lub kanały komunikacyjne. W naszym przykładzie interesujące są procesy reader oraz writer. Poprzez odpowiednie użycie se-maforów następuje ograniczenie dostępu do sekcji krytycznych. Jak zostało powiedziane wcześniej, w sekcji krytycznej może znajdo-wać się tylko jeden pisarz bądź dowolna licz-ba czytelników. Sekcje te zostały oznaczone przez etykietę cs. Posłuży ona do sformuło-wania własności poprawności dotyczącej te-go obostrzenia.

Ograniczenie dotyczące wykonania całe-go systemu jest zdefiniowane przez słowo kluczowe never. W przypadku jego speł-nienia, zostanie wygenerowane odpowied-nie ostrzeżenie oraz przedstawiony kontr-przykład. Jego spełnienie następuje w chwi-li, gdy zostanie osiągnięty nawias zamy-kający deklarację. W danym modelu mo-że się znajdować tylko jedna jego deklara-cja, stąd na listingu 4. pierwsze z nich zo-stało zakomentowane. Obostrzenie to jest warunkiem bezpieczeństwa i dotyczy wza-jemnego wykluczenia czytelników oraz pi-sarzy. Jego zajście byłoby widoczne po pra-wie całkowitym usunięciu linii specyfikacji odnoszących się do semaforów w procesach reader lub writer. Dodatkowego wytłu-maczenia wymaga linia reader[3]@cs &&

writer[5]@cs -> break;. Oznacza ona, iż jeśli instancje procesów reader o numerze 3 oraz writer o numerze 5 znajdą się w sek-cji krytycznej, ma zostać przerwana pętla, a

Listing 2. Działanie weryfikatora

pan: assertion violated (total==1500) (at depth 13)

pan: wrote bankaccount.pml.trail

(Spin Version 4.3.0 -- 22 June 2007)

Warning: Search not completed

+ Partial Order Reduction

Full statespace search for:

never claim - (none specified)

assertion violations +

cycle checks - (disabled by -DSAFETY)

invalid end states +

State-vector 40 byte, depth reached 16, errors: 1

48 states, stored

27 states, matched

75 transitions (= stored+matched)

0 atomic steps

hash conflicts: 0 (resolved)

2.622 memory usage (Mbyte)

Listing 3. Kontrprzykład

Starting :init: with pid 0

Starting credit with pid 1

1: proc 0 (:init:) line 29 state 1) [(run credit(1000))]

Starting debit with pid 2

2: proc 0 (:init:) line 30 (state 2) [(run debit(1000))]

3: proc 2 (debit) line 20 (state 1) [temp = total]

4: proc 2 (debit) line 21 (state 2) [temp = (temp-amount)]

5: proc 1 (credit) line 9 (state 1) [temp = total]

6: proc 1 (credit) line 10 (state 2) [temp = (temp+amount)]

7: proc 2 (debit) line 22 (state 3) [total = temp]

8: proc 2 (debit) line 24 (state 4) [pc = (pc-1)]

9: proc 2 terminates

10: proc 1 (credit) line 11 (state 3) [total = temp]

11: proc 1 (credit) line 13 (state 4) [pc = (pc-1)]

12: proc 1 terminates

13: proc 0 (:init:) line 35 (state 5) [((pc==0))]

spin: line 38 "bankaccount.pml", Error: assertion violated

spin: text of failed assertion: assert((total==1500))

14: proc 0 (:init:) line 38 (state 10) [assert((total==1500))]

spin: trail ends after 14 steps

#processes: 1

total = 2500

pc = 0

14: proc 0 (:init:) line 40 "bankaccount.pml" (state 11)

3 processes created

Page 71: Software Developers Journal PL 03/2009

03/200970

NarzędziaWeryfikacja przez model z narzędziem SPIN

www.sdjournal.org 71

co za tym idzie – wygenerowane ostrzeże-nie o błędzie.

Powróćmy na chwilę do problemu czytel-ników i pisarzy. W szczególnym przypadku może dojść do sytuacji, gdy czytelnicy do-konają aktu sabotażu na pisarzach. Zaraz po wyjściu z czytelni (sekcji krytycznej) będą do niej powracać. W ten sposób żaden z pi-sarzy nie uzyska dostępu do czytelni. W kon-sekwencji dojdzie do ich zagłodzenia. Aby za-pobiec takiemu zdarzeniu, należy odpowied-nio sformułować własność poprawności oraz ją zbadać.

Drugi z warunków poprawności zawiera kod, który służy temu zadaniu. Może on zo-stać sklasyfikowany jako warunek żywotno-ści, gdyż dotyczy poszukiwania nieskończo-nych pętli akcji, prowadzących do niepopraw-nego zachowania.

Warunek poprawności został wygenerowa-ny przy pomocy formuły logiki temporalnej.

Formuła [](en -> <>cs) mówi nam, iż za-wsze [] jeśli -> proces znajdzie się przy wej-ściu do sekcji krytycznej en, w końcu uzyska do niej dostęp <>cs. Jej weryfikacja będzie odbywała się przy pomocy deklaracji never (nigdy). Ponieważ jednak ma ona być zawsze spełniona, więc musimy ją zanegować. Odpo-wiedni kod uzyskuje się automatycznie przez polecenie spin -f '!([](en -> <>cs))'. Wygenerowanie weryfikatora oraz jego uru-chomienie doprowadzi do pokazania pętli, w której czytelnicy nieustannie wchodzą do sekcji krytycznej.

Rozwiązaniem, które usuwa ten problem, jest zastosowanie dodatkowego semafora turnstile.

Miejsca jego użycia są pokazane przy po-mocy komentarza /* 2 */. Po jego zasto-sowaniu nie będzie dochodziło do błędne-go działania systemu, spowodowanego za-głodzeniem pisarzy. Otrzymanie tych rezul-

tatów musi odbyć się z innymi parametrami weryfikatora.

spin -a readerswriters-nostarve.pml

gcc -w -o pan pan.c

./pan -a -n

spin -t -p bankaccount.pml

Aby uczynić opis języka PROMELA komplet-nym, należy wspomnieć o samych instruk-cjach. W przeciwieństwie do innych języków programowania, takich jak C czy Pascal, są one przedzielane, a nie kończone, znakami średni-ka oraz strzałki w prawo. Ze względu na czy-telność specyfikacji, średnika używa się do od-dzielenia dwóch instrukcji. Zwyczajowo po prawej stronie strzałki umieszcza się instruk-cję, która ma zostać wykonana, gdy warunek znajdujący się po lewej stronie zostanie speł-niony. Jednak nie jest to niezbędne. Oznacza to, iż na przykład instrukcja (a && b) zosta-

Listing 4. Czytelnicy i pisarze

mtype = { wait, signal };

byte readers = 0;

chan mutex = [0] of { mtype };

chan roomEmpty = [0] of { mtype };

chan turnstile = [0] of { mtype }; /* 2 */

proctype semaphore(chan sem) {

do

:: sem?wait -> sem?signal

od

}

proctype reader() {

do

:: skip;

turnstile!wait; /* 2 */

turnstile!signal; /* 2 */

mutex!wait;

readers = readers + 1;

if

:: (readers == 1) -> roomEmpty!wait;

:: else

fi;

mutex!signal;

/* sekcja krytyczna czytelnikow */

cs: skip;

printf("%d reads\n", _pid);

mutex!wait;

readers = readers - 1;

if

:: (readers == 0) -> roomEmpty!signal;

:: else

fi;

mutex!signal;

od

}

proctype writer() {

do

:: skip;

turnstile!wait; /* 2 */

en: roomEmpty!wait;

/* sekcja krytyczna pisarzy */

cs: skip;

printf("%d writes\n", _pid);

turnstile!signal; /* 2 */

roomEmpty!signal;

skip;

od

}

/* never {

do

:: reader[3]@cs && writer[5]@cs -> break;

:: else -> skip

od

} */

never { /* !([](en -> <>cs)) */

T0_init:

if

:: (1) -> goto T0_init

:: (!writer@cs && writer@en) -> goto accept_S4

fi;

accept_S4:

if

:: (!writer@cs) -> goto accept_S4

fi;

}

init {

run semaphore(mutex);

run semaphore(roomEmpty);

run semaphore(turnstile);

run reader();

run reader();

run writer();

}

Page 72: Software Developers Journal PL 03/2009

03/200972

Narzędzia

nie wstrzymana aż do spełnienia warunku. Czasami konieczne jest wykonanie instruk-cji pustej, dlatego też stosuje się słowo kluczo-we skip.

Instrukcje do oraz if również posiadają od-mienne znaczenie. Składają się z jednej lub kilku sekwencji instrukcji zaczynających się od znaku ::. Pierwsza z instrukcji znajdują-cych się za dwukropkiem pełni funkcję war-ty (guard), czy też warunku wykonania ta-kiej sekwencji. W przypadku spełnienia jed-nej z nich, zostają wykonane następujące po nim instrukcje.

Gdy spełnionych jest równocześnie kilka warunków, wybór sekwencji instrukcji nastę-puje niedeterministycznie.

W przypadku zaś niespełnienia żadnego, cała instrukcja do lub if jest blokowana. Aby

jednak uniknąć blokady, wprowadzono sło-wo kluczowe else. Instrukcje występujące po nim są wykonywane, gdy żadna inna se-kwencja instrukcji nie może być wykonana. Oczywiście instrukcja if kończy się po wy-konaniu jednej z sekwencji. W przypadku in-strukcji do, jej działanie wraca od początku. Pętlę tą można przerwać przez użycie słowa kluczowego break.

Ostatnimi instrukcjami jest wysłanie oraz odbiór wiadomości. Wysłanie wiadomości następuje poprzez wyszczególnienie kana-łu oraz jej treści. Do wysłania stosuje się wy-krzyknik. Odbiór następuje poprzez ozna-czenie kanału oraz znak zapytania. Poszcze-gólne pola wiadomości mogą być oddzielo-ne przecinkami. Do przesłania komunika-tu dochodzi, gdy dopasowane zostaną stałe

występujące po stronie nadającej i odbiera-jącej. Możliwe jest również zmienianie kolej-ności wiadomości w kanale komunikacyjnym oraz ich odczyt, bez usunięcia ich z kanału. Dodatkowo udostępnione są funkcje umożli-wiające na sprawdzenie, czy kanał komunika-cyjny jest pusty lub pełny. W języku PROME-LA istnieje możliwość specyfikacji kanałów komunikacyjnych o zadanej pojemności. W takim przypadku nadanie i odbiór wiadomo-ści zależy od ilości komunikatów w kanale. W przypadku odpowiedniej ilości dostępne-go miejsca bądź istnienia wiadomości w ka-nale, procesy odpowiednio kontynuują bądź wstrzymują działanie.

PodsumowanieDzięki weryfikacji przez model możliwe jest badanie zachowania systemów współbież-nych, których wykonanie nigdy się nie koń-czy. Uzyskane w ten sposób rezultaty mo-gą służyć do zapewnienia poprawności ich działania bądź usunięcia zauważonych błę-dów. Weryfikacja przez model nie gwaran-tuje a priori poprawności, zwiększa jednak rozumienie funkcjonowania systemów po-przez odkrywanie niespójności, niejedno-znaczności i niekompletności, które w in-nym przypadku mogłyby pozostać nie za-uważone. Znaczącym ograniczeniem sto-sowania tej metody jest wykładniczo rosną-cy rozmiar systemu, jaki musi zostać zbada-ny, wraz ze zwiększającą się liczbą procesów. Dzięki rozwojowi tej metody w ostatnim cza-sie, uzyskuje ona jednak coraz większe zasto-sowanie w praktyce.

Poniższy artykuł miał za zadanie zaznajo-mienie Czytelnika z weryfikacją przez model, a w szczególności z językiem PROMELA oraz narzędziem SPIN. Omawia on tylko najważ-niejsze elementy tych rozwiązań poprzez po-kazanie prostych przykładów. Intencją autora było jedynie zasygnalizowanie dostępności tej metody weryfikacji oraz zachęcenie do samo-dzielnego studiowania.

Listing 5. Pętla prowadząca do zagłodzenia procesów pisarzy

289: proc 5 (writer) line 56 (state 6)[(1)]

291: proc 4 (reader) line 39 (state 19)[mutex!signal]

292: proc 1 (semaphore) line 11 (state 2) [sem?signal]

294: proc 5 (writer) line 46 (state 1)[(1)]

Never claim moves to line 64 [((!((writer._p==cs))&&(writer._p==en)))]

296: proc 4 (reader) line 18 (state 1)[(1)]

Never claim moves to line 68 [(!((writer._p==cs)))]

298: proc 3 (reader) line 18 (state 1)[(1)]

<<<<<START OF CYCLE>>>>>

300: proc 4 (reader) line 21 (state 2)[mutex!wait]

301: proc 1 (semaphore) line 11 (state 1) [sem?wait]

303: proc 4 (reader) line 22 (state 3)[readers = (readers+1)]

305: proc 4 (reader) line 24 (state 4)[((readers==1))]

307: proc 4 (reader) line 24 (state 5)[roomEmpty!wait]

308: proc 2 (semaphore) line 11 (state 1) [sem?wait]

310: proc 4 (reader) line 27 (state 9)[mutex!signal]

311: proc 1 (semaphore) line 11 (state 2) [sem?signal]

313: proc 4 (reader) line 30 (state 10)[(1)]

4 reads

313: proc 4 (reader) line 31 (state 11)[printf('%d reads\\n',_pid)]

315: proc 4 (reader) line 33 (state 12)[mutex!wait]

316: proc 1 (semaphore) line 11 (state 1) [sem?wait]

318: proc 4 (reader) line 34 (state 13)[readers = (readers-1)]

320: proc 4 (reader) line 36 (state 14)[((readers==0))]

322: proc 4 (reader) line 36 (state 15)[roomEmpty!signal]

323: proc 2 (semaphore) line 11 (state 2) [sem?signal]

325: proc 4 (reader) line 39 (state 19)[mutex!signal]

326: proc 1 (semaphore) line 11 (state 2) [sem?signal]

328: proc 4 (reader) line 18 (state 1)[(1)]

spin: trail ends after 328 steps

SŁAWOMIR MALUDZIŃSKIJest doktorantem informatyki AGH. Specjalizuje się w metodach formalnych oraz systemach agento-wych. Posiada kilkuletnie doświadczenie zawodo-we w czołowych placówkach naukowych oraz fir-mach softwarowych.Kontakt z autorem: [email protected]

W Sieci

• http://spinroot.com/spin/whatispin.html,• http://ww w.spinroot.com/spin/Man/

promela.html,• http://bcook.cs.georgiasouthern.edu/

promela.htm.

Procesy oraz wątkiW teorii metod formalnych nazwa proces ma inne znaczenie niż to znane z systemów opera-cyjnych. W ten sposób oznacza się pojęcie mogące realizować pewne akcje i posiadać dostęp do zmiennych dzielonych oraz kanałów komunikacyjnych. Proces odpowiada więc wątkowi wykonania programu, znanego z języków programowania.

Page 73: Software Developers Journal PL 03/2009
Page 74: Software Developers Journal PL 03/2009

Felieton

03/200974

Felieton

www.sdjournal.org 75

Ludowe porzekadło przekonuje, że mała rewolucja od czasu do czasu jeszcze nikomu nie zaszkodziła. Podobnie jest w warun-kach wolnego rynku – krótkotrwałe wstrząsy mogą przynieść

wiele dobrego. Powodują wahania równowagi konkurencyjnej two-rząc możliwości pojawienia się na rynku nowych graczy czy produk-tów. Jeżeli jednak zamieszanie będzie za duże, a jego konsekwencje zbyt rozległe, to powstałe deregulacje przyniosą jedynie pozorne ko-rzyści. W dłuższym okresie czasu doprowadzą do zjawisk bardziej nie-bezpiecznych, niż sam kryzys (por. [1]).

Nikt już nie wątpi, że dzisiejsza gospodarka znalazła się na takim właśnie zakręcie. A już na pewno nikogo nie zaskoczy, gdy IT na tym ucierpi. Przedsmak tego odnajdujemy w prognozach na 2009 rok (da-ne IDC, Gartnera, Forrestera oraz ISuppli, [2]):

• Sprzedaż komputerów stacjonarnych ma wzrosnąć jedynie o 4% (zamiast wcześniej prognozowanych przez ISuppli prawie 12%, według IDC odpowiednio 2.4%, zamiast 6%), ale za to laptopów – aż o 15%;

• Wzrost wydatków na IT na świecie ma wynieść jedynie 2,6%, za-miast spodziewanych wcześniej 5,9%;

• Rynek serwerów fizycznych będzie rósł średnio o 4% rocznie, ale za to serwerów wirtualnych przybywać będzie już 55% rocznie (zob. [3]);

• Najbardziej dynamicznie rozwija się rynek serwerów wieloproce-sorowych (bazujących na x86), sprzedaż maszyn jednoproceso-rowych odnotowuje znaczące spadki;

• Rynek outsourcingu IT ma rosnąć o około 5% w latach 2009-2010.

Z powyższych danych wyłania się obraz wyzwań, jakie staną przed IT. Przyszłe miesiące to przede wszystkim konieczność ograniczenia tempa wydatków, rozwijanie systemów w oparciu o słabsze, ale bar-dziej mobilne stacje klienckie oraz tańsze, ale wieloprocesorowe ser-wery. Ograniczenia finansowe szybciej wymuszą optymalizację wy-korzystania istniejącej infrastruktury, niż jej rozszerzanie. Pojawi się potrzeba rozwiązań bardziej wydajnych oraz lepiej skalowalnych za-równo w górę (obsługa pików przetwarzania), jak i w dół (przestoje). Taka elastyczność umożliwi szybkie tworzenie otoczenia dla imple-mentacji i wdrażania produktów. Powinno to wspomagać koniecz-ność skrócenia tych etapów, co jest wymagane w obliczu zaostrzo-nej konkurencji. Wreszcie, zastępowanie stacji roboczych laptopa-mi i innymi urządzeniami mobilnymi (tablety internetowe, PDA, net-

booki, smartphony itp.), oznacza przesunięcie środka ciężkości prze-twarzania w stronę większych centrów obliczeniowych (również tych oferowanych przez zewnętrznych partnerów). Tendencje te potwier-dza Gartner, umieszczając wirtualizację oraz cloud computing na czo-łowych miejscach listy technologii strategicznych w 2009 ([4]).

Termin cloud computing (pol. chmura obliczeniowa) odwołuje się do dostarczania usług realizowanych przez wirtualne zasoby za pomocą standaryzowanych protokołów. Wirtualizacja jest tu rodzajem silnika or-ganizującego i napędzającego oferowane zasoby. Sedno tej idei polega na przeniesieniu odpowiedzialności na barki wyspecjalizowanych do-stawców odpowiednich usług w zakresie: tworzenia i utrzymywania in-frastruktury (komputerów, sieci), aspektów jej działania (np. współdzie-lenia zasobów, kontroli dostępu, tworzenia kopii zapasowych, zarządza-nia awariami) i funkcjonalności (aplikacji). Biznes może się wtedy skon-centrować na procesach będących bezpośrednio jego przedmiotem, na akcie tworzenia, dostarczania i konkurowania – a nie na działaniach je-dynie to umożliwiających. Wynika z tego, że cloud computing nie jest żadną konkretną technologią, a pewnym wielowarstwowym modelem. Poszczególne warstwy tego modelu odzwierciedlają poziomy specjali-zacji oferowanych usług. Na najniższym poziomie oferuje się czystą in-frastrukturę. Najwyższy poziom stanowią wyspecjalizowane aplikacje.W szczególności wyróżnia się następujące warstwy ([5]):

• dSaaS (ang. data-Storage-as-a-Service), która oferuje usługi prze-chowywania danych (np. Amazon/S3, Microsoft Live Workspace);

• IaaS (ang. Infrastructure-as-a-Service), która oferuje wirtualne ser-wery (Amazon/EC2, IBM Blue Grid, Sun Grid);

• PaaS (ang. Platform-as-a-Service), oferuje środowisko do tworze-nia i wykonywania aplikacji (system operacyjny, zestaw wymaga-nego oprogramowania, dedykowane bazy danych, np. Google App Engine);

• SaaS (ang. Software-as-a-Service), oferuje konkretne aplikacje (np. Google Docs, Salesforce CRM).

W takim modelu do zakresu obowiązków pracowników pionu IT na-leży poszukiwanie partnerów, którzy dostarczą usługi odpowiada-jące potrzebom firmy. Za to partnerzy – dostawcy pobierać będą opłaty. Z drugiej strony IT rozlicza dostawców z jakości oferowanych usług, dotrzymywania uzgodnionych parametrów użytkowych oraz zapewnionego poziomu bezpieczeństwa. W tym zakresie dostawcy będą konkurować ze sobą.

Aby wielu mogło na raz...

Cloud computing przedstawiane jest jako cudowny lek na kryzys w IT. Czy za tym terminem kryje się rzeczywisty sposób na stawienie czoła recesji? A może jest to jedynie sprytna sztuczka na sprzedanie starych idei w nowym, marketingowym opakowaniu?

Page 75: Software Developers Journal PL 03/2009

Felieton

03/200974

Felieton

www.sdjournal.org 75

Należy tu zauważyć, że w obrębie wymienionych warstw wyko-rzystuje się znane i sprawdzone technologie, takie jak wirtualizacja, Web 2.0, interpretery języków (np. Python dla Google Apps). Rów-nież idea wykorzystania Internetu jako medium dostępu do usług także nie jest specjalnie nowa (por. ang. Web services). Z drugiej stro-ny, w prawie każdej publikacji na temat przyszłości IT wspomina się o cloud computing (przynajmniej pośrednio). Co stało się powodem ta-kiej eksplozji popularności tego modelu?

Myślę, że podstawowym katalizatorem jest kryzys finansowy. Nawet jeżeli jego korzenie nie wiążą się bezpośrednio z rynkiem IT (jak to było przy krachu dotComów w 2001 roku), to firmy na-uczone bolesnym doświadczeniem, od razu zaczęły rozglądać się za potencjalnymi oszczędnościami. Możliwość obniżenia kosz-tów budowania i obsługi infrastruktury oferowana przez chmu-rę wydaje się bardzo na czasie. Zwłaszcza gdy nie odbywa się to kosztem istniejących wdrożeń. Można uniknąćw ten sposób np. kosztownych problemów z zachowaniem kompatybilności. Kry-zys to kurczenie się rynków zbytu. Szacuje się, że moce obliczeniowe

przedsiębiorstw z branży e-commerce wykorzystywane są jedynie w 85%. Patrząc na lata 2004-2007 w 25 krajach EU, liczba dostępnych łą-czy typu broadband zwiększyła się z około 10 do prawie 90 milionów. W tym samym czasie liczba gospodarstw domowych z szerokopasmo-wym dostępem do Internetu wzrosła jedynie o około 28 milionów (da-ne szacowane na podstawie Eurostat). Cloud computing obiecuje moż-liwość zyskownego zagospodarowania takich rezerw.

Kryzys to również skłonność do poszukiwania tańszych alterna-tyw. Dla przykładu, już dziś w Polsce więcej osób korzysta z przeglą-darek innych niż Internet Explorer (głównie Firefox). Kompleksowość usług dostarczanych przez model chmury obliczeniowej może się oka-zać zaletą.

Według mnie, ostatecznym katalizatorem jest szerzące się na świe-cie piractwo. To zjawisko osiągnęło taką skalę, że walka z nim jest bar-dzo trudna. Co więcej – część beneficjentów praw autorskich przed-kłada agresywne sposoby dochodzenia swoich roszczeń (na sali sądo-wej) nad elastyczność. Przynosi to mizerne zyski finansowe i powodu-je wiele negatywnych emocji. Decydując się na przeniesienie swoich

Spektakularne wycieki danych w latach 2007-2008

• Niemcy: wyciekły dane 21 milionów kont bankowych. Źródłem przecieku były najprawdopodobniej zewnętrzne firmy dostarczające usługi księ-gowe i finansowe. Kilka miesięcy wcześniej ujawniono wyciek danych 17 milionów klientów operatora T-Mobile, o czym opinia publiczna dowie-działa się dopiero ponad 1.5 roku po fakcie ([7], [8]);

• Wielka Brytania: na laptopie zakupionym na eBay znaleziono dane kilku milionów klientów Royal Bank of Scotland, Natwest oraz American Express ([9]); Rok wcześniej wyciekło nawet 90 milionów numerów kart kredytowych klientów sieci T.J. Maxx ([12]);

• Polska: dane osobowe (w tym numery kont bankowych) chętnych na zakup biletów na Euro2008 były dostępne przez kilka godzin. PZPN twierdzi, że jedyną odpowiedzialność ponosi prywatny operator [10];

• Polska: wyciekły życiorysy 3 tysięcy osób kandydatów do pracy w Pekao SA. Według ekspertów powodem były nieodpowiednie zabezpieczenia zastosowane przez firmę, której Pekao zleciło wykonanie strony ([11]);

• USA: podczas przewożenia taśmy z back-up'em skradziono dane 12,5 miliona klientów New York Mellon Bank, GE Money stracił w podobny spo-sób dane 650 tyś. klientów; Szpital Uniwersytecki Utah: 2.2 mln danych medycznych pacjentów zostało skradzionych z samochodu serwisanta systemów archiwizacji, podczas gdy ten był u innego klienta; Countrywide Financial: 2 mln danych kredytobiorców zostało ukradzionych i sprze-danych przez pracownika firmy, który łączył się zdalnie do sieci korporacyjnej ([12]);

Tabela 1. Wybrani gracze na rynku cloud computing (zob. [16], [17])

Firma/Produkt Model biznesowy Przykładowe ceny Ilość użytkowników

Amazon/ Amazon Web Services

Udostępnianie przestrzeni dyskowej (Simple Storage Service - S3:dSaaS), serwe-ry wirtualne (Elastic Compute Cloud - EC2: IaaS), kolejki wiadomości oraz baza da-nych (SimpleDB)

15 centów/1 GB powierzchni/miesiąc10-80 centów/godzinę pracy ser-wera

370 tyś.

Google/ Google App Engine (rów-nież Android)

Hosting aplikacji napisanych w Pythonie (PaaS: dostęp do przestrzeni dyskowej, serwerów ale również środowisko pro-gramistów).

15 - 18 centów/1 GB powierzchni/miesiąc (do 0.5 GB za darmo)10-12 centów/godzinę pracy ser-wera

n/a

Google/ Google Apps (również Gmail/Postini)

SaaS: procesor tekstu, arkusz kalkulacyj-ny, tworzenie prezentacji, klient poczto-wy, kalendarz (plus przestrzeń dyskowa)

Za darmo lub 50$ rocznie za usługi premium

Nawet 6 milionów (docs+spreadsheets) użytkow-ników, ale jedynie 4 (docs) - 6 minut (spreadsheet) spędzanych on-line (dane: www.compete.com)

Google/Salesforce: Sales-force CRM

SaaS: On-line CRM $10/miesiąc n/a

Salesforce: For-ce.com

PaaS: platforma aplikacji Web; Relacyjna baza danych, interfejs użytkownika, logika biznesowa, środowisko programistyczne, udostępnianie aplikacji (AppExchange)

n/a 1.1 miliona

Microsoft: Office Online, Live Work-space, Hotmail (w przygotowaniu: Azure)

PaaS: Oprogramowanie plus usługi (np. MS Word do tworzenia dokumentów i MS Live Workspace do zapisywania ich on-line).

n/a Około 0.5 milina unikalnych użytkowników witryny officelive.com (dane: www.compete.com)

Ulteo Desktop PaaS: wirtualny desktop linuxa Darmowy (community edition) lub płatne wsparcie

Około 6 tysięcy unikalnych użytkowników miesięcz-nie (dane: www.compete.com), ponad 140 tyś. sesji w ciągu ostatnich kilku miesięcy (w/g Ulteo)

Page 76: Software Developers Journal PL 03/2009

Felieton

03/200976

produktów do chmury, producenci uzyskują całkowitą kontrolę nad tym kto, jak często i w jakim zakresie ich używa. Problem piractwa przestaje istnieć.

O ile jestem zdecydowanym przeciwnikiem piractwa (w końcu sam korzystam z tantiem za swoją pracę), to podobny stopień kontroli jest dla mnie problematyczny.

Dyskomfort wiąże się przede wszystkim z koniecznością zaufania ze-wnętrznemu dostawcy. Łatwiej o takie zaufanie, kiedy mówimy o skle-pie mięsnym za rogiem. Wiem, że pracującej tam pani Basi zależy na klientach. Zbyt wiele podobnych sklepików jest w okolicy, aby mogła pozwolić sobie na sprzedanie mi nieświeżego towaru. Czy tak samo będzie zależeć na mnie (mojej firmie) korporacji, która obsługuje milio-ny podobnych klientów? Powtarzając za Greenspanem tłumaczącym przyczyny kryzysu finansowego: uwierzyłem, że banki są w stanie wy-konać właściwe posunięcia by zabezpieczyć interesy ich akcjonariuszy i klientów. Myliłem się.

Wydaje się, że to poziom bezpieczeństwa będzie warunkował po-pularność usług cloud computing. Jak dotychczas usługi świadczo-ne za pomocą Internetu trudno było uznać za bezpieczne. Przypad-ki ujawnienia danych niepowołanym osobom zdarzają się niemal na porządku dziennym (zob. Ramka Spektakularne wycieki danych w la-tach 2007-2008).

Ponieważ zaufanie będzie kluczową kwestią, można spodziewać się, że dostawcy nie będą zinteresowani nagłaśnianiem swoich wpadek. Dodatkowo, dowiedzenie ewentualnej winy dostawcy stanie się bar-dziej skomplikowane, niż w przypadku systemów lokalnych – również ze względu na trudności w określeniu zasięgu chmury.

Biorąc pod uwagę ryzyko, jakie przejmują na siebie dostawcy, po-ziom bezpieczeństwa nie będzie traktowany jako parametr usługi (np. usługi składowania danych), ale jako kolejna osobno płatna usługa (podobnie transfer, szybkość operacji, itd.). Udzielane gwarancje bę-

dą uzależnione od wartości opłacanego abonamentu (np. wysokość odszkodowania za straty wynikłe z utraty lub upublicznienia danych, przestojów systemu).

Kolejną kwestią wartą rozważenia jest niekompatybilność chmur. Oczywiście, wielu z dostawców zaproponuje własne standardy dostę-pu (protokoły, interfejsy). Istnieją więc duże szanse, że znowu będzie-my świadkami scysji podobnej do tej między ODF i OOXML (zob. [13]). Brak porozumienia doprowadzi do typowego vendor lock-in: przeniesie-nie danych między dostawcami stanie się na tyle trudne, że nie zrekom-pensuje potencjalnych zysków tytułem niższych opłat u innego dostaw-cy. To ograniczy presję konkurencyjną. Przydatność chmury do wymiany informacji między klientami różnych dostawców może być ograniczona. Przecież nie chodzi o to, żeby załączyć dokumenty do e-maila.

Z drugiej strony może się okazać, że takich dostawców nie będzie znowu aż tak wielu. Nawet jeśli sami stworzą rozwiązania odpowied-nio funkcjonalne i skalowalne, ilu z nich zostanie obdarzonych odpo-wiednim kredytem zaufania? Którym zdecydujemy się powierzyć ta-jemnice niejednokrotnie warunkujące istnienie naszego biznesu? Pro-giem wejścia na taki rynek jest nie tylko infrastruktura, know-how, ale aspekty czysto emocjonalne, jak np. zaufanie do marki.

Wątpliwości dotyczą również firm powiązanych z klientami za po-mocą produktów. Czy będą one w stanie przestawić się na model do-stawca-usługobiorca (zob. [14])?

Czynniki te mogą sprawić, że powstanie monopol kilku-, kilkunastu dostawców, czy korporacji o międzynarodowym zasięgu i renomie. Ograniczy to wpływ problemów z przenośnością, ale czy rzeczywiście tak powinien funkcjonować wolny rynek?

Bańkę spekulacyjną nadmuchała chciwość. Zagrożenie, jakie się wiąże z udzieleniem kolejnego kredytu subprime, było nieistotne. Większą wagę miała ilość zawartych umów, bo od tego zależała mie-sięczna premia. Jaka jest pewność, że podobna sytuacja się nie powtó-rzy? Niektóre z oferowanych usług będą przecież bardziej popularne niż inne. Dostawcy chętniej zainwestują w ich rozwój, bo to one przy-ciągną klientów i przyniosą największe zyski. Może to doprowadzić do sytuacji, w której pakiety usług staną się zunifikowane i przykrojone do najczęstszych potrzeb. Presja konkurencji przestanie się liczyć, ponie-waż zysk będzie pochodną ilości, a nie specyficzności. Oczywiście na usługach niszowych dostawca będzie mógł zarobić wielokrotnie wię-cej. Tylko czy małe i średnie firmy, do których cloud computing jest w pierwszym rzędzie adresowany, będzie na to stać? Raczej dostosują się do oferowanych usług, co przyniesie efekt dokładnie odwrotny do obiecywanego przez marketing. Czy właśnie to ma na myśli Sun pod eufemistycznym określeniem important tradeoffs (zob. [15])?

Chmura to chwytliwy i bardzo obrazowy slogan. Dobrze współbrzmi z Internetem, którego clue to decentralizacja. Z drugiej strony – chmu-ra jest synonimem pewnej nieokreśloności, rozmytości, a istotą chmu-ry obliczeniowej jest konsolidacja i centralizacja zasobów. Podobnie niejednoznaczne są moje odczucia. Z jednej strony nęci mnie obiet-nica uzyskania pewnego komfortu psychicznego (zrzucenia na kogoś choćby części odpowiedzialności związanej z infrastrukturą), możliwo-ści kształtowania infrastruktury według potrzeb, przebierania w usłu-gach (zamiast ich mozolnego tworzenia we własnym zakresie). Z dru-giej strony jednak studzi mnie brak przejrzystości reguł i długofalo-wych skutków. Ciekawy jestem co wygra?

Artykuł wyraża prywatne poglądy autora, które niekoniecznie od-zwierciedlają stanowisko Silicon & Software Systems Ltd. (S3)

ARKADIUSZ MERTAAutor od 10 lat zajmuje się zagadnieniami projektowania i realizacji oprogra-mowania. Aktualnie jest pracownikiem Silicon & Software Systems Polska za-trudnionym na stanowisku menadżera projektów.Kontakt z autorem: [email protected]

Bibliografia

• [1] Doktryna Szoku, Naomi Klein, Muza, październik 2008;• [2] Branża technologiczna nie poległa... Na razie, NetWord Online, li-

stopad 2008;• [3] Wirtualizacja 2.0 – trend czy standard? Prognozy rynku rozwoju

technologii, Jarek Smulski, IDC Polska, 2007;• [4] Dziesięć strategicznych technologii 2009 roku, IDG.pl, padziernik

2008;• [5] Cloud computing with Linux, M.Tim. Jones, wrzesień 2008;• [6] Dane Dow Jones: Google Finance; dane wyszukiwań: Google

Trends; dane odwiedzin domeny docs.google.com: Compete; wszystkie znormalizowane do % maksymalnej wartości w okresie październik 2007 – listopad 2008;

• [7] Niemcy: 21 milionów kont bankowych do kupienia, Dziennik In-ternautów,6 grudnia 2008;

• [8] Niemcy: Wyciekly dane 17 milionów klientów, Dziennik Internau-tów, 5 październik 2008;

• [9] Wyciek danych – nowa specjalnosc Brytyjczyków?, Dziennik Inter-nautów, sierpień 2008;

• [10] Wyciek danych polskich kibiców, Dziennik Internautów, luty 2008;

• [11] Wyciek danych z Pekao to nie atak hakerów, Dziennik Internau-tów, lipiec 2008;

• [12] Banking's Data Security Crisis, Andy Greenberg, Forbes, listo-pad 2008;

• [13] Zagadnienia procesu normalizacji OOXML opisywane były w SDJ numer 6/2008, 8/2008 oraz SDJ Extra! Numer 25;

• [14]The Risks and Rewards of Cloud Computing, Gartner Voice, lipiec 2008;

• [15] Demystifying Cloud Computing, Sun Inner Circle – Newsletter, listopad/grudzień 2008;

• [16] Demystyfying the Cloud, Information Week Research & Reports, June 2008;

• [17] Handicapping cloud computing, Larry Dignan, grudzień 2008;

Page 77: Software Developers Journal PL 03/2009

Felieton

www.sdjournal.org 77

Cel nie powinien byc postrzegany jako punkt. Kazda decyzja podejmowana w projekcie moze do niego przyblizac lub od-dalac. Dlatego cele nalezy rozpatrywac w kategoriach daze-

nia w wybranym kierunku.Pamiętam jedno opowiadanie Lema z serii Dzienników Gwiazdowych

[1]. Jego bohater Ijon Tichy, nie mogąc w pojedynkę poradzić sobie z naprawą statku kosmicznego, postanowił zapętlić czas, tak aby zwielo-krotnić samego siebie. Uzyskane w ten sposób dodatkowe ręce do pra-cy, miały pomóc w wyjściu z opresji. Niestety już po pierwszym rozmno-żeniu okazało się, że brakuje zapasowego skafandra. Po kilku powtórze-niach procesu, gdy liczba klonów bohatera gwałtownie wzrosła (zamie-rzenie lub jako efekt uboczny), chaos pogłębiał się a rakieta dryfowała co-raz dalej w nieznane.

Na pierwszy rzut oka może się wydawać, że problemy Ijona są tak wy-dumane, że nadają się jedynie na niedzielne czytadło. Spróbujmy jednak pomyśleć o podróży bohatera jako o pewnym projekcie. Przeszkody, któ-re pojawiły się w czasie jego realizacji (uszkodzenia statku), okazują się na tyle trudne, że powodzenie misji staje pod znakiem zapytania.

Mamy tu do czynienia z poważnie zagrożonym projektem i despe-racką próbą uratowania go. Nasz bohater decyduje się rozwiązać pro-blem poprzez zwiększenie ilości zasobów. Metoda taka (jak i jej wynik) jest dokładną ilustracją prawa Brooksa (sformułowanego jakieś 10 lat po wydaniu wspomnianego opowiadania – przypadek?). Prawo to mó-wi, że dodawanie kolejnych zasobów do spóźnionego projektu, czy-ni go jeszcze bardziej spóźnionym. Problem polega na tym, że im więk-szy jest zespół, tym więcej czasu trzeba poświęcić na wewnętrzną ko-munikację. Im później ludzie dołączają do projektu, tym więcej cza-su potrzebują na wdrożenie (tzn. tym później będą w stanie efektyw-nie wspomagać projekt, zob. [2]). Boleśnie tego doświadczył Ijon, kie-dy próbował ustalić, który klon jest kim, po co się pojawił i jaki ma spo-sób na rozwiązanie sytuacji. Zamiast pracować nad osiągnięciem ce-lu, uwikłał się w męczące spory, dyskusje i rozważania. A czas uciekał...Podobne historie przydarzyły się już wielu projektom. Goniące terminy, nieprzewidziane wydarzenia kradnące czas i zasoby, niedoszacowane za-dania – to wszystko sprawia, że zaczynamy panikować. Ściągamy dodat-kowe zasoby, nerwowo żonglując zadaniami między nimi – zgodnie ze wskazaniami ścieżki krytycznej. Zarywamy weekendy (o nadgodzinach nie wspominając). W zespole zaczyna robić się gęsto od nerwów. Niektó-rzy nie wytrzymują tempa i awantura gotowa.

Nie myślcie, że nie nachodziły mnie takie pomysły. Jednak mój szef produktu, na prośbę przydzielenia dodatkowych ludzi w celu dopięcia terminów, odmówił. Uzasadnił to krótko: bo chcę, żeby Ci się udało. Czy chodziło mu jedynie o prawo Brooksa?

Źródłem problemów Ijona była jego ślepa koncentracja na celu. Tak bar-dzo nastawił się na jego osiągnięcie, że przysłoniło mu to wszystkie inne, w jego pojęciu poboczne, aspekty – jak np. ilość skafandrów, miejsce czy zapasy pożywienia dla rosnącej załogi. Postrzegał problem w ograniczony sposób i źle ukierunkował działania. Osiągnięte rezultaty nie poprawiały

sytuacji. Okazana krótkowzroczność prowadziła do niechybnej zguby.Postrzeganie jest inspiracją dla działania (zob. [3]). Jeżeli będzie zakłóco-

ne, fałszywe, podyktowane nieobiektywnymi czy doraźnymi przesłanka-mi – podjęte na jego podstawie akcje mogą przynieść więcej szkody niż korzyści. Powstaje zatem pytanie, czy jesteśmy w stanie poprawnie po-strzegać (a więc i definiować) cele?

Powtarzając za Druckerem: to, co klient uważa za wartość, jest tak skomplikowane, że na pytanie o nią tylko on sam może odpowie-dzieć. Zarząd firmy nie powinien nigdy nawet próbować tego zgady-wać. Powinien zawsze i systematycznie szukać odpowiedzi u klienta [4].Firma funkcjonuje tak długo, jak długo potrafi zarabiać pieniądze. Aby za-pewnić stały dopływ środków, musi dotrzymywać swoich zobowiązań. Realizacja zadanych celów to podstawowe zadanie. Rolą liderów jest za-pewnienie tego. Trzeba jednak dokładnie rozumieć na czym polega biz-nes. Czy chodzi o dostawę, czy raczej spełnienie oczekiwań (potrzeb) klienta? Czy chodzi o sztukę, czy o produkt? Czy chodzi o tysiące linii ko-du, czy o postęp?

Należy również zdać sobie sprawę z faktu, że cele (potrzeby) klien-ta nie są stałe w czasie. Gdy dostarczamy np. proof-of-concept (dowód, że projekt jest wykonalny), klienta będą interesować jak najniższe kosz-ty i najkrótszy czas wykonania (tzn. minimalna strata w przypadku nie-możności realizacji). Z drugiej strony zadaniem podobnego prototypu jest przedstawienie, wizualizacja koncepcji przyszłego produktu, tak aby klient zdecydował się na realizację. Dostarczenie podobnej projekcji po-zostawia pole do kompromisu w zakresie kompletności i jakości. Oczywi-ście w miarę postępu prac nad projektem, pole manewru ulegnie znacz-nemu ograniczeniu. Nadal jednak świadome i odpowiedzialne balanso-wanie czasem, kosztami i zakresem może umożliwić osiągnięcie sukcesu – nawet w przypadku zagrożonych projektów.

Sztuczka polega na tym, aby cel postrzegać w kategorii dążenia, co-dziennego kursu i jego korekt, a nie tylko pojedynczego punktu w cza-sie. Wszystkie doraźne działania należy ważyć w kategorii zysków i strat, które będą przybliżać lub oddalać sukces. Brak długofalowej analizy wy-ników takich działań (nawet tych pozornie błahych) może skutkować dry-fem, a nie podążaniem w określonym kierunku. Refleksja na temat poten-cjalnych efektów nie może być rozpatrywana jedynie w kontekście ce-lu postawionego przed projektem. Konieczne jest uwzględnienie wszel-kich dodatkowych faktów, które mogą zaistnieć w wyniku podejmowa-nych decyzji. Przykładowo, planowe dostarczenie projektu było okupio-ne wzmożonym wysiłkiem zespołu. W dłuższym okresie może to prowa-dzić do spadku zaangażowania i kreatywności – a więc i wydajności.

Cele należy osiągać – to podstawa egzystencji firmy – ale trzeba być świadomym drogi, która prowadzi do ich realizacji. Wszystkie decyzje po-dejmowane w tym czasie trzeba rozpatrywać względem szerszego ho-ryzontu późniejszych skutków. Zaniedbanie przewidywania może się wkrótce zemścić, i to w całkowicie nieprzewidziany sposób.

PS. Nie zdradzę zakończenia opowiadania – zachęcam do lektury. Po-wiem jedynie, że rozwiązanie leżało nie tyle w ilości, ile w składzie zespołu i jego odpowiednim zaangażowaniu w rozwiązanie problemu.

Artykuł wyraża prywatne poglądy autora, które niekoniecznie odzwiercie-dlają stanowisko Silicon & Software Systems Ltd. (S3).

Najpierw cele

ARKADIUSZ MERTAAutor od 10 lat zajmuje się zagadnieniami projektowania i realizacji oprogra-mowania. Aktualnie jest pracownikiem Silicon & Software Systems Polska za-trudnionym na stanowisku menadżera projektów.Kontakt z autorem: [email protected]

Bibliografia• [1] Dzienniki Gwiazdowe: Podróż siódma, Stanisław Lem, Wydawnic-

two Literackie, 1966• [2] The Mythical Man-Month, Essays on Software Engineering, Peter

F. Brooks, Addison-Wesley, 1995• [3] Mądre życie, A. Roger Merrill, Rebecca Merril, Bertlsmann Me-

dia, Warszawa 2004• [4] Praktyka zarządzania, Peter F. Drucker, MT Biznes, 2008

Page 78: Software Developers Journal PL 03/2009

KLUB PROOferta skierowana dla firm

Jeżeli Twoja firma jest prenumeratorem Software Developer’s Journal za comiesięczną dopłatą 50 PLN +VAT możesz dodatkowo otrzymać reklamę.

Wystarczy tylko, aby profil Twojej firmy pokrywał się z naszym magazynem.

Wyślij do nas: logo firmy, dane kontaktowe i informację o firmie

Reklama przez 12 kolejnych numerów tylko za 600 PLN +VAT.

Jeżeli nie posiadasz jeszcze prenumeraty możesz ją zamówić w atrakcyjnej cenie.

Dla nowych prenumeratorów specjalna oferta – 690 PLN.

FRONTLINE STUDIOSFrontline Studios – amerykańsko-polski twórca gier konsolowych oraz PC – szuka utalentowanych ko-derów (bardzo dobra znajomość C/C++; Java, Del-phi, UML), doświadczonych grafików (2D, 3D) oraz zespołów developerskich. Oferujemy długotermi-nową pracę nad poważnymi projektami. Nie prze-gap tej okazji!

[email protected]

Future ProcessingFuture Processing to dynamiczna firma techno-logiczna działająca na globalnym rynku opro-gramowania. Jesteśmy zespołem wysokiej klasy specjalistów posiadających wiedzę i doświadcze-nie niezbędne do realizacji ambitnych projektów informatycznych. Jeśli programowanie to Twoja pasja dołącz do nas! (możliwość pracy zdalnej).

http://www.future-processing.pl

Skontaktuj się z nami:[email protected] tel. 22 427 36 91

[email protected] http://buyitpress.com

Kei.plKei.pl działa na rynku usług hostingowych od 2000 roku. Do naszych zadowolonych Klientów z du-mą możemy zaliczyć wiele przedsiębiorstw sekto-ra MSP, instytucji oraz osób prywatnych. W ofer-cie Kei.pl znajdują się pakiety hostingowe, a także usługi dla wymagających Użytkowników – platfor-my e-Biznes oraz serwery fizyczne.

http://www.kei.pl

Opera SoftwareOpera Software’s vision is to deliver the best In-ternet experience on any device. We are offering browser for PC/desktops and embedded pro-ducts that operates across devices, platforms and operating systems. Our browser can deliver a faster, more stable and flexible Internet expe-rience than its competitors.

http://www.opera.com

Architektury systemów ITTwórca frameworków JUVE i serwera aplikacji AVAX oferuje usługi, doradztwo, rozwiązania do tworzenia nowoczesnych, dużych systemów i roz-wiązań informatycznych/internetowych, integrują-ce architektury ery post-J2EE/.NET, wykorzystu-jące MDD/MDA dla dziedzin – bankowość, teleko-munikacja, handel, e-commerce, ERP/Workflow/CRM, rozwiązania internetowe, portalowe.www.mpsystem.com [email protected]

WSISiZ w WarszawieINFORMATYKA ZARZĄDZANIEstudia stopnia I i II (stacjonarne i niestacjonar-ne) specjalności: inżynierskie, magisterskie i li-cencjackie. Szczegółowe plany studiów, opisy poszczególnych specjalności – zapraszamy na stronę uczelni.

http://www.wit.edu.pl

Page 79: Software Developers Journal PL 03/2009

KLUB PRO

SWD Software Sp. z o.oSystem operacyjny czasu rzeczywistego RTOS QNX. Oficjalny dystybutor w Polsce.Zakres działalności: lokalizacja produktów QNX, dostawy sprzętu i oprogramowania, doradztwo przedsprzedażowe, wsparcie techniczne, certyfi-kowane szkolenia, opracowania na zamówienie.

http://www.swdsoft.pl

StatConsultingStatConsulting to firma o znaczącej pozycji na ryn-ku usług analitycznych oraz Data Mining. Nasza oferta obejmuje m.in. modele scoringowe, rozwią-zania Fraud Detection oraz modelowanie ryzyka. Tworzymy także własne rozwiązania informatycz-ne na potrzeby projektów Data Mining, Data Quali-ty, zarządzania ryzykiem itd.

http://www.statconsulting.com.pl

TTS Company Sp. z o.o.Sprzedaż i dystrybucja oprogramowania komputero-wego. Import programów na zamówienie. Ponad 200 producentów w standardowej ofercie. Chcesz kupić oprogramowanie i nie możesz znaleźć polskiego do-stawcy? Skontaktuj się z nami – sprowadzimy nawet pojedyncze licencje.

http://www.OprogramowanieKomputerowe.pl

IT SOLUTIONSWdrożenia i szkolenia z zakresu:• SQL Server• SharePoint Services• MS Project / Server• Tworzenie aplikacji w technologii .NET

http://[email protected]

IT SOLUTIONS

Softline rozwiązania mobilneWiodący producent systemów mobilnych, do-stawca aplikacji użytkowych dla biznesu (Sym-bian OS, Windows Mobile, J2ME ) zaprasza do współpracy. Zostań naszym partnerem. Dołącz do zespołu.

http://www.softline.com.pl

Transition Technologies S.A.Firma w branży high-tech od 1991. Producent opro-gramowania dla przemysłu (ponad 350 referencji z instalacji na całym świecie). Usługi z zakresu: hur-townie danych i Business Intelligence, rozwiązania eBusiness, optymalizacja, integracja danych, aplika-cji oraz procesów biznesowych, portale korporacyj-ne, consulting i outsourcing usług IT, zaawansowa-na automatyka cyfrowa.http://www.tt.com.pl

EPRONaszą misją jest projektowanie najwyższej jako-ści dedykowanych systemów IT, które cechuje wysoka niezawodność, wydajność, ergonomicz-ność i intuicyjność w obsłudze oraz administracji.Głównym elementem oferty EPRO jest oprogra-mowanie sklepu internetowego oraz identyfika-cja wizualna.tel. 085 743 66 38http://www.epro.com.pl

Proximetry Poland Sp. z o.o.Proximetry Poland Sp. z o.o. jest polskim od-działem amerykańskiej firmy Proximetry Inc. – dostawcy systemów zarządzania sieciami bez-przewodowymi opartymi na technologiach WiFi i WiMAX. Naszą misją jest dostarczenie klientom rozwiązań poprawiających jakość usług (QoS) dostarczanych drogą radiową. Dołącz do najlep-szych i zostań członkiem naszej ekipy!

http://www.proximetry.com

Systemy bankowe, ISOF HEUTHES istnieje na rynku od 1989 r. Obok systemów informatycznych dla banków, ofe-ruje nowoczesne oprogramowanie do obsługi firm. System ISOF jest udostępniany klientom w trybie SaaS lub licencji. Pracuje na platfor-mie Linux i zawiera m.in. takie moduły jak CRM, DMS, Magazyn, Sprzedaż, Logistyka oraz Rachunkowość. http://www.isof.pl

Page 80: Software Developers Journal PL 03/2009

v

Roczna prenumerata

tylko250

Software Developer’s Journal (poprzednio Software 2.0) jest miesięcznikiem głównie dla programistów, którzy li-czą, że dostarczymy im gotowe rozwiązania, oszczędza-jąc im czasu i pracy. Jesteśmy czytani przez tych, któ-rzy chcą być na bieżąco informowani o najnowszych osią-gnięciach w dziedzinie IT i nie chcą, żeby jakiekolwiek istotne wydarzenia umknęły ich uwadze. Aby zadowolić naszych czytelników, prezentujemy zarówno najnowsze rozwiązania, jaki starsze, sprawdzone technologie.

,-

Obsługa prenumeraty 1. Telefon+48 22 877 20 80 2. Fax+48 22 877 20 70 2. [email protected]

3. AdresEuroPress Polska Sp. z o.o.ul. Jana Kazimierza 46/5401-248 Warszawa

UWAGA!

Zmiana danych kontaktowych

Page 81: Software Developers Journal PL 03/2009

v 1

Zamówienie prenumeraty

Imię i nazwisko ...............................................................................

Nazwa firmy.....................................................................................

Dokładny adres ..............................................................................

.........................................................................................................

Telefon ............................................................................................

E–mail .............................................................................................

ID kontrahenta ................................................................................

Numer NIP firmy .............................................................................

Fax (wraz z nr kierunkowym) .........................................................

Prenumerujesz – zyskujeszl oszczędność pieniędzy l szybka dostawa l prezentyl bezpieczna płatność on–line

TytułIlość

nume-rów

Ilość zama-

wianych prenume-

rat

Od numeru pisma

lub mie-siąca

Cena

Software Develope-r’s Journal (1 płyta CD) – dawniej Software 2.0

12 250PLN

□ automatyczne przedłużenie prenumeraty

Prosimy wypełniać czytelnie i przesyłać faksem na numer: 00 48 22 877 20 70lub listownie na adres: EuroPress Polska Sp. z o.o.ul. Jana Kazimierza 46/5401-248 WarszawaPolskaE-Mail: [email protected]

Przyjmujemy też zamównienia telefoniczne:00 48 22 877 20 80

Jeżeli chcesz się dowiedzieć o formach płatności, wejdź na stronę:www.europress.pl lub napisz na e-mail: [email protected]

Zadzwoń+48 22 877 20 80

lubzamów

mailowo!

Page 82: Software Developers Journal PL 03/2009

W NASTĘPNYM NUMERZE SOFTWARE DEVELOPER’S JOURNAL 4/2009 (172)

Numer będzie poświęcony

Rich Internet Application

W magazynie:

• JavaFX

• Silverlight

• Adobe Flex

A także wiele innych interesujących artykułów z dziedziny programowania urządzeń mobilnych, testowania oprogramowania, języków programowania itp.

Redakcja zastrzega sobie możliwość zmiany zawartości pisma.

W sprzedaży w drugiej połowie marca

Page 83: Software Developers Journal PL 03/2009
Page 84: Software Developers Journal PL 03/2009