9/2010 (189)
SPIS TREŚCI
BIBLIOTEKA MIESIĄCA 4 STL w praktyce: Wyszukiwanie. Efektywne wyszukiwanie obiektów przy pomocy biblioteki STL.
Rafał Kocisz Programisto C++! Czy jesteś pewien, że wykorzystujesz w praktyce potencjał swojej wspaniałej biblioteki standardowej? Jeśli chcesz się przekonać, czy Twoja wiedza na temat operacji wyszukiwania oferowanych przez STL jest pełna, to koniecznie przeczytaj ten artykuł!
KLUB TECHNICZNY 14 Technologie Progress OpenEdge – Część 10. Web serwisy w OpenEdge – Pobieranie usług innych dostawców.
Piotr Tucholski Web serwisy są środkiem do szybkiego osiągnięcia integracji i elastyczności aplikacji w zgodzie z architekturą SOA. Oferują wymierne korzyści, jak łatwość użycia i niezależność od języka programowania i platformy systemowej. OpenEdge oferuje możliwości zarówno wykorzystania Web serwisów oferowanych przez innych dostawców, jak i wystawianie własnych usług. W niniejszym odcinku zajmiemy się pierwszym z powyższych aspektów.
PROGRAMOWANIE C++ 22 Stałość Stałość logiczna i stałość fizyczna.
Robert Nowak Oznaczanie obiektów, argumentów, metod i składowych jako stałe zwiększa czytelność kodu oraz dostarcza dodatkowych warunków poprawności.
Phone 7. Dokonano zmiany całej platformy, co zrewolucjonizowało pisanie aplikacji na urządzenia mobilne. Firma Microsoft pokazała także urządzenie prototypowe, które spełniało wszystkie podstawowe wymagania, jakie postawiła firma. Przyjrzyjmy się zatem, co tak naprawdę się zmieniło i co najważniejsze, czy te zmiany pomogą Nam, programistom.
36 Windows Phone – Pierwsze kroki. Prosta aplikacja do Twittera.
Dariusz Gunia 15 lutego 2010 roku, na konferencji Mobile World Congress, Steve Balmer (CEO firmy Microsoft) ogłosił nowy mobilny system operacyjny Windows Phone 7 Series (obecnie oficjalna nazwa brzmi: Windows Phone 7). Bardzo ciekawy jest fakt, że WP7 od strony technicznej nie ma prawie nic wspólnego z poprzednimi wersjami platformy (Windows Mobile), bowiem firma Microsoft postanowiła, że system ten zostanie napisany od podstaw. Producenci smartfonów (np. HTC) zapowiadają pierwsze telefony z WP7 pod koniec bieżącego roku, ale programiści już teraz mogą tworzyć oprogramowanie na nowy system operacyjny.
46 Metody Synchronizacji Bazy Mobilnej SQL Server Compact z SQL Server 2008. Na przykładzie Remote Data Access.
Daniel Dudek Pomimo iż firma Microsoft na konferencji MIX 2010 zaprezentowała nowy system mobilny Windows Phone 7, to oznajmiła jednocześnie, że poprzednia wersja systemu, Windows Mobile 6.5, będzie nadal wspierana. Duża ilość aplikacji mobilnych z sektora biznesowego i/lub przemysłowego czy medycznego stosuje systemy Windows Mobile 5.0, 6.0, 6.1, jak również 6.5. W dzisiejszych czasach nie można sobie wyobrazić aplikacji działającej bez dostępu do bazy danych. W artykule pokażę, jak wykonać kopię bazy firmowej do wersji mobilnej, oraz jak przekazać wprowadzone zmiany z powrotem na serwer firmowy.
PROGRAMOWANIE URZĄDZEŃ PROGRAMOWANIE PYTHON 54 Kurs Pythona. Odcinek 3: Model obiektowy. MOBILNYCH 26 Rozpocznij przygodę z Windows Phone – Zobacz, jak to się robi w technologii Microsoft.
Daniel Dudek Na konferencji MIX 2010 w Las Vegas firma Microsoft zaprezentowała swój nowy system operacyjny Windows
2
Łukasz Langa Dwa pierwsze odcinki miały za zadanie zapoznać nas z podstawowymi cechami języka i środowiska Python. Ostatnią wielką niewiadomą pozostały dla nas klasy. Po ich poznaniu będziemy mogli uznać, że rozumiemy fundamenty Pythona. Do dzieła!
9/2010
SPIS TREŚCI
SPIS TREŚCI
APLIKACJE BIZNESOWE
narzędzia do opracowywania, które współpracuje z .NET Framework 2.0 i kolejnymi wersjami.
58 Zwinna jakość. Strategie testowania i zapewnienia jakości w Agile.
FELIETON
Karolina Zmitrowicz W ostatnich latach zapanowała prawdziwa moda na lekkie metodologie wytwarzania oprogramowania. Szczególnie podejścia zwinne, Agile, takie jak Scrum, zdobywają sobie coraz więcej zwolenników. Szybko, tanio, bez zbędnej biurokracji, działające oprogramowanie na końcu każdej iteracji – ale czy przy zachowaniu wysokiej jakości?
20 Outsourcing IT Czyli polska szansa na sukces.
Z ŻYCIA ITOLOGA
Michał Gronowski Polski rynek IT zmienia się dynamicznie, jednak ciągle ma duże perspektywy rozwoju. Coraz częściej stosowanym rozwiązaniem wsród wielu przedsiębiorstw jest outsourcing IT. Centra usług IT (świadczące usługi zarówno dla polskich, jak i zagranicznych klientów) działają prężnie w naszym kraju. Jako przykład można podać ośrodek AccentureTechnology Solutions w Łodzi.
70 Scrum – Nowa metoda zarządzania projektami.
80 Make IT Green!
Mariusz Chrapko Zajęcia z WF-u – tak średnio wspominam. Rzucanie piłką lekarską o dziwo nawet mi nieźle wychodziło (czułem się jak jakiś Gigant w walce z bogami Olimpu), ale już na przykład palantówka, biegi dookoła szkoły, skoki przez kozła, stanie na rękach, przewroty – mógłbym być bohaterem programu: „O ludziach, którzy przeżyli własną śmierć”. A Gry Zespołowe? A, to co innego, zwłaszcza siatka. Tu się naprawdę realizowałem: dwie drużyny, rywalizacja, wspólny cel… Może dlatego tak lubię Scrum – Grę w Projekt, z dużym zapasem zdrowego rozsądku.
EFEKTYWNOŚĆ PRACY 74 Najprostsze możliwe środowisko – O potędze prostoty.
Michał Bartyzel, Mariusz Sieraczkiewicz Kto nie uwielbia tych wspaniałych chwil, kiedy projekt nabiera kształtu, kolejne funkcjonalności pojawiają się jedna za drugą i nie możemy się nacieszyć wspaniałym, programistycznym dziełem. A diabeł czyha …
PRZEGLĄD NOWOŚCI 78 Generator raportów dla .Net (Visual Studio) FastReport.NET 1.4.
FastReport.Net – generator raportów z wieloma funkcjami dla deweloperów, korzystających z Microsoft Visual Studio 2005 oraz 2010, Delphi Prism lub z dowolnego innego
Roger Zacharczyk Biznes i ekologia? Czemu nie… Również firmy z branży IT mogą wiele zrobić, aby połączyć swoją działalność z ochroną środowiska. Jak? Odpowiedzią jest Green IT, do niedawna tylko moda, a od jakiegoś czasu konieczność, wymóg nakładany na firmy przez Unię Europejską, ale także inne organizacje. Brzmi strasznie? Na szczęście – jak to się mówi – nie taki diabeł straszny jak go malują. Miesięcznik Software Developer’s Journal (12 numerów w roku) jest wydawany przez Software Press Sp. z o.o. SK Redaktor naczelny: Łukasz Łopuszański lukasz.lopuszanski@software.com.pl Skład i łamanie: Tomasz Kostro www.studiopoligraficzne.com Kierownik produkcji: Andrzej Kuca andrzej.kuca@software.com.pl Adres korespondencyjny: Software Press Sp. z o.o. SK, ul. Bokserska 1, 02-682 Warszawa, Polska tel. +48 22 427 36 91, fax +48 22 224 24 59 www.sdjournal.org cooperation@software.com.pl Dział reklamy: adv@software.com.pl 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. Wszystkie znaki firmowe zawarte w piśmie są własności odpowiednich firm. Zostały użyte wyłącznie w celach informacyjnych. Osoby zainteresowane współpracą prosimy o kontakt: cooperation@software.com.pl
BIBLIOTEKA MIESIĄCA
STL w praktyce: Wyszukiwanie Efektywne wyszukiwanie przy pomocy biblioteki STL Programisto C++! Czy jesteś pewien, że wykorzystujesz w praktyce potencjał swojej wspaniałej biblioteki standardowej? Jeśli chcesz się przekonać, czy Twoja wiedza na temat operacji wyszukiwania oferowanych przez STL jest pełna, to koniecznie przeczytaj poniższy artykuł! Dowiesz się:
Powinieneś wiedzieć:
• Jakie klasy sekwencji obsługuje STL; • W jaki sposób STL porównuje ze sobą obiekty; • Jakie opcje wyszukiwania obiektów oferuje STL.
• Solidna znajomość podstaw języka C++; • Solidna znajomość podstaw biblioteki STL.
C
udze chwalicie, swego nie znacie, sami nie wiecie, co posiadacie. Mam wrażenie, że to mądre, polskie przysłowie jak ulał pasuje do niektórych użytkowników biblioteki STL. A przecież Standard Template Library uważana jest w różnych kręgach za jedną z najlepiej zaprojektowanych bibliotek w całej historii informatyki. Jej autorom udało się zrealizować zadanie iście karkołomne: zaprojektować oprogramowanie wielokrotnego użytku, łatwo rozszerzalne i jednocześnie bardzo wydajne. Jak połączyć te wykluczające się cechy oprogramowania? Odpowiedzią jest paradygmat programowania uogólnionego (ang. generic programming), który można stosować dzięki takim właściwościom języka C++ jak wzorce funkcji i klasy szablonowe. Jedną z pułapek czyhających na użytkowników STL jest jej pozorna łatwość. Problem w tym, że wiele dostępnych w sieci samouczków opera się na pobieżnym rozważaniu prostych przykładów użycia tej biblioteki, które rozwodzą się nad tym, jak łatwo można podmienić w kodzie wektor (std::vector) na listę (std:: list). Okazuje się, że rzeczywistość jest o wiele bardziej złożona. Głównym natchnieniem do rozpoczęcia cyklu artykułów traktujących o bibliotece STL stało się dla mnie szkolenie, które przeprowadziłem latem br. dla grupy zawodowych programistów języka C++. Szkolenie zatytułowałem Efektywne wykorzystanie biblioteki STL, zaś jego celem było omówienie zestawu praktycznych
4
idiomów, których stosowanie pozwala korzystać z STL w sposób poprawny i co ważne – efektywny. Idąc na to szkolenie, bałem się trochę, czy aby nie zanudzę moich słuchaczy (spora część prezentowanych materiałów odnosiła się do elementarnej wiedzy na temat STL). Ku mojemu zdziwieniu, materiał, który przygotowałem, okazał się dla większości uczestników bardzo cennym uzupełnieniem ich wiedzy na temat standardowej biblioteki wzorców. Wtedy właśnie wpadłem na pomysł opisania i przedstawienia na łamach kolumny Biblioteka Miesiąca cyklu artykułów zatytułowanego Praktyczny STL, w którym znalazłoby się szczegółowe omówienie podstawowych aspektów korzystania z tej biblioteki. Na początek postanowiłem opisać, jakie mechanizmy wyszukiwania elementów w sekwencjach oferuje nam standardowa biblioteka wzorców. W kolejnych odsłonach cyklu, które pojawiać się będą co jakiś czas na stronicach Software Developer's Journal, omówię również metody sortowania sekwencji i usuwania elementów z sekwencji. Oddzielny artykuł poświęcony będzie kontenerowi std::vector, kolejny zaś – kontenerom asocjacyjnym.
STL: krótka klasyfikacja kontenerów
Pytanie jest proste: jak można wyszukiwać za pomocą biblioteki STL? Okazuje się, iż odpowiedź na to pytanie wcale już taka prosta nie jest. Jeśli jedyne, co przychodzi Ci do głowy, to odpowiedź w stylu: no cóż, można
9/2010
Wyszukiwanie przy pomocy biblioteki STL
zapewne użyć algorytmu std::find()..., to zdecydowanie powinieneś przeczytać poniższy artykuł! Zanim udzielę odpowiedzi na postawione wyżej pytanie, chciałbym przypomnieć kilka podstawowych faktów na temat biblioteki STL. Zacznijmy od przypomnienia sobie sprawy najbardziej elementarnej. Trzy główne filary biblioteki STL to: • • •
kontenery – obiekty, które pozwalają przechowywać inne obiekty, algorytmy – funkcje służące do przetwarzania obiektów przechowywanych w kontenerach, iteratory – obiekty, które pozwalają traktować kontenery jako sekwencje obiektów; stanowią swoisty klej pomiędzy kontenerami i algorytmami.
Ważnym pojęciem w nomenklaturze STL jest sekwencja. Sekwencja to – mówiąc prosto – ciąg obiektów, po którym można się na różne sposoby poruszać. O tym, w jaki sposób to poruszanie się wygląda, decydują klasy iteratorów opisujących sekwencje. Na przykład, jeśli sekwencja opisana jest parą iteratorów wejścia (ang. Input Iterators), to jedyne, na co możemy sobie pozwolić, to przejście przez wszystkie elementy sekwencji, po kolei, bez możliwości żadnych skoków czy powrotów. W kontekście tematu, który nas dziś szczególnie interesuje (tj. wyszukiwanie elementów w sekwencjach), niezwykle istotna jest cecha sekwencji zwana uporządkowaniem. Sprawa jest prosta: sekwencje występujące w STL mogą być nieuporządkowane tudzież uporządkowane (mówiąc innymi słowami: posortowane wedle określonego kryterium). Ciekawe jest to, że taka klasyfikacja sekwencji przenosi się bezpośrednio na jedną z klasyfikacji kontenerów, które można podzielić na dwie kategorie: • •
Listing 1. Czy żądany element występuje w sekwencji nieposortowanej? #include <algorithm> #include <cassert>
#include <iterator> #include <list>
#include <vector> #include <boost/assign/std/list.hpp>
#include <boost/assign/std/vector.hpp> using namespace boost::assign; using namespace std;
template <class Iter, class T>
bool hasValue(Iter first, Iter last, const T& val)
{
}
{
www.sdjournal.org
vector<int> vec;
vec += 1, 2, 3, 4, 5, 6, 7, 8, 9; assert(hasValue(vec.begin(), vec.end(), 3)); assert(hasValue(vec.begin(), vec.end(), 5)); assert(hasValue(vec.begin()+vec.size()/2, vec.end(), 8));
assert(!hasValue(vec.begin(), vec.end(), 13)); assert(!hasValue(vec.begin(), vec.end(), 15)); assert(!hasValue(vec.begin(),
vec.begin()+vec.size()/2, 8));
list<int> lst;
lst += 2, 4, 6, 8, 10; assert(!hasValue(lst.begin(), lst.end(), 3));
Kategoryzacja ta jest bardzo ważna dla każdego użytkownika biblioteki STL. Dlaczego? Otóż dlatego, że pierwsza część odpowiedzi na pytanie jak można wyszukiwać za pomocą biblioteki STL? brzmi: to zależy od tego, czy chcesz przeszukiwać sekwencję uporządkowaną czy nieuporządkowaną. Skoro znamy już pierwszą część odpowiedzi na nasze pytanie, warto poszukać kolejnej. Okazuje się, że będzie ona... kolejnym pytaniem. W tym miejscu moż-
return found != last;
int main()
kontenery sekwencyjne (std::vector, std::list, std::deque i std::string) – ich zawartość domyślnie nie jest uporządkowana; kontenery asocjacyjne (std::set, std::multiset, std::map i std::multimap) – ich zawartość zawsze jest uporządkowana.
Co to znaczy „szukać”?
Iter found = find(first, last, val);
list<int>::const_iterator it(lst.begin()); advance(it, lst.size()/2);
assert(hasValue<list<int>::const_
iterator>(lst.begin(), it, 4));
}
return 0;
5
BIBLIOTEKA MIESIĄCA
na pokusić się o stwierdzenie, że efektywne korzystanie z biblioteki STL wymaga ciągłego (i umiejętnego) stawiania sobie pytań i podejmowaniu na ich podstawie (właściwych) decyzji. Jakie więc pytanie (tudzież pytania) powinniśmy postawić sobie, aby znaleźć odpowiednią metodę wyszukiwania obiektów w sekwencjach? Odpowiedź kryje się w zrozumieniu istoty procesu wyszukiwania. No więc, co to znaczy: szukać? W kontekście STL przez szukanie rozumiemy znajdowanie odpowiedzi na następujące pytania: • •
Czy żądany element występuje w ciągu? Czy żądany element występuje w ciągu, a jeśli tak, to gdzie znajduje się jego pierwsze wystąpienie?
• • • •
Gdzie znajduje się pierwszy obiekt, którego wartość nie jest poprzednikiem żądanego elementu? Gdzie znajduje się pierwszy obiekt, którego wartość jest następnikiem żądanego elementu? Jak wiele obiektów w sekwencji posiada żądaną wartość? Gdzie znajdują się elementy o żądanej wartości?
Jest tego trochę, prawda? O ile dwa pierwsze i dwa ostatnie pytania wydają się dosyć oczywiste, o tyle pytanie trzecie i czwarte wydają się na pierwszy rzut oka nieco egzotyczne... Wartość, która nie jest poprzednikiem? O co tutaj chodzi? Nie martw się! Pojęcie istoty tych dwóch środkowych pytań wymaga zro-
Listing 2. Czy żądany element występuje w sekwencji posortowanej? #include <algorithm> #include <cassert>
("may",
#include <map>
("september", 30)("october",
#include <iterator> #include <set>
31)("august",
("november",
#include <string>
30) 31) 31)
30)("december", 31);
map<string,int>::const_iterator it(months.begin());
#include <vector>
advance(it, months.size()/2);
#include <boost/assign/list_inserter.hpp> #include <boost/assign/std/vector.hpp>
map<string,int>::value_type val("september", 30);
using namespace boost::assign;
bool b1 = binary_search(months.begin(),
using namespace std;
assert(b1);
int main()
{
vector<int> vec;
bool b2 = binary_search<map<string,int>::const_
iterator>(
sort(vec.begin(), vec.end());
months.begin(), it, val);
assert(!b2);
assert(binary_search(vec.begin(), vec.end(), 3));
bool b3 = binary_search<map<string,int>::const_
assert(binary_search(vec.begin(), vec.end(), 5)); assert(binary_search(vec.begin()+vec.size()/2,
iterator>(
vec.end(), 8));
it, months.end(), val);
assert(b3);
assert(!binary_search(vec.begin(), vec.end(),
set<int> ints;
13));
assert(!binary_search(vec.begin(), vec.end(),
insert(ints)(1)(2)(2)(3)(3)(3);
15));
bool b4 = binary_search(ints.begin(), ints.end(),
assert(!binary_search(vec.begin(),
vec.begin()+vec.size()/2, 8));
assert(b4);
map<string,int> months; insert(months)
("january", ("march",
months.end(), val);
assert(months.count("september") > 0);
vec += 2, 1, 4, 3, 6, 5, 8, 7, 9;
6
31)("june",
("july",
assert(ints.find(2) != ints.end());
31)("february", 28) 31)("april",
2);
30)
}
return 0;
9/2010
Wyszukiwanie przy pomocy biblioteki STL
zumienia różnicy pomiędzy równością i równoważnością – tematem tym zajmiemy się o jeden podpunkt dalej. Teraz rozważmy, jak przy pomocy STL znaleźć odpowiedź na pierwsze pytanie:
Listing 3. Implementacja standardowego algorytmu std:: �nd() template<class _InIt, class _Ty> inline
Czy żądany element występuje w ciągu?
Okazuje się, że STL pozwala to fundamentalne zadanie związane z wyszukiwaniem rozwiązać na cztery sposoby. Wszystko zależy od tego, z jakim rodzajem sekwencji mamy do czynienia. Tak jak ustaliliśmy wcześniej, w pierwszej kolejności należy odpowiedzieć sobie na pytanie: czy sekwencja, którą chcę przeszukać, jest uporządkowana, czy nie. W drugim przypadku sprawa jest prosta: odpowiedź na postawione pytanie da nam algorytm std::find(). Algorytm ten działa w ten sposób, że przekazujemy do niego sekwencję opisaną parą iteratorów, oraz element, który chcielibyśmy wyszukać. std::find() zwraca iterator; jeśli jest on różny od znacznika końca sekwencji, to znaczy, że poszukiwany element występuje w ciągu. W tym miejscu przypominam, że sekwencja w STL opisana jest przez dwa iteratory, pierwszy z nich wskazuje na początkowy element sekwencji, zaś drugi, na element znajdujący się za ostatnim elementem sekwencji. Przykład użycia algorytmu std::find() pokazany jest na Listingu 1. Sercem pokazanego tam przykładu jest szablon funkcji hasElement(), który zwraca logiczną wartość true w sytuacji, kiedy przekazana do niego sekwencja zawiera określony element. Szablon ten jest wykorzystany do sprawdzenia, czy określone elementy znajdują się (lub nie) w wektorze oraz w liście. Analizując ten Listing, warto zwrócić uwagę na następujące rzeczy: •
•
•
Sekwencja niekoniecznie musi opisywać cały kontener, w kilku przypadkach badałem wystąpienie elementu w pierwszej bądź w drugiej połowie ciągu. W przypadku listy nie mogłem stworzyć iteratora wskazującego na środkowy element kontenera, podobnie jak w przypadku wektora (ze względu na to, że lista nie oferuje iteratorów o bezpośrednim dostępie); aby uzyskać zamierzony efekt, musiałem użyć funkcji std::advance(). W celu uproszczenia (i skrócenia) kodu odpowiedzialnego za wstawianie testowych wartości do kontenerów użyłem biblioteki Boost.Assign.
Co zrobić w sytuacji, gdy mamy do czynienia z sekwencją uporządkowaną? W tym przypadku mamy do rozważenia następujące opcje: •
Jeśli mamy do czynienia z którymś z kontenerów asocjacyjnych i chcemy przeszukać całą ich zawartość, to należy użyć dedykowanych funkcji składowych dostępnych w tych kontenerach.
www.sdjournal.org
_InIt _Find(_InIt _First, _InIt _Last, const _Ty& {
_Val)
// find first matching _Val
_DEBUG_RANGE(_First, _Last);
for (; _First != _Last; ++_First) if (*_First == _Val) break;
return (_First);
}
•
W przypadku kontenerów std::set i std::map należy skorzystać z metody count(), zaś w przypadku std::multiset i std::multimap – z metody find(). Jeśli mamy do czynienia z uporządkowaną sekwencją, która jest umieszczona w kontenerze sekwencyjnym (np. w posortowanym wektorze), tudzież z jakichś względów chcemy przeszukać jedynie część zawartości kontenera asocjacyjnego, to powinniśmy skorzystać z algorytmu std::binary _ search().
Na Listingu 2 przedstawione są poszczególne opcje z wymienionych powyżej opcji wyszukiwania. Wszystko to, co opisałem wyżej, jest niewątpliwie bardzo przydatne. Do momentu, kiedy zdecydujemy się na to, aby zastosować jakieś własne kryterium wyszukiwania. Co wtedy? Okazuje się, że na niedoświadczonych użytkowników biblioteki STL czyha tutaj kolejna pułapka. Aby jej uniknąć, należy zrozumieć subtelną różnicę pomiędzy pojęciami równość (ang. equality) i równoważność (ang. equivalence). Zanim rozważymy kolejne scenariusze wyszukiwania obiektów w sekwencjach STL, zatrzymajmy się na chwilę w celu analizy znaczenia tych pojęć.
Równość kontra równoważność
Aby zrozumieć, co oznacza pojęcie równości, rozważmy, jak zaimplementowany jest algorytm std::find(). Na Listingu 3 przedstawiona jest implementacja tej funkcji wzięta z biblioteki standardowej dołączonej w kompilatorze MSVC++ 2008 Professional. To, na co warto zwrócić uwagę, to warunek w pętli iterującej po sekwencji: if (*_First == _Val)
Widać tutaj, że algorytm std::find() używa operatora równości (operator==()) w celu porównania zawartości obiektu, na który wskazuje iterator, oraz poszu-
7
BIBLIOTEKA MIESIĄCA
kiwanego obiektu _ Val. W tym przypadku mamy do czynienia z pojęciem równości (ang. equality). Porównywanie obiektów za pomocą operatora równości to standardowy sposób, którego używają wszystkie algorytmy przeznaczone do wyszukiwania elementów w sekwencjach nieposortowanych, aby odpowiedzieć sobie na pytania: czy te dwa obiekty są takie same? Proste i logiczne. Spróbujmy przećwiczyć ten scenariusz w praktyce. Rozważmy następujący scenariusz: stworzyliśmy klasę Employee, reprezentującą informacje na temat pracownika w dużym systemie informatycznym. Na Listingu 4 przedstawiony jest wycinek definicji tej klasy. To, co widać już na pierwszy rzut oka, to fakt, że nasza klasa jest dość skomplikowaną strukturą danych. W sytuacji gdy potrzebowalibyśmy wyszukiwać obiekty
tej klasy w kontenerach, to prawie na pewno nie chcemy robić tego przy pomocy wygenerowanego automatycznie operatora równości, który porównuje ze sobą wszystkie składowe badanych obiektów. W tej sytuacji należy oczywiście zdefiniować własny operator równości dla klasy Employee. Przykład implementacji takiego operatora pokazałem na Listingu 5. Analizując kod źródłowy przedstawiony na tym Listingu, można się przekonać, że porównujemy jedynie unikalne identyfikatory obiektów. Zaimplementowanie testowego przypadku użycia powyższej klasy, weryfikującego działanie wspomnianego operatora równości, pozostawiam jako zadanie dla dociekliwych Czytelników. Teraz pytanie za sto punktów: co w sytuacji, gdy obiekty omówionej wyżej klasy Employee umieścimy w jednym z kontenerów asocjacyjnych? Czy przy wy-
Listing 4. Fragment de�nicji klasy Employee Listing 6. Wyszukiwanie z predykatem
#include <string> #include <vector>
#include <boost/shared_ptr.hpp> class Person;
#include <algorithm> #include <cassert> #include <string> #include <vector>
typedef boost::shared_ptr<Person> PersonPtr; class Employee
#include <boost/assign/std/vector.hpp> using namespace boost::assign; using namespace std;
{
public:
struct IsMaleName
// ... int uid() const { return m_uid; };
{
bool operator()(const string& name)
{
// ... private:
{
int m_uid;
}
std::string m_firstName; std::string m_lastName;
std::vector<std::string> m_secondNames; // ...
};
std::vector<PersonPtr> m_children;
};
{
8
return false;
vector<string> names;
names += "Ola", "Monika", "Agnieszka", "Piotr"; vector<string>::const_iterator found
= find_if(names.begin(), names.end(),
bool operator==(const Employee& employee1, const
}
}
return name[name.length()-1] != 'a';
int main()
Listing 5. Implementacja operatora równości dla klasy Employee
{
if (!name.empty())
IsMaleName());
Employee& employee2)
return employee1.uid() == employee2.uid();
assert(found != names.end()); }
assert(*found == "Piotr");
9/2010
Wyszukiwanie przy pomocy biblioteki STL
szukiwaniu tych obiektów ich zachowanie będzie takie jak sobie założyliśmy, tj. czy obiekty będą porównywane według identyfikatorów? Otóż jeśli (zgodnie z wytycznymi podanymi wyżej) skorzystamy z wbudowanej funkcji kontenera (np. std::set::count()), to wynik będzie inny od tego, czego oczekujemy. Różnica ta wynika z faktu, że algorytmy operujące na sekwencjach posortowanych (a zawartość kontenerów asocjacyjnych zawsze jest posortowana!) używają zupełnie innej metody porównywania obiektów. Metoda ta, zwana równoważnością (ang. equivalence), zakłada porównywanie dwóch obiektów na zasadzie badania ich relatywnych pozycji w uporządkowanej sekwencji. Brzmi skomplikowanie? Na szczęście, jest to stosunkowo proste. Wyobraźmy sobie, że mamy sekwencję uporządkowanych obiektów, przy czym porządek w tej sekwencji zdefiniowany jest za pomocą operatora mniejszości (<). Chcąc sprawdzić, czy dwa elementy (e1, e2) w tej sekwencji są równoważne, należy sprawdzić następujący warunek: !(e1 < e2) && !(e2 < e1).
Powyższy warunek można zinterpretować następująco: jeśli obiekt e1 nie poprzedza w sekwencji elementu e2 i jednocześnie e2 nie poprzedza elementu e1, znaczy to, że ich relatywna pozycja w posortowanym ciągu jest taka sama (tj. gdybyśmy wstawiali te dwa obiekty do ciągu, trafiłyby w to samo miejsce), ergo – obiekty te są równoważne. W przypadku STL do badania równoważności obiektów zamiast funkcji operator<() stosuje się bardziej ogólny predykat (obiekt funkcyjny) key_comp(), który zwraca wartość logiczną: prawdę, jeśli pierwszy z elementów przekazanych do tego predykatu poprzedza element drugi, fałsz – gdy jest odwrotnie. Przy takim założeniu wspomniany wcześniej warunek wygląda następująco:
:binary_serach(),
std::lower_bound(), std::upper_ również opierają się na równoważności obiektów. Algorytmy te jako dodatkowy argument przyjmują predykat, określający kryterium uporządkowania sekwencji. Kiedy mówimy o porównywaniu obiektów, to jest jeszcze jeden scenariusz, który warto rozważyć. Otóż w przypadku przeszukiwania sekwencji uporządkowanych może wystąpić sytuacja, kiedy nie chcemy, aby porównywanie obiektów odbywało się za pomocą operatora równości. Zamiast tego wolelibyśmy przekazać do algorytmu własny warunek, który określi kryterium wyszukiwania. Odpowiedzią są specjalne wersje algorytmów standardowych, które jako dodatkowy argument przyjmują predykat. Nazwy tych algorytmów charakteryzują się postfiksem _if, np. std::find_if(). Wyobraźmy sobie, że mamy sekwencję imion i musimy w niej znaleźć pierwsze imię męskie. W przypadku imion polskich możemy zastosować prosty test polegający na sprawdzeniu, czy ostatnia litera imienia jest różna od a. Na Listingu 6 pokazano, jak można zaimplementować coś takiego. bound())
Obiekcie, gdzie jesteś?
Teraz, kiedy jesteśmy w pełni świadomi tego, jak STL porównuje obiekty (równość vs. równoważność), możemy kontynuować przegląd metod ich wyszukiwania. Kolejny scenariusz, który rozważymy, to poszukiwanie odpowiedzi na pytanie: czy żądany element występuje w ciągu, a jeśli tak, to gdzie znajduje się jego pierwsze wystąpienie? W tym przypadku mamy do rozważenia następujące opcje: Listing 7. Użycie algorytmu std::�nd w celu odnalezienia określonej wartości w sekwencji nieposortowanej vector<int> vec; // Wstaw wartości do vec.
!c.key_comp()(e1, e2) && !c.key_comp()(e2, e1),
przy czym c to kontener asocjacyjny, który przechowuje predykat. W przypadku standardowych kontenerów asocjacyjnych domyślnie stosowany jest standardowy predykat std::less(), który dokonuje porównania obiektów za pomocą operatora mniejszości. Dociekliwym Czytelnikom proponuję stworzyć następujący zbiór: std::set<int, std::greater<int> > s;
wypełnić go kilkoma losowymi wartościami i sprawdzić, w jaki sposób będą one uporządkowane. Należy pamiętać również o tym, że globalne algorytmy przeszukujące sekwencje posortowane (np. std:
www.sdjournal.org
vector<int>::iterator found
= find(vec.begin(), vec.end(), value);
if (found != vec.end())
{
// Szukana wartość (value) została znaleziona, // wskazuje na nią iterator found.
}
else
{
// Szukana wartość (value) nie występuje // w sekwencji.
}
9
BIBLIOTEKA MIESIĄCA
•
•
•
•
Jeśli przeszukujemy sekwencję nieposortowaną, to należy skorzystać z algorytmu std::find(). Algorytm ten, jak już wspominałem, zwraca iterator, który wskazuje bądź to na poszukiwany element (a bardziej ściśle: na pierwsze wystąpienie tego elementu), bądź to na znacznik końca sekwencji. Użycie tej metody w omawianym tu kontekście (wraz z odpowiednimi komentarzami) pokazane jest na Listingu 7. Jeśli przeszukujemy sekwencję posortowaną, umieszczoną w kontenerze sekwencyjnym (np. posortowany wektor lub listę), to należy skorzystać z algorytmu std::equal _ range(), który zwraca parę iteratorów opisujących zakres równoważnych elementów (zauważ, że nazwa equal w nazwie tego algorytmy może być nieco myląca :)). Na Listingu 8 przedstawione jest użycie tego algorytmu. Jeśli przeszukujemy zbiór (std::set) bądź mapę (std::map), to należy skorzystać z ich składowych funkcji find(). Mechanika użycia tej funkcji jest identyczna jak w przypadku globalnego algorytmu std: :find(), należy jedynie pamiętać, że find() jako składowa używa do wyszukiwania predykatu równoważności zdefiniowanego dla danego kontenera. Jeśli przeszukujemy wielozbiór (std::multiset) bądź wielomapę (std::multimap), to należy użyć składowej funkcji find(), bądź – jako alternatywy – składowej funkcji lower _ bound(). Na temat tej ostatniej opowiem bardziej szczegółowo w kolejnym podpunkcie niniejszego artykułu.
Rola funkcji lower_bound() i upper_bound()
Standardowy algorytm std::lower_bound() działa następująco: zwraca iterator, który wskazuje na pierwszy poszukiwany element (jeśli takowy udało się znaleźć), bądź wskazujący na miejsce, w którym poszukiwany element powinien się znaleźć. Analogicznie działa funkcja std::upper_bound(), tyle że szuka ona ostatniego równoważnego elementu w sekwencji. Mówiąc inaczej, funkcje te odpowiadają na pytania: gdzie znajduje się pierwszy obiekt, którego wartość nie jest poprzednikiem żądanego elementu? oraz gdzie znajduje się pierwszy obiekt, którego wartość jest następnikiem żądanego elementu? Skąd jednak mamy wiedzieć, czy zwrócony iterator wskazuje na element znaleziony, czy na miejsce, w którym powinien się on znaleźć? W tym celu musimy wykonać porównanie obiektów. Wielu programistów robi w tym miejscu poważny błąd, używając w tym celu operatora równości. A przecież zarówno std::lower_bound() jak i std::upper_bound() operują na ciągach posortowanych, więc do porównywania obiektów znajdujących się w tych ciągach należy użyć testu na równoważność! O tym, jak to wykonać w praktyce, już za moment. Najpierw jednak zastanówmy się nad jakimś
10
sensownym przypadkiem użycia dla tego typu algorytmów. Ciekawy use case, który pokazuje przydatność funkcji lower_bound() to wstawianie i uaktualnianie elementów w standardowym kontenerze std::map. Powszechnie wiadomo, że wstawiać elementy do mapy można następująco: m["test"] =13;
Co jednak w przypadku, gdy klucz "test" wcześniej już występował w kontenerze m? Jeśli taka sytuacja występuje, to mamy problem z wydajnością, gdyż przeładowana funkcja operator[] w kontenerze std: :map jest bardzo nieoptymalna pod względem uaktualniania wartości istniejących już w nim elementów. O wiele lepszym scenariuszem byłoby sprawdzenie, czy szukany element już w mapie występuje, jeśli tak – uaktualnienie jego wartości, a jeśli nie – wstawienie do kontenera nowego elementu za pomocą składowej funkcji insert(). I tutaj z pomocą może przyjść nam algorytm lower _ bound(). Na Listingu 9 przedstawiona jest definicja szablonu funkcji insertOrUpdate(), która realizuje opisany wyżej scenariusz. Listing 8. Użycie algorytmu std::equal_range w celu odnalezienia określonej wartości w ciągu posortowanym vector<string> names; // Wstaw wartości do names. sort(names.begin(), names.end()); typedef vector<string>::const_iterator Iter; typedef std::pair<Iter, Iter> IterPair;
IterPair range = std::equal_range(names.begin(), names.end(), value); if (range.first != range.second)
{
// Odnaleziony zakres jest niepusty. // range.first wskazuje na pierwszy // element tego zakresu, range.second // - na ostatni.
}
else
{
// Odnaleziony zakres jest pusty. // Szukany element nie występuje // w sekwencji.
}
9/2010
Wyszukiwanie przy pomocy biblioteki STL
Rozważmy implementację tego szablonu funkcji. Przyjmuje on trzy parametry (będące przy okazji parametrami szablonowymi): mapę, klucz i wartość. Aby pozostać w zgodności z konwencją STL (podobnie jak funkcje z rodziny insert()), nasz szablon zwraca iterator wskazujący na miejsce, w którym nowy element został wstawiony\uaktualniony. W pierwszej kolejności przy pomocy składowej funkcji lower_bound() z przekazanej mapy pobieramy iterator wskazujący na interesujące nas miejsce. Proszę zwrócić uwagę, że lower_bound() pasuje wręcz idealnie do naszych potrzeb. W sytuacji gdy zwrócony iterator pokazuje na poszukiwany element, wiemy, że operacja wstawienia nie jest potrzebna. Aby się o tym przekonać, wykonujemy połowę testu na równoważność (połowa wystarczy, gdyż lower_bound() gwarantuje to, iż wyszukany obiekt będzie znajdował się z prawej strony wzorcowego elementu w przeszukiwanej sekwencji; w przypadku gdybyśmy korzystali z algorytmu upper_bound(), należałoby wykonać drugą część testu):
Samo uaktualnienie jest bardzo proste:
!(map.key_comp()(key, found->first))
Rozważmy kolejny scenariusz wyszukiwania: zliczanie wystąpień obiektów w kontenerze. Oto jakie mamy opcje:
Listing 9. Użycie algorytmu lower_bound() w celu efektywnego wstawiania\uaktualniania elementów w mapie template <class Map_, class Key_, class Value_> typename Map_::iterator insertOrUpdate(
gdyż wiemy, iż iterator found w tym przypadku wskazuje na interesujący nas element. Druga gałąź warunku obsługuje scenariusz, kiedy poszukiwany element nie występuje w mapie. W tym przypadku wstawiamy go za pomocą funkcji insert(): map.insert(found, Map_::value_type(key, value));
Voila! Dociekliwych Czytelników gorąco zachęcam do tego, aby przy pomocy debuggera, krok po kroku przeanalizować, jak działa przedstawiona funkcja w różnych przypadkach użycia. Jako ciekawe zadanie polecam też Czytelnikom zaimplementowanie podobnej funkcji, tyle że operującej na posortowanym wektorze.
Jak wiele obiektów w sekwencji posiada żądaną wartość?
Listing 10. Zliczanie elementów w posortowanej sekwencji umieszczonej w kontenerze sekwencyjnym
Map_& map,
#include <algorithm>
const Value_& value)
#include <deque>
const Key_& key,
{
found->second = value;
Map_::iterator found = map.lower_bound(key); if ((found != map.end()) &&
{
}
!(map.key_comp()(key, found->first))) found->second = value; return found;
#include <cassert>
#include <iterator>
#include <boost/assign/std/deque.hpp> using namespace boost::assign; using namespace std; int main()
{
else
{
}
}
std::deque<int> deq;
deq += 7, 1, 9, 2, 8, 3, 7, 4, 5, 7; sort(deq.begin(), deq.end());
return map.insert(
typedef deque<int>::iterator Iter;
found, Map_::value_type(key, value));
typedef pair<Iter, Iter> IterPair;
IterPair range = equal_range(deq.begin(), deq.end(), 7);
// ... insertOrUpdate(m, "test1", 1);
assert(distance(range.first, range.second) == 3);
insertOrUpdate(m, "test2", 2); insertOrUpdate(m, "test1", 3);
www.sdjournal.org
}
return 0;
11
BIBLIOTEKA MIESIĄCA
• • •
Jeśli przeszukujemy sekwencję nieposortowaną, to należy skorzystać z algorytmu std::count(). Jeśli przeszukujemy kontener asocjacyjny, to należy skorzystać ze składowej funkcji count(). Jeśli przeszukujemy posortowaną sekwencję umieszczoną w kontenerze sekwencyjnym, to należy użyć algorytmy std::equal _ range(), a następnie funkcji std::distance().
Pierwsze dwa przypadki są banalnie proste. Czy to jako algorytm globalny, czy jako funkcja składowa, count() zwraca liczbę elementów występujących w kontenerze. Kropka! W przypadku posortowanej sekwencji umieszczonej w kontenerze sekwencyjnym sprawa jest odrobinkę bardziej skomplikowana (patrz: Listing 10). W tym przypadku musimy najpierw znaleźć zakres równoważnych elementów za pomocą algorytmu std::equal_range(). Następnie musimy je policzyć. Pojawia się w tym miejscu pytanie: jak mając dwa iteratory, najszybciej obliczyć długość sekwencji, którą one opisują? Odpowiedzią jest standardowa funkcja std::distance().
Listing 11. Wyszukiwanie wszystkich elementów w sekwencji nieposortowanej #include <algorithm> #include <cassert>
#include <boost/assign/std/vector.hpp> using namespace boost::assign; using namespace std; int main()
{
vec += 7, 1, 9, 2, 8, 3, 7, 4, 5, 7; int value = 7;
std::vector<int>::iterator found
= find(vec.begin(), vec.end(), value);
std::vector<int>::iterator end = vec.end();
while (found != end)
Gdzie znajdują się elementy o żądanej wartości?
Pozostał nam do rozważania ostatni scenariusz wyszukiwania: znajdowanie w sekwencji wszystkich elementów o równej bądź równoważnej wartości. Ten scenariusz należy rozważyć pod kątem dwóch opcji: przeszukiwanie sekwencji posortowanej i nieposortowanej. W pierwszym przypadku wszystkie równoważne elementy położone są obok siebie, więc oczywistym sposobem na rozwiązanie tego problemu jest użycie algorytmu equal_range(), który zwróci nam parę iteratorów wskazujących na interesujący nas zakres. Jedyne, o czym należy pamiętać, to to, że w przypadku kontenerów asocjacyjnych wypada użyć składowej, a nie globalnej wersji equal_range(). Jest to zresztą generalna zasada dotycząca efektywnego korzystania z biblioteki STL: jeśli masz do wyboru funkcję globalną i składową o tej samej nazwie, to zawsze używaj tej drugiej. Przykład zastosowania funkcji equal_range() prezentowany był już kilkukrotnie na listingach dołączonych do niniejszego artykułu (np. na Listingu 10), więc nie będę go po raz kolejny powtarzał. Sprawa jest trochę bardziej złożona w przypadku sekwencji nieposortowanej. Tutaj interesujące nas elementy mogą być rozrzucone dowolnie po całym badanym zakresie. Jedyne, co nam pozostaje, to funkcja std::find() wywoływana w pętli. Przykład zastosowania takiej techniki pokazany jest na Listingu 11. Analizując ten przykład, warto zwrócić uwagę na linijki: ++found;
12
vector<int> vec;
{
// Tutaj przetwarzaj znaleziony obiekt, np: *found *= 2; // Przejdź do następnego elementu. ++found; // Rozpocznij kolejną iterację wyszukiwania.
}
found = find(found, vec.end(), value);
assert(vec[0] == 14); assert(vec[6] == 14); assert(vec[9] == 14); return 0;
}
oraz found = find(found, vec.end(), value);
Pierwsza z nich przesuwa iterator wskazujący na znaleziony obiekt o jeden krok do przodu. Gdybyśmy zapomnieli o tym przesunięciu, to pętla mogłaby kręcić się w nieskończoność (akurat w naszym przykładzie tak by się nie stało, bo wcześniej zmodyfikowałem wartość znalezionego elementu; gdyby jednak wartość ta pozostała niezmodyfikowana i iterator nie byłyby przesunięty do przodu, to mielibyśmy poważny problem).
9/2010
Wyszukiwanie przy pomocy biblioteki STL
W drugiej linijce pokazane jest, jak uaktualniony iterator found zostaje użyty jako nowy początek zakresu przeszukiwania. Podsumowując: jeśli musisz przeglądać sekwencję nieuporządkowaną, tak jak to pokazałem powyżej – uważaj! Łatwo zrobić tutaj subtelny błąd, który może spowodować, że pół roku po zakończeniu projektu Twoje oprogramowanie wróci do Ciebie z reklamacją.
Podsumowanie
Tak oto drogi Czytelniku przebrnąłeś przez cały ocean opcji wyszukiwania, który oferuje STL. Przy okazji miałeś okazję przypomnieć sobie kilka fundamentalnych zasad porównywania obiektów, które stosuje ta biblioteka, a bez zrozumienia których trudno korzystać z niej świadomie i efektywnie. Nie pozostaje Ci nic jak tylko wykorzystać nową wiedzę w praktyce. Kiedy już będziesz to czynił, pamiętaj o ważnej zasadzie: korzystanie z STL polega na ciągłym zadawaniu sobie pytań i podejmowaniu decyzji. Mam nadzieję, że mój artykuł pomoże Ci stawiać sobie odpowiednie pytania związane z wyszukiwaniem elementów w sekwencjach STL i – co najważniejsze – szybko i pewnie znajdować na nie właściwe odpowiedzi! Kończąc niniejszy artykuł chciałbym podziękować wszystkim uczestnikom mojego szkolenia (tego o któ-
rym wspominałem we wstępie) – ucząc Was sam również nauczyłem się wielu nowych rzeczy, a Wasze uwagi i pytania były dla mnie bardzo cennymi wskazówkami przy pisaniu niniejszego artykułu. Cykl artykułów STL w praktyce chciałbym zadedykować Scottowi Meyersowi, którego wspaniałe książki z cyklu Effective są dla mnie nieustannym źródłem natchnienia przy pracy z językiem C++. Dzięki Scott! W kolejnym artykule z cyklu STL w praktyce omówię mechanizmy sortowania oferowane przez standardową bibliotekę wzorców. Z góry zapraszam do jego lektury!
RAFAŁ KOCISZ Pracuje na stanowisku Kierownika ds. Badań i Rozwoju w �rmie Gamelion, wchodzącej w skład Grupy BLStream. Rafał specjalizuje się w technologiach związanych z produkcją oprogramowania na platformy mobilne, ze szczególnym naciskiem na tworzenie gier. Grupa BLStream powstała by efektywniej wykorzystywać potencjał dwóch, szybko rozwijających się producentów oprogramowania – BLStream i Gamelion. Firmy wchodzące w skład grupy specjalizują się w wytwarzaniu oprogramowania dla klientów korporacyjnych, w rozwiązaniach mobilnych oraz produkcji i testowaniu gier. Kontakt z autorem: rafal.kocisz@game-lion.com
Reklama
www.sdjournal.org
13
KLUB TECHNICZNY
Technologie Progress OpenEdge Część 10. Web serwisy w OpenEdge – Pobieranie usług innych dostawców Web serwisy są środkiem do szybkiego osiągnięcia integracji i elastyczności aplikacji w zgodzie z architekturą SOA. Oferują wymierne korzyści, jak łatwość użycia i niezależność od języka programowania i platformy systemowej. OpenEdge oferuje możliwości zarówno wykorzystania Web serwisów oferowanych przez innych dostawców, jak i wystawianie własnych usług. W niniejszym odcinku zajmiemy się pierwszym z powyższych aspektów. Dowiesz się:
Powinieneś wiedzieć:
• Wykorzystywaniu Web serwisów w aplikacjach ABL z punktu widzenia odbiorcy; • Jak analizować dane z pliku WSDL.
• Ogólną koncepcję Web serwisów.
W
eb serwisy można zdefiniować jako niezależne moduły dostępne przez Internet poprzez standardowe protokoły. Web serwis jest rodzajem pozbawionej interfejsu użytkownika procedury, wykonującej jednostkową pracę, np. przesłanie zamówienia, podanie kursów walut itd. Serwisy te tworzy się w oparciu o standardy tak, aby każda aplikacja, bez względu na język programowania i platformę, na której jest uruchomiona, a spełniająca te standardy, mogła je wykorzystywać lub dostarczać. Niniejszy artykuł dotyczy wykorzystywania Web serwisów w aplikacjach OpenEdge. Tworzeniem i wystawianiem własnych usług zajmiemy się w następnym odcinku. Web serwisy mają niewątpliwe zalety, do których należy zaliczyć: • • •
14
Oszczędność czasu na implementację i zarządzanie usługą (jest ona dostarczana przez innego dostawcę. Poprawianie wydajności wystawianych Web serwisów przez dostawców wyspecjalizowanych w danej technologii. Integracja systemów aplikacyjnych wewnątrz
przedsiębiorstwa napisanych w odmiennych technologiach. Wadą jest konieczność kontrolowania działania samych usług, a w szczególności ich sygnatur (typów i rodzajów przesyłanych parametrów), które mogą być zmienione bez powiadomienia. Dlatego gdy Web serwisy nie są stosowane w obrębie jednej korporacji, rzadko są związane z funkcjonalnością krytyczną. Innym problemem jest osiągnięcie odpowiedniej wydajność i trudności związane z transakcyjnością.
Model Web serwisu
Aby zastosować Web serwisy, należy dobrze zrozumieć ich model koncepcyjny. Oparte są one na standardach stworzonych przez organizację World Wide Web Consortium (W3C). Web serwisy można obsługiwać jako dostawca (provider) lub odbiorca (consumer). Do korzystania z usług konieczna jest dokładna znajomość ich funkcjonalności. Od dostawcy możemy wymagać wiarygodności i rzetelności wystawianych usług. Powinien on także dostarczyć niezbędnych informacji, aby odbiorca mógł dokładnie poznać funkcjonalność Web serwisu. Standardowym me-
9/2010
Technologie Progress OpenEdge
chanizmem opisu takich informacji jest WSDL (Web Services Description Language ). WSDL definiuje wszystkie operacje (procedury, funkcje), jakie odbiorca może wykorzystać. Grupa operacji określana jest jako portType. Każda operacja ma określoną nazwę, parametry wejścia-wyjścia, typ komunikatu błędów w przypadku ich wystąpienia zwany SOAP Fault. Wymiana informacji pomiędzy dostawcą i odbiorcą serwisu odbywa się przy wykorzystaniu komunikatów w formacie SOAP (Simple Object Access Protocol), a warstwą transportową jest HTTP i HTTPS (Rysunek 1). Prześledźmy podstawowe kroki w celu wykorzystania Web serwisu w aplikacji (Rysunek 2). Po pierwsze, należy przyłączyć się do serwera, na którym działa odpowiednia usługa i pobrać dokument WSDL (1). Na jego podstawie można zdefiniować we własnej aplikacji kod dla wywołania określonych operacji Web serwisu: nazwę grupy, nazwę operacji, parametry itd. (2). Teraz można wywołać żądaną operację (3), a po jej zakończeniu odłączyć się od serwera i zwolnić zaalokowane wcześniej obiekty (4).
WSDL
Rozpoczynając fazę dewelopmentu, najistotniejszą sprawą jest więc odczyt informacji z pliku WSDL. W tym celu trzeba pozyskać od dostawcy składnię URL z lokalizacją tego pliku np.: http://www.mysite.org/2010/ myws1.wsdl czy file:///E:wservices\ wsdl\myws1.wsdl. Plik WSDL jest typu XML i składa się z następujących sekcji – głównych znaczników (Rysunek 3): • • • •
• •
•
wsdl:service – definicja Web serwisu: porty, których użytkownicy powinni użyć, z jakich powiązań te porty korzystają.
Plik WSDL zawiera informacje neutralne z punktu widzenia platformy, na której działa. Dostawca nie wie także, w jakiej technologii jest napisana aplikacja, która będzie korzystać z Web serwisu. Dlatego do wykorzystania usługi w aplikacjach Progress ABL konieczne jest zastosowanie narzędzia Web Analyzer.
Web Analyzer
OpenEdge Web Analyzer przekształca informacje o operacjach i typach danych w pliku WSDL na czytelny format, użyteczny dla deweloperów aplikacji ABL. Wygenerowana w ten sposób dokumentacja (w postaci plików HTML) zawiera nawet fragmenty kodu, które można wkleić do programu (Rysunek 5). Uruchomienie analizatora odbywa się poprzez wywołanie komendy bprowsdldoc z linii wiersza poleceń, po uprzednim wczytaniu skryptu proenv. Przykładowe wywołanie może wyglądać następująco:
ĀȀ̀ЀԀऀࠀ܀ఀഀ
ĀȀȀ̀ЀԀ
ఀༀကȀᄀሀࠀ ጀ᐀ကᔀ᐀ᄀᘀᔀЀ
ĀȀȀ̀ЀԀ
ᜀȀᔀऀࠀᘀሀࠀ ጀ᐀ကᔀ᐀ᄀᘀᔀЀ
ऀࠀ܀ఀഀ ༀԀ܀က
ĀȀ̀ЀԀऀࠀ܀ఀഀ
wsdl:definitions – główny eleRysunek 1. Przesyłanie komunikatów między dostawcą i odbiorcą ment dokumentu; wsdl:documentation – dokumentacja dostawcy serwisu; wsdl:types – wszystkie typy XML Schema, które powinny być znane dla operacji; wsdl:message – definicje wszystkich komunikatów, które mogą być odbierane lub przesyłane przez użytkowników serwisu; wsdl:portType – definicje wszystkich grup operacji portType dla serwisu; wsdl:binding – definicje wszystkich powiązań dla serwisu. Binding to szczególny protokół przesyłania komunikatów wykoRysunek 2. Schemat wykorzystanie Web serwisu w aplikacji ABL rzystywanych przez portType;
www.sdjournal.org
15
KLUB TECHNICZNY
bprowsdldoc http://localhost:8080/wsa/mywsa/
wsdl?targetURI=urn:OpenEdgeServices: myService serviceInfo
Pierwszym parametrem komendy jest ścieżka lub URL do dokumentu WSDL. Drugim parametrem jest katalog, do którego analizator ma zapisać wygenerowane pliki HTML. Pełna składnia dopuszcza więcej parametrów; w powyższym przykładzie podałem tylko te najważniejsze i najczęściej używane. WSDL Analyzer tworzy następujące typy plików: •
• • •
index – punkt startowy dla wygenerowanej dokumentacji. Jeśli w pliku WSDL znajdują się definicje kilku serwisów, index zawiera powiązania do każdego z nich; dokumentacja serwisu – opisuje Web serwis, zawiera powiązania do dokumentacji portType i DataType; dokumentacja portType – opisuje sposób połączenia się z Web serwisem oraz wszystkie operacje dla portType; dokumentacja DataType – zawiera opis typów danych XML Schema;
Rysunek 4. Plik index wygenerowany narzędziem WSDL Analyzer
•
CSS (Cascading Style Sheet) – definiuje format wyświetlania powyższych plików HTML (fonty, tło itp).
Rysunek 4 przedstawia wygenerowany plik index.html. Widać w nim powiązania m.in do dokumentacji portType ( NewCoServiceObj) i DataType. W pliku portType znajdujemy informację, dzięki której można w bezpośredni sposób połączyć się z Web serwisem i wywołać operacje (Rysunek 5).
Wywołanie Web serwisu w aplikacji
Rysunek 3. Przykładowy plik WSDL
16
Posiadając powyższe wiadomości, możemy napisać kod w języku ABL (Listing 1). Połączenie z Web serwisem wykonuje się poprzez zdefiniowanie wskaźnika obiektu SERVER i wywołanie metody CONNECT z podaniem parametrów. Parametry te można znaleźć w dokumentacji portType. Metoda CONNECT wysyła żądanie pod podany adres URL. W odpowiedzi zwracany jest dokument WSDL (jeśli jest dostępny pod powyższą lokalizacją), który umieszczany jest w pamięci aplikacji.
9/2010
Technologie Progress OpenEdge
Listing 1. Wykorzystanie Web serwisu we własnej aplikacji ABL DEFINE VARIABLE lerr AS LOGICAL NO-UNDO. /* Definicje zmiennych dla przyłączenia się do Web serwisu i wywołania operacji. */ DEFINE VARIABLE lReturn AS LOGICAL NO-UNDO. DEFINE VARIABLE hServer AS HANDLE NO-UNDO.
DEFINE VARIABLE hPortType AS HANDLE NO-UNDO.
/* Przyłączenie się do serwisu */ CREATE SERVER hServer.
lReturn = hServer:CONNECT("-WSDL http://localhost:8080/wsa/wsa1/wsdl? targetURI=urn:OpenEdgeServices: NewCoService -Port NewCoServiceObj").
IF lReturn = NO THEN DO:
MESSAGE
"Could not connect to WebService server"
VIEW-AS ALERT-BOX INFO BUTTONS OK.
APPLY "CLOSE":U TO THIS-PROCEDURE. RETURN.
END.
/* Ustawienie portType */ RUN NewCoServiceObj SET hPortType ON SERVER hServer. IF NOT VALID-HANDLE(hPortType) THEN DO:
MESSAGE
"Could not establish portType"
VIEW-AS ALERT-BOX INFO BUTTONS OK.
APPLY "CLOSE":U TO THIS-PROCEDURE. RETURN.
END.
/*
Wywołanie operacji ValidateCustomer
*/
RUN ValidateCustomer IN hPortType (INPUT iCustNum, OUTPUT cCustName) NO-ERROR.
/* Procedura sprawdza czy w poprzednim wywołaniu nie było błędów */ RUN ErrorInfo (OUTPUT lerr). IF NOT lerr THEN DO:
DISPLAY cCustName WITH FRAME default-frame.
END.
END.
/* Odłączenie sie od usługi i usunięcie zasobów */ DELETE PROCEDURE hPortType. hServer:DISCONNECT().
DELETE OBJECT hServer.
www.sdjournal.org
17
KLUB TECHNICZNY
Rysunek 5. Fragment pliku dokumentacji portType wygenerowany narzędziem WSDL Analyzer
Następnym krokiem jest ustawienie wskaźnika procedury dla wybranego portType (analogicznie jak dla procedur uruchomionych w trybie PERSISTENT). W ten sposób uzyskujemy dostęp do operacji zdefiniowanych w portType, które możemy wywoływać, jak np. ValidateCustomer. Dla obsługi błędów w wywołaniu operacji możemy uruchomić procedurę ErrorInfo i w końcu, aby zakończyć korzystanie z usługi, wywołać metodę DISCONNECT i usunąć zasoby. Więcej informacji związanych z obsługą błędów, wywołań serwisów dla złożonych parametrów itp. można znaleźć w dokumentacji online. Jeśli zaintere-
sował Państwa temat Web serwisów, zapraszam do następnego odcinka, w którym mowa będzie o wystawianiu własnych Web serwisów na platformie OpenEdge.
PIOTR TUCHOLSKI Autor jest od 12 lat związany z technologiami Progress Software. Wieloletni konsultant i Kierownik Działu Szkoleń Progress Software sp. z o.o., specjalizujący się w technologii OpenEdge. Kontakt z autorem: piotr.tt@gmail.com
W Sieci • • •
18
http://communities.progress.com/pcom/community/psdn/openedge – Progress Software Developers Network, część ukierunkowana na zagadnienia techniczne związane z OpenEdge® http://web.progress.com – strona Progress Software Corporation http://www.progress.com/pl – strona Progress Software sp z o.o.
9/2010
FELIETON
Outsourcing IT Czyli polska szansa na sukces Polski rynek IT zmienia się dynamicznie, jednak ciągle ma duże perspektywy rozwoju. Coraz częściej stosowanym rozwiązaniem wsród wielu przedsiębiorstw jest outsourcing IT. Centra usług IT (świadczące usługi zarówno dla polskich, jak i zagranicznych klientów) działają prężnie w naszym kraju. Jako przykład można podać ośrodek Accenture Technology Solutions w Łodzi.
W
Accenture wykorzystujemy model Nearshore, który pozwala ulokować grupę specjalistów w jednym miejscu (tak zwane Delivery Center) oraz oddelegować małą część zespołu - konsultantów do siedziby klienta. Najczęściej usługi takie są świadczone w różnych krajach (kraj docelowy jest inny niż ten, w którym powstaje produkt). Jedną z podstawowych zalet tego modelu jest centralizacja wiedzy i umiejętności w jednym miejscu, które niekoniecznie jest lokalizacją, gdzie dany produkt czy usługa będzie funkcjonowała. Oczywiście zalety nearshoringu dostrzegają firmy o różnej wielkości i różnym profilu działalności. Zaskakującym może być fakt, ile systemów docelowo działających w USA/UK powstaje w Warszawie, Łodzi, Krakowie, Wrocławiu i innych, większych, czy mniejszych miastach naszego kraju.
Nearshoring w praktyce
Mało kto wie, że system billingowy dla włoskiego giganta z branży telewizyjnej (notabene której fundatorem jest Silvio Berlusconi) został w całości zaprojektowany i wykonany w Łodzi oraz Warszawie przez zespół polskich wysoko wykfalifikowanych specjalistów z Accenture. Wysokowydajne C w połączeniu z Javowymi aplikacjami GUI oraz interfejsami w architekturze JCA i Web Services obsługuje niemal 2 miliony włoskich rodzin, tworząc miesięcznie około miliona faktur. Więcej informacji na temat tego projektu można znaleźć w broszurze PDF. Sukces nie byłby jednak możliwy bez odpowiednich narzędzi wspomagających pracę zdalną i komunikację oraz dostosowanych procesów, które pomagają zarządzać projektami w środowisku rozproszonym. W tym momencie chciałbym skupić się nieco na procesach i komunikacji, które często są w solą w oku wszystkich, począwszy od szefów projektów a skończywszy na docelowych użytkownikach systemów informatycznych. Można sobie wyobrazić, ile problemów niesie ze sobą komunikacja w środowisku projektów międzynarodowych. Aby poradzić sobie z tą kwestią Accenture wypracowało system polityk i praktyk umożliwiających skuteczną
20
komunikację pomiędzy członkami zespołów międzynarodowych. Praktyki te wspierane są przez odpowiednie narzędzia (komunikatory, telekonferencje, wirtualne centra konferencyjne), dzięki którym proces przepływu informacji może stać się nie tylko łatwy, ale również bardziej efektywny. Nie mniej ważna jest odpowiednia polityka szkoleniowa. Szkolenia winny się odbywać zarówno z zakresu umiejętności technicznych (jako że spektrum technologii outsourcowanych jest bardzo szerokie), jak i tak zwanych umiejętności miękkich (w tym z zakresu komunikacji międzynarodowej). Oczywiście czasem ważne jest również doskonalenie umiejętności językowych kraju, w którym dany produkt będzie funkcjonował. Na przykład w centrum w jednym z projektów dla klienta zza naszej wschodniej granicy wprowadzono lekcje języka rosyjskiego. Okazało się to bardzo pomocne podczas fazy wsparcia, która również była prowadzona zdalnie z Łodzi.
Co nas czeka
Dynamiczny rozwój rynków IT i technologii pozwala nam programistom mieć nadzieję, że doskonaląc nasze umiejętności będziemy mieli okazję uczestniczyć w projektach, z których korzystają użytkownicy na całym świecie. Globalne trendy pozwalają nam na odnalezienie swojej szansy w outsourcingu usług IT, szczególnie skierowanych do krajów bliskich nam nie tylko geograficznie, ale również kulturowo. Centra, takie jak centrum Accenture Technology Solutions w Łodzi (wspierane przez grupę specjalistów z Warszawy), są bazą dla wysoko wykwalifikowanej kadry programistów, projektantów, testerów i wszystkich innych członków procesu tworzenia oprogramowania. Bazą, która dostarcza rozwiązania innowacyjne, wydajne, dobrze zaprojektowane i wdrożone. Jest niemal pewne, że centra takie będą się rozrastały, gdyż zapotrzebowanie na usługi nearshore jest i będzie wysokie... także przyszłość należy do nas.
MICHAŁ GRONOWSKI
Analityk Accenture
9/2010
���������������������������������������������� ������������������������������������������������ ������������������������������������������������ ������������������������������������������������ ������������������������������������������������ ������������������������������������������������� ��������������������������������������������� ������������������������������������������� ��������������������������������� �������������������������������������������� �������������������������������������������
������������������������������������
�������������������������������������
���������������������������� ���������� ������������������������ �����������������
PROGRAMOWANIE C++
Stałość Stałość logiczna i stałość fizyczna Oznaczanie obiektów, argumentów, metod i składowych jako stałe zwiększa czytelność kodu oraz dostarcza dodatkowych warunków poprawności.
Dowiesz się:
Powinieneś wiedzieć:
• Dlaczego oznacza się obiekty jako stałe; • Co to jest stałość logiczna; • Co to jest stałość fizyczna.
• Jak pisać proste programy w C++.
Wprowadzenie
wskaźnikiem, zabroniona jest zmiana wskaźnika (adresu) oraz wartości wskazywanej. W kontenerach biblioteki standardowej rolę wskaźników pełnią iteratory i tutaj także możemy definiować dwa rodzaje stałości: stały iterator oraz iterator do stałej. Z tego względu dostarcza się dwóch rodzajów iteratora: iterator do zmiennej, który pozwala na zmianę wartości wskazywanej (T::iterator, gdzie T jest typem kontenera), oraz iterator do stałej, nie pozwala on modyfikować wartości wskazywanej (T: :const_iterator). Używając kwalifikatora const można utworzyć stały iterator oraz stały iterator do stałej, patrz Listing 2. Metody, które nie są statyczne, mają dodatkowy (niejawny) argument będący wskaźnikiem na obiekt, na rzecz którego wołamy metodę (wskaźnik this). Jeżeli metoda nie modyfikuje tego obiektu, to można ją oznaczyć jako metodę stałą (literał const po deklaracji metody). Wtedy obiekt this jest wskaźnikiem na stałą (tzn. const T*). Dzięki wyróżnieniu metod nieinwazyjnych, zwiększamy czytelność kodu, programista widzi już w deklaracji metody, że nie zmienia ona stanu obiektu. Kompilator pozwala wołać takie metody na rzecz stałych.
Obiekty w języku C++ mają przypisany typ, który określa zbiór dopuszczalnych operacji. Pozwala to wykrywać przypadki nieprawidłowego użycia obiektów już na etapie kompilacji. Artykuł omawia kwalifikator const, oznaczający zobowiązanie do niemodyfikowania obiektu. Klasyfikator ten modyfikuje typ obiektu, pozwalając kompilatorowi na dodatkową kontrolę. Obiekty, które mają typ poprzedzony kwalifikatorem const, nazywa się stałymi. Stosowanie stałych zwiększa czytelność kodu, programista wie, że obiekt nie będzie zmieniany, jeżeli został przekazany jako stały. Prostym zastosowaniem stałych jest zastępowanie tzw. „magicznych” liczb lub „magicznych” napisów. Czytelność kodu jest zwiększana, gdyż nazwa stałej niesie informacje o jej znaczeniu, podatność kodu na zmiany również rośnie, ponieważ można tę samą stałą stosować wielokrotnie i jeżeli zajdzie potrzeba zmian, to wystarczy zmienić wartość w jednym miejscu, co pokazano na Listingu 1. Kompilator może w miejsce obiektu stałego wstawiać odpowiadającą mu wartość. Dla wskaźników niezależnie określa się, czy stała jest zawartość wskaźnika (przechowywany adres), czy wartość wskazywana (obiekt umieszczony pod adresem przechowywanym we wskaźniku). Najwygodniej zapamiętać składnię, czytając napis od prawej do lewej, tzn. int const* oraz const int* oznacza wskaźnik do stałej całkowitej (adres można zmienić, wartość wskazywaną – już nie), zaś int* const czytamy jako stały wskaźnik do obiektu przechowującego liczbę całkowitą. Obiekt typu const int* const jest
22
Szybki start
Aby uruchomić przedstawione przykłady, należy mieć dostęp do kompilatora C++ oraz edytora tekstu. Na wydrukach pominięto dołączanie odpowiednich nagłówków oraz udostępnianie przestrzeni nazw, pełne źródła dołączono jako materiały pomocnicze.
9/2010
Stałość
Oznaczenie metody jako stałej (nieinwazyjnej) zmienia jej sygnaturę, mogą istnieć dwie różne wersje metody o tej samej nazwie i takiej samej liście argumentów, różniące się stałością. Jedna z nich będzie wołana dla stałych, zaś druga dla zmiennych, patrz Listing 3.
Unikanie powielania kodu
Obiekt zawsze można przekształcić w obiekt stały tego samego typu. Często wykonujmy takie przekształcenie właśnie po to, aby wykorzystać kompilator do wykrywania prób zmiany stanu obiektu we fragmentach kodu, które tego robić nie powinny. Próba przekształcenia obiektu stałego na obiekt zmienny tego samego typu (przekształcenie odwrotne), jeżeli jest dokonywane niejawnie, jest niedozwolone. Konieczność wykonania takiego przekształcenia oznacza zazwyczaj błąd projektowy. Przykładem takiej, niedozwolonej konwersji, jest sytuacja, gdy argumentem
formalnym funkcji jest T& ,a argumentem dostarczanym jest const T&. Wystąpi wtedy błąd kompilacji. W pewnych sytuacjach takie przekształcenie jest przydatne, dlatego język dysponuje operatorem rzutowania const_cast. Operator ten jest pomocny, gdy chcemy dostarczyć dwóch wersji metody (wersja dla stałej i wersja dla zmiennej) i chcemy unikać powielania kodu. Przykład przedstawiony na Listingu 4 wykorzystuje ten sam kod w dwóch wersjach metody get(). Jeżeli obiekt jest dostarczony jako stały, to wymuszenie traktowania go jako zmienny jest poprawne tylko wtedy, gdy mamy pewność, że obiekt jest zmienną.
Stałość fizyczna i logiczna
Metody oznaczona jako stałe nie mogą modyfikować stanu obiektu. Jest to sprawdzane przez kompilator i jest nazywane stałością fizyczną. Metody stałe mogą jednak zezwalać na zmianę stanu innym fragmen-
Listing 1. Stałe zwiększają czytelność kodu oraz ułatwiają jego zmiany const int MAX_VALUE = 5 ;// stała nazwana zamiast „magicznej” liczby 5 for( int i = 0; i < MAX_VALUE; ++i )
// w tej pętli wykorzystuje się tą stałą
for( int j = 0; j < MAX_VALUE; ++j )
// tutaj używa się tej samej stałej, wystarczy jej wartość zmienić w jednym miejscu
Listing 2. Stałość w bibliotece standardowej const int TAB[] =
2, 3, 8, 5 ;// tablica stałych
const int TAB_SIZE = sizeof(TAB)/sizeof(TAB[0]);
std::vector<int> v(TAB, TAB + TAB_SIZE); // inicjacja wektora
const std::vector<int>::iterator it = v.begin(); // stały iterator
++it; // błąd, stały iterator
*it = 5;//można zmieniać wartość wskazywaną
std::vector<int>::const_iterator it2 = v.begin(); //iterator do stałej ++it2;//można zmieniać iterator
*it2 = 8; // błąd, stała wartość wskazywana
const std::vector<int>::const_iterator it3 = v.begin();//stały iterator do stałej
++it3; //błąd
*it3 = 13; //błąd
Listing 3. Metody stałe class Foo { public:
void f() const; //metoda stała, nie zmienia stanu obiektu void f(); //metoda, która
};
nie jest stała (zmienia stan obiektu) o tej samej nazwie i parametrach
void g(); // metoda g jest dostarczana tylko w wersji inwazyjnej
const Foo f; // obiekt f jest stałą
f.f(); // woła metodę ’void f() const’
f.g(); // błąd, próba wołania metody g dla stałego obiektu
www.sdjournal.org
23
PROGRAMOWANIE C++
tom kodu, na przykład wtedy, gdy zwracają wskaźnik lub referencję do składowej. Jeżeli występuje taka sytuacja, to stan obiektu może być zmieniony, gdy wołane są jedynie metody stałe. Jest to błędem nazywanym brakiem stałości logicznej. Błąd ten nie jest wykrywany przez kompilator. Przykład pokazano na Listingu 5. Stałość logiczna jest pojęciem bardziej ogólnym, niż stałość fizyczna. Oznacza ona brak możliwości zmiany stanu dla stałych obiektów zarówno przez metody danej klasy, jak też przez inne fragmenty kodu. Osiągnięcie stałości logicznej jest pożądane przy tworzeniu oprogramowania. Aby zapewnić ten rodzaj stałości w metodach stałych nie należy zwracać wskaźników ani referencji do składowych, można zwracać wskaźnik do stałej albo stałą referencję. Poprawiony kod klasy Foo, zapewniający stałość logiczną, jest pokazany na Listingu 6. Zazwyczaj, jeżeli zapewniona jest stałość logiczna, występuje także stałość fizyczna (stałość fizyczna oznacza brak modyfikacji składowych w metodach oznaczonych jako stałe). W pewnych szczególnych przypadkach stałość logiczna występuje w metodach, które modyfikują składowe, czyli gdy brak
Listing 6. Klasa zapewnia stałość logiczną class Foo {
int* x_;
public:
const int* get() const { // metoda stała pozwala
tylko na odczyt
}
return x_;
void set(int* x) {// metoda zmienia stan, nie jest
stała
};
}
x_ = x;
jest stałości fizycznej. Ilustracją tego przypadku jest klasa Str przedstawiona na Listingu 7, która obudowuje wskaźnik do napisu w stylu C i dostarcza metodę zwracającą długość napisu. Metoda getLength oblicza długość napisu tylko raz, przy pierwszym wołaniu tej metody, zaś przy każdym kolejnym zwraca zapamiętaną długość. Ze względu na tę optymalizację, metoda nie może być ozna-
Listing 4. Wykorzystanie operatora const_cast do dostarczania dwóch wersji metody class Foo { public:
Foo(int v) : val_(v) {}
int& get() {//metoda wołana dla zmiennej
// rzutowanie const_cast bezpieczne, metoda stała zwraca referencję do składowej, która może być zmieniana // rzutowanie static_cast niezbędne, aby uniknąć rekurencji
}
return const_cast<int&>( static_cast<const Foo*>(this)->get() );
const int& get() const {//metoda wołana dla stałej
// dodatkowe czynności, np. rejestracja dostępu // return val_;
}
private:
};
int val_;
Listing 5. Klasa nie zapewnia stałości logicznej struct Foo {
};
int* x_;// możliwy swobodny dostęp do wskaźnika
void fun(const Foo& f) { // obiekt f przekazywany jako stała int i = 34;
f.x_ = &i; // błąd, stan f został zmieniony, kompilator pozwoli na to }
24
*f.x_ = 4; // błąd, jak wyżej
9/2010
Stałość
Listing 7. Klasa obudowuje napis w stylu C. Metoda getLength nie może być oznaczona jako stała
Listing 8. Klasa obudowuje napis w stylu C. Metoda getLength nie może być oznaczona jako stała
class Str {
class Str {
public:
const char* str() const { // metoda stała
}
public:
const char* str() const { // metoda stała
return str_;
}
int getLength() { // metoda nie może być stała
int getLength() const { // metoda stała
if(! validLength_) {
if(! validLength_) {
length_ = strlen(str_); // zmienia składową
} }
length_ = strlen(str_);
validLength_ = true; // zmienia składową
}
return length_;
private:
char* str_;
}
return length_;
char* str_;
mutable bool validLength_; // składowa może być
int length_;
czona jako stała, ponieważ zmienia ona składowe validLength_ oraz length_. Pomimo tego, że odczyt długości napisu nie zmienia tego napisu, czyli jest zachowana stałość logiczna, nie można wołać tej metody dla stałego obiektu. Aby umożliwić tworzenie metod stałych w takich przypadkach stosuje się modyfikator mutable, którym oznacza się składowe, które mogą być zmieniane w metodach stałych. Poprawiony kod klasy Str został pokazany na Listingu 8. Składowymi, które mogą być zmieniane w metodach stałych, są często obiekty synchronizacyjne (np. muteksy) albo obiekty związane z optymalizacjami (tak jak powyżej). Nierozsądne stosowanie modyfikatora mutable może doprowadzić do zupełnego braku kontroli nad stałością, dlatego mechanizmu tego powinniśmy używać tylko w uzasadnionych przypadkach.
validLength_ = true;
private:
bool validLength_;
};
return str_;
zmieniana w metodach stałych
mutable int length_; // składowa może być
zmieniana w metodach stałych
};
je typ obiektu. Pomiędzy stałością i ulotnością nie ma sprzeczności, obiekt może być jednocześnie stały i ulotny. Obiekty ulotne, w odróżnieniu od obiektów stałych, są tworzone sporadycznie, dlatego nie będą opisywane tutaj szerzej.
Podsumowanie
Oznaczanie klas, metod, argumentów jako stałe zwiększa kontrolę kompilatora nad dostarczanym kodem. Warto wykorzystywać takie konstrukcje, gdyż pomimo nieco większego nakładu pracy (musimy oznaczać odpowiednie byty jako stałe), pozwalają one wychwycić szereg błędów, związanych z niewłaściwym użyciem obiektów.
Obiekty ulotne
Język C++ dostarcza kwalifikatora volatile, który oznacza zależność stanu obiektu od innego wątku lub innego procesu. Obiekty oznaczone jako ulotne nie mogą podlegać optymalizacjom. Kwalifikator volatile, podobnie jak kwalifikator const modyfiku-
W Sieci • •
http://www.parashift.com/c++-faq-lite - opis wykorzystywania stałości w C++ http://www.possibility.com/Cpp/const.html – opis wykorzystywania stałości w C++
Więcej w książce
Zagadnienia dotyczące współcześnie stosowanych technik w języku C++, wzorce projektowe, programowanie generyczne, prawidłowe zarządzanie zasobami przy stosowaniu wyjątków, programowanie wielowątkowe, ilustrowane przykładami stosowanymi w bibliotece standardowej i bibliotekach boost, zostały opisane w książce Robert Nowak, Andrzej Pająk ,,Język C++: mechanizmy, wzorce, biblioteki'', która ukaże się niebawem.
www.sdjournal.org
ROBERT NOWAK Adiunkt w Zakładzie Sztucznej Inteligencji Instytutu Systemów Elektronicznych Politechniki Warszawskiej, zainteresowany tworzeniem aplikacji bioinformatycznych oraz zarządzania ryzykiem. Programuje w C++ od ponad 10 lat. Kontakt z autorem:rno@o2.pl
25
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
Rozpocznij przygodę z Windows Phone 7 Zobacz, jak to się robi w technologii Microsoft
Na konferencji MIX 2010 w Las Vegas firma Microsoft zaprezentowała swój nowy system operacyjny Windows Phone 7. Dokonano zmiany całej platformy, co zrewolucjonizowało pisanie aplikacji na urządzenia mobilne. Firma Microsoft pokazała także urządzenie prototypowe, które spełniało wszystkie podstawowe wymagania, jakie postawiła firma. Przyjrzyjmy się zatem, co tak naprawdę się zmieniło i co najważniejsze, czy te zmiany pomogą Nam, programistom. Dowiesz się:
Powinieneś wiedzieć:
• Co zostało zmienione w platformie Windows Phone 7 względem Windows Mobile; • Jak bardzo te zmiany wpłyną na pisanie oprogramowania; • Jaki jest nowy cykl produkcji aplikacji; • Jakie wymagania musi spełnić urządzenie, by można było na nim zainstalować Windows Phone 7.
• Jak obsługiwać narzędzie Microsoft Visual Studio oraz Microsoft Expression Blend.
F
irmy starają się jak najbardziej unowocześniać swoje systemy mobilne, tak by sprostały wymaganiom rynku, a co najważniejsze wymaganiom klientów. Każdy system jest uzależniony od tego, na jakim urządzeniu jest instalowany. Firma Apple robi to w dość rygorystyczny sposób. Ich system jest instalowany na urządzeniach jedynie ich produkcji, co znacznie ułatwia podejście do pisania nowych aplikacji, gdyż dokładnie wiemy, czego się spodziewać. Firma Microsoft natomiast jest znacznie bardziej otwarta i z ich rozwiązań mobilnych korzystają takie firmy jak: HTC, Motorola, Samsung i wiele innych. To bardzo podoba się klientom końcowym, gdyż mają bardzo duży wybór w urządzeniach, lecz jest zmorą programistów, którzy jeśli chcą wydać aplikację niezależną od platformy sprzętowej, muszą przewidzieć przeróżne rozmiary i rozdzielczości ekranów, położenie pionowe oraz poziome, rodzaj wyświetlacza, czy występuje klawiatura sprzętowa, czy nie, a może nasza aplikacja potrzebuje odbiornika GPS bądź innej technologii. Dlatego wraz z wydaniem nowego systemu Microsoft zdecydowała się na ogromne zmiany. System Windows Phone 7 to nie tylko kolejne wydanie mobilnego Windows`a, to totalnie nowy system, który z wie-
26
kiem będzie dojrzewał, ale zobaczmy, co dostaliśmy w tym roku. Czy na pewno podjęte decyzje były trafne i czy zrewolucjonizują one sposób pisania aplikacji, czy teraz możemy powiedzieć, że pisanie aplikacji mobilnych jest równie łatwe, jak pisanie stron www czy aplikacji desktopowych?
Wymagania Stawiane Przed Urządzeniami
Podstawową zmianą jest to, iż firma Microsoft chce kontrolować dostawców urządzeń mobilnych i postawiła przed nimi konkretne warunki, które musi spełnić każde urządzenie, na którym będzie instalowany system Windows Phone 7. Przyjrzyjmy się teraz tym wymaganiom: 1. Ekran musi być typu „multitouch”, co oznacza, że można implementować w aplikacjach różnego rodzaju ułatwienia, jak bardzo znane przybliżanie i oddalanie za pomocą zbliżania i oddalania dwóch palców na ekranie. 2. Każde urządzenie musi posiadać pod ekranem trzy przyciski. Ta metoda ułatwi poruszanie się po różnych aplikacjach, a że jest jednakowa dla wszystkich, użytkow-
9/2010
Rozpocznij przygodę z Windows Phone 7
3. 4.
5. 6. 7. 8.
nicy raz nauczą się obsługi i w każdej aplikacji będą w stanie się przemieszczać, jakby już ją znali. Zobaczmy, do czego służy każdy z przycisków: a) Pierwszy z lewej to tak zwany przycisk powrotu (ang. Back). Przycisk ma dwa zastosowania. Po pierwsze, jeśli znajdujemy się w głównym oknie aplikacji, to zamyka ją, natomiast jeśli jesteśmy gdzieś wewnątrz aplikacji, służy do powrotu do formatki, na której byliśmy poprzednio. Działanie takie zostało zapożyczone z aplikacji internetowych, gdzie mamy przycisk powrotu do strony oglądanej poprzednio. b) Środkowy przycisk włącza telefon, a jeśli mamy uruchomioną aplikację, przenosi nas do głównego okna systemu. Nie można tego przycisku oprogramowywać z wewnątrz aplikacji. c) Ostatni przycisk, z prawej, służy do wyszukiwania. W tym miejscu możemy implementować jakąkolwiek funkcjonalność przeszukiwania wewnątrz naszej aplikacji. Dostępne będą jedynie dwie rozdzielczości: 800x480 oraz 480x320. Ekrany będą wykonane w technologii OLED, które niesie ze sobą pewne plusy i minusy. Jeśli nasza aplikacja będzie napisana poprawnie (większość komponentów w naszej aplikacji będzie posiadała ciemne kolory, a najlepiej czarne), to możemy zaoszczędzić na zużyciu baterii. Dlatego domyślny ekran Windows Phone 7 jest czarny. Na tej samej technologii oparte są odtwarzacze ZUNE. Procesor taktowany od 1 GHz. Sprzętową akcelerację graficzną. Opcjonalnie mogą być montowane klawiatury sprzętowe. Każdy smartphone musi być wyposażony w: a) Wi-Fi. b) Kamerę – minimum 5-megapixel oraz flash. c) Akcelerometr – określa położenie urządzenia, zastosowanie może mieć podczas obracania telefonu, który automatycznie zmieni położenie ekranu z pionowego na poziomy. W grach może służyć do sterowania postacią czy też innym elementem. d) Kompas. e) Rozpoznawanie mowy. f) Wibrację. g) Push Notifications – technologia zostanie dokładniej omówiona w dalszej części artykułu.
Jak można szybko zauważyć, firma Microsoft ustanowiła poprzeczkę bardzo wysoko i spora część urządzeń dostępnych obecnie na rynku nie spełnia podstawowych wymagań. Ale czy tak właściwie te dane są potrzebne programistom? Oczywiście, że tak. Pisząc aplikację i testu-
www.sdjournal.org
jąc ją na urządzeniu A, mamy niemal stuprocentową pewność, że na urządzeniu B będzie ona działać tak samo, nawet jeśli będziemy korzystać z niestandardowych elementów, jak GPS czy akcelerometr, a nawet kompas. Możemy być pewni, że wszystkie urządzenia będą posiadały te komponenty i nie musimy już ograniczać się do wybranej ilości urządzeń, co w efekcie pozwala na dostęp do naszej aplikacji większej ilości klientów, którzy nie będą już ograniczani z powodu braku któregoś z komponentów.
Dostępne Technologie Oraz Języki Programowania
Do tej pory na Windows Mobile mogliśmy pisać aplikacje tylko przy pomocy formatek (Windows Forms) w trzech językach: C#, VB, oraz Visual C++. Wraz z wprowadzeniem Windows Phone postanowiono zmienić platformę, co niesie za sobą zmianę technologii. Obecnie dostępne są dwie metody pisania ogrogramowania. Możemy korzystać z technologii Silverlight, jak również XNA. W obu przypadkach dostępnym językiem jest tylko C#, tak więc nie mamy już możliwości pisania aplikacji niezarządzalnych. Założeniem jest, by wszystkie aplikacje „okienkowe” pisać za pomocą Silverlight, natomiast wszelkiego rodzaju gry lub aplikacje wymagające wysokiej akceleracji graficznej powinny być pisane w XNA. Technologia Silverlight NIE jest tutaj jakąkolwiek wersją light czy pomniejszoną biblioteką. Jest to w pełni dostępny Silverlight, który do tej pory stosowaliśmy podczas pisania aplikacji internetowych w tej technologii. Co jest zaskakujące i dość niepokojące, to fakt, iż mimo że sam interfejs jest dostępny w technologii Silverlight, to uruchamiając przeglądarkę Internet Explorer Mobile i wpisując adres strony, która jest wykonana w technologii Silverlight, nie możemy jej zobaczyć lub
27
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
dostępne będą jedynie komponenty nie będące częścią Silverlight. Firma Microsoft pracuje nad umożliwieniem wyświetlania aplikacji internetowych napisanych w Silverlight przez Internet Explorer Mobile, lecz w najbliższym wydaniu Windows Phone będzie ta opcja niedostępna.
Dostępne Narzędzia Dla Programistów Oraz Grafików
Windows Phone 7 daje duże możliwości dla programistów, ale jako że mamy dostępną technologię Silverlight, to graficy mają teraz czym się pochwalić w aplikacjach mobilnych. Aktualizując Microsoft Expression Blend do wersji 4 mamy możliwość budowy bogatych aplikacji mobilnych, co powinno bardzo spodobać się użytkownikom końcowym. Podczas mojego pierwsze kontaktu z tym systemem odniosłem wrażenie, iż to już nie ten sam biznesowy system. Kiedyś wygląd grał drugoplanową rolę, a jakiekolwiek sterowanie systemem za pomocą dotyku było dość uciążliwe i w wielu przypadkach nie obywało się bez rysika. Nowy interfejs daje większe możliwości i jest dokładnie przemyślany, by użytkownicy już nigdy nie sięgali po rysik. Niestety za pełną wersję Microsoft Expression Blend przyjdzie nam zapłacić za licencję i nie ma w chiwli obecnej darmowej wersji (poza wersją testową ograniczoną czasowo). Zatem co się zmieniło dla programistów? Po pierwsze trzeba mieć świadomość, że pisanie aplikacji na Windows Phone 7 będzie dostępne tylko w Visual Studio 2010, firma Microsoft nie planuje wydawać SDK dla Visual Studio 2008. Można by pomyśleć, że będzie się to wiązać z nowymi wydatkami, gdyż trzeba będzie zakupić nowe licencje. Nic bardziej mylnego! Microsoft wydał jeden instalator, który za jednym razem instaluje wszystko to, co potrzeba, by można spokojnie pisać aplikacje mobilne. Jeśli się jeszcze nie domyślasz, to śpieszę poinformować, że wraz z tym instalatorem instaluje się Visual Studio 2010 Express for Phone, które oferuje wszystko to, co pełne VS 2010, przy czym ograniczając się do projektów mobilnych. By zacząć
Rysunek 1. Nowy projekt
Rysunek 2. Menu
28
już dziś pisać aplikację i dokończyć artykuł wraz z testowaniem kodu zawartego w artykule, wystarczy pobrać instalator i można zacząć zabawę. To bardzo pozytywna decyzja firmy Microsoft, gdyż daje możliwość dostępu do większej ilości osób chcących pisać aplikacje mobilne. Może w ten sposób wśród studentów i społeczności zwiększy się zainteresowanie Windows Phone 7 jako platformą prograRysunek 3. Emulator mistyczną. Co jeśli już mamy zainstalowaną którąś z wersji Visual Studio 2010? Instalator doda elementy mobilne do już zainstalowanej wersji, dając nam dwie możliwości, albo będziemy korzystać z pełnej wersji Visual Studio 2010 i z jego poziomu tworzyć nowe projekty mobilne, lub możemy korzystać z Visual Studio 2010 Express for Windows Phone, tak czy inaczej instalator zainstaluje wersję Express. Niestety w chwili obecnej nie możemy wybrać, by ten komponent nie był instalowany, pomimo iż posiadamy pełną wersję oprogramowania.
Pierwsza Aplikacja Dla Windows Phone 7
Po zainstalowaniu Windows Phone 7 Developer Tool możemy uruchomić Visual Studio 2010 Express for Windows Phone lub któreś z pełnych Visual Studio 2010. Tak czy inaczej, by utworzyć nowy projekt, klikamy w File/New/Project... lub używamy skrótu klawiszowego Ctrl+Shift+N. Pojawi się nowe okno podobne do tego zaprezentowanego na Rysunku 1. Korzystając z pełnej wersji Visual Studio 2010, po lewej stronie mamy sporą listę możliwych do wybrania projektów. Nas oczywiście interesuje projekt Silverlight for Windows Phone. W środkowej części wybieramy jedną z przygotowanych skórek. Na początku interesujące są dwie pierwsze: Windows Phone Application oraz Windows Phone List Application. Pierwsza z nich utworzy czystą „formatkę” z dwoma elementami tekstowymi, natomiast druga przygotuje „formatkę” tak, by wyświetlała przykładową listę. Wybierzmy na początek pierwszą opcję (Windows Phone Application). Zanim jednak klikniemy OK, warto ustawić nazwę oraz lokalizację projektu. Jak można było oczekiwać, Visual Studio przygotował dość sporą część kodu, jak również pierwszą formatkę.
9/2010
Rozpocznij przygodę z Windows Phone 7
Po utworzeniu nowego projektu poza widoczną formatką, której mogliśmy się spodziewać, wyszczególniono kod, który definiuje nową formatkę. Kod ten jest zapisany w kodzie XAML i wszelkie zmiany, które dokonamy (np. przeciągając nowy element z Toolbox),
będą automatycznie widoczne w kodzie XAML, jak również na formatce. Nadal mamy dostęp do kodu, który jest umieszczany „pod” formatką, jak poprzednio, który jest pisany w języku C#. W taki sposób właśnie firma Microsoft od-
Listing 1. Przykładowy, wyedytowany przycisk <Grid x:Name="LayoutRoot" Background="{x:Null}" Height="93" Width="194">
<Button Content="Click" Foreground="Blue" Background="Transparent" Height="68" HorizontalAlignment="Left"
Margin="12,12,0,0" Name="button1" VerticalAlignment="Top" Width="172" Click="button1_Click" />
</Grid>
Listing 2. Wiadomość, która pojawi się po naciśnięciu przycisku private void button1_Click(object sender, RoutedEventArgs e) { }
MessageBox.Show("Witaj SDJ", "Wiadomość", MessageBoxButton.OK);
Listing 3. Zmody�kowany komponent Grid <Grid x:Name="ContentGrid" Grid.Row="1"> <Grid.RowDefinitions>
<RowDefinition Height="100" />
</Grid.RowDefinitions>
</Grid>
Listing 4. Wywołanie komponentu private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) {
}
DemoControl.DemoControl dc = new DemoControl.DemoControl(); ContentGrid.Children.Add(dc);
Listing 5. Dodanie właściwości InputScope w kodzie XAML <Grid x:Name="ContentGrid" Grid.Row="1">
<TextBox InputScope="TelephoneNumber" Height="32" HorizontalAlignment="Left" Margin="6,6,0,0" Name="textBox1" </Grid>
Text="" VerticalAlignment="Top" Width="474" />
Listing 6. Dodanie właściwości InputScope w kodzie C# textBox1.InputScope = new InputScope { Names = { new InputScopeName { NameValue = InputScopeNameValue.Telephone Number } } };
Listing 7. Wywołanie wibracji przez dwie sekundy var vc = VibrateController.Default; vc.Start(TimeSpan.FromSeconds(2));
www.sdjournal.org
29
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
dzieliła część kodu odpowiedzialną za wizualną stronę aplikacji od kodu odpowiedzialnego za logikę, którą ma wykonywać dana formatka. Zanim przejdziemy do wprowadzania zmian, poświęćmy chwilę na sposób uruchamiania aplikacji i emulator. Jak wiadomo, aplikacja mobilna może zostać uruchomiona na dwa sposoby. Możemy uruchamiać aplikację bezpośrednio na urządzeniu, które jest podłączone do komputera, lub testować aplikacje na emulatorze. Jako że w chwili obecnej nie ma jeszcze urządzeń z systemem Windows Phone na rynku, dlatego musimy zadowolić się emulatorem, który znacznie się zmienił od tego, który znamy z Windows Mobile. Teraz emulator jest swego rodzaju maszyną wirtualną i wspiera wirtualizację sprzętową, przez co sam emulator uruchamia się szybciej i jest o wiele wydajniejszy od poprzedniego. Emulator wspiera wiele rzeczy, jak GPS czy położenie pionowe/poziome, ale też nie jest w stanie zastąpić 100% fizycznego urządzenia. Możemy wybierać opcję, by emulator był pionowo czy poziomo, natomiast emulator nie jest w stanie zasymulować akcelerometru. Wszelkie testy tego typu będziemy musieli wykonać po uruchomieniu aplikacji na fizycznym urządzeniu. Jeśli popatrzymy na menu u góry, to możemy dostrzec, iż znajdują się tam trzy listy widoczne na Rysunku 2.
Rysunek 5. Wybór wersji Silverlight
Patrząc od lewej, mamy listę z możliwością wyboru, czy aplikacja będzie uruchamiana na emulatorze, czy też na urządzaniu, następnie czy będzie to tryb Debug, czy Release, ostatecznie możemy wybrać rodzaj procesora. Ustawienia domyślne (widoczne na Rysunku 2) są jak najbardziej dla naszego przykładu poprawne. Zatem jak uruchomić emulator? Emulator jest uruchamiany automatycznie podczas pierwszego uruchomienia aplikacji, zatem klikamy w zieloną strzałkę tuż obok pierwszej listy lub klikamy w Debug\Start Debugging lub używamy skrótu F5. W ten sposób nasza aplikacja została skompilowana i uruchomiona na emulatorze. Zakończyć działanie aplikacji możemy, klikając w strzałkę w dolnej części emulatora lub przechodząc do Visual Studio 2010
Rysunek 4. Rozpoczęcie projektu, który będzie korzystał ze wspólnego komponentu w projekcie internetowym i mobilnym
30
9/2010
Rozpocznij przygodę z Windows Phone 7
i klikając w Debug\Stop Debugging lub korzystając ze skrótu Shift+F5. Przyjrzyjmy się teraz samemu emulatorowi. Rysunek 3 przedstawia nowy emulator. Po prawej stronie u góry mamy małe menu emulatora i zaczynając od góry, mamy dostępne: zamknięcie emulatora, zminimalizowanie, obrócenie w lewo, obrócenie w prawo, ustawienie rozmiaru emulatora względem ekranu, oraz opcje, które dostarczają jedynie możliwość zmiany rozmiaru emulatora. Co jest wielką, a zarazem pozytywną zmianą to to, iż emulator jest od razu tak skonfigurowany, że otrzymuje ustawienia sieci naszego komputera, a co za tym idzie, jeśli nasz notebook ma połączenie z internetem, to uruchamiając aplikację Internet Explorer Mobile i wpisując np.: http://www.sdjournal.org , to zostanie nam wyświetlona konkretna strona. W przypadku Windows Mobile musieliśmy korzystać z dodatkowego oprogramowania (z Device Emulator Manager, dostępnego z poziomu Visual Studio, oraz ActiveSync w przypadku Windows XP, lub Windows Mobile Device Center dla Windows Vista czy Windows 7). Co ciekawe, uruchamiając Device Emulator Manager z poziomu Visual Studio 2008 na liście możemy zobaczyć Windows Phone 7, lecz z poziomu narzędzia nie możemy nic skonfigurować, ani nawet uruchomić emulatora. Klikając w strzałkę obok ikony Internet Explorer, przejdziemy do zakładki z dostępnymi aplikacjami oraz ustawieniami. Na pierwszym miejscu będzie widoczna nasza aplikacja, którą wcześniej uruchomiliśmy. Klikając w jej ikoną lub tytuł, możemy uruchomić aplikację ponownie, która jednak nie będzie już w trybie debbug, gdyż jest uruchamiana bezpośrednio z emulatora. Skoro już poznaliśmy podstawy, to przejdźmy do wybranych zagadnień programistycznych Windows Phone 7. Budową wyglądu i pewnymi normami, które muszą zostać spełnione, zajmiemy się w dalszej części artykułu, teraz będziemy ustawiać kontrolki w dowolnych lokalizacjach bez większego przejmowania się wyglądem naszej aplikacji.
dałem, to czy gotowe komponenty gotowych aplikacji napisanych w technologii Silverlight można wykorzystać w nowych projektach Windows Phone 7. To z punktu widzenia programisty znacznie przyspieszyłoby nam pracę. Co bardzo mnie ucieszyło, to to, że zadbano w trakcie budowy nowej platformy o kompatybilność projektów internetowych tworzonych w technologii Silverlight z tymi budowanymi obecnie na platformie Windows Phone 7. Jeśli mamy wcześniej przygotowane przez nas kontrolki, które stosowaliśmy w aplikacji internetowej i chcemy, by ograniczyć czas pracy nad nowymi elementami, to możemy bardzo łatwo korzystać z gotowych komponentów, wystarczy odpowiednie elementy dodać do naszego projektu. Zróbmy bardzo prosty przykład, który zaprezentuje tę możliwość. Otwórzmy Microsoft Visual Studio 2010 i dodajmy nowy projekt Silverlight/Silverlight Class Library. Nazwę solucji, jak i projektu możemy ustawić dowolną (przykład prezentuje Rysunek 4). Kolejnym krokiem jest dobór wersji Silverlight (Rysunek 5). Ważne jest, by pamiętać, iż wersja Silverlight wykorzystana w Windows Phone 7 jest w wersji 3, a nie 4, dlatego zaznaczamy, by projekt był prowadzony w Silverlight 3. Plik Class1.cs możemy usunąć, za to dodajemy nowy element (Rysunek 6). Na liście w kolejnym oknie wybieramy Silverlight User Control (Rysunek 7). W ten sposób dodamy nowy komponent, który będzie wykorzystany na dwóch platformach. Na czystą formatkę dodajemy przycisk (Button), poprzez rozwinięcie zakładki Tool-
Kompatybilność Projektów
Pierwszym dość ważnym pytaniem, jakie sobie za- Rysunek 6. Dodanie nowego elementu
www.sdjournal.org
31
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
Rysunek 7. Dodajemy komponent User Control
box i przeciągnięcie komponentu Button. Zmieniamy grafików przy użyciu narzędzia Expression Blend, ale jego rozmiar oraz ustawiamy właściwość Content na dla programisty o wiele lepszym rozwiązaniem jest pidowolny napis, który ma się pojawić na przycisku. Je- sanie kodu ręcznie. Przyśpiesza to znacznie pracę. śli ktoś ma doświadczenie z komponentami Windows By przycisk dostosował się do wyglądu naszej aplikaForms, to może szukać właściwości Text, niestety nie cji mobilnej, jak i internetowej jako Background na eleznajdzie takowej, gdyż przycisk jest teraz komponen- mencie Grid ustawiamy x:null, co oznacza, by komtem Silverlight i jego nazwa została zmieniana z Text ponent nie posiadał koloru, a więc był transparentny. na Content. Właściwość tę możemy zmienić, klika- Podobnie robimy z przyciskiem, z tym że Background jąc przycisk (Button), a następnie klikając w klawisz ustawiamy na Transparent. Klikając dwukrotnie przyF4. Zostanie rozwinięta lista właściwości i tutaj doko- cisk, tworzymy zdarzenie, które domyślnie dla przynujemy zmiany. Jednak jest szybszy i bardziej wygod- cisku to kliknięcie. W kodzie C# dodajemy komuniny sposób. Możemy edytować plik XAML i jeśli odszukamy sobie w kodzie komponent Button, to możemy szybko dokonać zmiany. Jeśli chcemy dodać jakiś element, np. kolor czcionki na przycisku, to wystarczy dopisać ten element (Listing 1 demonstruje przykładowy przycisk po zmianach). Z doświadczenia wiem, iż programiści wolą pisać kod sami, niż generować go w jakiś sposób poprzez gotowe do tego komponenty. Pisząc różne, bardziej lub mniej zaawansowane programy, przywykłem do ręcznego edytowania kodu XAML głównie dlatego, iż jest to szybsze, niż przeszukiwanie list właściwości. Można by pomyśleć, że jest to uciążliwe, ale IntelliSense (podpowiedzi w Visual Studio) bardzo usprawniają ten proces, a nowe możliwości w Vistual Studio 2010 znacznie go jeszcze usprawniły, przez co polecam w wolnym czasie douczenie się paru podstawowych elementów z zakresu Silverlight/ WPF, oczywiście zaawansowane elementy będą wykonywane przez Rysunek 8. Uruchomienie aplikacji mobilnej
32
9/2010
Rozpocznij przygodę z Windows Phone 7
kat z informacją, która powie nam, że nasz komponent działa. Listing 2 pokazuje przykładowy kod. Pierwszy etap ukończyliśmy. Teraz dodajmy dwa nowe projekty do naszej solucji (klikamy w nazwę solucji – napis na samej górze drzewka, i wybieramy Add/ New Project...). Jednym będzie projekt Silverlight/ Silverlight Application, a drugim Silverlight for Windows Phone/Windows Phone Application. Zaczniemy od modyfikacji projektu mobilnego, gdyż to on jest dla nas najważniejszy. Dodajemy nową referencję, klikając prawym klawiszem myszy w nazwę projektu mobilnego, a z menu wybieramy „Add Reference...”. W nowym oknie przechodzimy do zakładki Projects i wybieramy projekt komponentu utworzonego uprzednio i klikamy „OK”. Teraz przejdziemy do edycji pliku XAML, a dokładniej zmodyfikujemy komponent Grid o nazwie ContentGrid w sposób podany na Listingu 3, a następnie tworzymy zdarzenie Loaded dla całej naszej formatki, klikając dwukrotnie nad przyciskami u dołu skórki smartfona. W kodzie dodajemy kod zawarty na Listingu 4. Teraz możemy uruchomić naszą aplikację mobilną w sposób pokazany na Rysunku 8. Po uruchomieniu naszej aplikacji możemy przetestować jej działanie. Po kliknięciu w przycisk, jak można było się spodziewać, pojawia się komunikat, a kolorystyka przycisku jest dostosowana do naszej aplikacji dzięki uprzednim ustawieniom, by kom-
ponent był przeźroczysty. Jeśli dodamy ten sam komponent do aplikacji internetowej, to będzie on robił dokładnie to samo, przy czym na innej platformie. W taki sposób wiemy, że przygotowując aplikację mobilną na Windows Phone 7 czy też aplikację internetową działającą w technologii Silverlight, nie musimy powielać pracy, możemy przygotować jeden komponent raz i wykorzystać go w dwóch różnych miejscach, co znacznie zaoszczędzi nam czas. Zobaczmy teraz kilka wybranych zagadnień, które zmieniły się względem Windows Mobile.
Wirtualna Klawiatura
Wszystkie urządzenia, na których będzie instalowany Windows Phone 7, muszą domyślnie być sterowane poprzez dotykowy ekran. Oczywiście klawiatura fizyczna jest tutaj opcją, ale w takim razie, czy coś się zmieniło w aspekcie wprowadzania danych? Tak, zmieniło się i to zdecydowanie na lepsze. W przypadku Windows Mobile klawiatura ekranowa w domyślnym ustawieniu była totalnie nieprzystosowana, by w jakikolwiek sposób z niej korzystać, klikając palcami, by wpisać tekst, musieliśmy używać rysika. Pierwszą zmianą w Windows Phone 7 jest dostosowanie klawiatury ekranowej w taki sposób, by pisanie na niej za pomocą palców nie sprawiało już problemów. To jeden z głównych proble-
Reklama
Wybierz swój nowy system, poznaj Linuksa krok po kroku! Twoje pierwsze �ród�o wiedzy o Linuksie
w wortalu: recenzje dystrybucji porównanie funkcji opis instalacji i du�o wi�cej
ponad �wier� miliona odwiedzin miesi�cznie!
jakilinux.org
www.sdjournal.org
kontakt / reklama borys.musielak@gmail.com
33
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
mów, który rozwiązano, lecz to nie wszystko. Firma Microsoft postanowiła znacznie usprawnić nową klawiaturę. Teraz możemy wybierać, co ma się pojawić na klawiaturze. Jeśli przykładowo wpisujemy adres i nasza aplikacja w osobnym miejscu oczekuje na wpisanie nazwy miejscowości, a w osobnym kodu pocztowego czy telefonu, to racjonalne jest, by w pierwszym przypadku udostępnić same litery, a w dwóch następnych tylko cyfry. W ten sposób „klawisze” mogą być większe, a jednocześnie użytkownik może wpisać tylko odpowiednie znaki, co polepsza interfejs, a co ważniejsze praca z naszą aplikacją staje się przyjemniejsza. Element taki możemy dodać do komponentu TextBox w pliku XAML, jak i z poziomu kodu C#. Listing 5 i 6 przedstawiają wykorzystanie właściwości InputScope, która ułatwi wprowadzanie danych. Nieważne, której metody użyjemy, efekt będzie taki sam (przykład na Rysunku 9 i 10). Osobiście zalecam metodę pierwszą, czyli wpisać właściwość w kodzie XAML, gdyż w ten sposób nasz kod jest znacznie czystszy, a najważniejsze elementy związane z wizualną częścią nie „zaśmiecają” kodu programu. Jeśli tylko możemy, to najlepiej, by cała część odpowiedzialna na wygląd aplikacji znajdowała się w kodzie XAML, a część odpowiedzialna za logikę aplikacji w kodzie C#. We wpisywaniu tekstu jest jednak wciąż błąd, który nie został poprawiony do dzisiaj, a mankament ten był obecny już za czasów Windows Mobile. Jeśli ustawimy TextBox, by przyjmował hasło, czyli każdy nowy znak zamieniał na kropkę, to zauważymy, że podczas wpisywania ostatni znak zawsze jest widoczny. Jest to bardzo niebezpieczne, gdyż osoba spoglądająca na ekran naszego urządzenia może z łatwością odczytywać znaki wpisywane, jako hasło.
Wibracja I Odtwarzanie Video
Ciekawym elementem jest wibracja, którą można wywołać w dwóch linijkach kodu, jednak bez urządzenia nie możemy się przekonać, czy faktycznie nasz kod działa poprawnie, mimo to myślę, że warto pokazać, jak wywołać tę funkcjonalność, gdyż w różnych miejscach naszego programu wibracją możemy użytkownika informować o jakimś zdarzeniu. Listing 7 prezentuje wywołanie wibracji przez dwie sekundy. Uprzednio musimy jednak dodać referencję do biblioteki Microsoft.Devices. Jak widać na przykładzie, kod jest bardzo prosty i nie wymaga większej analizy. Jeśli chodzi o wyświetlanie np. filmów, to sprawa jest jeszcze prostsza. W nowym projekcie do formatki dodajmy komponent MediaElement. W kodzie XAML do komponentu MesiaElement musimy dodać właściwość CacheMode="BitmapCache". Opcja ta w przyszłości będzie ustawiona automatycznie, jednak w obecnej chwili musimy zadbać o to sami. Kolejną właściwością, jaką trzeba ustawić, jest Source, czyli element, który będzie
34
Rysunek 10. Wykorzystanie właściwości InputScope Rysunek 9. Wykorzystanie właściwości InputScope
wyświetlany. Dodatkowo możemy ustawić poziom Volume (głośność), oraz czy video ma się włączać automatycznie, czy nie (AutoPlay). Jeśli odtwarzanie chcemy kontrolować z poziomu kodu, to rozpoczęcie odtwarzania obsługuje metoda Play(), a przerywa metoda Stop(). Do dyspozycji mamy także metodę Pause().
Budowa Interfejsu
Interfejs możemy budować za pomocą Visual Studio, jak do tej pory, jednak o wiele bardziej wydajnym i przyjemniejszym narzędziem do tego typu zadań jest Microsoft Expression Blend, który został specjalnie zaprojektowany z myślą o osobach, które zajmują się budową interfejsów. Jest to program dostosowany do grafików, którzy tworzą nietypowe interfejsy szyte na miarę dla klienta. Nie będę tutaj opisywał, jak działa to narzędzie, gdyż jest to osobny temat na artykuł, dlatego proponuję odwiedzić witrynę produktu, na której możemy znaleźć wszystkie informacje na temat produktu, jak również artykuły, jak zacząć pracę z produktem. Jak można zauważyć na wstępie, interfejs Windows Phone 7 uległ radykalnie zmianie. Co ważniejsze, firma Microsoft chce, by wszystkie aplikacje wytwarzane na platformę Windows Phone 7 były utrzymane w tej samej konwencji. Nowy interfejs ma nazwę kodową „Metro”. Generalnie kierowano się łatwością w prze-
9/2010
Rozpocznij przygodę z Windows Phone 7
kazywaniu komunikatów na tablicach informacyjnych umieszczanych w metro czy na lotniskach. Czy jest to właściwa droga? O tym przekonamy się, gdy użytkownicy będą mieli dostęp do urządzeń. Dodać mogę tylko, iż podobny interfejs oferują nowe ZUNE HD.
Podsumowanie
Rynek aplikacji mobilnych rozwija się bardzo szybko, a razem z nim oczekiwania użytkowników są coraz wyższe. Z jednej strony potrzeba dobrych urządzeń, a z drugiej wybór systemów jest już tak duży, iż jest o co powalczyć. Kolejnym ważnym aspektem jest to, czy system operacyjny daje nam, jako programistom, spore możliwości, czy nie. Jeśli chodzi o platformę Windows Phone 7, to wychodzi ona naprzeciw i jednej, i drugiej grupie z bardzo dużymi zmianami. Czy rynek zaakceptuje nowy system, czy nie, dowiemy się w najbliższym roku, jednak warto przygotować
nasze aplikacje, by działały z nowym systemem, gdyż już teraz wokół nowego systemu jest głośno. Zmian możemy także oczekiwać w sposobie dostarczania aplikacji do klienta. Nie mamy już możliwości przygotować pliku CAB czy też innego instalatora. Nasza aplikacja musi zostać wysłana do certyfikacji, a po pozytywnym jej przejściu trafia do Marketplace, z którego nasz klient może sobie pobrać naszą aplikację. W ten sposób naszą aplikację będą mogli pobrać użytkownicy z całego świata i to z jednego miejsca.
DANIEL DUDEK Zajmuje się programowaniem aplikacji mobilnych na systemach Microsoft Windows Mobile od ponad dwóch lat. Jest liderem Śląskiej Regionalnej Grupy Microsoft. Autor jest także prelegentem konferencji społecznościowych: http://msgroups.pl/speakerbiuro/Strony/DanielDudek.aspx. Kontakt z autorem: dan.dudek@hotmail.com
W Sieci • • • •
Strona główna systemu Windows Phone 7 http://www.windowsphone7.com Witryna przeznaczona dla programistów http://developer.windowsphone.com Marketplace http://marketplace.windowsphone.com/ Witryna produktu Microsoft Expression Blend http://www.microsoft.com/expression/
Reklama
www.sdjournal.org
35
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
Windows Phone 7 – Pierwsze kroki Prosta aplikacja do Twittera 15 lutego 2010 roku, na konferencji Mobile World Congress, Steve Balmer (CEO firmy Microsoft) ogłosił nowy mobilny system operacyjny Windows Phone 7 Series (obecnie oficjalna nazwa brzmi: Windows Phone 7). Bardzo ciekawy jest fakt, że WP7 od strony technicznej nie ma prawie nic wspólnego z poprzednimi wersjami platformy (Windows Mobile), bowiem firma Microsoft postanowiła, że system ten zostanie napisany od podstaw. Producenci smartfonów (np. HTC) zapowiadają pierwsze telefony z WP7 pod koniec bieżącego roku, ale programiści już teraz mogą tworzyć oprogramowanie na nowy system operacyjny. Dowiesz się:
Powinieneś wiedzieć:
• W jaki sposób przygotować środowisko developerskie pod Windows Phone 7; • W jaki sposób używać emulatora Windows Phone 7; • W jaki sposób rozpocząć tworzenie oprogramowania na tę platformę, na przykładzie prostej aplikacji do Twittera.
• Jak programować w języku C#; • Jak tworzyć proste elementy interfejsu graficznego użytkownika w XAML.
W
indows Phone 7 jest najnowszym mobilnym system operacyjnym firmy Microsoft. W porównaniu do swoich poprzedników wprowadza wiele drastycznych zmian – należy chociażby zwrócić uwagę na zupełnie nowy interfejs użytkownika lub integrację serwisów społecznościowych w samym systemie. Zmiany nie dotyczą jednak tylko przyszłych użytkowników smartphonów z WP7 – programiści zainteresowani tworzeniem oprogramowania na tę platformę powinni znać następujące fakty (na dobry początek): •
•
•
36
Programiści mogą tworzyć oprogramowanie, wykorzystując platformę Silverlight lub XNA (obydwie platformy to kod zarządzany) – natywne aplikacje nie są obecnie wspierane. Aplikacje są uruchamianie w swoich własnych izolowanych przestrzeniach (ang. sandbox), co zapewnia duży poziom bezpieczeństwa, ale uniemożliwia np. standardową komunikację pomiędzy procesami. Wszystkie aplikacje muszą zostać zarejestrowane w Windows Phone Marketplace (patrz: ramka
•
•
•
Windows Phone Marketplace) zanim będą mogły zostać zainstalowane na telefonach użytkowników (nie dotyczy to oczywiście aplikacji testowanych na emulatorze). Wymagania sprzętowe telefonów WP7 są dość szczegółowe – programiści mogą być pewni, że zawsze w telefonie będzie znajdować się np. GPU, WiFi, akcelerometr, GPS czy też wsparcie dla funkcji multitouch. Programiści powinni stosować się do zaleceń firmy Microsoft odnośnie platformy WP7, w przeciwnym wypadku stworzona aplikacja/gra może zostać odrzucona przy próbie rejestracji na Windows Phone Marketplace – praktyka ta ma zapewnić użytkownikom spójność w użytkowaniu telefonu oraz przewidywalny poziom jakości oprogramowania. Istotnym elementem nowej platformy jest tzw. chmura (ang. Cloud computing) oraz serwisy webowe.
Niniejszy artykuł stanowi wstęp dla osób zainteresowanych tworzeniem oprogramowania na WP7 lub sa-
9/2010
Prosta aplikacja do Twittera
mą platformą. Na początku opiszę, jakie narzędzia są niezbędne przy pisaniu aplikacji oraz jak należy je skonfigurować. Następnie zajmę się prostym programem typu Witaj Świecie!, który będzie pierwszym małym krokiem w świecie Windows Phone 7. Dalsza część artykułu skupi się na prostej aplikacji do Twittera (zostanie wykorzystana platforma Silverlight), która zaprezentuje kilka możliwości nowej platformy – nale-
ży zwrócić uwagę, że w chwili pisania artykułu SDK do WP7 nie umożliwia jeszcze korzystania ze wszystkich API systemu.
Pierwsza aplikacja
Zgodnie z tradycją, nasz pierwszy program będzie aplikacją typu Witaj Świecie!. Przed przystąpieniem do pisania należy przygotować środowisko develo-
Windows Phone Marketplace
Windows Phone Marketplace jest platformą dystrybucyjną, która umożliwia zarządzanie aplikacjami na platformie mobilnej firmy Microsoft. Jedną z nowości w systemie Windows Mobile 6.5 była aplikacja Marketplace, która była jednocześnie debiutem omawianej platformy dystrybucyjnej – nie odniosła ona jednak sukcesu (kiedy porównamy ją np. do platformy Apple App Store). Liczne prośby i uwagi zarówno użytkowników, jak i programistów spowodowały wprowadzenie wielu zmian – należy zwrócić uwagę między innymi na: • • • • • •
Udostępnienie nowego API, które umożliwia wprowadzenie próbnego okresu użytkowania aplikacji. Nowy system notyfikacji, który znacznie ułatwia kontakt użytkowników danej aplikacji z jej autorem. Brak limitu na dystrybuowane aplikacje (5 pierwszych aplikacji można zarejestrować za darmo). Kilka modeli biznesowych do wyboru. Udostępnianie aplikacji w fazie beta wybranym użytkownikom. Możliwość ograniczenia dostępności aplikacji tylko do wybranych krajów/kraju.
Istotny jest fakt, że użytkownicy Windows Phone 7 są niejako skazani na korzystanie z Windows Phone Marketplace (w przypadku Windows Mobile 6.5 było to opcjonalne) – jest to bowiem jedyny sposób na instalowanie aplikacji i gier. Szczegółowe informacje można znaleźć pod adresem http://developer.windowsphone.com/ Zachęcam także do obejrzenia sesji poświęconej temu zagadnieniu z konferencji Microsoft TechEd pod adresem http:// www.msteched.com/2010/NorthAmerica/WPH312
Szybki start: Narzędzia i SDK
Aby rozpocząć pracę z nowym systemem mobilnym WP7, należy udać się na stronę http://developer.windowsphone.com/ windows-phone-7/ i pobrać darmowe narzędzia w postaci jednej wygodnej paczki msi. Należy zwrócić uwagę, że obecnie narzędzia te dostępne są tylko dla platform Windows Vista i Windows 7. Pobrana paczka msi zainstaluje następujące narzędzia i SDK: • • • •
Visual Studio 2010 Express for Windows Phone CTP; Windows Phone Emulator CTP; Silverlight for Windows Phone CTP; XNA Game Studio 4.0 CTP.
Należy zwrócić uwagę, że omawiane narzędzia i SDK są w wersji CTP (Community Technology Preview), w związku z tym od czasu do czasu można spodziewać się dziwnego zachowania z ich strony. Po tej instalacji jesteśmy gotowi do rozpoczęcia tworzenia oprogramowania na Windows Phone 7.
Windows Phone Emulator
Windows Phone Emulator jest aplikacją, która ma ułatwić programistom tworzenie oprogramowania na Windows Phone 7. W chwili pisania niniejszego artykułu nie ma jeszcze oficjalnego urządzenia z WP7, nie mniej jednak sporo aplikacji WP7 zostało już napisanych - można je zobaczyć chociażby w serwisie youtube (polecam obejrzeć prezentację aplikacji do czytania komiksów dostępną pod adresem http://www.youtube.com/watch?v=LYNVz83BcmQ). Wszystko to dzięki emulatorowi, który z powodzeniem zastępuje rzeczywiste urządzenie. W chwili pisania niniejszego artykułu emulator dostarcza, między innymi, następujące funkcjonalności: • • • • • • •
Możliwość uruchamiania i testowania aplikacji, Emulacja procesora, pamięci RAM, ekranu urządzenia i jednostki GPU, Emulacja połączenia sieciowego (emulator korzysta z połączenia dostępnego na komputerze), Emulacja audio, Możliwość zapisywania i ładowania stanów emulatora, Debugowanie (ang. debugging), Multitouch (należy posiadać monitor dotykowy).
www.sdjournal.org
37
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
perskie – krok ten został opisany w ramcie: Szybki start: Narzędzia i SDK. Następnie uruchamiamy Visual Studio 2010 i wybieramy opcję File->New Project – mamy do wyboru kilka szablonów w kategorii Silverlight for Windows Phone (patrz: Rysunek 2). Do stworzenia naszej pierwszej aplikacji skorzystamy z szablonu Windows Phone Application, który wygeneruje dla nas solucję. Wygenerowaną solucję można od razu zbudować i uruchomić (klawisz F5). Należy zwrócić uwagę, że pierwszy start emulatora zajmuje trochę czasu (około 20 sekund), w związku z tym proponuję nie wyłączać go, jeżeli chcemy kilkakrotnie budować i testować nasze aplikacje na WP7. Po zbudowaniu solucji i jej uruchomieniu Visual Studio automatycznie uruchomi naszą aplikację na emulatorze. Póki co nie wygląda ona zbyt efektownie – nie wyświetla nawet napisu Witaj Świecie. Zanim jednak dokonamy modyfikacji, to zapoznamy się z najważniejszymi elementami typowej aplikacji WP7 opartej na platformie Silverlight.
Solucja i jej elementy
Wygenerowana solucja w Visual Studio (patrz: Rysunek 3) składa się z kilku istotnych elementów: •
Properties – możemy tutaj znaleźć standardowy manifest aplikacji (AppManifest.xml), meta-dane opisujące tworzoną assembly (AssemblyInfo.cs) oraz specyficzny manifest dla aplikacji WP7 (WMAppManifest.xml). Dwa pierwsze elementy są standardowe dla niemal wszystkich aplikacji pisanych w oparciu o platformę Microsoft .NET, natomiast interesujący jest ostatni element, któremu warto się przyjrzeć (patrz: Listing 1). Należy w szczególności zwrócić uwagę na tag Capabilities, który określa funkcjonalności platformy Windows Phone 7, z których korzysta nasza aplikacja (rozwiązanie znane chociażby z platformy Symbian) – jest to istotne z punktu widzenia procesu rejestracji aplikacji w Windows Phone Marketplace,
Listing 1. Manifest aplikacji Windows Phone 7 opartej na platformie Silverlight <?xml version="1.0" encoding="utf-8"?> <Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.0">
<App xmlns="" ProductID="{cfe17e32-87ba-40e5-9f66-2464f4c6f3ef}" Title="WindowsPhoneApplication1" RuntimeType= "SilverLight" Version="1.0.0.0" Genre="NormalApp"
Author="" Description="" Publisher="">
<IconPath IsRelative="true" IsResource="false">ApplicationIcon.png</IconPath> <Capabilities>
<Capability Name="ID_CAP_NETWORKING" /> <Capability Name="ID_CAP_LOCATION" /> <Capability Name="ID_CAP_SENSORS" />
<Capability Name="ID_CAP_MICROPHONE" /> <Capability Name="ID_CAP_MEDIALIB" />
<Capability Name="ID_CAP_GAMERSERVICES" /> <Capability Name="ID_CAP_PHONEDIALER" />
<Capability Name="ID_CAP_PUSH_NOTIFICATION" />
<Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
</Capabilities> <Tasks>
<DefaultTask
</Tasks>
Name ="_default" PlaceHolderString="Default task"/>
<Tokens>
<PrimaryToken TokenID="WindowsPhoneApplication1Token" TaskName="_default"> <TemplateType5>
<BackgroundImageURI IsRelative="true" IsResource="false">Background.png</BackgroundImageURI> <Count>0</Count>
<Title>WindowsPhoneApplication1</Title>
</TemplateType5>
</PrimaryToken>
</Tokens>
</App>
</Deployment>
38
9/2010
Prosta aplikacja do Twittera
•
References – są te referencję do innych assembly, z jakich korzysta nasza aplikacja. Oprócz standardowych (takich jak System.Core lub Sys-
tem.Net) możemy zauważyć też kilka specyficznych dla platformy WP7 – np. Microsoft.Phone.Controls.
Listing 2. App.xaml.cs // Przestrzenie nazw (ang. namespace), z których chcemy korzystać. using System;
using System.Collections.Generic; using System.Linq; using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media;
using System.Windows.Media.Animation; using System.Windows.Shapes;
namespace WindowsPhoneApplication1 {
// Klasa 'App', która reprezentuje naszą aplikację. public partial class App : Application {
// Konstruktor. public App() {
// Za każdym razem, gdy jakiś wyjątek nie zostanie obsłużony, to metoda 'Application_ UnhandledException' zostanie wywołana.
UnhandledException += new EventHandler<ApplicationUnhandledExceptionEventArgs>(Application_ UnhandledException);
// Inicjalizacja. }
InitializeComponent();
// Metoda 'Application_UnhandledException'.
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) {
if (System.Diagnostics.Debugger.IsAttached)
{
}
// Jeżeli debugger jest podłączony to wywołujemy przerwanie w tym miejscu. System.Diagnostics.Debugger.Break();
else
{
// Jeżeli debugger nie jest podłączony to wyświetlamy komunikat. e.Handled = true;
MessageBox.Show(e.ExceptionObject.Message + Environment.NewLine + e.ExceptionObject.StackTrace,
}
}
}
}
www.sdjournal.org
"Error", MessageBoxButton.OK);
39
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
•
App.xaml – element na pewno znany programistom Silverlight – w tym pliku aplikacja definiuje współdzielone zasoby (np. obiekty typu Brush) oraz jest to jednocześnie punkt startowy dla naszej aplikacji. Należy zwrócić uwagę, że element ten składa się tak naprawdę z kodu napisanego w XAML, ale jest jednocześnie powiązany z plikiem App.xaml.cs, który z kolei zawiera kod napisany w języku C#. Takie rozdzielenie interfejsu graficznego użytkownika (XAML) od logiki biznesowej (C#) jest charakterystyczne dla platformy Silverlight. Jeżeli klikniemy prawym przyciskiem myszy na ten element i wybierzemy opcję View Code, to zobaczymy zawartość pliku App.xaml.cs (patrz: Listing 2). Klasa App dziedziczy po klasie Application i jest reprezentacją naszej aplikacji.
•
W tym miejscu możemy np. oczekiwać na zdarzenie zamknięcia aplikacji przez użytkownika. MainPage.xaml – ten element to główny widok naszej aplikacji. Zawiera interfejs użytkownika (w postaci kodu XAML) oraz logikę (w postaci kodu C#). Proponuję teraz przeanalizować kod XAML (patrz: Listing 3). Na początku definiowane są przestrzenie nazw (podobnie jak ma to miejsce w standardowym pliku cs), z których będziemy korzystać, a następnie ustawiona jest czcionka. Należy zauważyć, że wykorzystujemy czcionkę zdefiniowaną wcześniej w App.xaml - <FontFamily
x:Key="PhoneFontFamilyNormal">Segoe
FontFamily>,
WP</
czyli będziemy korzystać z czcionki Segoe WP. Po zdefiniowaniu czcionki przychodzi czas na określenie układu (ang. layout) – został
Listing 3. MainPage.xaml <!--Przestrzenie nazw i czcionka--> <phoneNavigation:PhoneApplicationPage
x:Class="WindowsPhoneApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"> <!--Główny układ, definicja dwóch wierszy--> <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}"> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--Zawartość pierwszego wiersza, dwie kontrolki typu TextBlock--> <Grid x:Name="TitleGrid" Grid.Row="0">
<TextBlock Text="MY APPLICATION" x:Name="textBlockPageTitle" Style="{StaticResource PhoneTextPageTi tle1Style}"/>
<TextBlock Text="page title" x:Name="textBlockListTitle" Style="{StaticResource PhoneTextPageTitle2 </Grid>
Style}"/>
<!--Zawartość drugiego wiersza--> <Grid x:Name="ContentGrid" Grid.Row="1"> </Grid>
</Grid>
</phoneNavigation:PhoneApplicationPage>
40
9/2010
Prosta aplikacja do Twittera
wybrany układ siatki (ang. grid), w którym znajdują się dwa wiersze i jedna kolumna. Wysokość pierwszego wiersza została ustawiona na Auto (co oznacza, że wartość wysokości dostosuje się do zawartości), a wysokość drugiego na * (co oznacza, że wykorzystane zostanie pozostałe wolne miejsce). W pierwszym wierszu zostały zdefiniowane dwie kontrolki typu TextBlock, natomiast drugi wiersz jest pusty. Dodatkowo można zauważyć, że wierszom zostały przypisane style graficzne, które też możemy znaleźć w pliku App.xaml.
Wprowadzamy pierwsze zmiany
Nadszedł czas, żeby wprowadzić kilka prostych zmian do naszej pierwszej aplikacji. Na początku
zmienimy wartości właściwości Text naszych jedynych dwóch kontrolek. Proponuję zmiany dla pierwszej kontrolki dokonać ręcznie w pliku MainPage.xaml – musimy odnaleźć tam linijkę <TextBlock Text="MY
APPLICATION"
Style}"/>
i zamienić ją na
le"
x:Name="textBlockPageTit
Style="{StaticResource
aplikacja"
Style="{StaticResource "/>.
PhoneTextPageTitle1
<TextBlock
Text="Moja
x:Name="textBlockPageTitle" PhoneTextPageTitle1Style}
Jak widać, dokonaliśmy prostej zmiany wartości dla właściwości Text. Podobną zmianę wykonamy także dla drugiej kontrolki, ale tym razem z pomocą Visual Studio – w tym celu musimy otworzyć plik MainPage.xaml (np. dwa razy klikając na niego w Solution Explorer). Visual Studio przedstawia kod napisany w XAML w graficznym edytorze, co znacznie uła-
Listing 4. MainPage.xaml dla aplikacji do Twittera <phoneNavigation:PhoneApplicationPage
x:Class="AplikacjaDoTwittera.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"> <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}"> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="TitleGrid" Grid.Row="0">
<TextBlock Text="" x:Name="textBlockPageTitle" Style="{StaticResource PhoneTextPageTitle1Style}"/>
<TextBlock Text="Twitter" x:Name="textBlockListTitle" Style="{StaticResource PhoneTextPageTitle2Sty </Grid>
le}"/>
<Grid x:Name="ContentGrid" Grid.Row="1">
<TextBox Height="32" HorizontalAlignment="Left" Margin="0,6,0,0" Name="textBox1" Text="TextBox" VerticalAlignment="Top" Width="308" />
<Button Content="Szukaj" Height="70" HorizontalAlignment="Left" Margin="314,6,0,0" Name="button1" VerticalAlignment="Top" Width="160" />
<ListBox Height="562" HorizontalAlignment="Stretch" Margin="11,84,9,0" Name="listBox1" </Grid>
VerticalAlignment="Top" Width="460" HorizontalContentAlignment="Stretch" />
</Grid>
</phoneNavigation:PhoneApplicationPage>
www.sdjournal.org
41
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
Rysunek 1. Emulator Windows Phone 7
twia modyfikowanie istniejącego kodu lub tworzenie nowego interfejsu użytkownika (można także skorzystać z Expression Blend 4, które jest dedykowanym narzędziem do XAML). Zaznaczamy kontrolkę o nazwie textBlockListTitle i w okienku Properties (jeżeli okno to nie jest widoczne, to można użyć skrótu Ctrl + W, P) odnajmujemy właściwość Text, której wartość zmieniamy na Witaj Świecie!. Możemy teraz przebudować solucję i podziwiać wprowadzone zmiany na ekranie emulatora. Przed przystąpieniem do tworzenia aplikacji do Twittera dokonamy jeszcze małego ulepszenia w naszej aplikacji typu Witaj Świecie!, w celu zapoznania się z systemem zdarzeń w WP7. Dodajemy dwie nowe kontrolki do MainPage.xaml – przeciągamy kontrolkę typu TextBox i Button do graficznego edytora w Visual Studio (kontrolki znajdują się w oknie Toolbox). Następnie zaznaczamy kontrolkę typu Button i w oknie Properties przełączamy się na zakładkę Events – możemy teraz obejrzeć wszystkie zdarzenia, jakie generuje zaznaczona kontrolka. Odnajmujemy zdarzenie Click (zdarzenie to generowane jest zawsze wtedy, kiedy użytkownik naciśnie kontrolkę) i klikamy dwa razy lewym przyciskiem myszy na to zdarzenie – spowoduje to wygenerowanie metody NazwaKontrolki_Zdarzenie (w tym wypadku button1_Click).
Rysunek 2. Szablony nowego projektu Windows Phone 7
42
9/2010
Prosta aplikacja do Twittera
Do ciała wygenerowanej metody wpisujemy następujący kod: textBlockListTitle.Text = "Witaj " + textBox1.Text; (przy założeniu, że nazwy kontrolek
nie zostały zmienione). Po tej zmianie, przy każdorazowym kliknięciu na guzik tekst w kontrolce textBlockListTitle zmieni się odpowiednio. Możemy dodatko-
Listing 5. private void button1_Click(object sender, RoutedEventArgs e) {
WebClient twitter = new WebClient(); string userName = textBox1.Text; twitter.DownloadStringCompleted += new DownloadStringCompletedEventHandler(twitter_DownloadStringCo mpleted);
twitter.DownloadStringAsync(new Uri("http://api.twitter.com/1/statuses/user_timeline.xml?screen_ name=" + userName));
}
Listing 6. void twitter_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) {
if (null != e.Error) return;
XElement answer = XElement.Parse(e.Result); listBox1.ItemsSource = from tweet in answer.Descendants("status") select new TwitterItem {
Image = tweet.Element("user").Element("profile_image_url").Value, Message = tweet.Element("text").Value,
};
}
UserName = tweet.Element("user").Element("screen_name").Value
Listing 7. <ListBox Height="562" HorizontalAlignment="Stretch" Margin="11,84,9,0" Name="listBox1" VerticalAlignment="Top" Width="460" HorizontalContentAlignment="Center">
<ListBox.ItemTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal" Height="132">
<Image Source="{Binding Image}" Height="73" Width="73" VerticalAlignment="Top" Margin="0,10,8,0"/>
<StackPanel Width="370">
<TextBlock Text="{Binding UserName}" Foreground="#FFC8AB14" FontSize="28" /> <TextBlock Text="{Binding Message}" TextWrapping="Wrap" FontSize="24" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
www.sdjournal.org
43
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
wo ustawić wartość właściwości TextWrapping kontrolki textBlockListTitle na Wrap, co spowoduje zawijanie się wierszy w tej kontrolce.
Aplikacja do Twittera
Tworzenie naszej aplikacji do Twittera zaczniemy od przygotowania nowego projektu WP7 w Visual Studio – użyjemy tego samego szablonu, jak w przypadku wcześniejszej aplikacji typu Witaj Świecie!. Kolejnym krokiem będzie przygotowanie interfejsu użytkownika, który będzie się składał z trzech kontrolek: • • •
TextBox – w tej kontrolce wprowadzana będzie nazwa użytkownika z serwisu Twitter. Button – zdarzenie Click powodować będzie pobranie wiadomości z serwisu Twitter dla wcześniej wprowadzonej nazwy użytkownika. ListBox – w tej kontrolce aplikacja będzie wyświetlać pobrane wiadomości z serwisu Twitter.
Przykładowa implementacja przedstawionego interfejsu użytkownika znajduje się na Listingu 4. W następnej kolejności zajmiemy się implementacją potrzebnej logiki do komunikacji z serwisem Twitter. W tym celu wyślemy zapytanie do serwisu w metodzie, która obsłuży zdarzenie Click naszej kontrolki typu Button. Metoda ta wygląda następująco (Listing 5). W pierwszej kolejności tworzymy instancję klasy typu WebClient, która będzie odpowiadać za komunikację z serwisem Twitter. Następnie pobieramy wprowa-
dzoną nazwę użytkownika z kontrolki typu TextBox i wysyłamy zapytanie do serwisu. Należy zauważyć, że platforma Silverlight cechuje się asynchronicznymi wywołaniami – z tego względu przed wysłaniem zapytania rejestrujemy się dodatkowo na zdarzenie DownloadStringCompleted, żeby mieć możliwość przeanalizowania odpowiedzi od serwisu (w momencie wystąpienia tego zdarzenia zostanie z kolei wywołana metoda twitter_DownloadStringCompleted). Następnym krokiem będzie analiza odpowiedzi z serwisu, w celu wyszukania istotnych dla nas informacji. Odpowiedź na nasze zapytanie zostanie wysłana w formacie xml – w związku z tym wykorzystamy mechanizm LINQ do łatwego jej sparsowania (ang. parsing). Aby skorzystać z LINQ, musimy dodać referencję System.Xml.Linq do projektu (klikamy prawym przyciskiem myszy na element References i wybieramy opcję Add Reference...) oraz odpowiednią przestrzeń nazw (using System.Xml.Linq) w pliku MainPage.xaml.cs. Przy analizie odpowiedzi z serwisu wykorzystamy także pomocniczą klasę TwitterItem, która przedstawia się następująco: public class TwitterItem {
public string UserName { get; set; } public string Message { get; set; }
}
public string Image { get; set; }
Rysunek 3. Wygenerowana solucja aplikacji Windows Phone 7
44
9/2010
Prosta aplikacja do Twittera
Zawiera ona trzy istotne informację, które będziemy wyszukiwać w odpowiedzi nasłanej przez serwis Twitter. Instancje tej klasy staną się także źródłem danych dla kontrolki typu ListBox. Po tych przygotowaniach nadszedł wreszcie czas na implementację metody twitter_DownloadStringCompleted, w której sprawdzimy odpowiedź z serwisu. Metoda ta przedstawia się następująco (Listing 6). W pierwszej kolejności sprawdzamy, czy nie pojawił się żaden błąd (należy pamiętać, że potrzebny jest nam dostęp do Internetu), a następnie parsujemy odpowiedź do instancji klasy typu XElement, która reprezentuje standardowy element formatu xml. Możemy w tym momencie uruchomić LINQ i wyłuskać potrzebne nam informacje – tworzymy tyle instancji klasy TwitterItem, ile wiadomości znajduje się w odpowiedzi. Kolekcja ta staje się z kolei źródłem danych dla kontrolki typu ListBox. Zostało nam już ostatnie zadanie – kontrolka typu ListBox nie wiem, w jaki sposób ma interpretować dane zawarte w instancjach klasy TwitterItem (np. powinna wiedzieć, że pole Image jest tak naprawdę obrazem i należy go odpowiednio wyświetlić). Do wykonania tego zadania stworzymy prosty szablon, w którym wykorzystamy mechanizm bindowania danych (ang. DataBinding). Szablon należy dodać do pliku MainPage.xaml: Szablon składa się z dwóch elementów typu StackPanel (odpowiedzialnych za pozycjonowanie swoich elementów dzieci). Pierwszy zawiera kontrolkę typu Image oraz drugi StackPanel, który z kolei zawiera dwie kontrolki typu TextBlock. Należy dodatkowo zauważyć, że pierwszy StackPanel jest poziomy, a drugi pionowy. Po uruchomieniu naszej aplikacji i wpisaniu poprawnej nazwy użytkownika serwisu Twitter (np. JimCarrey) nasza aplikacja powinna prezentować się tak jak na Rysunku 4.
Podsumowanie
Nowy mobilny system operacyjny firmy Microsoft (Windows Phone 7) jest bardzo ciekawą i radykalną zmianą w porównaniu do poprzednich edycji Windows Mobile. Pomimo faktu, że pierwsze urządzenia z no-
Rysunek 4. Aplikacja do Twittera w akcji
wym systemem dopiero się ukażą, a obecne SDK nie jest jeszcze kompletne, to developerzy już tworzą bardzo ciekawe aplikacje na tę platformę. Niniejszy artykuł stanowi pierwsze kroki do nowego i bardzo ciekawego świata Windows Phone 7. Gorąco zachęcam wszystkich Czytelników do lepszego poznania omawianej platformy!
DARIUSZ GUNIA Pracuje na stanowisku Programisty Aplikacji Mobilnych w �rmie BLStream. Dariusz specjalizuje się w technologiach związanych z produkcją oprogramowania na platformy mobilne, ze szczególnym naciskiem na platformę Windows Mobile. Programuje głównie w języku C++ oraz C#. Kontakt z autorem: dariusz.gunia@blstream.com
W sieci • • • • • • •
http://www.windowsphone7.com/ – oficjalna strona Windows Phone 7; http://developer.windowsphone.com/ – oficjalny portal dla programistów Windows Phone 7; http://windowsteamblog.com/windows_phone/ – oficjalny blog Windows Phone 7; http://msdn.microsoft.com/en-us/library/ff402535(v=VS.92).aspx – opisy platformy, zalecenia przy pisaniu aplikacji, przykłady; http://www.msteched.com/Tracks/WindowsPhone – zbiór sesji poświęconych WP7 z konferencji Microsoft TechEd 2010; http://phone.codeplex.com/ – darmowe kontrolki Windows Phone 7, których obecnie brakuje w SDK; http://social.msdn.microsoft.com/Forums/en-US/category/windowsphone – forum Windows Phone 7;
www.sdjournal.org
45
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
Metody synchronizacji bazy mobilnej SQL Server Compact z SQL Server 2008 Na przykładzie Remote Data Access Pomimo iż firma Microsoft na konferencji MIX 2010 zaprezentowała nowy system mobilny Windows Phone 7, to oznajmiła jednocześnie, że poprzednia wersja systemu, Windows Mobile 6.5, będzie nadal wspierana. Duża ilość aplikacji mobilnych z sektora biznesowego i/lub przemysłowego czy medycznego stosuje systemy Windows Mobile 5.0, 6.0, 6.1, jak również 6.5. W dzisiejszych czasach nie można sobie wyobrazić aplikacji działającej bez dostępu do bazy danych. W artykule pokażę, jak wykonać kopię bazy firmowej do wersji mobilnej, oraz jak przekazać wprowadzone zmiany z powrotem na serwer firmowy. Dowiesz się:
Powinieneś wiedzieć:
• Jak szybko i sprawnie zbudować bazę mobilną; • W jaki sposób dokonać zmian na bazie mobilnej; • Jak przesłać dokonane zmiany na serwer lub ewentualnie jak pobrać nowe elementy z bazy.
• Jak obsługiwać narzędzie Microsoft Visual Studio, oraz Microsoft SQL Server Management Studio; • Jak konfigurować SQL Server; • Jak konfigurować IIS; • Jak umożliwić łączność z siecią w emulatorze.
T
echnologia, która zostanie zaprezentowana w tym artykule, może zostać wykorzystana na systemach Windows Mobile lub systemach desktopowych. Obecny od niedawna system Windows Phone 7 nie pozwala na dostęp do baz mobilnych, a jednocześnie polityka względem dostępu do danych całkowicie się zmieniła. Teraz wszelkie dane z serwera powinny być przesyłane za pomocą Web Services. Rozwiązanie to nie zawsze jest dopuszczalne, a często niemożliwe, dlatego jedynym rozwiązaniem, by nasza aplikacja miała dostęp do danych, to lokalna kopia bazy. Działania na takiej bazie są zdecydowanie szybsze, niż ciągłe odpytywanie bazy zewnętrznej. Również nie musimy ciągle posiadać połączenia z siecią firmową, by móc korzystać z aplikacji. Zatem zobaczmy, jak wygląda baza mobilna i jak działa technologia Remote Data Access umożliwiająca synchronizację.
Microsoft SQL Server Compact
Mobilna baza w aktualnej wersji 3.5 daje spore możli-
46
wości i w większości przypadków nie odczujemy różnicy. Oczywiście nie mamy tutaj dostępu do procedur składowanych czy też do zaawansowanych funkcji T-SQL, ale za to dostajemy lekką bazę danych, którą możemy łatwo przenosić i co najważniejsze zarządzanie nią nie sprawia żadnego kłopotu. Ponieważ temat bazy SQL Server Compact został dogłębnie omówiony w artykule pt. „MS SQL Server CE 3.5 – Jak wykorzystać w swojej aplikacji silnik SQL Server CE 3.5” przez Łukasza Strąka w Biblii Programisty (SDJ Extra Nr 34 z 2009 roku), to tutaj przedstawię jedynie podstawy budowy bazy mobilnej w kontekście synchronizacji, tak by można było od razu przejść do dalszej części artykułu bez obaw, że będą jakieś braki w wiedzy. Odsyłam jednak do artykułu w celu dogłębnego zbadania tematu bazy mobilnej. Podstawową funkcją wersji Compact jest przechowywanie lokalnych kopii bazy danych firmowych instancji, lecz także tutaj wprowadzono pewne ograniczenia, o których opowiem nieco później.
9/2010
Remote Data Access
Kolejną ogromną zaletą tej wersji jest jej oszałamiający rozmiar. To zaledwie 1.8MB, przy czym instalacja jest wymagana w przypadku wersji starszych, niż Windows Vista, gdyż na tym systemie SQL Server Compact jest już instalowany automatycznie. Jak już wspomniałem, ta wersja jest zintegrowana całkowicie z aplikacją, przez co nie wymaga administratora, oraz jest to pojedynczy plik. Zabezpieczenia są tu na poziomie plików oraz dostępne jest także szyfrowanie i EFS (Encrypted File System to zintegrowana z systemami Windows technologia umożliwiająca zabezpieczenie zapisanych danych). Działa w trybie In-Proc, dzięki czemu nie występują żadne dodatkowe usługi systemowe. Możemy tworzyć wiele połączeń do danych, mamy dostępną obsługę transakcji. To wszystko to dane inżynieryjne, lecz to, co powinno interesować programistów, to fakt, iż jest dostępne wsparcie ADO.NET oraz technologii LINQ, a synchronizacja występuje w różnych trybach, nad którymi skupimy się podczas omawiania Sync Services, jak i nad problemami wynikającymi z synchronizacji. Należy tu wspomnieć o jeszcze jednej ważnej rzeczy. Podczas pracy z mobilnymi bazami możemy zauważyć, dodając referencje w naszych solutions do baz, iż wersja najnowszej bazy (SQL Server Compact 3.5), to 3.5.0.0, a wcześniejszej SQL Server Compact 3.1, to 9.0.242.0.
Zadając to pytanie programistom, nie zawsze otrzymamy odpowiedź, jednak zadając to same pytanie administratorom baz danych, to odpowiedź otrzymamy niemal natychmiastowo. Wcześniejsza wersja SQL Compact była częścią SQL Server, która była w wersji 9.0, od wersji 3.5 Microsoft zdecydował, iż produkt ten będzie osobnym produktem samym w sobie, a numerację zaczęto od 3.5, jak numer wersji SQL Compact, zamiast od 1.0. Czasem bywa to mylące, bo żaden inny produkt w wersji nowszej nie ma numeru mniejszego od wersji poprzedniej. Rozpocznijmy nowy projekt mobilny, otwierając Visual Studio 2008 (dla pisania aplikacji mobilnych wymagane jest Visual Studio od wersji Standard. Wersje Express nie wspierają systemu Windows Mobile). Dodajemy nowy projekt, klikając w File, a następnie New/ Project... . W nowym oknie jako Project types wybieramy Smart Device. Teraz możemy wpisać nazwę projektu, jak również nazwę całej solucji lub pozostawić domyślne nazwy. Poprawne ustawienia prezentuje Rysunek 1. W kolejnym oknie wybieramy Target platform, czyli platformę, na którą dedykowana jest nasza aplikacja. Windows Mobile 5.0 Pocket PC SDK jest bardzo dobrym wyborem, jeśli nie instalowaliśmy dodatkowych SDK dla kolejnych wersji, przy czym dla naszego przykładu nie ma to znaczenia, gdyż baza SQL
Rysunek 1. Dodanie nowego projektu
www.sdjournal.org
47
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
Server Compact, jak i RDA (Remote Data Access) na platformach Windows Mobile technologia ta działa dokładnie tak samo. Jako .NET Compact Framework version polecam wybrać .NET Compact Framework Version 3.5, a Templates wybieramy Device Application. Rysunek 2 przedstawia poprawne ustawienia. Nim przejdziemy do przystosowania formatki i napisania odpowiedniego kodu, zacznijmy od poznania bazy SQL Server Compact. Nową bazę możemy dodać, klikając w nazwę projektu prawym klawiszem myszki i z menu wybieramy Add/New Item. W nowym oknie wybieramy Database File. Po kliknięciu przycisku ADD automatycznie zostanie dodana nowa baza do solucji i pojawi się nowe okno „Data Source Configuration Wizard”. W tym oknie klikamy w Cancel z dwóch powodów. Po pierwsze, jest to nasza baza testowa, której nie będziemy prezentować na formatkach, więc nie potrzebujemy komponentu DataSet, a po drugie, nie mamy tabel w bazie, na podstawie których można by zbudować jakikolwiek model. Otwieramy teraz Server Explorer, klikając w View/Server Explorer. Rozwijamy listę Data Connections i odszukujemy naszą bazę, którą również rozwijamy i klikamy prawym klawiszem my-
szy w Tables, po czym z menu wybieramy Create table. W Name wpisujemy nazwę naszej tabeli i wypełniamy odpowiednie elementy tabeli, jak Column Name i inne. Przykładowa tabela jest pokazana na Rysunku 3. W taki sposób dodaliśmy nową bazę, jak również nową tabelę. Następnie możemy dokonywać modyfikacji samej tabeli, jak również dodać do niej dane poprzez kliknięcie prawym klawiszem myszy na nazwę tabeli i z menu wybraniu Show Table Data. Zostanie wyświetlona zawartość tabeli, która zaraz po utworzeniu jest pusta, lecz możemy w tym miejscu także dodawać nowe elementy. Kolejnym sposobem jest napisanie zapytania w języku SQL. Skoro wiemy, jak łatwo można dodać bazę do projektu i jak na niej działać, przejdźmy do głównego tematu artykułu, czyli synchronizacji bazy mobilnej z bazą firmową. Jeśli nie potrafisz pobrać danych z bazy i wyświetlić ich na formatce, nie przejmuj się. W dalszej części artykułu zostanie to pokazane.
Tradycyjna Komunikacja Klient-Serwer
Rysunek 4 przedstawia schemat standardowej aplikacji klient-serwer.
Rysunek 2. Ustawienia projektu
48
9/2010
Remote Data Access
Widzimy tutaj, iż w firmie zainstalowano serwer bazodanowy, do którego klienci mają dostęp teoretycznie bez przerwy. Czy tak jest na pewno? Czy zawsze mamy taki nieograniczony dostęp do zasobów serwera bazodanowego? Wyobraźmy sobie sytuację, w której jedziemy, jako przedstawiciel firmy X, do klienta, i prezentujemy mu nasz produkt. W pewnym momencie okazuje się, że nie mamy dostępu do Internetu, a nasza aplikacja nie jest w stanie działać bez odpowiednich danych, które są zawarte na serwerach firmy. W tym przypadku stajemy się bezsilni i musimy odwołać spotkanie. Brak połączenia z Internetem to tylko jeden problem tego rozwiązania. Nawet gdy mamy połączenie z Internetem, to wciąż nie mamy pewności, czy będziemy w stanie połączyć się z serwerami firmy. Wystarczy, że wystąpi jakikolwiek problem w łączach wewnątrz serwerowni w firmie, lub serwer baz danych ulegnie uszkodzeniu. To ciągle nie jest takie najgorsze, gdyż możemy mieć połączenie z Internetem, możemy mieć dostęp do bazy danych, lecz
ciągle możemy mieć problemy z otrzymywaniem danych, które są nam potrzebne, ponieważ obciążenie serwera może być tak duże, że dane będą zbyt wolno do nas docierać. W końcu sami możemy być powodem obciążenia sieci na tyle, że zostaniemy odcięci od jej zasobów. Tak to wygląda od strony osoby, która korzysta z aplikacji klient-serwer, lecz jak na to wszystko patrzy programista? Jakie problemy czekają na nas, projektując tego typu aplikacje? Oczywiście są to wszystkie czynniki wymienione wcześniej, na które nikt nie ma wpływu. Czas naprawy jednych to czasem chwila, a na naprawę innych przyjdzie nam trochę poczekać. Programiści mogą się spotkać z kolejnymi dodatkowymi problemami, o których użytkownik aplikacji nawet może nie mieć pojęcia. Dokonywanie jakichkolwiek zmian w bazie danych jest często niemożliwe, ponieważ musimy najpierw poprosić o zgodę administratora baz danych. Nierzadko bywa tak, iż na odpowiedź przyjdzie nam trochę po-
Rysunek 3. Dodanie nowej tabeli
www.sdjournal.org
49
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
czekać, a do tego nie zawsze jest to zezwolenie na zmianę. Czasem tak trywialna sprawa, jak dodanie indeksu lub dodanie procedury składowanej bywa problemem między programistą a administratorem, przez co mamy niepotrzebne przerwy w tworzeniu oprogramowania, co jest jednoznaczne z niezadowoleniem klienta, który musi dłużej czekać na naszą aplikację, co jednocześnie powoduje złe relacje z szefami. W taki sposób, jako programiści, będziemy musieli sobie poradzić z wieloma niedogodnościami.
Zobaczmy, Jak Synchronizacja Prezentuje Się W Teorii
Rysunek 5 przedstawia schemat synchronizacji. Remote Data Access jest mechanizmem wspomagającym synchronizację pomiędzy bazą umieszczoną na specjalnie do tego celu wyznaczonym serwerze a bazą przenośną. Przy pomocy RDA możemy wysyłać informacje, jak również je pobierać z i do serwera. Programista ma tu dostęp do odpowiednich klas Push, która umożliwia wysłanie danych na serwer, jak również Pull, która pobiera informacje z serwera. Czas takiej synchronizacji jest uzależniony od ilości danych, które wymagają synchronizacji, oraz to, jak szybkie, oraz jak bardzo obciążone jest nasze łącze.
Przygotujmy Interfejs Dla Naszej Aplikacji
Zaczniemy od przygotowania interfejsu dla naszej aplikacji. Dodajmy nową bazę mobilną, która będzie
odzwierciedlać przykładową bazę dostępną na serwerze bazodanowym. Przykładowa baza będzie posiadać jedną tabelę Customers, a w niej CustomerID, oraz FirstName. Przygotujmy taką samą bazę na serwerowej wersji bazy (musimy także ustawić, by z serwerem można było się łączyć zdalnie, oraz dodajemy konto użytkownika do bazy). Dodajmy także jednego klienta do bazy, tak by po synchronizacji był widoczny nowy wpis. Kolejnym etapem będzie dodanie komponentu DataSet do naszej aplikacji. Dodajemy go, klikając w Data/Show Data Sources, a następnie w Add New Data Source... . W pierwszym oknie wybieramy Database i klikamy w Next. W kolejnym oknie łączymy się z naszą bazą mobilną, która powinna być na rozwijanej liście, a następnie dodajemy naszą tabelę Customers i klikamy w Finish. Na formatkę przeciągamy komponent Customers z okna Data Sources, a następnie lekko zmieniamy wygląd naszej formatki, edytując dodany komponent DataGrid, jak również tytuł okna. Dodajemy także małe menu. Po lewej stronie ustawiamy tekst Wyjście, a po prawej Sync i dodajemy dwa podmenu: Pobierz i Wyślij. Nasza aplikacja obecnie będzie wyglądać, jak ta przedstawiona na Rysunku 6.
Instalacja SQL Server Compact 3.5 SP1 Server Tools, Oraz Konfiguracja Web Synchronization
Pierwszym etapem umożliwiającym synchronizację jest pobranie oraz instalacja komponentu Microsoft SQL Server Compact 3.5 SP1 Server Tools. Ważne jest, by uprzednio mieć zainstalowany, oraz poprawnie skonfigurowany serwer www, w naszym przypadku wymagany jest IIS. Jeśli naszą maszyną deweloperską jest maszyna z systemem Windows XP, to nie ma jakiegokolwiek problemu z kompatybilnością, jeśli jednak jest to Windows Vista czy też Windows 7, to należy dodać wszelkie komponenty wspierające IIS 6. Teraz uruchamiamy Web Synchronization Wizard i przeprowadzamy konfigurację naszego „serwera”. Po dokonaniu konfiguracji rezultat możemy sprawdzić, otwierając przeglądarkę i wpisując adres: http: Listing 1. Wywołanie funkcji synchronizacji, oraz odświeżenie zawartości komponentu DataGrid private void menuItem3_Click(object sender, {
EventArgs e)
ImportFromServer();
this.customersTableAdapter.Fill(this.sDJDemoDBDataSe
Rysunek 4. Standardowy schemat aplikacji klient-serwer.
50
}
t.Customers);
9/2010
Remote Data Access
//ip_serwera/folder/sqlcesa35.dll. Jako wynik powinniśmy otrzymać: „Microsoft SQL Server Compact Server Agent”. Warto także sprawdzić konfigurację emulatora. Należy podłączyć emulator do sieci przy pomocy narzędzia Devide Emulator Manager i otwierając przeglądarkę, wpisujemy ponownie ten sam adres. Wynik powinien także być ten sam.
Pobieranie I Wysyłanie Danych
Jeśli mamy skonfigurowane wszystkie elementy serwerowe, to pora przejść do najważniejszego elementu, jakim jest oprogramowanie przycisków Pobierz i Wyślij. Zacznijmy od przycisku pobierz. Jak ustaliliśmy, szybciej w bazie mamy jeden wpis, który chcemy pobrać do bazy lokalnej. Pod zdarzeniem Click przycisku „Pobierz” wpisujemy wywołanie funkcji, oraz odświeżamy DataGrid z zawartością. Listing 1 prezentuje przykładowy kod.
Rysunek 6. Interfejs aplikacji
Rysunek 5. Schemat synchronizacji
www.sdjournal.org
Następnie dodajemy nową funkcję ImportFromServer oraz DeleteTable. Pierwsza funkcja dokonuje pobrania danych z serwera, natomiast druga czyści bazę przed dokonaniem synchronizacji. Listing 2 prezentuje kod. Omówmy teraz szczegółowo, co dzieje się w kodzie. Na początku deklarujemy trzy stałe. Pierwsza z nich reprezentuje połączenie do bazy na serwerze, druga wskazuje na komponent synchronizacji, który jest dostępny poprzez IIS, a na samym końcu podajemy lokalizację bazy danych. By razem z projektem była dodawana baza, w jej opcjach musimy ustawić właściwość Copy to Output Directory na Copy always. Następnie pokazujemy komponentowi SqlCeRemoteDataAccess, jaka jest lokalizacja naszej witryny, oraz gdzie znajduje się lokalna baza. Przed każdą synchronizacją na bazie nie możemy posiadać tabeli, którą synchronizujemy, dlatego też uprzednio musimy ją usunąć, co wykonuje metoda DeleteTable. Następnie tworzymy zapytanie, które pobierze interesujące nas elementy z wybranej tabeli. W zapytaniach tego typu najlepiej dodać klauzulę WHERE, by ograniczyć ilość wyników, a ostatecznie dokonujemy pobrania danych.
51
PROGRAMOWANIE URZĄDZEŃ MOBILNYCH
Kilka słów na temat zapytania do bazy. W przykładzie zostaną pobrane wszystkie elementy tabeli, co nie jest najlepszym rozwiązaniem. Powinniśmy tutaj wybrać tylko te elementy, które nas interesują. Im mniej danych będziemy pobierać, tym krócej synchronizacja będzie trwała, a w późniejszym czasie nasza aplikacja będzie działać wydajniej. Jak już wspomniałem, warto także dodać klauzulę WHERE, która ograniczy ilość wyników. Jeśli tylko jesteśmy w stanie, to powinniśmy właśnie w tym miejscu jak najbardziej ograniczyć ilość danych przesyłanych przez serwer.
Jeśli tylko możemy, to ograniczamy ilość danych przesyłanych przez sieć i pamiętajmy, iż nasza aplikacja mobilna działa wydajniej na mniejszej ilości danych. Po pobraniu danych w DataGrid zostanie wyświetlony nowy element, który był dostępny na serwerze. W ten sposób jakiekolwiek wpisy dodane na serwerze możemy pobierać do aplikacji klienckiej. Wysłanie danych jest nieco łatwiejsze, gdyż nie musimy uprzednio usuwać tabeli z danymi. Listing 3 pokazuje, w jaki sposób możemy dokonać wysłania nowych danych na serwer.
Listing 2. Wywołanie funkcji synchronizacji public static void ImportFromServer() {
const string rdaOleDbConnectionString = @"Provider=SQLOLEDB.1;Data Source=Adres_IP,NR_Portu;Persist Security
Info=False;Initial Catalog=Nazwa_Bazy;User ID=Użytkownik;Password=Hasło;";
const string rdaUrl = @"http://Adres_IP/Katalog/sqlcesa35.dll";
const string localConnection = @"Data Source = \Program Files\Nazwa_Projektu\SDJDemoDB.sdf";
try {
Cursor.Current = Cursors.WaitCursor; var rda = new SqlCeRemoteDataAccess(rdaUrl, localConnection); DeleteTable("DROP TABLE Customers", localConnection); const string customers = "SELECT * FROM Customers";
rda.Pull("Customers", customers, rdaOleDbConnectionString, RdaTrackOption.TrackingOnWithIndexes);
}
MessageBox.Show("Synchronizacja zakończona powodzeniem."); catch (SqlCeException ex) {
MessageBox.Show("Wystąpił problem podczas synchronizacji!\r\nTreść błędu:\r\n" + ex.Message);
}
finally {
Cursor.Current = Cursors.Default;
}
}
private static void DeleteTable(string sql, string connection) {
var conn = new SqlCeConnection(connection); conn.Open();
var deleteTable = sql;
var comm = new SqlCeCommand(deleteTable, conn); comm.ExecuteNonQuery(); }
52
conn.Close();
9/2010
Remote Data Access
Listing 3. Wysłanie danych na serwer const string rdaOleDbConnectionString = @"Provider=SQLOLEDB.1;Data Source=Adres_IP,NR_Portu;Persist Security
Info=False;Initial Catalog=Nazwa_Bazy;User ID=Użytkownik;Password=Hasło;";
const string rdaUrl = @"http://Adres_IP/Katalog/sqlcesa35.dll"; const string localConnection = @"Data Source = \Program Files\Nazwa_Projektu\SDJDemoDB.sdf";
try {
var rda = new SqlCeRemoteDataAccess(rdaUrl, localConnection);
rda.Push("Customers", rdaOleDbConnectionString, RdaBatchOption.BatchingOn); rda.Dispose();
}
MessageBox.Show("Synchronizacja zakończona powodzeniem.");
catch (Exception ex) {
MessageBox.Show("Wystąpił problem podczas synchronizacji!\r\nTreść błędu:\r\n" + ex.Message); }
Wysyłanie danych jest bardzo skróconą wersją pobierania. Znowu deklarujemy trzy stałe, które wskazują na potrzebne komponenty, a następnie mówimy, co ma zostać wysłane na serwer. W tym przypadku wszystko, co zostało wyedytowane, dodane lub usunięte, zostanie przesłane na serwer bazodanowy. Elementy, które nie uległy zmianie lub nie są nowe, nie zostaną przesłane, co ograniczy ilość elementów, które mogłyby obciążyć łącze.
Podsumowanie
Pomimo iż tendencje odnośnie wyciągnięcia danych z bazy przechodzą pewną ewolucję w stronę wywołania odpowiednich web services, to synchronizacja z bazą przechowywaną lokalnie jest nadal w pewnych przypadkach jedyną możliwością dostarczenia danych dla naszej aplikacji. Jeśli ktoś poszukuje alternatywnych rozwiązań, to proponuję zainteresować się technologią Microsoft Sync Services for ADO.NET. Jest to technologia now-
sza, która także może być stosowana w aplikacjach mobilnych, jak i w aplikacjach desktopowych. W artykule pokazałem, jak przygotować całą infrastrukturę od instalacji komponentów serwerowych, a na aplikacji mobilnej kończąc. Co ciekawe, te same metody możemy wykorzystać do budowy aplikacji dekstopowej. Tak więc jeśli dobrze przygotujemy klasy wykonujące synchronizację, to bez jakichkolwiek zmian możemy implementować je w projektach mobilnych, jak i desktopowych.
DANIEL DUDEK Zajmuje się programowaniem aplikacji mobilnych na systemach Microsoft Windows Mobile od ponad dwóch lat. Jest liderem Śląskiej Regionalnej Grupy Microsoft. Autor jest także prelegentem konferencji społecznościowych: http://msgroups.pl/speakerbiuro/Strony/DanielDudek.aspx Kontakt z autorem: dan.dudek@hotmail.com
W Sieci • • • • •
Strona dla programistów aplikacji mobilnych dla urządzeń z systemem Windows Mobile http://developer.windowsmobile.com Strona poświęcona programowaniu aplikacji mobilnych, zawarta jako część MSDN http://msdn.microsoft.com/pl-pl/ windowsmobile/default(en-us).aspx Witryna poświęcona urządzeniom mobilnym https://www.microsoft.com/windowsmobile/pl-pl/default.mspx Windows Mobile Marketplace – globalny sklep z aplikacjami Windows Mobile http://developer.windowsmobile.com/ Marketplace.aspx Witryna SQL Server Compact http://www.microsoft.com/sqlserver/2008/en/us/compact.aspx
www.sdjournal.org
53
PROGRAMOWANIE PYTHON
Kurs Pythona Odcinek 3: Model obiektowy Dwa pierwsze odcinki miały za zadanie zapoznać nas z podstawowymi cechami języka i środowiska Python. Ostatnią wielką niewiadomą pozostały dla nas klasy. Po ich poznaniu będziemy mogli uznać, że rozumiemy fundamenty Pythona. Do dzieła! Dowiesz się:
Powinieneś wiedzieć:
• Jak korzystać z wbudowanych oraz bibliotecznych klas i obiektów; • Jak zbudować własną klasę; • Czym są dekoratory.
• Jak zainstalować i uruchomić interpreter Python 2.6 ; • Jak używać wbudowanych w Pythona list, słowników, krotek i zbiorów.
M
odel klasowy Pythona składa się z dość prostej składni i funkcjonalności, która jest mieszanką systemów obiektowych znanych w C++, Perlu i Objective-C. Od każdego z tych modeli różni się jednak na tyle, że warto przejść przez wszystkie cechy klas pythonowych dokładnie.
Podstawowa klasa
Zacznijmy od razu od przykładu. Na Listingu 1 znajduje się prosty model klasowy, który prezentuje wszystkie podstawowe cechy języka. Prezentowane klasy opisują odpowiednio "grzałkę", "dmuchawę" oraz ich połączenie, czyli "suszarkę do włosów". Zwróć uwagę, że mimo tego, że nie omówiłem jeszcze żadnej kwestii dotyczącej klas, już jesteś w stanie dużo zrozumieć.
dami. O funkcjach zdążyliśmy sobie opowiedzieć sporo już ostatnim razem. Zdążyliśmy też wspomnieć o wbudowanych funkcjach i związanych z nimi funkcjach specjalnych mających w nazwie po dwa znaki "_" z przodu i z tyłu. W przypadku metod funkcje te nabierają szczególnego znaczenia, ponieważ pozwalają klasie implementować szereg opcjonalnych funkcjonalności takich jak ładna reprezentacja tekstowa w metodach __unicode__ i __str__ czy możliwość porównywania arytmetycznego ze sobą różnych obiektów danej klasy, w metodach __lt__ (mniejszy), __gt__ (większy), __eq__ (równy) itd. Jedną z takich metod specjalnych jest metoda __init__, nazywana w pewnym uproszczeniu konstruktorem [1]. To znaczy, że tworząc nowe obiekty, wywołujemy właśnie tę metodę:
Róbta co chceta
hairdryer = Hairdryer()
Najbardziej fundamentalną cechą klas i obiektów w Pythonie jest to, że nie ma w nich podziału na składowe publiczne i prywatne. Oznacza to, że każdy użytkownik danego obiektu ma pełen dostęp do wszystkich metod i pól zadeklarowanych w danej klasie. Użytkownikom Javy, C++ i C# wyda się to nie do pomyślenia, jednak taka decyzja powoduje szereg bardzo pozytywnych skutków, o czym powiemy sobie później. Ustalanie, jakie składniki klasy należą do jej wewnętrznej implementacji, jest możliwe przez konwencję, zgodnie z którą nazwy takich składników poprzedza się pojedynczym znakiem "_".
Metody
Funkcje znajdujące się wewnątrz klasy nazywamy meto-
54
normal_heater = Heater()
hot_heater = Heater(max_temp=80)
Jak widać, pierwszym argumentem metody _ _ init _ _ i wszystkich innych metod w klasach pythonowych jest self, czyli zmienna wskazująca na aktualny obiekt. Zmienna ta jest wpisywana do argumentów automatycznie podczas wywołania metody, więc nie musimy jej dodatkowo podawać, np.: >>> hairdryer.dry(5)
Heating to 40 degrees for 5 minutes. >>> hairdryer.max_temp 50
9/2010
Model obiektowy
>>> hot_heater.max_temp 80
automatycznie dołączy do wykonania metody pierwszy argument self wskazujący na obiekt hairdryer. Argument 45 trafi więc do zmiennej how _ long. Niektóre języki umożliwiają przygotowywanie wielu wersji tej samej metody, różniących się typem lub liczbą argumentów. W świecie Pythona taka możliwość nie jest potrzebna ze względu na obecność argumentów opcjonalnych. Przykład takiego argumentu mamy w konstruktorze klasy Heater, który przez to możemy wołać zarówno nie podając żadnych dodatkowych argumentów, jak również specyfikując niestandardową temperaturę maksymalną.
Pola
W prezentowanym na Listingu 1 przykładzie widać dwa przykłady pól: klasa Heater prezentuje pola klasowe, czyli takie, których wartość jest wspólna dla wszystkich obiekListing 1. Podstawowa struktura klas class Heater(object):
min_temp = 28 max_temp = 50
def __init__(self, max_temp=None): if max_temp:
self.max_temp = max_temp
def heat(self, temp, how_long):
if self.min_temp <= temp <= self.max_temp: print "Heating to", temp,
print "degrees for", how_long, "minutes."
else:
raise ValueError, "Temperature out or range."
class Blower(object):
def __init__(self):
self.blowing = False
def blow(self):
self.blowing = True
def stop(self):
self.blowing = False
class Hairdryer(Heater, Blower):
def __init__(self):
super(Hairdryer, self).__init__()
def dry(self, how_long): self.blow()
self.heat(40, how_long)
www.sdjournal.org
tów danej klasy. W klasie Blower w metodzie __init__() znajdziemy natomiast pola instancji, czyli takie, które są zawarte tylko w konkretnym obiekcie (czyli w pojedynczej instancji danej klasy). Inne języki posiadają podobne rozgraniczenie, nazywając często pola klasowe statycznymi. Ciekawą cechą, którą można zaobserwować w przykładzie, jest fakt, że w metodzie heat() klasy Heater odwołujemy się do pól klasowych tak, jak gdyby były one polami instancji. Jest to często używany skrót, który dodatkowo pozwala w razie potrzeby na przesłonienie danego pola klasowego polem instancji. Przykład takiej techniki znajduje się w konstruktorze klasy Heater, gdzie jeżeli podamy opcjonalny argument max_temp, konstruktor przesłoni nam domyślną wartość pola klasowego nowym polem instancji. Powoduje to, że klasa w ogólności zachowuje swoje domyślne ustawienie, ale obiekty mogą to ustawienie dostosowywać do własnych potrzeb.
Dziedziczenie
Jak widać w naszym przykładzie, Python obsługuje wielokrotne dziedziczenie. Jest to funkcjonalność stosunkowo rzadko wykorzystywana i głównie do "przyklejania" dodatkowej funkcjonalności do istniejących klas, tak też zrobiliśmy w naszym przykładzie, gdzie suszarka jest po prostu grzałką z dmuchawą. Klasy, po których dziedziczymy, wymieniamy po przecinku w nawiasach za nazwą klasy. Domyślnie, jeżeli nie chcemy dziedziczyć z jakiejś klasy, powinniśmy dziedziczyć z klasy object. Klasy, które nie dziedziczą po tym typie, są w świecie Pythona znane jako klasy starego stylu i posiadają szereg niewygodnych ograniczeń [2]. Stąd, jeżeli tylko możemy, powinniśmy dziedziczyć z object. Klasy, po których dziedziczymy w świecie Pythona, nazywamy klasami bazowymi. W każdym przypadku, kiedy Listing 2. Dziedziczenie z wbudowanego typu >>> class AttrDict(dict): ... ...
def __getattr__(self, attr):
... ... ...
try:
return self[attr]
except KeyError: return ''
>>> a = AttrDict()
>>> a['monty'] = 'python' >>> a['star'] = 'bucks' >>> a
{'star': 'bucks', 'monty': 'python'} >>> a.star 'bucks'
>>> a.monty 'python'
>>> a.bill ''
55
PROGRAMOWANIE PYTHON
chcemy odnieść się do jakiejś metody lub pola z klasy bazowej, możemy to zrobić bez żadnego kłopotu. Przykład widać w metodzie dry() klasy Hairdryer, która odwołuje się do metod blow() i heat() zdefiniowanych w klasach bazowych. Może się jednak zdarzyć sytuacja, że w aktualnej klasie definiujemy składnik o takiej samej nazwie jak występujący w klasie bazowej. Wówczas trzeba użyć konstrukcji super(), która umożliwia wykonanie metody lub uzyskanie dostępu do pola z klasy bazowej [3]. Po wbudowanych typach też można dziedziczyć, co prezentuje Listing 2. Mamy tam definicję magicznego typu, który jest jednocześnie słownikiem, ale także udostępnia elementy słownika jako swoje atrybuty. Jest to możliwe dzięki prostej implementacji specjalnej metody __getattr_ _. Dodatkowo w metodzie tej zapewniliśmy, że w przypadku odwołania się do nieistniejącego atrybutu otrzymamy pusty łańcuch znaków zamiast rzuconego wyjątku.
Pola są lepsze niż metody
W świecie Pythona bardzo często używaną cechą jest możliwość bezpośredniego odwołania się do pól danej klasy czy obiektu. Wywołania typu osoba.data_urodzenia lub samochod.silnik.pojemnoc są na porządku dziennym. Takie rozwiązanie ma szereg zalet, z których największą jest fakt, że tak pisany kod jest bardzo czytelny. Dodatkowo przez to, że odwołujemy się bezpośrednio do pola, wykonanie takiego żądania jest całkiem wydajne. Programiści Javy mogą w tym momencie zaalarmować, że takie zachowanie niesie za sobą zagrożenie! Mianowicie, możliwe, że później zmienimy architekturę naszej klasy i już nie będzie można bezpośrednio pobrać daty urodzenia danej osoby z pola, ale trzeba będzie wykonać metodę. W takim przypadku trzeba będzie edytować kod, który korzysta z danej klasy, a to jest czasochłonne i niebezpieczne. Na szczęście w Pythonie możemy się od tego odciąć poprzez właściwości, czyli specjalne pola, które tak naprawdę są metodkami wywołanymi za naszymi plecami. Przykład widzimy w Listingu 3. Za pomocą specjalnej konstrukcji nazywanej dekoratorem, którą poprzedzamy defi-
Przypisy
[1] Właściwie konstrukcją obiektu zajmuje się inna metoda _ _ new _ _ , a metoda _ _ init _ _ pozwala jedynie logicznie zainicjalizować dany obiekt. Jest to jednak zaawansowane zagadnienie i dla większości potrzeb można myśleć o _ _ init _ _ jako o konstruktorze obiektów danej klasy. [2] Jednym z takich ograniczeń jest brak dostępu do funkcji super(). [3] O tym, jaka to konkretnie klasa, definiuje zasada nazywająca się MRO (ang. Method Resolution Order). Jest to zaawansowany temat, dla ciekawskich: http:// www.enterthefoo.com/static/prez/mro/index.html lub http: //www.python.org/download/releases/2.3/mro/.
56
Listing 3. Właściwości >>> class Traditional(object): ...
field = 'A'
>>> t = Traditional() >>> t.field 'A'
>>> t.field = 'B' >>> t.field 'B'
>>> class Smart(object): ... ... ... ... ... ... ...
_data = 'A'
@property
def field(self):
return self._data
@field.setter
def field(self, value): self._data = value
...
>>> s = Smart() >>> s.field 'A'
>>> s.field = 'B' >>> s.field 'B'
>>> class Smart(object): ... ...
@property
...
def field(self): return 'A'
>>> s = Smart() >>> s.field 'A'
nicję metody, oznaczamy ją jako właściwość, czyli metodkę przebraną za pole. Jak widać, można nawet definiować grupy metod, które umożliwiają nadawanie takim "polom" nowych wartości. Morał z tej historii jest taki, że należy korzystać, kiedy się tylko da, z tradycyjnych pól. W razie potrzeby można je zamienić właściwościami, co ma tę dodatkową zaletę, że sposób korzystania z takiej klasy pozostaje cały czas prosty.
W następnym odcinku
W następnym miesiącu wykorzystamy wiedzę, którą zgromadziliśmy do operacji na plikach i przetwarzania tekstu. Do zobaczenia za miesiąc!
ŁUKASZ LANGA programuje w Pythonie od 8 lat, aktualnie współpracuje z STX Next, rozwijając oprogramowanie dla sektora bankowego. Prywatnie miłośnik muzyki fortepianowej, początkujący ojciec i mąż. Adres e-mail autora: lukasz@langa.pl.
9/2010
APLIKACJE BIZNESOWE
Zwinna jakość Strategie testowania i zapewnienia jakości w Agile W ostatnich latach zapanowała prawdziwa moda na lekkie metodologie wytwarzania oprogramowania. Szczególnie podejścia zwinne, Agile, takie jak Scrum, zdobywają sobie coraz więcej zwolenników. Szybko, tanio, bez zbędnej biurokracji, działające oprogramowanie na końcu każdej iteracji – ale czy przy zachowaniu wysokiej jakości? Dowiesz się:
Powinieneś wiedzieć:
• Jakie są główne wytyczne metodyk Agile w zakresie testowania i jakości; • Jakie są różnice pomiędzy realizacją projektów według metodyki Agile, a podejściem tradycyjnym (na przykładzie RUP).
• Podstawowa wiedza z zakresu realizacji projektów wg metodyk zwinnych; • Podstawowa wiedza z zakresu realizacji projektów wg tradycyjnych metodyk; • Podstawowa wiedza z dziedziny testowania i zapewnienia jakości.
J
ak zapewnić wysoką jakość produktu, jeżeli metodologia jego wytwarzania zakłada minimalizację dokumentacji projektowej / produktowej i maksymalizację szybkości dostarczenia rezultatów prac? Jak zagwarantować, że produkt, którego każdą działającą, potencjalnie gotową do wydania wersję, mamy dostarczyć w ciągu iteracji trwającej przykładowo zaledwie dwa tygodnie? Podejścia Agile są lekkie, zwinne, szybkie – ale czy dostarczają jakości równej podejściom tradycyjnym, które choć z pozoru czasochłonne i nieefektywne, przynajmniej produkują pełną, kompletną dokumentację, na której w razie potrzeby testerzy mogą się oprzeć? Na pierwszy rzut oka, dla osób dotychczas pracujących w metodykach tradycyjnych, ciężkich, podejście Agile jest często nieakceptowalne. Jak to? Nie ma dokumentacji? To jak mamy testować? Nie trzeba zgłaszać szczegółowych raportów błędów, wystarczy pokazać developerowi defekt w aplikacji i poczekać, aż naprawi? A monitorowanie defektów, a ich obsługa, cała procedura zarządzania defektami? Agile z pozoru może wydawać się zbyt luźne, bez podpory w postaci procedur, wytycznych, dokumentacji, rozbudowanych procesów zarządzania zmianą czy defektami. Słowem – nieco (lub dla niektórych bardziej, niż nieco) chaotyczne i niezorganizowane. Spróbujmy przełamać ten stereotyp i poznać Agile lepiej.
58
Agile, czyli jak zwinnie prowadzić projekt
Na czym polega wytwarzanie Agile? Dlaczego miałoby być lepsze, efektywniejsze, korzystniejsze, niż dotychczasowe metodyki? Nie ma oficjalnej definicji zwinnego wytwarzania oprogramowania – niektórzy wskazują na Manifest Agile, jako na wartości i zasady będące wyznacznikiem tego podejścia. Warto jednak przytoczyć definicję sformułowaną przez Scotta Amblera, głównego metodyka Agile w IBM Kanada. W jego rozumieniu Agile to: Iteracyjne i przyrostowe podejście do wytwarzania oprogramowania, wykonywane w ścisłej współpracy przez samo-organizujące się zespoły wewnątrz efektywnego środowiska zarządczego, z tylko taką ilością ceremonii, by wytworzyć wysokiej jakości oprogramowanie w efektywny pod względem kosztu i czasu sposób, które spełnia zmieniające się potrzeby udziałowców. Proces wytwarzania oprogramowania znany pod nazwą Agile (ang. zręczny, sprawny) jest podejściem skupionym na produkcji oprogramowania (jego komponentów, działających modułów) i demonstracji wyników prac udziałowcom w możliwie małych odstępach czasu – aby uniknąć rozbieżności pomiędzy wymaganiami i oczekiwaniami klienta a developerską wizją lub interpretacją owych wymagań. Agile należy do lekkich metodologii projektowania oprogramowania. W odróżnieniu od koncepcji starszych, ciężkich, takich jak RUP (Rational Unified Process), w których nakład pracy przeznaczanej na
9/2010
Zwinna jakość
samą dokumentację projektową osiąga wartość 50%, Agile preferuje bezpośrednią komunikację z klientem. W rozumieniu koncepcji Agile, miarą postępu projektu jest ilość działających komponentów, nie ilość dokumentacji. Ponieważ ilość dokumentacji produkowanej przy wykonywaniu projektów zgodnie z Agile jest mniejsza, niż w przypadku tak zwanych tradycyjnych metodologii, kluczowym dla powodzenia projektu czynnikiem jest zgrany zespół, którego członkowie darzą siebie wzajemnym zaufaniem i potrafią efektywnie komunikować. Warunkiem koniecznym jest także co najmniej poprawny poziom relacji pomiędzy wykonawcą (producentem oprogramowania) a zamawiającym (klientem) – gdyż wzajemne zrozumienie i ścisła ko- Rysunek 1. Cykl wytwarzania systemu w metodyce Agile munikacja jest jedną z podstaw sukcesu stosowania Agile. • inicjacyjne; Mniej dokumentacji, mniej formalizmu, większy nacisk • konstrukcyjne; na współpracę i samoorganizację – jak w takich warun- • wydań. kach zapewnić jakość? Jak upewnić się, że przy braku szczegółowych specyfikacji wymagań i pozostałej doku- Podejście do testowania i QA będzie inne w zależności mentacji projektowej, testowanie będzie efektywne, a na od tego, w której iteracji aktualnie się znajdujemy, np. wyjściu otrzymamy produkt wysokiej jakości? w iteracji konstrukcyjnej zastosujemy inne techniki i naAby zrozumieć strategie testowania i jakości Agile, na- rzędzia QA, niż używaliśmy w iteracji inicjacyjnej. leży najpierw pojąć ich miejsce w cyklu życia wytwarzania oprogramowania (SDLC – Software Development Li- Strategie testowania Agile fe Cycle). SDLC w ujęciu Agile prezentuje Rysunek 1. Rysunek 2 przedstawia elementy wchodzące w skład Projekty Agile są organizowane w tak zwane time boxy strategii testowania Agile – jak widać, strategia ta nie – iteracje. W metodyce Scrum określane są jako Sprinty. jest wcale uboga. Cykl życia Agile jest iteracyjny, ale i zawiera pewne elementy seryjności (ciągłości) – w zależności od kontekstu, Inicjacja projektu w jakim go rozpatrujemy. Ta seryjność wynika z faktu, że Inicjacja projektu – czyli inaczej Sprint 0 (w Scrum) lub w Agile istnieją przynajmniej 3 różne rodzaje iteracji: Iteracja 0 (w innych metodach Agile). Głównym zada-
Manifest Agile
Poprzez wytwarzanie oprogramowania oraz pomaganie innym w tym zakresie odkrywamy lepsze sposoby realizowania tej pracy. W wyniku tych doświadczeń zaczęliśmy przedkładać: • • • •
Ludzi i ich wzajemne interakcje (współdziałanie) ponad procedury i narzędzia; Działające oprogramowanie nad wyczerpującą dokumentację; Współpracę z klientem nad negocjację umów; Reagowanie na zmiany nad realizowanie planu.
Oznacza to, że wprawdzie doceniamy to, co wymieniono po prawej stronie, to jednak bardziej cenimy to, co wymieniono po lewej.
www.sdjournal.org
59
APLIKACJE BIZNESOWE
niem jest tu identyfikacja i zorganizowanie podejścia do testów oraz rozpoczęcie prac nad stworzeniem środowiska testowego. W fazie inicjacji wykonywana jest wstępna identyfikacja wymagań oraz architektury – co umożliwi zrozumienie zakresu projektu i wybór optymalnego w danej sytuacji podejścia do testowania. W zależności od zdefiniowanego zakresu, złożoności projektu oraz predyspozycji samego zespołu Agile, można przyjąć następujące strategie organizacji prac testowych: • •
Kompletny zespół Niezależny zespół testowy
programiście błąd w aplikacji, a ten może go niemal natychmiast poprawić. Podejście niezależnego zespołu testowego można rozpatrywać jako strategię zaawansowaną. Podejście kompletnego zespołu jest dobre i efektywne, jeżeli stosujemy je przy względnie prostych sytuacjach. W złożonych, trudnych, wymagających specjalistycznej wiedzy dziedzinowej, projektach, testowanie przez sam zespół może okazać się niewystarczające. Na przykład, jeśli rozwijany system dotyczy obszaru z zakresu ubezpieczeń, przepisów prawnych, rachunkowości etc., gdzie wymagana jest bardzo szczegółowa, specjalistyczna wiedza dziedzinowa – zespół developerski nie będzie w stanie go prawidłowo i dokładnie przetestować. W tej sytuacji konieczne jest zapewnienie wsparcia z zewnątrz. Takim wsparciem jest niezależny zespół testowy. Będzie on wykonywał testy równocześnie z pracami prowadzonymi przez zespół developerski, skupiając się na testowaniu tych obszarów, których nie są w stanie zweryfikować członkowie kompletnego zespołu. Dodatkowo, ponieważ niezależny zespół testowy tworzą specjaliści, będą wykonywać bardziej złożone formy testowania – nie tylko testowanie potwierdzające (a do tego dość często ograniczają się testy wykonywane przez kompletny zespół). Niezależne zespoły testowe zazwyczaj wspierają wiele zespołów projektowych – nie tylko jeden, co mogłoby
Ponadto, jak już wspomniano, w fazie inicjacji organizowane jest środowisko testowe. Strategia kompletnego zespołu opiera się na założeniu, że zespół developerski musi składać się z osób posiadających wszelkie wymagane do osiągnięcia sukcesu umiejętności – czyli nie tylko samych programistów, ale i ludzi z umiejętnościami analitycznymi, projektowymi, przywódczymi i testowymi. Zespół Agile ma być w pewnym sensie samowystarczalny, ma być w stanie wykonać wszystkie związane z implementacją systemu zadania – programowanie, dokumentowanie, zarządzanie, testowanie. W podejściu kompletnego zespołu odchodzi się od specjalizacji, powszechnej w podejściu tradycyjnym – nie wystarczy tylko testować czy tylko programować; członkowie zespołu mają być w stanie wykonywać różne zadania i aktywnie wspierać zespół w każdy możliwy sposób. Niewątpliwą korzyścią takiego podejścia jest możliwość nauki i poszerzania kwalifikacji – członkowie zespołu, mniej biegli w danej kwestii, uczą się od kolegów, w zamian dzieląc się swoją wiedzą oraz umiejętnościami. Testowanie w podejściu kompletnego zespołu jest organizowane i realizowane w sposób całkowicie odmienny od tego przyjętego w podejściach tradycyjnych. Testerzy nie czekają już, aż programiści napiszą kod, przygotują odpowiednią wersję systemu (lub komponentu) do testowania i przerzucą do nich pałeczkę. Zamiast tego – pracują ramię w ramię z programistami, weryfikując wyniki prac na bieżąco. Dzięki temu znacznie skraca się czas uzyskiwania informacji zwrotnej, czas wykrywania defektu i jego poprawy. Minimalizuje to również konieczność tworzenia szczegółowych raportów błędów – gdyż tester może zwyczajnie pokazać Rysunek 2. Elementy strategii testowania Agile
60
9/2010
Zwinna jakość
się okazać nieefektywne pod względem kosztu. W większości organizacji IT równocześnie pracuje co najmniej kilka zespołów developerskich, można więc zapewnić im wszystkim wsparcie zespołu testowego i osiągnąć wymierne korzyści, np. minimalizację ilości licencji na narzędzia testowe oraz ilości samych narzędzi, oszczędność na środowiskach sprzętowych, które będą mogły być dzielone pomiędzy wieloma projektami, oraz optymalne wykorzystanie zasobów ludzkich.
Z pozoru może się wydawać, iż niezależny zespół testowy jest tym samym, co tradycyjne zespoły QA. Jednak nie jest tak – niezależne zespoły testowe Agile pracują w odmienny sposób. Skupiają się na mniejszej części prac testowych (ponieważ większość i tak jest wykonywana przez zespół developerski), za to na tej trudniejszej części, wymagającej specjalistycznej wiedzy, technik, narzędzi. W odróżnieniu od zespołów tradycyjnych nie testują wszystkiego, ale koncentrują się na tych
Iteracje w Agile
Iteracja 0. Jest to iteracja początkowa. W złożonych projektach może ich być wiele – niekoniecznie tylko jedna. Celem Iteracji 0 jest zainicjowanie projektu – czyli pozyskiwanie wstępnych, wysokopoziomowych wymagań, identyfikacja zarysu architektury, organizowanie zespołu projektowego (zarówno ze strony dostawcy IT, jak i klienta), pozyskiwanie funduszy itp. Czynności testowania i QA na tym etapie mogą obejmować identyfikację środowiska testowego, narzędzi, które będą potrzebne, w miarę możliwości – określanie optymalnego podejścia do testowania oraz przeglądy tworzonej dokumentacji projektowej. Iteracje konstrukcyjne. Celem każdej iteracji konstrukcyjnej jest dostarczenie potencjalnie gotowego oprogramowania (ang. potentially shippable software). Zespoły Agile stosują przy implementacji zasadę priorytetyzacji wymagań – każde wymaganie ma ustalony priorytet; w każdej iteracji implementowane są wymagania o najwyższym priorytecie. W metodykach zwinnych, testerzy zwykle należą do zespołu developerskiego, ściśle współpracując z programistami. Dlatego testowanie odbywa się równocześnie z developmentem. Równoległe niezależne testowanie. Mimo że w zespole developerskim znajdują się testerzy i testowanie wykonywane jest praktycznie stale, dobrą praktyką jest zaangażowanie niezależnego zespołu testerów, wspierającego weryfikację produktów prac. Niezależny zespół łatwiej znajdzie defekty, przeoczone przez zespół developerski, ponadto posiada bardziej zaawansowane umiejętności testowania i jest w stanie wykonać testy, które są poza zakresem możliwości developerów – np. testy integracyjne systemu, testy bezpieczeństwa, użyteczności etc. Iteracje wydań. W tych iteracjach następuje instalacja systemu w środowisku produkcyjnym. Wiążą się z tym również czynności dodatkowe: szkolenia użytkowników końcowych i administratorów, potencjalne poprawki defektów i awarii, wdrożenie pilotowe/stabilizacja systemu, finalizacja dokumentacji systemowej i użytkowej etc. W iteracjach wydań nadal wykonywane jest testowanie, choć mniej intensywnie, niż w iteracjach konstrukcyjnych. Celem tego testowania jest upewnienie się, że system jest gotowy do pracy na produkcji i prawidłowo funkcjonuje w docelowym środowisku.
Wady i korzyści w podejściu kompletnego zespołu
Jak każde podejście, tak i kompletny zespół ma swoje wady i zagrożenia. Oto najważniejsze: • •
Myślenie grupowe. Jest to ryzyko występujące w każdym zespole, jednak zespoły Agile są na nie szczególnie narażone – głównie z tej przyczyny, iż ich członkowie ściśle ze sobą współpracują i z biegiem czasu zaczynają myśleć w podobny sposób. W efekcie – mogą przestać dostrzegać pewne problemy, lub, odwrotnie, przeoczać możliwości. Brak niezbędnych umiejętności. Może to wynikać z przecenienia swoich umiejętności przez niektórych członków zespołu. Przykładowo – przy planowaniu prac testowych zidentyfikowano potrzebę wykonania testów użyteczności. Zespół developerski zadeklarował posiadania takich umiejętności (ponieważ jedna osoba twierdziła, że ma w tym wystarczającą wiedzę i doświadczenie) i brak konieczności zatrudniania specjalisty w tym obszarze. W praktyce może okazać się, że rzekome umiejętności w obszarze testów użyteczności są zbyt małe, by sprostać wymaganiom (np. klienta), co z kolei naraża projekt na niepowodzenie lub dodatkowe koszty – zlecenia wykonania testów użyteczności zewnętrznemu zespołowi czy koszty poprawy defektów zgłoszonych przez klienta, a dotyczących niedociągnięć w aspektach usability.
Jednak korzyści przeważają nad potencjalnymi problemami. • •
•
Zwiększona produktywność. Wynika to głównie ze zmniejszenia, a często całkowitego wyeliminowania, czasu oczekiwania pomiędzy programowaniem a testowaniem Mniejsza biurokracja. Nie ma potrzeby produkowania mnóstwa dokumentacji, takiej jak szczegółowe plany testów, raporty błędów etc. W podejściach tradycyjnych często konieczne jest tworzenie wielu dokumentów, a to z powodu przekazywania pracy pomiędzy odrębnymi zespołami (np. pomiędzy testerami a programistami). W podejściu Agile, większość prac wykonuje jeden zespół, ściśle ze sobą współpracujący, i wymiana informacji obywa się głównie poprzez bezpośrednią komunikację. Ciągłe uczenie się. W zespołach Agile członkowie zespołu uczą się od siebie nawzajem. Szczególnie widoczne jest to w pierwszych tygodnia tworzenia się zespołu – programiści nabywają umiejętności testowania, testerzy zapoznają się z kodowaniem – w wyniku tego wszyscy doskonalą swoje umiejętności i wykonują lepszą pracę (ponieważ świadomość tego, że programista będzie brał udział w testowaniu, wpływa na niego motywująco; będzie dążył do napisania kodu o jak najwyższej jakości).
www.sdjournal.org
61
APLIKACJE BIZNESOWE
aspektach, których nie może zweryfikować zespół developerski.
Tworzenie środowiska testowego
Inicjacja projektu wiąże się z koniecznością przygotowania środowiska testowego – obszaru pracy, sprzętu, narzędzi etc. Można wykorzystać już istniejące środowiska – o ile oczywiście takowe są, i o ile odpowiadają wymaganiom danego projektu. Jeśli jednak środowisk nie ma – należy przygotować je od podstaw. Praktycy Agile zalecają tu kilka strategii: •
•
•
Stosowanie narzędzi open source. Dotyczy to zarówno narzędzi dla developerów – do tworzenia oprogramowania oraz wykonywania testów jednostkowych, jak i dla niezależnego zespołu testowego. Stosowanie wspólnego systemu zarządzania defektami. Wspólnego, czyli dzielonego pomiędzy zespołem developerskim a niezależnym zespołem testowym. Dlaczego? Z prostej przyczyny – developerzy zapewne będą zgłaszać pewne błędy wewnętrznie i obsługiwać je w określonym narzędziu. To samo narzędzie powinno być dostępne zespołowi testowemu; wyeliminuje to konieczność zarządzania dwoma systemami śledzenia błędów oraz zwiększy przejrzystość sytuacji w projekcie. Ponadto – to samo narzędzie może być wykorzystywane jako system zarządzania zadaniami oraz zmianą, co znacznie zmniejsza wysiłek potrzebny do obsługi tych procesów i pozwala na ich swego rodzaju ujednolicenie. Stosowanie narzędzi do ciągłej integracji (ang. continuous integration (CI)) i ciągłej instalacji (ang. continuous deployment (CD)). Nie są to co prawda narzędzia testowe, ale znacząco wspomagają prace zespołu developerskiego przygotowującego wersje aplikacji do testów. Upraszczają również same developerskie testy regresji, wykonując pewne czynności za programistów (takie jak automatyczne budowanie aplikacji i jej instalacja we wskazanym środowisku).
Strategie testowania w zespole developerskim Jakie strategie przyjmuje sam zespół developerski? Jeśli testowanie opiera się na podejściu kompletnego zespołu, w której to zespół jest odpowiedzialny za większość – o ile nie całość – testowania, jakie metody i techniki są stosowane? Najczęściej zespoły developerskie Agile stosują następujące praktyki: • • • •
Ciągła integracja (CI) jest to praktyka stosowana w trakcie rozwoju oprogramowania, polegająca na częstej i regularnej integracji bieżących zmian wykonywanych w kodzie do głównego repozytorium. Członkowie zespołu Agile powinni co najmniej raz na każde kilka godzin, a najlepiej jeszcze częściej wykonywać następujące czynności: •
•
•
Rysunek 3. Poziomy TDD
62
ciągła integracja (ang. Continous Integration (CI)); ciągła instalacja (ang. Continuous Deployment (CD)); Wytwarzanie Kierowane Testami (ang. Test-Driven Development (TDD)); podejście testuj natychmiast po (ang. Test Immediately After).
zbudować system – co jest rozumiane zarówno jako kompilacja kodu, jak i ponowna budowa testowej bazy danych. W przypadku złożonych systemów, składających się z wielu podsystemów, należy rozważyć, czy za każdym razem konieczna jest budowa całego systemu, czy tylko podsystemów, w których dokonano zmian z kodzie. W ciągu dnia można na przykład budować tylko te składniki systemu, nad którymi pracowano, natomiast na noc uruchomić build całego systemu. uruchomić testy regresji – niekoniecznie pełny zestaw testów dla całego systemu, zwykle wystarczy jedynie podzbiór testów obejmujący zakres danego builda. Należy pamiętać, że ponieważ taki zestaw będzie uruchamiany kilka razy dziennie (po każdej budowie systemu czy podsystemu), testy powinny wykonywać się możliwie jak najszybciej. Nie będzie dobrym rozwiązaniem czekanie godzinę po zbudowaniu części podsystemu na wykonanie się wszystkich dostępnych testów regresji. Efektywniej jest uruchamiać tylko te testy, które sprawdzą zmienione elementy oprogramowania, a pełen zestaw testów wykonać np. w trybie nocnym lub weekendowym. wykonywać analizę statyczną. Zgodnie z definicją, analiza statyczna to analiza kodu źródłowego aplikacji przeprowadzona bez wykonywania oprogramowania. W tej technice automatyczne narzędzie sprawdza kod w poszukiwaniu defektów, takich jak problemy ze stylem kodowania, błędy zabezpieczeń etc.
9/2010
Zwinna jakość
Ciągła instalacja to kolejna przydatna, a często wykorzystywana przez zaawansowane zespoły Agile strategia. Koncepcja ta opiera się na automatyzacji instalacji stworzonego builda w określonym środowisku. Pozwala to szybko i sprawnie zainstalować w danym środowisku każdą nową wersję systemu celem na przykład udostępnienia jej testom (również niezależnym testom) lub w celach demonstracyjnych – by udostępnić osobom spoza zespołu projektowego wgląd w aplikację i monitorowanie bieżących postępów prac. Wytwarzanie Kierowane Testami (TDD) (ang. Test-driven development (TDD)) jest techniką tworzenia oprogramowania polegającą na wielokrotnym powtarzaniu następujących kroków: •
Najpierw programista pisze automatyczny test sprawdzający dodawaną funkcjonalność. Test w tym momencie nie powinien się udać. Następnie funkcjonalność jest implementowana. W tym momencie wcześniej napisany test powinien się udać. W ostatnim kroku programista wykonuje refactoring napisanego kodu tak, by spełniał on oczekiwane standardy.
• •
TDD łączy kilka elementów: •
Refactoring. Refactoring jest techniką, która polega na wykonywaniu małych zmian w istniejącym kodzie źródłowym (lub danych źródłowych) celem poprawienia projektu bez zmiany jego semantyki. Zmiany takie to na przykład: zmiana nazwy operacji w kodzie, wyrównanie pól i zastosowanie jednolitej czcionki na ekranach interfejsu użytkownika, podzielnie kolumn w bazie danych. Refactoring to nie tylko poprawki kosmetyczne – często są to zmiany drobne, ale znacznie poprawiające jakość kodu (i nie tylko kodu). Należy pamiętać, że celem refactoringu nie jest dodanie nowego kodu, a poprawienie tego, który już istnieje. Celem nie jest więc wy-
•
twarzanie nowej funkcjonalności, ale utrzymywanie odpowiedniej, wysokiej jakości organizacji systemu. W ramach refactoringu można wykonywać modyfikację elementów systemu w celu dopasowania ich do ustalonych standardów i wzorców lub pokusić się na poszukiwanie nowych standardów i wzorców, które pojawiły się w systemie w trakcie jego rozwoju i ich precyzyjne definiowanie (łącznie z wpasowywaniem istniejących elementów w te definicje). Refactoring umożliwia ograniczenie redundancji w systemie (nadmiarowości – np. w przypadku istnienia wielu obiektów i procedur o takiej samej lub bardzo zbliżonej funkcjonalności, a mających niezależne implementacje) i wprowadza standardy – co z kolei znacząco poprawia jakość kodu (a w perspektywie czasu i jakość procesu, gdyż programiści wykonujący refactoring jednocześnie uczą się dobrych praktyk). Wytwarzanie “najpierw test” (ang. Test-first development (TFD)). Podejście to polega na napisaniu w pierwszej kolejności pojedynczego testu, a następnie odpowiadającego mu kodu (w dokładniej takiej ilości, by ten test pokryć – nie mniej, nie więcej). Opisane jest to następującym prostym algorytmem: stwórz test oraz tyle kodu, by ten test dał wynik negatywny (1), wykonaj test, by upewnić się, że rzeczywiście daje wynik negatywny (2), następnie zmień kod tak, by test przeszedł z wynikiem pozytywnym (3), po czym wykonaj test jeszcze raz. Cały cykl się powtarza (dla kolejnych testów).
Zauważmy, że stosując podejście Wytwarzania Kierowanego Testami, powodujemy, iż przygotowywane testy stają się szczegółowymi, wykonywalnymi specyfikacjami. Dobrze napisane testy jednostkowe/developerskie dostarczają działającej specyfikacji kodu – czyli mogą stanowić istotną część dokumentacji technicznej. Analogicznie – testy akceptacyjne tworzą ważny element dokumentacji wymagań. Tworzenie wykonywalnych specyfikacji jest uważane za jedną z najlepszych praktyk Modelowania Agile.
Analiza statyczna
Istnieje kilka technik analizy statycznej. • •
• •
Analiza przepływu sterowania. Technika ta dostarcza informacji na temat logicznych punktów decyzyjnych w oprogramowaniu i o złożoności ich struktury. Analiza przepływu danych. Jest to ustrukturalizowana technika testowania, która sprawdza ścieżki pomiędzy tymi miejscami w kodzie, w których ustawiana jest wartość zmiennej, a miejscami, gdzie ta wartość jest użyta. Ścieżki te określane są jako pary definicja-użycie lub ustawienie-użycie. W tej metodzie zbiór testów generowany jest tak, aby pokryć 100% par (o ile jest to możliwe). Technika ta uwzględnia również przepływ sterowania w testowanym oprogramowaniu, monitorując ścieżki pomiędzy definicją i użyciem zmiennych – i tym samym sprawdzając instrukcje decyzyjne. Zgodność ze standardami kodowania. Analiza statyczna umożliwia ocenę zgodności kodu z określonymi standardami kodowania. To powoduje, że oprogramowanie będzie łatwiejsze do pielęgnacji i bardziej testowalne konkretne wymagania języków programowania. Generowanie miar kodu. Podczas analizy statycznej można generować miary kodu, np. rozmiar kodu, częstość występowania komentarzy, liczba poziomów zagłębień czy liczba wywołań funkcji.
www.sdjournal.org
63
APLIKACJE BIZNESOWE
Podejście testuj natychmiast po jest swego rodzaju alternatywą dla TDD. Podejście to można postrzegać (przynajmniej w pewnym sensie) jako skutek niekonsekwencji w stosowaniu TDD – gdyż w praktyce okazuje się, że członkowie zespołu Agile o wiele częściej piszą najpierw kod, a dopiero po tym kilka testów do walidacji owego kodu. Stosowanie czystego TDD wymaga bardzo dużej dyscypliny, wielu programistom jest po prostu łatwiej (i bardziej naturalnie) najpierw napisać kod, a dopiero później testy. Jeśli testy te są jednak napisane tuż po kodowaniu – czyli natychmiast po – podejście to jest niemal tak samo dobre, jak TDD. Gorzej, jeśli pisane są po kilku dniach, tygodniach czy w ogóle nie są pisane... Wsparciem dla podejścia testuj natychmiast po są wszelkiego rodzaju narzędzia do weryfikacji pokrycia kodu. Umożliwiają one programistom sprawdzenie, czy napisany przez nich kod ma pokrycie w testach. Niezależne równoległe testowanie Jak już wspomniano w poprzedniej części artykułu, podejście kompletnego zespołu nie zawsze wystarcza, by zapewnić dokładne testowanie i spełnienie oczekiwań udziałowców co do jakości produktu. Niezależny zespół testowy nie potrzebuje szczegółowej specyfikacji wymagań – ponieważ nie testuje całości funkcjonalności, a jedynie te obszary, których zespół developerski nie jest w stanie zweryfikować samodzielnie. Może jednak potrzebować diagramów architektury oraz listy zmian wykonanych w aplikacji od momentu, w którym ostatnio testował system. Kiedy należy rozważyć konieczność zaangażowania niezależnego zespołu testowego? Warto zastanowić się nad tym w następujących okolicznościach: •
•
64
Poziomy TDD •
•
•
•
Akceptacyjne TDD Polegają na stosowaniu TDD na poziomie wymagań – poprzez pisanie pojedynczego testu odpowiadającego i równoważnego testowi funkcjonalnemu lub akceptacyjnemu w podejściu tradycyjnym. Developerskie TDD Polegają na stosowaniu TDD na poziomie projektu - poprzez pisanie pojedynczego testu developerskiego.
niemal całkowicie na testowaniu potwierdzającym – czyli weryfikacji, iż zaimplementowali wszystko, co mi opisano. Złożona dziedzina problemu. W przypadku, gdy rozwijany system jest bardzo złożony, dotyczy skomplikowanej dziedziny (np. oprogramowanie krytyczne dla życia lub wspierające procesy finansowe), zespół developerski często nie ma możliwości (wiedzy, umiejętności, czasu czy narzędzi), by wykonać wystarczające testy. Wsparcie niezależnego zespołu testowego, wykonującego zaawansowane testy równolegle do podstawowych testów realizowanych stale przez zespół Agile może rozwiązać ten problem. Wymogi prawne. Niektóre projekty i oczekiwania ich udziałowców wymagają zapewnienia niezależności testów (ze względu na większy obiektywizm testerów niezależnych i tym samym prawdopodobień-
Brak zasobów. W wielu zespołach Agile nie ma zasobów (zarówno ludzkich, jak i sprzętowych) potrzebnych do realizacji testów integracji systemowej, użyteczności, bezpieczeństwa etc. Może również nie być ludzi posiadających wiedzę biznesową niezbędną do rzetelnego przetestowania aplikacji. W tej sytuacji rozwiązaniem jest niezależny zespół testowy, wyposażony w odpowiednie umiejętności i narzędzia do realizacji takich zadań. Testowanie dochodzeniowe. Niezależni testerzy mogą wykryć pominięte wymagania, czego raczej nie jest w stanie dokonać zespół developerski, skupiający się Rysunek 4. Elementy strategii jakości Agile
9/2010
Zwinna jakość
stwo, iż przetestowany niezależnie produkt będzie spełniał oczekiwania). Weryfikacja gotowości do pracy na produkcji. W wielu przypadkach, a szczególnie, gdy rozwijany system ma współpracować z wieloma innymi systemami, już działającymi produkcyjnie, udziałowcy projektu będą oczekiwać zapewnienia, iż oprogramowanie jest gotowe do pracy na produkcji oraz że jego instalacja nie będzie miała niepożądanego wpływu na zależne aplikacje. Aby odpowiednio to zweryfikować, może być konieczne testowanie naszego systemu razem z wersjami innych systemów, które są obecnie w trakcie wytwarzania – a to oznacza, że testerzy będą musieli mieć dostęp do aktualnych wersji różnych aplikacji w regularnych odstępach czasu. Najlepiej zlecić te prace niezależnemu zespołowi testowemu (zespół developerski może nie być w stanie uzyskać dostępu do wszystkich aplikacji i rzetelnie przetestować współpracę pomiędzy nimi), który będzie odpowiedzialny za realizację testów na poziomie integracji systemowej.
•
Zarządzanie defektami Zarządzanie defektami w podejściach tradycyjnych kojarzy się zwykle z mnóstwem defektów zgłaszanych cyklicznie (po każdym wydaniu nowej wersji systemu), długim czasem rozwiązania owych defektów, nieporozumieniami co do istoty problemu i sposobem rozwiązania, konfliktami pomiędzy developerami a testerami etc.
W zespołach Agile wygląda to diametralnie inaczej. W testowaniu wykonywanym przez kompletny zespół nie ma podziału na testerów i developerów oraz odseparowania prac implementacyjnych i testowych - zwykle kiedy znajdowany jest defekt, jest on na miejscu naprawiany, najczęściej przez osobę, która ów defekt umieściła w aplikacji. W praktyce wygląda to tak, że osoba programująca i osoba testująca siadają razem przy aplikacji, wspólnie testują i tester na bieżąco zgłasza swoje uwagi, które developer na bieżąco poprawia w kodzie. Tym sposobem cały cykl zarządzania defektami sprowadza się do rozmowy pomiędzy tymi ludźmi, niekonieczne jest nawet rejestrowanie błędu w systemie zarządzania defektami. Co więcej – po naprawieniu problemu, tester może od razu zweryfikować jego poprawność, ewentualnie zgłosić dalsze uwagi lub stwierdzić, iż poprawka spełnia jego oczekiwania. Cykl informacji zwrotnej jest niezwykle krótki – od kilkunastu minut do maksymalnie kilku godzin w przypadku złożonych, poważnych problemów. Nie dni czy nawet tygodni (w praktyce widziałam otwarte problemy wiszące w próżni przez parę miesięcy, ponieważ nie miał kto się nimi zająć), jak ma to miejsce w podejściach tradycyjnych! Jeśli w testowanie zaangażowany jest niezależny zespół testowy i pojawia się konieczność oficjalnego zgłaszania błędów w systemie zarządzania defektami, oba zespoły (niemal zawsze) używają tego samego systemu (porównajmy to z sytuacją w projektach tradycyjnych, gdzie bardzo często zespół developerski używa inne-
Tabela 1. Cykl informacji zwrotnej
Strategia Agile
Cykl informacji zwrotnej
Aktywny udział udziałowców
Minuty. Omówienie z udziałowcami problemu, zagadnienia, ich oczekiwań i uzyskanie informacji zwrotnej w czasie rzeczywistym.
Development non-solo
Sekundy. Wykonywanie pracy wspólnie z partnerem (partnerami), który na bieżąco ją weryfikuje i dostarcza informacji wejściowych oraz informacji zwrotnej co do wyników prac.
Wytwarzanie Kierowane Testami (TDD)
Minuty. Stworzenie testu, napisanie dokładnie takiej ilości kodu, by pokryć ten test, uruchomienie aplikacji oraz owego testu i sprawdzenie, czy to, co właśnie zostało zrobione – działa.
Non-solo Development – ile można zyskać?
Gdyby podejście non-solo nie było opłacalne, nikt by go zapewne nie stosował. Oto kilka kluczowych korzyści developmentu non-solo: • •
• •
Wyższa jakość. Podejście non-solo to ciągła weryfikacja, monitorowanie – słowem, przegląd i inspekcja. Wspólna praca nad jednym zadaniem powoduje, że łatwiej i szybciej wychwytywane są ewentualne pomyłki i błędy; szybciej i efektywniej są również poprawiane – ponieważ nie tylko osoba poprawiająca będzie weryfikować wynik poprawki, ale i jej partner. Wzajemna nauka. Wspólna praca oznacza dzielenie się wiedzą i umiejętnościami. Jeżeli przykładowo jeden programista z pary ma większe umiejętności w testowaniu, przekaże je swojemu partnerowi; jeśli jeden programista ma większe doświadczenie w kodowaniu, lepiej zna pewne techniki – nauczy ich kolegę. Tym sposobem zwiększamy kwalifikacje członków zespołu – a to z kolei w dłuższej perspektywie czasu przekłada się na wzrost efektywności pracy i jakości powstających produktów. Mniej biurokracji. Wzajemne uczenie się od siebie członków zespołu, lepsza i bezpośrednia komunikacja, krótki cykl informacji zwrotnej powoduje, że nie ma potrzeby produkowania dużej ilości zewnętrznej dokumentacji. Budowanie zespołu. Wspólna praca powoduje, że członkowie zespołu zbliżają się do siebie, mają poczucie wspólnego celu i skupiają się na jego osiągnięciu. Praca staje się bardziej zespołowa, w przeciwieństwie do podejścia tradycyjnego, które promuje bardziej postawę indywidualnego sukcesu.
www.sdjournal.org
65
APLIKACJE BIZNESOWE
go narzędzia do wewnętrznego zarządzania zadaniami i błędami, a zespół QA innego – co powoduje problemy z synchronizacją i aktualnością informacji: importować defekty z bazy testerów, czy zapewnić programistom dostęp do systemu używanego przez zespół QA?). Ponadto, zespoły Agile często łączą swoje strategie zarządzania wymaganiami i zarządzania defektami, by uprościć ogólny proces zarządzania zmianą. W podejściu Agile traktuje się w pewnym sensie jednakowo zarówno wymagania, jak i raporty błędów – dla zespołu developerskiego są to po prostu pewne rodzaje zadań (elementów pracy), które można potraktować równoważnie – są one szacowane, priorytetyzowane i układane na stosie elementów pracy. W takim podejściu nie ma nienienaturalnego czy wymuszonego – defekty są po prostu innym typem wymagań, podobnie jak wymagania są typem defektu – po prostu brakującą funkcjonalnością. Niektóre zespoły Agile idą o krok dalej i zbierają wymagania przy użyciu narzędzia zarządzania defektami, na przykład Bugzilli czy JIRY, które umożliwiają zarządzanie bardzo różnymi typami elementów pracy – od zadań, poprzez zmiany i sugerowane ulepszenia, wymagania, kończąc na defektach. Testowanie na końcu cyklu życia Testowanie nie ogranicza się do weryfikacji systemu podczas jego implementacji. Wiele zespołów Agile uważa za niezbędne wykonywanie pewnych testów również na etapie wydania gotowego oprogramowania. Niekoniecznie robią to developerzy – wręcz przeciwnie, zwykle prace te wykonuje niezależny zespół testowy, aby jak najlepiej i jak najbardziej obiektywnie ocenić, czy system jest gotowy przejść na produkcję. Jeżeli w trakcie całego cyklu życia systemu stosowano praktykę niezależnego równoległego testowania, wtedy testowanie na końcu cyklu życia może okazać się bardzo krótkie – ponieważ większa część funkcjonalności została już dokładnie przetestowana w wcześniejszych etapach. Z reguły takie końcowe testowanie skupi się na testowaniu systemu jako całości, bez wnikania w szczegóły pojedynczych funkcjonalności.
Strategie jakości Agile
W dodatku do strategii testowych Agile są jeszcze strategie jakości Agile. Strategie te obejmują elementy przedstawione na Rysunku 4. Zauważmy, że niektóre elementy strategii jakości są analogiczne do strategii testowania - np. Refactoring. Non-Solo Development Podejście non-solo polega na tym, że dwóch lub więcej ludzi wspólnie pracuje nad jednym zadaniem, zgodnie ze starą zasadą dwie ręce są lepsze, niż jedna. W podejściu non-solo, na przykład w Programowaniu w Parach (ang. Pair Programming), dwóch programistów (para) siada
66
przy jednym komputerze, jeden z nich pisze kod, a drugi na bieżąco weryfikuje wyniki pracy i dostarcza nowych koncepcji oraz uwag. Programiści systematycznie zmieniają się miejscami, co eliminuje ryzyko znużenia wykonywanymi obowiązkami i wprowadza pewną dynamikę. Inną praktyką non-solo jest Modelowanie z innymi (ang. Modelling with Others) polegające na tym, że kilka osób zbiera się przy wspólnym środowisku modelowania (np. zwykłej tablicy) i wspólnie pracuje nad przemyśleniem jakiegoś zagadnienia projektowego czy uszczegóławianiem wymagań. Można to porównać do burzy mózgów – tam, gdzie jedna osoba może napotkać problemy i nie radzić sobie z rozwiązaniem, więcej ludzi (szczególnie w tym przypadku – gdy każda z osób jest zaangażowana w przedmiot dyskusji i świadoma tematu) szybciej dojdzie do konstruktywnych wniosków. Takie podejście zdarza się i w projektach realizowanych metodami tradycyjnymi, jednakże nie na taką skalę jak w Agile, i nie w regularny sposób – co niestety przekłada się na mniejszą efektywność zespołów tradycyjnych. Można mieć wątpliwości, czy metody non-solo są efektywne. Jak to, pracuje właściwie tylko jedna osoba zamiast dwóch (w przypadku Programowania w Parach)? Jednak praktyka pokazuje, iż takie podejście jest efektywne i wydajne, i to o wiele bardziej, niż podejście tradycyjne. Dlaczego? Ponieważ pracując razem, ludzie wzajemnie się motywują, kontrolują, ponadto mają lepsze pomysły i dostarczają produktów wyższej jakości, niż gdyby pracowali indywidualnie, każdy na własny rachunek. Przeglądy i inspekcje Przeglądy to technika walidacji polegająca na tym, że zespół wykwalifikowanych ludzi poddaje produkt pracy krytycznej ocenie. Ocena ta dotyczy nie tylko stopnia spełnienia wymagań odbiorców czy też określonych standardów, ale i czy spełnia inne wymogi jakości, np. jest łatwy do rozwijania czy ulepszania. Przeglądom można poddać kod, oprogramowanie, dokumentację – słowem, każdy produkt projektu informatycznego. Niektórzy praktycy Agile uważają przeglądy za coś, co mogłoby być całkowicie zbędne, jeżeli proces wytwarzania byłby wcześniej realizowany efektywnie i przy zastosowaniu technik czy praktyk eliminujących problemy (wykryte przez przeglądy) w momencie ich powstawania. Przykładowo, w podejściu tradycyjnym według metodyki RUP (ang. Rational Unified Proces) przeglądy dokumentacji są nieodzowną częścią iteracji projektowania. Zwykle przeglądy takie wykazują mnóstwo usterek. Co to oznacza? To mianowicie, że popełniono wiele błędów podczas tworzenia tej dokumentacji, że proces dokumentacji jest efektywny, ponieważ daje produkty niskiej jakości. Czy przegląd pomaga zapewnić jakość, poprawić jakość? Tylko częściowo – nie zapobiega powstawaniu błędów, jedynie je wykrywa (i to z reguły po długim
9/2010
Zwinna jakość
Pojęcia •
• • • •
•
• • •
•
• • •
•
•
•
Agile - Zwinne programowanie ((ang.) Agile software development) – grupa metodyk wytwarzania oprogramowania opartego o model przyrostowy. Wymagania oraz rozwiązania ewoluują przy współpracy samo organizujących się, których celem jest przeprowadzanie procesów wytwarzania oprogramowania. Pojęcie zwinnego programowania zostało zaproponowane w 2001 w Agile Manifesto. Metodyka oparta jest o zdyscyplinowane zarządzanie projektem, które zakłada częste inspekcje wymagań i rozwiązań wraz z procesami adaptacji (zarówno specyfikacji jak i oprogramowania). Metodyka ta najczęściej znajduje zastosowanie w małych zespołach programistycznych, w których nie występuje problem komunikacji, przez co nie trzeba tworzyć rozbudowanej dokumentacji kodu. Kolejne etapy wytwarzania oprogramowania zamknięte są w iteracjach, w których za każdym razem przeprowadza się testowanie wytworzonego kodu, zebranie wymagań, planowanie rozwiązań itd. Metoda nastawiona jest na szybkie wytwarzanie oprogramowania wysokiej jakości. CD (ang. Continuous Deployment) – polega na automatyzacji instalacji stworzonego builda w określonym środowisku. Pozwala to szybko i sprawnie zainstalować w danym środowisku każdą nową wersję systemu. CI (ang. Continuous Integration) - praktyka stosowana w trakcie rozwoju oprogramowania, polegająca na częstym, regularnym włączaniu (integracji) bieżących zmian w kodzie do głównego repozytorium. W praktyce, każdy członek zespołu programistycznego powinien przynajmniej raz dziennie umieścić wykonaną przez siebie pracę w repozytorium. Non-solo development – podejście do pracy polegające na tym, że dwóch lub więcej ludzi wspólnie pracuje nad jednym zadaniem. Pair Programming - czyli programowanie w parach jest jedną z technik pisania oprogramowania. W technice tej dwie osoby pracują przy jednej maszynie, gdzie jedna pisze kod (tak zwany kierowca) a druga (tak zwany nawigator) przegląda w poszukiwaniu błędów to, co napisała pierwsza osoba. Osoby te powinny się zmieniać rolami dość często. Zadaniem nawigatora jest także podpowiadanie kierowcy oraz myślenie, w którym kierunku powinien się rozwijać program. Product Backlog – zbiór wymagań, które muszą być wykonane (zaimplementowane),aby osiągnąć cel projektu. Jest to pełna lista wymagań/funkcjonalności produktu, który jest celem projektu. Jest ona przygotowywana przez Product Owner'a czyli osobę reprezentująca klienta (eksperta znającego biznesową funkcjonalność produktu, który może podejmować decyzje związane z produktem). Product Owner - osoba odpowiedzialna za Product Backlog, która również priorytyzuje Product Backlog oraz podejmuje decyzje związane z elementami Product Backlog'u. Jest to przedstawiciel klienta często: Osoba z marketingu lub Product Manager. Refactoring - pojęcie związane z wytwarzaniem systemów informatycznych, w szczególności z programowaniem. Jest to proces wprowadzania zmian w projekcie/programie, w wyniku którego zasadniczo nie zmienia się funkcjonalność. Celem nie jest więc wytwarzanie nowej funkcjonalności, ale utrzymywanie odpowiedniej, wysokiej jakości organizacji systemu. Scrum - Scrum to metodyka prowadzenia projektów. Zaliczana do tzw. metodyk zwinnych, zgodnych z Agile Manifesto. Najczęściej wykorzystywana jest w projektach informatycznych. Używana jest w skomplikowanych projektach, w których nie można przewidzieć wszystkiego, co może się przydarzyć lub w przypadku przedsięwzięć o wysokim stopniu innowacyjności. Metodyka skupia się na dostarczaniu kolejnych, coraz bardziej dopracowanych wyników projektu, włączaniu się przyszłych użytkowników w proces wytwórczy, samoorganizacji zespołu projektowego. Scrum jest to nie tylko nazwa metodyki, ale również nazwa codziennego spotkania zespołu. Spotkanie to jest codziennym przeglądem wykonanej i planowanej pracy. Scrum powinien być prowadzony przez ScrumMaster’a. Każdy z członków zespołu powinien odpowiedzieć na 3 pytania: 1. Co zrobiłeś od ostatniego Scrum? 2. Co planujesz wykonać do następnego Scrum’u? 3. Czy coś utrudnia Ci wykonywanie efektywnie swojej pracy? Spotkanie takie powinno być bardzo zwięzłe, co zwykle oznacza czas trwania do 15 minut. ScrumMaster - jedna z trzech ról w procesie Scrum. Należy pamiętać, iż rola ta nie odpowiada roli Project Managera z klasycznych metodyk. Rolą ScrumMaster’a jest nadzorowania i kontrolowanie procesu scrum. Tak aby zmaksymalizować korzyści wynikające z jego stosowania. ScrumMaster powinien również pomagać zespołowi w przypadku pojawienia się problemów. Rolą ScrumMaster nie jest przydzielanie zadań członkom zespołu. Sprint – W Scrum to stały czas, podczas którego zespół ma wykonać zaplanowane zadania. Sprint to odpowiednik iteracji. Sprint Backlog – zbiór zadań do wykonania w danym Sprincie (iteracji). XP (ang. Extreme Programming) - to paradygmat i metodyka programowania mające na celu wydajne tworzenie małych i średnich projektów wysokiego ryzyka, czyli takich, w których nie wiadomo do końca, co się tak naprawdę robi i jak to prawidłowo zrobić. Przyświeca temu koncepcja prowadzenia projektu informatycznego, wywodząca się z obserwacji innych projektów, które odniosły sukces. Podstawą ekstremalnego programowania jest synergia wynikająca ze stosowania rozmaitych praktyk, które same w sobie mają wiele zalet, lecz mogą być trudne w zastosowaniu. Łączne użycie tych praktyk ma zapewniać wyeliminowanie niedogodności każdej z nich. TDD (ang. Test-Driven Development) - jest techniką tworzenia oprogramowania polegającą na wielokrotnym powtarzaniu następujących kroków: najpierw programista pisze automatyczny test sprawdzający dodawaną funkcjonalność. Test w tym momencie nie powinien się udać. Następnie funkcjonalność jest implementowana. W tym momencie wcześniej napisany test powinien się udać. W ostatnim kroku, programista wykonuje refactoring napisanego kodu tak, by spełniał on oczekiwane standardy. User Story – jest to sposób opisu wymagań projektowanej aplikacji. Opisujący krótko pojedynczą funkcjonalność lub zestaw funkcjonalności, który bez siebie nawzajem nie miałby sensu. Np: Użytkownik może wysłać powiadomienie email o nowo stworzonym spotkaniu. Każde zdanie historii użytkownika zaczyna się od osoby której tyczy się ta historia. Osoby te nazywamy ‘Rolami’ i są one w zasadzie analogiczne do aktorów w przypadkach użycia (Use Cases). Zespół – ostatnia (po Product Ownerze i Scrum Masterze) i najważniejsza rola w procesie Scrum. Zespół to grupa licząca zwykle od 5 do 9 osób (Za wartość optymalną uznaje się 7 osób). Zespół jest odpowiedzialny za realizację zaległości sprintu. Przy czym bardzo ważna jest kwestia odpowiedzialności, bowiem fundamentem metodyki Scrum jest założenie, iż zespół powinien się sam organizować. Również z uwagi na założenia Scrum’u w skład zespołu powinny wchodzić osoby o różnych specjalizacjach: Analitycy, Architekci, Programiści, Testerzy.
www.sdjournal.org
67
APLIKACJE BIZNESOWE
czasie od momentu ich powstania). Gdyby zastosować technikę non-solo do tworzenia dokumentacji, to znaczy skierować do pracy nad danym dokumentem np. dwie osoby, liczba usterek z pewnością byłaby mniejsza a poprawki dokonywane w krótszym czasie. Demo iteracji/sprint Demo iteracji jest popularną praktyką w wielu zespołach Agile. Na końcu każdej iteracji (czy Sprintu w Scrum) zespół demonstruje swój działający produkt kluczowym udziałowcom (lub wybranej grupie ich reprezentantów) celem zaprezentowania postępów prac oraz uzyskanie informacji zwrotnej. Demo jest w zasadzie nieformalnym przeglądem – udziałowcy mogą zgłaszać swoje uwagi i sugestie co do rozwiązania, które (po odpowiedniej analizie) zespół może wdrożyć w kolejnej iteracji. Demo All-hands Rzadko jest tak, że wszyscy udziałowcy są świadomi sytuacji w danym projekcie. Nie każdy udziałowiec będzie równie zaangażowany w prace zespołu i będzie z zespołem bezpośrednio współpracował – pozostanie wielu takich, których wiedza o projekcie ograniczy się do tego, iż taki projekt jest. Warto zatem jak najwcześniej wykonać demo systemu dla szerokiego grona odbiorców – nie jak w przypadku demo iteracji, dla grupy kluczowych udziałowców, ale dla wszystkich (o ile to możliwe z praktycznego punktu widzenia). Celem takiego demo all-hands jest m.in. przekazanie aktualnego stanu prac ogółowi udziałowców, ale i pewnego rodzaju sprawdzenie Właściciela Produktu (ang/ Product Owner), czy prezentowane przez niego stanowisko w istocie odpowiada poglądom wszystkich udziałowców. Jeśli informacja zwrotna uzyskana z demo jest negatywna (kolokwialnie mówiąc, produkt nie podoba się udziałowcom) lub istnieją znaczne różnice pomiędzy tym, co komunikują bezpośrednio udziałowcy, a tym, co przekazał zespołowi Właściciel Produktu – może to oznaczać, iż nie rozumie on potrzeb całej społeczności udziałowców. Co stanowi problem, który należy rozwiązać jak najszybciej. Krótkie cykle informacji zwrotnej Niezaprzeczalną korzyścią podejścia Agile jest minimalizacja czasu pomiędzy uzyskaniem informacji zwrotnej
a jej walidacją i wykorzystaniem. Przejawia się to nie tylko w testowaniu czy jakości, ale i w wielu innych procesach projektowych – kodowaniu, dokumentowaniu. Wynika to z ulepszonej komunikacji i bliskiej współpracy pomiędzy członkami zespołu – informacja przekazywana jest szybko, bezpośrednio, bez udziału pośredników i zbędnej biurokracji. Liczy się efekt – czyli rozwiązanie problemu, eskalacja zagrożenia, poinformowanie o otwartych możliwościach.
Podsumowanie
Trzeba przyjąć rzeczywistość – w obecnych czasach klienci firm IT oczekują dostarczenia im gotowych produktów szybciej, oczekują od dostawcy elastyczności i możliwości płynnej zmiany wymagań w trakcie trwania projektu, jednocześnie pragnąc wysokiej jakości. Chcą być zaangażowani w prace projektowe i na bieżąco śledzić postępy prac. Podejścia tradycyjne, ciężkie, nie nadążają za tym trendem. Agile – o ile prawidłowo i konsekwentnie zastosowane oraz dostosowane do możliwości i potrzeb projektu – jest metodyką efektywną i dającą znakomite rezultaty. Wbrew opiniom niektórych sceptyków kładzie duży nacisk na jakość i szybkie rozwiązywanie problemów – czego przykłady opisano w niniejszym artykule.
KAROLINA ZMITROWICZ Pracuje na stanowisku Analityka biznesowego w �rmie Pro�-Data. Karolina specjalizuje się obecnie w modelowaniu wymagań biznesowych. Wcześniej pracowała jako Manager Quality Assurance w projektach informatycznych w sektorze �nansowo – bankowym. Pro�-Data to producent oprogramowania specjalizujący się w budowie dedykowanych rozwiązań informatycznych dla ubezpieczeń, bankowości i administracji publicznej. Firma posiada certy�kat jakości ISO 9001:2008 w zakresie produkcji oprogramowania. Karolina jest również redaktorem naczelnym magazynu c0re – kwartalnika dla testerów i specjalistów QA. c0re powstał z inicjatywy grupy niezależnych testerów, pod patronatem GASQ oraz SJSI. Celem inicjatywy jest wymiana wiedzy z zakresu szeroko pojętej jakości oraz aktywizacja środowiska osób zawodowo zajmujących się tym tematem. Kontakt z autorem: zmitrowiczkarolina@gmail.com
W Sieci • • • • • • •
68
agilemanifesto.org - Manifest Agile. www.agilealliance.org - Oficjalna strona Agile Alliance. www.testingexperience.com/testingexperience03_09.pdf - Artykuł z Testing Experience na temat testowania w Agile agile.csc.ncsu.edu/SEMaterials/AgileTesting.pdf - Kolejna publikacja na temat testowania Agile oraz automatyzacji www.ambysoft.com - Strona Scotta Amblera, wiele wartościowych publikacji na temat Agile www.mcbreen.ab.ca/talks/AgileQANotes.pdf - Publikacja na temat zapewnienia jakości w projektach Agile. mike2.openmethodology.org/wiki/Agile_Quality_Assurance - Artykuł o zapewnieniu jakości w Agile opisujący proces i praktyki wykorzystywane przez analityków QA w zespołach projektowych Agile.
9/2010
Z ŻYCIA ITOLOGA
Scrum Nowa metoda zarządzania projektami Zajęcia z WF-u – tak średnio wspominam. Rzucanie piłką lekarską o dziwo nawet mi nieźle wychodziło (czułem się jak jakiś Gigant w walce z bogami Olimpu), ale już na przykład palantówka, biegi dookoła szkoły, skoki przez kozła, stanie na rękach, przewroty – mógłbym być bohaterem programu: „O ludziach, którzy przeżyli własną śmierć”. A Gry Zespołowe? A, to co innego, zwłaszcza siatka. Tu się naprawdę realizowałem: dwie drużyny, rywalizacja, wspólny cel… Może dlatego tak lubię Scrum – Grę w Projekt, z dużym zapasem zdrowego rozsądku. Dowiesz się:
Powinieneś wiedzieć:
• Co ma wspólnego „Pan Samochodzik” z tworzeniem oprogramowania; • Dlaczego Scrum tak bardzo „namieszał” w inżynierii oprogramowania; • Jak Scrum może pomóc „ludziom z kryjówek”.
• Że oprogramowanie tworzą (!) ludzie.
S
crum jest metodą zarządzania projektami, nie tylko informatycznymi, które należą do rodziny metod określanych słowem agile (z ang. „zwinny”, „lekki”). Jego nazwa została zaczerpnięta z rugby i w polskim tłumaczeniu oznacza „młyn”. Jest to figura sportowa, która polega na tym, iż dwie drużyny stają w kole, chwytają się za bary i wspólnie walczą o piłkę. YouTube dobrze zilustruje to, o czym mówię. Założenia metody Scrum są bardzo proste. Całość pracy dzielona jest na mniejsze kawałki, zwane „sprintami”. Przyjmuje się, że sprinty nie powinny trwać dłużej niż 30 dni kalendarzowych, choć oczywiście czas ten jest zróżnicowany i zależy od charakterystyki Zespołu. Wśród projektów, z którymi współpracowałem, zdarzały się takie, które preferowały 2-tygodniowe sprinty, ale były i takie, którym najlepiej się pracowało w odstępach 4-tygodniowych. Na koniec każdego sprintu dostarczany jest fragment działającej funkcjonalności, którą może nacieszyć się Klient, zgłosić swoje uwagi i zastrzeżenia. Sprinty mają swój rytm, który nie jest jednak „agresywny”. Powiedziałbym raczej, że jest to rytm brazylijskiej bossanovy w wykonaniu Oscara Castro-Nevesa czy Eliane Elias. Każdy sprint rozpoczyna się intensywnym planowaniem, które nadaje pracy programistów
70
odpowiedni kierunek. Codziennie odbywają się krótkie spotkania (max. 15 min), z udziałem całego Zespołu, który komunikuje między sobą, na jakim etapie znajdują się jego prace. Każdy sprint kończy się spotkaniem z Klientem, podczas którego demonstrowane są uzyskane wyniki. Ważnym elementem, niestety często pomijanym w trakcie cyklu Scruma, jest tzw. „retrospektywa”, którą jeden z moich amerykańskich kolegów bardzo trafnie nazwał „Pit-Stop Meeting”. Jest to krótki „postój” w Projekcie, podobny do tego w wyścigu Formuły 1, wykorzystywany na zatankowanie paliwa, zmianę opon, czasem nawet na usunięcie wadliwego spojlera czy fragmentu nadwozia). Celem retrospektywy jest podsumowanie sprintu: co nam poszło dobrze?, w czym możemy być lepsi?, co należy zmienić? Jak już pewnie zdążyliście zauważyć, Scrum używa dość specyficznego żargonu, którego zazwyczaj nie spotyka się w „normalnych” metodykach. Wymagania klienta nazywane są „backlogiem” (z ang. zaległości). Kolejne iteracje, w trakcie których rozwijane są fragmenty produktu, to „sprinty”. Śledzenie ryzyk projektowych, tak bardzo popularne w tradycyjnym zarządzaniu projektem, zostało zastąpione codziennym monitorowaniem tzw. „impediments” (z ang. blokady) – to, co utrudnia lub wręcz
9/2010
Scrum – nowa metoda zarządzania projektami
uniemożliwia Zespołowi wykonywanie zadań projektowych. Dodatkowo, Scrum definiuje specyficzne role projektowe, które momentami przypominają nazwy postaci, rodem z gier RPG, choć bynajmniej nie są one fikcyjne, a ich rozgrywka nie zakłada z góry ustalonego scenariusza. Klient oraz kluczowi interesariusze projektu pełnią rolę tzw. „Product Owner’a” (z ang. Właściciel Produktu). Drugą ważną rolą jest „ScrumMaster”. Uwaga! To nie jest Kierownik Projektu. Można go raczej porównać do mistrza Yoda, jednego z bohaterów sagi filmowej „Gwiezdne wojny”. Ma on za zadanie chronić Zespół przed „ciemną stroną mocy” – różnego rodzaju przeszkodami, które mogą „sabotować” jego prace. ScrumMaster też organizuje i moderuje wszystkie spotkania scrumowe i... zagrzewa do walki: „Nie próbuj! Rób albo nie rób. Prób nie ma”(Mistrz Yoda). I wreszcie Zespół (zazwyczaj 5-9 osób), który jest odpowiedzialny za sukces projektu i implementację poszczególnych funkcjonalności. Zespoły same organizują swoją pracę. I tutaj dochodzimy do ważnego momentu w tej metodzie, który chciałbym odrobinę podrążyć.
Pan Samochodzik i tworzenie oprogramowania
Metody agile’owe powstały jako reakcja na założenie, którym od samego początku było głęboko zakorzenione w inżynierii oprogramowania: „proces tworzenia oprogramowania jest procesem, który niczym nie różni się od procesu produkcyjnego”. Jest linia produkcyjna, są stanowiska robocze (maszynowe, ręczne lub mieszane), pogrupowane wg kolejnych operacji procesu technicznego. Idea „linii produkcyjnej”, w momencie powstania, była alternatywą dla dotychczasowej produkcji rzemieślniczej, i jej powstanie stanowiło niekwestionowaną zasługę amerykańskiego koncernu Ford. Inżynierowie oprogramowania popełnili jednak zasadniczy błąd, próbując przenieść ten pomysł na grunt projektów softwarowych. Co gorsza, na tym założeniu osadzona została cała dotychczasowa filozofia zarządzania ludźmi. Na czym ten błąd polegał? Wyobraź sobie Drogi Czytelniku, że awansowałeś i zostałeś menedżerem w zakładzie Tomasza N. N. (Tytułowy bohater filmu „Pan Samochodzik”), któremu znudziła się już praca historyka sztuki i postanowił otworzyć masową produkcję jego pokracznego wehikułu, zbudowanego na bazie rozbitego Ferrari 410 Superamerica. Jako menedżer odpowiadasz za linię produkcyjną. Natychmiast eliminujesz wszystkie pojawiające się defekty; jesteś wściekły i nie tolerujesz błędów popełnianych przez pracowników, którzy obsługują linię; traktujesz ich jak trybik maszyny, który w razie potrzeby zawsze można wymienić na inny; no i jesteś mistrzem wszelkich instrukcji – wszystko musi „tykać” jak w szwajcarskim
www.sdjournal.org
zegarku i na wszystko jest standardowa procedura. Aha, i jeszcze jedno – nie znosisz eksperymentów – nie ma czasu sprawdzać, czy coś się da wykonywać bardziej optymalnie, czy nie – to nie jest przecież twoja rola. Otóż takie podejście faktycznie ma sens i sprawdza się podczas pracy przy linii produkcyjnej, na przykład samochodów. Natomiast ogromnym błędem jest próba zaaplikowania tego modelu do projektów softwarowych, w których kluczową rolę odgrywa tzw. „czynnik ludzki”. To od stopnia zaangażowania ludzi, ich kreatywności, umiejętności akceptowania i radzenia sobie z problemami (często błędami), zdolności komunikacji, działania w grupie – zależy sukces danego projektu. Natomiast stosowanie mechanizmów, zaczerpniętych ze świata produkcji, może prowadzić do postaw zupełnie odwrotnych – stłumienia inicjatywy, braku odwagi w wyrażaniu swoich opinii i pomysłów, chowania się do „kryjówek”, z których nie muszę się zbytnio wychylać, żeby przeżyć kolejny dzień w pracy.
Ludzie z kryjówek
Ponieważ prywatnie zawsze byłem i jestem „fanatykiem” filozofii w każdym wydaniu, przytoczę krótki fragment „Myślenia według wartości” ks. Józefa Tischnera (na pewno kojarzycie jego kultową już dzisiaj „Filozofię po góralsku”, jeśli nie – polecam!): „Człowiek w kryjówce chroni się przed światem i przed innymi. Przyszłość nie obiecuje człowiekowi nic wielkiego, pamięć przeszłości podsuwa mu przed oczy same doznane porażki, przestrzeń nie zaprasza do żadnego ruchu. Wprawdzie w kryjówce nadzieja nie znika bez reszty, tylko maleje, ale maleje do tego stopnia, że staje się jedynie nadzieją przetrwania”. Styl zarządzania, który próbuje odzwierciedlać świat produkcji, „spycha” członków Zespołów Projektowych właśnie do „kryjówek”. Zauważcie, w ilu projektach, w których sami uczestniczyliście, mieliście do czynienia z sytuacją, gdy menedżer zawsze brał sprawy w swoje ręce, w obawie o wasze kompetencje. Współpracowałem kiedyś z firmą, w której spotkałem się z dość komiczną sytuacją, nazwijmy ją „cenzury projektowej”. Każdy mail, który ScrumMaster lub Lider Techniczny wysyłali do Klienta, był wcześniej przez Kierownika Projektu autoryzowany. Z aptekarską wręcz „precyzją” analizował każdą wiadomość (kiedy on znajdował na to czas?!), nanosił – jak zawsze podkreślał – kluczowe poprawki. Kiedyś zapytałem go, dlaczego to robi. Dostałem odpowiedź, że jego ludzie nie mają wyczucia tzw. „kwestii politycznych”, i nie będzie ryzykował kontraktu z Klientem, który jest jego jedyną „dojną krową”. Niestety nie byłem w stanie go przekonać, że w ten sposób zabija inicjatywę w Zespole, i – w efekcie – kształtuje mentalność „ludzi z kryjówek”, którzy wcześniej czy póź-
71
Z ŻYCIA ITOLOGA
niej zejdą do defensywy i przestaną wykazywać jakąkolwiek wolę do twórczego działania: po co go podejmować, skoro zawsze istnieje ryzyko, że może się to źle skończyć dla projektu. Innym, poważnym błędem menedżerów wychowanych w świecie produkcji jest zabijanie indywidualności. Przez „indywidualistę” rozumiem osobę, która ma swoje zdanie, jest kreatywna, a jej spojrzenie na problemy, które wcześniej czy później pojawią się w projekcie, będzie zawsze nowatorskie i inne od wszystkich proponowanych. Nie chodzi mi jednak o „artystę”, który pojawia się w pracy, kiedy chce, a jak już przyjdzie, to wszystko, co robi, traktuje jako środek do samo-podniety. Obecność takich ludzi w Zespole Projektowym jest dla niego bardzo destruktywna, i trzeba dobrze się się zastanowić, zanim zatrudnimy takich „gagatków” do pracy w naszej firmie. Dla menedżera, który swoją inspirację czerpie z linii produkcyjnej, programista-indywidualista jest tylko źródłem problemów. Tymczasem to właśnie wyjątkowość decyduje o sukcesie realizowanych projektów. Kto oglądał film „Lśnienie”, oparty na powieści Stephena Kinga (rewelacyjna rola Jacka Nicholsona), ten wie o czym mówię. Ostatnią rzeczą, o której chciałbym wspomnieć, w kontekście tradycyjnego stylu zarządzania, jest koncentracja na realizacji zadań. W zarządzaniu wzorującym się na produkcji samochodów nie ma czasu na myślenie o tym, jak coś zrobić. Zadania muszą być wykonywane mechanicznie, żeby ze wszystkim zdążyć. Tymczasem, w projektach softwarowych tak się nie da. Oczywiście wszyscy o tym wiemy, i to, co teraz piszę, większość z was uzna za czcze gadanie. A jednak, chyba mam trochę racji. Nieprawdaż? Jest w nas coś takiego, że jak już dostaniemy projekt, rzucamy się w wir pracy, najczęściej nie mając odpowiedniej ilości czasu na planowanie, analizę nowych metod i technologii, na szkolenia, czytanie fachowych książek, na wspólne dyskusje o problemach. W ubiegłym roku miałem przyjemność współpracować z firmą, która „programowała na odległość” dla niemieckiego zleceniodawcy – dużej korporacji, z wydawałoby się uporządkowaną strukturą i tzw. „dojrzałym ładem organizacyjnym”. Jednym z moim zadań, do których wspomniana firma mnie zatrudniła, było usprawnienie procesów szacowania parametrów projektu. Chodziło o to, żeby nauczyć ludzi przygotowywać WBS-a, odpowiednio definiować zadania projektowe, a także wdrożyć jedną z technik estymacyjnych. Początkowo wszystko szło jak z płatka; Zespół z Polski bardzo szybko złapał o co w tym wszystkim chodzi. Przygotowaliśmy kilka arkuszy estymacyjnych, do kilku złożonych wcześniej zamówień. I tu się zaczęły schody. Nasi niemieccy koledzy nie mogli zrozumieć, dlaczego w wycenie uwzględniliśmy: spotka-
72
nia projektowe (składały się na nie wszystkie ceremonie scrumowe, które, jak się je zliczy, są niemałym naddatkiem), analizę rozwiązań architektonicznych, czas spędzony na telekonferencjach/ skype/ GTalk itp.; monitoring i kontrolę projektu, a także burzę mózgów, dotyczącą możliwości zastosowania jednego z rozwiązań technicznych, które wydawało nam się jako jedyne i słuszne.
Wychodzenie z kryjówki
Scrum jest metodą, która pomaga ludziom, zarządzanym wg metod świata produkcji, wyjść z kryjówek. „Kryjówka ma jakiś próg ,który trzeba przekroczyć. Próg znaczy koniec kryjówki i początek nowej przestrzeni. Jeśli się widzi koniec, a nie widzi początku, będzie się mimo wszystko więcej kochać złudzenie niż prawdę.” (J. Tischner). Jaki początek proponuje Scrum? Przede wszystkim Scrum, dzięki iteracyjnej metodzie pracy – akceptuje „prawo” członków Zespołów Projektowych do popełniania błędów. Zastanówcie się przez chwilę, na ile ślepych zaułków w trakcie realizacji waszych projektów natrafiliście (bez względu na ich rozmiar i złożoność). Ile było meandrów? Ile razy waliliście głową w mur, nie wiedząc, co dalej – w którą stronę? Metoda Scrum zakłada, że projekty są podatne na błędy i częste zmiany kierunku prac rozwojowych. Klient co kilka tygodni dostaje fragmenty działającego produktu, może go sobie oglądnąć, nacieszyć się nim – zgłosić swoje „ale” i nowe pomysły. To jest duża siła tej metody. Pamiętam, że jako początkujący Kierownik Projektów, przygotowując harmonogram prac, w oparciu o metodykę kaskadową, zawsze miałem problem ze zmiennością wymagań. Zbierałem nawet metrykę, śledzącą ich fluktuację (ile pojawiło się nowych?, ile zmieniono starych?, ile te zmiany nas kosztowały?), a wszystko po to, żeby „dokopać” Klientowi – kiedy po raz kolejny rozminęliśmy się z osiągnięciem zaplanowanego punktu milowego, bo w trakcie implementacji dwa razy zmienił swoje zdanie i dołożył 3 nowe funkcjonalności. Muszę przyznać, że zawsze byłem bezsilny. Natomiast odkąd wdrożyłem Scruma, wszystko się zmieniło. Scrum „oswoił” zmianę. Pokazał, że „nie taki diabeł straszny…”. Scrum promuje także, opisany przeze mnie wcześniej – indywidualizm. W tym sensie jest drogą pod prąd tradycyjnego stylu zarządzania. Dzięki stosowanym metodom i narzędziom, tworzy coś, co moglibyśmy nazwać demokratycznym sposobem zarządzania. Kierownik Projektu nie jest już „królem”, który panuje nad ludem, niezależnie od układów politycznych i systemów. Odgrywa on zupełnie inną rolę, w porównaniu do tradycyjnego sposobu zarządzania, który wzoruje się na świecie produkcji. Pojawia się tak-
9/2010
Scrum – nowa metoda zarządzania projektami
że rola ScrumMastera, który w jakimś stopniu „odciąża” Kierownika Projektu, ale i przejmuje obowiązki, które często należały do Inżyniera Jakości. Mam tutaj na myśli głównie czuwanie nad tym, aby metoda Scrum, jej reguły i założenia były faktycznie realizowane w codziennym życiu projektowym (kontrola procesu). O „demokracji” świadczy wreszcie to, że „władza została oddana w ręce ludu” – to Zespół Projektowy decyduje o tym, jak dane zadania będą realizowane, i kto je będzie wykonywał. Mamy tutaj do czynienia z pełną demokracją – co jest dodatkowo możliwe, ponieważ Zespoły Scrumowe są, pod względem funkcji ich poszczególnych członków, wymieszane (ang. cross-functional). Weźmy jako przykład fantastyczne trio jazzowe Keitha Jarretta z basistą Garym Peacockiem i perkusistą Jackiem DeJohnette'em (uwielbiam standardy w ich wykonaniu). Mamy tutaj małe demo nie tylko wymieszanych funkcji w Zespole (pianista, basista i perkusista), ale i samo-zarządzania się Zespołu. Jazz to przede wszystkim wolność, która wyraża się w improwizacji. Wolność, która jednak nie opiera się na założeniu, że wszystko wolno. Jest to wolność „ograniczona” określonymi regułami – mamy kilka nut, które tworzą temat; jest metrum, a więc puls utworu; mamy wreszcie określoną interakcję jego członków. Improwizacja nie ma nic wspólnego z chaosem muzycznym. Muzycy, oprócz wirtuozerskich umiejętności, muszą się doskonale komunikować, „do bólu” muszą rozumieć każdy element jazzu. Dzięki temu, słuchając improwizacji, czujemy pod skórą, że mimo wszystko jest to świat oparty na pewnych zasadach – wyjątkowy i niepowtarzalny. Taki jest też Scrum. Scrum to praca zespołowa, która nie skupia się tylko na wykonaniu zadania – tak, jak to ma miejsce bardzo często w tradycyjnym zarządzaniu. Scrum bardzo duży nacisk kładzie na planowaniu tego, nad czym Zespół będzie pracował w ciągu kolejnych kilku tygodni. Pamiętam, że jak pierwszy raz przeglądałem prezentację Mike’a Cohna (jednego z wizjonerów tej metody) „Wprowadzenie do Scrum” (do pobrania na http://www.mountaingoatsoftware.com/) uderzył mnie slajd, na którym napisane było, że planowanie w Scrumie zajmuje bite 8 godzin. Nie wierzyłem, dopóki nie planowałem z chłopakami pierwszego sprintu: 6 i pół godziny! Najpierw ustalenie listy funkcjonalności do zaimplementowania, potem priorytety, gatki-szmatki z Klientem, próba zrozumienia, o co mu tak naprawdę chodzi, potem estymaty i planning poker, znowu dyskusje, obiad, znowu szacowanie, dalej tworzenie zadań do user stories i wreszcie koniec – 16.30. Wszyscy myślą o jednym – Sweet Home! Dodatkowo, częścią każdego sprintu jest czas na analizę i wspólne projektowanie wybranych rozwiązań technicznych (tzw. Collaborative
www.sdjournal.org
Design). Wprawdzie jest to praktyka, o której Scrum wprost nie mówi, ale też i nie zabrania. Implementując Scruma w swoich projektach, musicie zdawać sobie sprawę, że Scrum to tylko metoda organizacji pracy i jako taka nie zawiera żadnych praktyk developerskich. Jest rzeczą zrozumiałą, że wymaga dodatkowego uzupełnienia, do czego świetnie nadają się na przykład praktyki związane z popularnym Extreme Programming, które jest inną „zwinną” metodą rozwoju oprogramowania. O tym jednak innym razem.
O tym, i kolejnym artykule
W artykule celowo nie wchodziłem w teoretyczne aspekty, związane z metodyką Scrum. Moim zamiarem było „uderzenie” w samo epicentrum tej metody – LUDZI, którzy „tworzą”, a nie „produkują” software. Należy jednak pamiętać, że Scrum – mimo bardzo prostych zasad – wcale nie jest łatwy! Jego podstawowa trudność, zwłaszcza z punktu widzenia Kierownika Projektu o mentalności świata produkcji, polega na zmianie sposobu organizacji pracy. Trzeba nauczyć się ufać ludziom, oddać im władzę i decyzyjność w zakresie realizowanych zadań projektowych, akceptować możliwość popełnienia przez nich błędów, dostrzegać indywidualizm i więcej czasu poświęcać na planowanie i analizę. Od jakiegoś czasu obserwuję bardzo dużo dyskusji na temat tego, jak Scrum wypada na tle modelu CMMI, o którym pisałem w poprzednim artykule. Czy nie mamy tutaj do czynienia z kolejną „wojną światów”? Czy Scrum nie jest gigantyczną machiną, którą Ray (Tom Cruise) w filmie „War of the Worlds” zauważył przed swoim domem? Na to pytanie odpowiem w następnym numerze.
MARIUSZ CHRAPKO Jest wieloletnim praktykiem w zakresie doskonalenia procesów tworzenia oprogramowania w oparciu o model CMMI®. Wspiera �rmy informatyczne na terenie całej Europy, prowadząc coaching zespołów projektowych oraz szkolenia na różnych szczeblach organizacyjnych. Dodatkowo jest praktykiem we wdrażaniu i adaptacji metod Agile Software Development (wcześniej Agile Coach/ Centrum Oprogramowania Motoroli w Krakowie), Programu Metryk Organizacyjnych, a także procesu Peer Review. Jest autorem wielu publikacji z zakresu inżynierii oprogramowania oraz prelegentem na konferencjach krajowych i międzynarodowych. Autor pierwszej w Polsce książki na temat modelu CMMI raz jego praktycznego zastosowania. Od roku 2009 współpracuje z �rmą LOYCON® business solutions. Kontakt z Autorem: mariusz.chrapko@loycon.pl
73
EFEKTYWNOŚĆ PRACY
Najprostsze możliwe środowisko O potędze prostoty
Kto nie uwielbia tych wspaniałych chwil, kiedy projekt nabiera kształtu, kolejne funkcjonalności pojawiają się jedna za drugą i nie możemy się nacieszyć wspaniałym, programistycznym dziełem. A diabeł czyha ... Dowiesz się:
Powinieneś wiedzieć:
• Jakie pułapki czyhają na programistów podczas tworzenia kodu w złożonym systemie;
• Tylko to, co już wiesz.
K
ażdy projekt prędzej czy później staje się bardzo złożony. Jeśli na przykład pracujemy nad aplikacją internetową, to przychodzi taki moment, kiedy aplikacja obsługuje logowanie, transakcje, współpracę z bazą danych, wielojęzyczność, złożone reguły bezpieczeństwa, reguły biznesowe, integruje się z zewnętrznymi systemami. Ponadto istnieje również pewna logika przetwarzania zdarzeń użytkownika – najczęściej korzystamy z jakiegoś szkieletu MVC lub podobnego rozwiązania. Restart całej aplikacji zajmuje kilkanaście, czasem kilkadziesiąt sekund, a nawet kilka minut. Załóżmy, że pracujemy nad nową funkcjonalnością i musimy użyć komponentu, biblioteki, której nie znamy. Pierwszy odruch powoduje, że implementację rozpoczynamy w opisanym wcześniej, złożonym środowisku. A przecież dopiero się uczymy... Dopiero eksperymentujemy! Nie jest nam potrzebny cały ten narzut. Przypuśćmy, że w trakcie eksperymentów coś nie do końca działa tak, jak byśmy chcieli. W zasadzie nie wiemy o co chodzi. Na przykład cały system się nie uruchamia, bo naprędce oprogramowaliśmy kontroler z MVC, więc przy okazji zmagamy się z jego błędami – na przykład przytrafia się problem z dostępem do danych. W końcu udało się. Wracamy do testowanego komponentu, ale jeszcze musimy zrestartować aplikację. Trwa to dość długo. Zbyt długo.
74
Czy w ogóle to całe środowisko jest potrzebne do przetestowania komponentu? Narzut ogromny – należy stworzyć wszystkie elementy potrzebne do uruchomienia testowego fragmentu, które narzuca środowisko. Czas potrzebny na efektywne badanie kolejnych parametrów jest subiektywnie oceniając wydłużony o 10-50 % z powodu złożoności systemu, w którym proces się odbywa. Może lepiej byłoby eksperymentować w najprostszym środowisku, poza zasadniczą aplikacją czy systemem. Być może wydaje się to bardzo oczywiste – bo jest oczywiste. Jednak niezwykle często wpadamy w opisaną powyżej pułapkę! Całość powyższych rozważań można sprowadzić do zasadniczej myśli:
Pracuj w możliwie najprostszym środowisku
Bardzo łatwo ulec przekonaniu, które z pewnością w tym momencie przychodzi do głowy: „... ale w moim środowisku nie można nic uprościć! Nie można przenieść tego, co robię, w inne, prostsze środowisko...”. Możemy Cię zapewnić Czytelniku, że prawie zawsze można środowisko uprościć. Główne pytanie, na które trzeba sobie odpowiedzieć, to czy rzeczywiście warto, ponieważ bywają sytuacje, w których stworzenie uproszczonego środowiska lub przygotowania środowiska będzie mało opłacalne. Jednak w dużej części przypadków warto to robić, tym bardziej że wypracowane rozwiązanie często może zostać użyte podczas prac nad następnymi funkcjonalnościami. Zatem poniesiony wysiłek zaprocentuje jeszcze wielokrotnie.
9/2010
Najprostsze możliwe środowisko
Kilka praktycznych sposobów na upraszczanie środowiska opisujemy poniżej. Jesteśmy przekonani, że będą stanowić inspiracje, dzięki którym będziesz pracował jeszcze efektywniej i wspaniały zawód programisty stanie się jeszcze wspanialszy.
Twórz uproszczone konteksty pracy
W zasadzie przedstawiony na wstępie przykład jest ucieleśnieniem tej zasady. Kiedy chcesz sprawdzić nowy komponent, bibliotekę, zastanów się, jak możesz najprościej ją przetestować i poznać jej właściwości. Zazwyczaj złożona aplikacja, nad którą właśnie pracujemy, jest ostatnim miejscem nadającym się do tego celu. Jeśli nigdy dotąd nie używałeś wyrażeń regularnych, a teraz będą ci potrzebne, zanim zaczniesz z nimi pracę najzwyczajniej w świecie stwórz prostą klasę. I tam przetestuj wszystkie interesujące Cię przypadki. W miejsce wyrażeń regularnych można wstawić każdą dowolną inną funkcjonalność: obiekty funkcyjne z jakarta-commons, generowanie plików pdf, kopiowanie danych, łączenie się z serwerem SMTP i wysyłanie maili, bibliotekę do współpracy z bazą danych, funkcje statystyczne, integracja z usługą sieciową. Można wymieniać bez liku. Kiedy już pracujesz w złożonym środowisku i chcesz przetestować nowy komponent graficzny, zazwyczaj lepiej zrobić to w środowisku poza projektem, a nie w aplikacji, którą właśnie tworzysz.
Testuj jednostkowo i hermetyzuj logikę
Jeśli kiedyś zastanawiałeś się, do czego mogą przydać Ci się testy jednostkowe, to mogę Cię zapewnić, że między innymi mogą posłużyć jako świetne narzędzie do upraszczania środowiska pracy. Dodatkowo dzięki użyciu mock objects jesteśmy w stanie pracować z minimalnym podzbiorem logiki biznesowej. Na przykład jeśli pracujemy nad metodą lub funkcją, która (1) przygotowuje treść maila i (2) go wysyła, nie musimy go fizycznie wysyłać. Podstawiamy mock object (bardzo uproszczoną implementację do celów testowych) i nie musimy czekać za każdym razem, żeby mail został wysłany. Oczywiście samo wysyłanie wiadomości też można przetestować. Ale można zrobić to osobno, a ewentualnie na końcu, kiedy oba mechanizmy (1) i (2) działają, przetestować je razem. Zgodnie z zasadą
W danej chwili testuj, zmieniaj lub pracuj nad jedną rzeczą
(ta zasada nie ogranicza się do programowania!) Chcielibyśmy zaznaczyć jedną rzecz. Stosowanie powyższych zasad nie uchroni Cię przed błędami, ale pozwoli Ci zmniejszyć ilość sytuacji, w których błędy się będą pojawiać. Wyobraź sobie, że dzięki nawykowi upraszczania środowiska oszczędzisz godzinę dziennie (a możesz z pewnością więcej), w ciągu tygodnia
www.sdjournal.org
oszczędzasz 5 godzin, w ciągu miesiąca 20 godzin. W ciągu roku ... ? Powróćmy jednak do testów. Żeby w pełni używać testów jednostkowych, musimy nauczyć się pewnej cennej umiejętności, którą nazywamy hermetyzacją logiki. Tworząc oprogramowanie, musimy tworzyć je modułowo, tak aby poszczególne części były jak najmniej między sobą zależne, tak aby można było ich używać niezależnie. W przypadku systemów obiektowych istnieje cała filozofia projektowania obiektowego, której celem jest osiągnięcie stanu, w którym poszczególne części systemu są od siebie jak najmniej zależne. Jednak zarówno w przypadku systemów obiektowych, jak i nieobiektowych można zastosować ogólniejszą zasadę odpowiedzialności, tzn. tak tworzyć system, aby wszystkie jego części miały jednoznacznie określoną odpowiedzialność, bez względu czy to będzie metoda, klasa, pakiet, procedura, funkcja czy formularz interfejsu użytkownika. Część taka będzie zamykać w sobie dobrze zdefiniowaną funkcjonalność, bez zbędnych powiązań z zewnętrznymi elementami. Jeśli zatem kodujesz logikę aplikacji w interfejsie użytkownika, jesteś daleki od realizacji tej zasady. W ten sposób wyraźnie wiążesz ze sobą interfejs użytkownika i logikę, nie jesteś w stanie jej w prosty sposób rozdzielić i pracować nad nimi osobno. Jeśli tworzysz interfejs użytkownika, umieszczaj w tej części kod, który dotyczy tylko i wyłącznie interfejsu użytkownika – czyli budowania jego wyglądu, ustawiania pól i ich odczytywania. W interfejsie użytkownika nie powinniśmy tworzyć złożonych algorytmów przetwarzania danych (no chyba, że dotyczą wyświetlania elementów na ekranie), do tego celu używamy niezależnych funkcji, metod, klas.
W danej chwili testuj, zmieniaj lub pracuj nad jedną rzeczą
Powyższa reguła, choć już wspomniana wcześniej, jest tak istotna, że zasługuje na osobny punkt. Być może znacie odpowiedź na pytanie: „Jak zjeść słonia?”. „Po kawałku”. Dokładnie ta reguła powinna towarzyszyć nam bezkompromisowo w codziennej pracy. A często nie towarzyszy... Zabierając się do realizacji większego zadania (takiego przynajmniej na 3-4 godziny), warto poświęcić kilka chwil na to, żeby zaplanować swoje działania. Zaplanować po to, by naszym słoniem, jak duży by on nie był, się nie udusić. Pamiętamy bardzo dobrze własne doświadczenia programistyczne, kiedy podejmując się jakiegoś zadania, tworzyliśmy je kilka godzin i następnie uruchamialiśmy... po raz pierwszy. Nigdy rozwiązanie nie działało w tym momencie, bo w zasadzie nie miało prawa. Następne kilka godzin poświęcone było debugowaniu i poprawianiu kodu.
75
EFEKTYWNOŚĆ PRACY
Zatem co warto zrobić na początku realizacji zadania? Mały plan. Tak aby ustalić przybliżony sposób tworzenia rozwiązania fragment po fragmencie. Załóżmy, że mam napisać sieć neuronową. (Jeśli nie wiesz zbyt dobrze, co to takiego, nie przejmuj się, nie ma to dużego znaczenia w dalszych rozważaniach.) Nie twórz gotowego rozwiązania. Krok po kroku. Zaimplementuj najprostsze rzeczy. Na początek być może warto zaimplementować funkcję symulującą działanie neuronu. Być może później stworzyć klasę neuronu. Przetestować jego metody. Następnie być może implementować sieć. Następnie regułę propagacji wstecznej. To tylko przykładowa kolejność. Ważne, żeby w danym momencie rozwijać, zmieniać jedną rzecz na raz. Kiedy ona zacznie działać i będzie przetestowana, brać się za następną. Oczywiście całość warto przemyśleć już na samym początku (przynajmniej na pewnym poziomie ogólności), ale implementować kawałek po kawałku, krok po kroku. Takie mikroiteracje. Ciekawą formą osiągnięcia opisanego wyżej efektu jest Test-Driven Development.
Szukanie przyczyn błędów
Powyżej opisane sposoby mogą znacząco zmniejszyć ilość popełnianych błędów, ale bądźmy szczerzy – przyjdzie taki moment, kiedy przydarzy się sytuacja, w której nasz system lub jego fragment nie działa poprawnie. Jeśli stosujesz zasadę W danej chwili testuj, zmieniaj lub pracuj nad jedną rzeczą, to zadanie znalezienia przyczyny błędu masz znacząco ułatwione. Ponieważ dokonujesz niewielkich kroków rozwijając kod i łatwo możesz określić zmiany, które doprowadziły do wystąpienia błędu. Ta reguła działa, kiedy kroki są wystarczająco małe. Jeśli przez ostatnią godzinę dokonałeś mniej więcej kilkunastu zmian w plikach konfiguracyjnych, kodzie i w HTML-u, to znaleźć przyczynę będzie trudniej. Jeśli natomiast najpierw dokonałeś zmiany w pierwszym pliku konfiguracyjnych i całość zadziałała, później zmiany w drugim pliku konfiguracyjnym i całość zadziałała, następnie dokonałeś zmian w kodzie i tu pojawił się błąd – to wszystko jasne. Oczywiście w życiu nie jest tak różowo i zdarzają się sytuacje, kiedy błędy pojawiają się po pewnym czasie (na przykład kilka dni po zmianach albo nawet po kilku miesiącach). Otóż w takich sytuacjach proponowana zasada brzmi następująco:
Zasady pracy w możliwie najprostszym środowisku • • • •
76
Twórz uproszczone konteksty pracy. Testuj jednostkowo i hermetyzuj logikę. W danej chwili testuj, zmieniaj lub pracuj nad jedną rzeczą. Uprość dany fragment rozwiązania, tak aby zaczął działać, a następnie dodawaj kolejne elementy, aż do momentu wystąpienia błędu.
Uprość dany fragment rozwiązania, tak aby zaczął działać, a następnie dodawaj kolejne elementy, aż do momentu wystąpienia błędu. Załóżmy, że występuje taka sytuacja: Aplikacja oparta o MVC – zdarzenie polega na tym, żeby pobrać odpowiednie dane i wygenerować plik pdf. Istnieje komponent, w jakiś sposób zainicjalizowany, który realizuje to zadanie: 1. pobiera dane ze źródła danych; 2. na ich podstawie generuje obiekt potrzebny do wygenerowania pliku pdf; 3. tworzony jest plik pdf; 4. plik pdf wysyłany jest na ekran. Jak upraszczamy? Oto przykład postępowania - oczywiście szczegóły działania będą zależne od poszczególnego przypadku. Najpierw upewnijmy się, że komponent, którego używamy, jest poprawnie zainicjalizowany. Można na przykład podstawić za niego inny komponent (np. bardzo uproszczoną implementację komponentu) lub zainicjować go ręcznie, jeśli domyślnie jest tworzony na podstawie pliku konfiguracyjnego. Jeśli konfiguracja komponentu nie była przyczyną błędu, możemy zamiast pobierać dane ze źródła danych spreparować wyniki (badamy, czy błąd związany jest z wynikami pochodzącymi ze źródła danych). Następnie możemy sami wygenerować sztuczny obiekt do tworzenia pliku pdf (lub go w ogóle nie tworzyć). Zamiast tworzyć pdf (strumień binarny) można pokusić się o proste dane znakowe (strumień znakowy) i w ten sposób wykluczyć ewentualne błędy tworzenia pliku pdf i pokazywania go na ekranie. Jeśli na którymś etapie odkryjemy, że pojawia się błąd, analizujemy dany etap, stosując powyższy algorytm, ograniczając go do tego etapu. W procesie wyszukiwania błędów niezwykle przydatne są pliki logów czy testy regresyjne. Są to jednak tylko narzędzia i mogą co najwyżej wesprzeć powyżej opisany proces. Całość pracy intelektualnej musimy wykonać sami. Skoro jesteśmy przy wyszukiwaniu błędów, to przy okazji jeszcze jedna wskazówka: Przyczyny błędów są najczęściej ukryte tam, gdzie dalibyśmy sobie głowę uciąć, że ich tam nie ma. Najprostsza i jedna z częstszych przyczyn błędów to literówka.
MICHAŁ BARTYZEL, MARIUSZ SIERACZKIEWICZ Trenerzy i konsultanci w �rmie BNS IT. Badają i rozwijają metody psychologii programowania, pomagające programistom lepiej wykonywać ich pracę. Na co dzień autorzy zajmują się zwiększaniem efektywności programistów poprzez szkolenia, warsztaty oraz coaching i trening. Kontakt z autorami: m.bartyzel@bnsit.pl, m.sieraczkiewicz@bnsit.pl
9/2010
PRZEGLĄD NOWOŚCI
Generator raportów dla .Net (Visual Studio) FastReport.NET 1.4 FastReport.Net – generator raportów z wieloma funkcjami dla deweloperów, korzystających z Microsoft Visual Studio 2005 oraz 2010, Delphi Prism lub z dowolnego innego narzędzia do opracowywania, które współpracuje z .NET Framework 2.0 i kolejnymi wersjami.
K
orzystając z FastReport.Net, mogą Państwo tworzyć raporty niezależnie od aplikacji. Innymi słowy, FastReport.Net może być wykorzystywany jako samodzielne narzędzie do tworzenia raportów.
Charakterystyka: • • •
•
można połączyć się z wybraną bazą danych, korzystać z jej dowolnych tabeli lub stworzyć własne zapytania w języku SQL; można dodać jedno lub kilka okien dialogowych do raportu, w celu określenia parametrów przed uruchomieniem raportu; korzystając z wbudowanego skryptu, można zarządzać interakcją pomiędzy elementami zarządzania przy pomocy okien dialogowych i wykonywać złożoną obróbkę danych; na koniec, można zobaczyć rezultat w oknie podglądu, wydrukować raport lub eksportować w różnych znanych formatach.
•
FASTREPORT®.NET – Elementy raportu •
•
Właściwości: •
• •
•
78
FastReport.Net jest zapisany tylko w C# i zawiera tylko kod zarządzania. Jest kompatybilny z .NET Framework 2.0 i kolejnymi wersjami. .Nie współpracuje z NET Framework 1.x. FastReport.Net jest dostarczany z kodami wejściowymi (wersja Professional). Może być dostosowany do Państwa potrzeb. Rozsądna cena oraz licencja. W skład licencji wchodzi projektant wizualny - użytkownicy mają możliwość samodzielnego opracowywania raportów. Nie potrzeba żadnych dodatkowych opłat! Rozszerzona architektura FastReport.Net pozwala tworzyć i włączać do raportu swoje własne obiek-
ty, filtry eksportu, funkcje, szablony, silniki baz danych. Jeżeli istniejące funkcje są niewystarczające – można je rozszerzyć! Kompaktowy i zadziwiająco szybki!
• •
• •
FASTREPORT®.NET – to generator raportów działający na podstawie band. Dostępnych jest 13 typów band: Tytuł raportu, Stopka raportu, Tytuł strony, Stopka strony, Tytuł kolumny, Stopka kolumny, Tytuł danych, Dane, Stopka danych, Tytuł grupy, Stopka grupy, Element potomny, nakładka. Mogą Państwo również korzystać z podraportów, które są w pełni obsługiwane. Bogaty wybór band pozwala na tworzenie raportów dowolnego rodzaju: • lista, master-detail, • raport z grupowaniem, wielokolumnowy master-detail-detail i wiele innych. Wiele obiektów, które można stosować w raporcie: tekst, obrazy, linie, formularze, diagramy*, kody kreskowe, macierz, tabela, obiekt rtf, obiekt „flaga”. Raport może zawierać kilka stron. Można utworzyć raport, który składa się z okładki, danych i strony końcowej. Obiekt „Tabela” pozwala tworzyć raporty typu tabeli ze zmienną ilością wierszy oraz/lub kolumn, jak w MS Excel. Można również korzystać z funkcji agregatowych. Wszechstronna i w pełni konfigurowalna „Macierz” pozwala łatwo tworzyć zbiorowe raporty. FASTREPORT®.NET zawiera wizualizację GDI+, co daje możliwość korzystania również z takich funkcji GDI+ jak czcionki i grafika z wyrównaniem, półprzezroczyste wypełnienie i gradienty. Wszyst-
9/2010
Generator raportów dla .Net (Visual Studio) FastReport.NET 1.4
•
ko to pomoże użytkownikowi stworzyć estetyczne i profesjonalnie wyglądające raporty. Dziedziczenie raportów. Posiadają Państwo wiele raportów zawierających jednakowe elementy (tytuł, stopka, elementy firmowe, logotypy)? Wystarczy umieścić wszystkie wspólne elementy w raporcie bazowym i tworzyć na jego podstawie pozostałe raporty.
FASTREPORT®.NET – Projektant raportów •
•
• • •
FASTREPORT®.NET przy tworzeniu i modyfikacji raportów nie korzysta z narzędzia MS Visual Studio, w przeciwieństwie do wielu innych generatorów raportów. Zamiast tego, posiada on projektanta wizualnego, zawierającego funkcję powiększania, bufor undo/redo, siatkę oraz linijki. Interfejs projektanta jest w pełni regulowany i jest imitacją narzędzie MS Visual Studio. Projektant może być używany w trybie run-time, Państwa użytkownicy mają możliwość samodzielnego opracowywania i modyfikowania istniejących raportów oraz tworzenia nowych. Nie wymaga dodatkowych opłat licencyjnych. Element zarządzania „Struktura raportu” pokazuje w podglądzie logiczną strukturę raportu. Pozwala to na lepsze zrozumienie raportu, zwłaszcza, jeżeli nie są Państwo jego autorami. >Szablon do tworzenia raportów bazy. Wystarczy przejść 5 kroków i uzyskać dopracowany, gotowy do wykorzystania raport. Szablon do drukowania etykietek zawiera większość rodzajów etykietek i pomoże stworzyć raport przy pomocy kilku kliknięć myszką. Projektant może być używany w trybie MDI (MultiDocument Interface) do pracy z większą ilością raportów jednocześnie.
•
•
FASTREPORT®.NET – Przeglądanie, drukowanie, eksportowanie • • • •
•
•
FASTREPORT®.NET – Przetwarzanie danych •
• • •
•
>FASTREPORT®.NET współpracuje ze źródłami danych ADO.NET. Ma możliwość sortowania i filtrowania danych, relacji master-detail. Wszystko to może być wykonane za pomocą kilku kliknięć myszką. Podłączenie bazy danych do ADO, MS SQL. Możliwość uzyskiwania danych z obiektów biznesowych typu IList, IEnumerable, ITypedList*. Raport może zawierać dane (tabele, zapytania, połączenia z bazą danych) W ten sposób, użytkownik może nie tylko korzystać z danych, udostępnionych w aplikacjach, ale również samodzielnie podłączyć się do wybranych baz danych bezpośrednio z raportu. FastReport.Net zawiera silnik skryptowy, obsługujący dwa języki.NET, C# i VB.NET. Mogą Państwo
www.sdjournal.org
wykorzystać całą moc .NET w Państwa raporcie do wykonania złożonego przetwarzania danych, zarządzania oknami dialogowymi i do wielu innych rzeczy. Raport może zawierać okna dialogowe do określania parametrów przed utworzeniem raportu. Dialogowe elementy zarządzania zawierają funkcję podłączenia do danych, a następnie przefiltrowania ich. Filtrowanie można dokonać w dowolnym raporcie, bez potrzeby wpisywania żadnego kodu. Korzystając z wizualnego konstruktora zapytań, użytkownik nie musi znać języka SQL, aby utworzyć złożoną kwerendę z kilku tabeli*.
• •
•
Poręczne okno podglądu w stylu MS Word. Wyszukiwanie tekstu w gotowym raporcie. Edytowanie stron gotowego raportu. Nawigacja w oknie podglądu. Przy tworzeniu raportu użytkownik może wydzielić elementy, które utworzą schemat raportu. Schemat ten zostanie pokazany w oknie podglądu. Po kliknięciu elementu schematu, zostanie wyświetlony odpowiadający mu element raportu. Użytkownik może również wybrać aktywne elementy raportu, które będą reagować na kliknięcie myszą. Można to wykorzystać do nawigacji do innego elementu raportu lub do zewnętrznego URL. Raporty interaktywne. Można przypisać reakcję kliknięcia myszą do obiektu w oknie podglądu. Można, na przykład, utworzyć i wyświetlić inny raport, który pokazuje szczegółowe dane obiektu, który użytkownik kliknął myszką. Szerokie możliwości drukowania raportu: Dzielenie dużych stron na małe, drukowanie kilku małych stron na jednej dużej, drukowanie w wybranym formacie przy użyciu skali. Muszą Państwo wydrukować raport zawierający strony w formacie A3 na zwykłej drukarce o formacie А4? Teraz to żaden problem! Dodawanie znaków wodnych do raportów w łatwy sposób. Filtry eksportu gotowego raportu do wielu formatów(PDF, RTF, XLS, XML, HTML, JPG, BMP, GIF, TIFF, TXT, CSV, Open Document Format)*. Wysyłanie raportów pocztą elektroniczną za pomocą jednego kliknięcia myszą*. Dodawanie znaków wodnych do raportów w łatwy sposób. Więcej o produkcie na http://www.fast-report.com/pl/
79
FELIETON
Make IT Green! Biznes i ekologia? Czemu nie… Również firmy z branży IT mogą wiele zrobić, aby połączyć swoją działalność z ochroną środowiska. Jak? Odpowiedzią jest Green IT, do niedawna tylko moda, a od jakiegoś czasu konieczność, wymóg nakładany na firmy przez Unię Europejską, ale także inne organizacje. Brzmi strasznie? Na szczęście – jak to się mówi – nie taki diabeł straszny jak go malują. Dowiesz się:
Powinieneś wiedzieć:
• Czym jest Green IT, • Jak ma się Green IT w Polsce
• Że urządzenia elektroniczne emitują ciepło szkodliwe dla środowiska, • Że degradację środowiska można powstrzymać
N
a początku zatem trochę teorii, abyśmy wiedzieli, z czym tak naprawdę mamy do czynienia. Pod nazwą Green IT, po polsku Zielone IT, rozumie się wszelkie działania, które mają wyeliminować lub zmniejszyć szkodliwy wpływ na środowisko, jaki generują firmy z branży IT. Działania te mają także zwiększyć oszczędność w obrębie tego sektora. Powyższe cele można osiągnąć na wiele sposobów, np. stosując wydajne zarządzanie energią, prawidłowo segregując i pozbywając się e-odpadów, używając odnawialnych źródeł energii itd. Jednym zdaniem można zatem podsumować, że zielona informatyka ma być energooszczędna i przyjazna środowisku.
Czy to ważne?
Rozwój technologii informatycznych sprawia, że notuje się znaczny wzrost zużycia energii. Najbardziej energochłonnymi elementami infrastruktury IT są centra danych, które wykorzystują ponad połowę zasilania. Najwięcej energii zużywa się na zasilanie i chłodzenie serwerów. Dlatego też firmy opracowują wiele innowacyjnych rozwiązań, które mogłyby ograniczyć nie tylko koszty ale także zużycie energii. Jak wiadomo, firma to organ nastawiony głównie na zysk, dlatego jeśli dana korporacja nie wprowadza proekologicznych rozwiązań z myślą o środowisku, to na pewno robi to z myślą o swoim budżecie. Obecnie odnotowuje się znaczący wzrost cen energii elektrycznej.
80
Należy także dodać, że każda rozwijająca się firma wykorzystuje coraz więcej urządzeń elektrycznych (komputerów, serwerów, drukarek itp.). IDC prognozuje, że do 2015 roku ceny energii wzrosną o tyle, iż energia stanie się podstawowym kosztem obsługi informatycznej przedsiębiorstwa. Natomiast wg badań firmy McKinsey, w ciągu 20 lat zużycie prądu w firmach IT będzie wzrastać aż o 3% rocznie. Wniosek z powyższego jest prosty: wdrażając politykę Green IT, firma nie tylko chroni środowisko naturalne, ale także odnosi realne korzyści ekonomiczne. Mniejsze rachunki za prąd, to przecież oszczędzanie środków, które następnie mogą być przeznaczane na rozwój przedsiębiorstwa. Ktoś mógłby jednak zauważyć, że inwestycje w ekologię są drogie i w sumie niekoniecznie będzie opłacać się to firmie. Otóż nic bardziej mylnego. IBM szacuje, że pełny zwrot z inwestycji w proekologiczne technologie IT następuje już po 2 latach od wdrożenia danej technologii, biorąc pod uwagę tylko zużycie energii elektrycznej.
Jakie działania?
Teraz dokładniej o tym, jakie działania ma podjąć firma, aby móc się pochwalić tym, że działa zgodnie z Green IT. Pierwszym i jednym z najważniejszych aspektów polityki proekologicznej w przedsiębiorstwie IT jest zakup energooszczędnych urządzeń komputerowo-biurowych. Następnym ważnym
9/2010
Make IT Green!
działaniem są nowoczesne rozwiązania komunikacyjne i zdalnego dostępu, np. WLAN/WAN, VPN, VoIP, wideokonferencje, hosting. Jeżeli mowa o firmach z branży IT, to nie sposób tu także nie wspomnieć o zoptymalizowanych technologiach gromadzenia i przechowywania danych, jak Data Center, storage, wirtualizacja, systemy chłodzące. Zielona firma IT to także taka, która oferuje swym klientom ekologiczne usługi. Jak wynika z badań, świadomość proekologiczna wśród społeczeństwa rośnie, ludzie coraz częściej wybierają te produkty i usługi, które mają przyczepioną metkę z napisem „produkt przyjazny środowisku”. Korzystanie z ekologicznych technologii informatycznych jest częścią polityki „odpowiedzialnego społecznie biznesu” i „zrównoważonego rozwoju”.
Dobre praktyki, czyli przykład, co należy robić
Skandynawię uznaje się za rejon świata, który jest znany ze swojej ekologiczności. Również w przypadku Green IT tamtejsi producenci, czy też dostawcy usług mogą się pochwalić niemałym dorobkiem. Jako przykład, niech posłuży nam Tieto – skandynawska firma z branży nowoczesnych technologii, świadcząca usługi IT, R&D oraz doradcze, która swoją działalność prowadzi w wielu różnych krajach, w tym także w Polsce. Przechodząc do szczegółów – jakimi dobrymi praktykami może pochwalić się wspomniana wyżej firma? O działalności proekologicznej Tieto możemy się dowiedzieć, poznając jej cele środowiskowe, które firma stawia sobie do zrealizowania do 2013 roku. Pierwszym celem korporacji jest zmniejszenie rocznej całkowitej emisji dwutlenku węgla do atmosfery spowodowanej działalnością firmy. W efekcie aktywnych działań na tym polu, Tieto postrzegana jest jako firma wiodąca w temacie Green IT. Dlatego też wszystkie oddziały Tieto są certyfikowane zgodnie ze standardami WWF (World Wildlife Fund, organizacja ekologiczna o charakterze międzynarodowym, stara powstrzymywać degradację środowiska naturalnego na Ziemi) dotyczącymi zielonych biur. Tieto posiada także certyfikat ISO 14001 na poziomie korporacyjnym. Ten standard ISO jest związany z ekozarządzaniem, a dokładniej z zarządzaniem środowiskowym w firmie. Innym aspektem polityki środowiskowej Tieto jest to, że wszyscy jej dostawcy są zobowiązani do przestrzegania zasad programu ONZ Global Compact. Poza tym, co najmniej 90% wszystkich nabytych towarów i usług pochodzi od dostawców, którzy posiadają certyfikat ISO 14001 lub inną normę prawną równą wspomnianemu certyfikatowi ISO. Kolejnym celem, jaki korporacja zamierza zrealizować do 2013 roku, jest niższe zużycie energii w biu-
www.sdjournal.org
rach i innych obiektach o co najmniej 7% rocznie (w 2013 zużycie energii ma być aż o 30% niższe niż w roku 2008). Planuje niższe zużycie energii w centrach danych o co najmniej 8% rocznie (do 2013 roku zużycie ma być o 34% niższe niż w 2008 roku). Jeszcze innym czynnikiem, który również korzystnie wpływa na środowisko, ale także na wizerunek firmy w prowadzeniu polityki zrównoważonego rozwoju i jednocześnie nie jest skomplikowany we wdrożeniu jest to, że do 2013 roku zamierza zwiększyć wykorzystanie wideo i audio konferencji oraz technologii związanych z tego typu działalnością, aby zachęcić pracowników do pracy zdalnej w celu zmniejszenia podróży i kosztów z nimi związanych o co najmniej 9% w skali roku. Należy także wspomnieć, że jednym z celów, jakie postawiła sobie firma Tieto, jest obniżenie całkowitego zużycia papieru o co najmniej 10% rocznie. Warto także wspomnieć o zamiarze znacznego zwiększenia swej oferty w dziedzinie Green IT dla kluczowych i najważniejszych klientów. Oprócz tego firma Tieto, bazując na doświadczeniach minionego stulecia, postanowiła jeszcze bardziej unowocześnić i rozpowszechnić swój sposób
81
FELIETON
ogrzewania pomieszczeń, a co za tym idzie oszczędność pieniędzy. W jednej z filii Tieto w Szwecji (dokładnie w Sätterstrand) wykorzystano pompy ciepła, które „odzyskują” ciepło z atmosfery uprzednio wyemitowane przez urządzenia wykorzystywanej w tejże filii. Dzięki temu zabiegowi, korporacja może sprzedawać wytworzoną u siebie energię lokalnemu dostawcy energii cieplnej. Projekt ten działa od lutego 2010 roku, dlatego nie ma jeszcze dokładnych danych, jaki wpływ ma na odzyskiwanie ciepła, ale według wstępnych kalkulacji, metodą tą będzie można rocznie ogrzać około 140 domów jednorodzinnych. Pomysł z odzyskiwaniem ciepła i jego sprzedażą jest zdecydowanie najważniejszym i najlepszym pomysłem, jaki firma mogła zastosować. W przypadku Tieto był on na tyle trafny, że w kolejnej filii korporacji, w Sztokholmie, również działa ten system i ogrzewa okoliczne domy. Także w najnowszym centrum danych w Espoo postanowiono wdrożyć takie rozwiązanie, jednakże w tym przypadku energia wytwarzana przez komputery firmy ma ogrzać ponad 1000 domów mieszkalnych, co jest liczbą naprawdę imponującą i pozwala na wyobrażenie sobie, jak łatwo moż-
na spowolnić degradację środowiska – wystarczy tylko chcieć. Widać więc wyraźnie, że Green IT poza granicami Polski ma się dobrze. Jak jednak jest w naszym kraju? Również tutaj można posłużyć się przykładem Tieto, które działa także na naszym rodzimym rynku. Przede wszystkim, zauważyć można, że coraz częściej spotyka się przeniesienie pewnych aspektów życia do infrastruktury sieciowej, poprzez np. telepracę, teleusługi. Ważny jest tutaj też sposób dostarczania danych – zamiast stosować nośniki wymagające zużycia zasobów fizycznych, co powoduje degradację środowiska (nie tylko przy ich wytwarzaniu, ale również przy późniejszym ich składowaniu), dane dostarcza się klientom przez sieć, co jest dodatkowo znacznie szybsze i mniej kosztowne. M.in. na tym właśnie skupia się Tieto w Polsce – zasoby naturalne wykorzystuje w sposób bardzo ostrożny, podejmuje działania profilaktyczne, które mają na celu zminimalizowanie oddziaływania na środowisko. Z bardziej ogólnych działań można wymienić również redukcję zużycia energii i świadome podejście do lokalizacji biurowych, recykling materiałów biurowych, odpadów, dobór materiałów przyjaznych środowisku. Również ważnym aspektem jest stosowanie wideokonferencji, kiedy tylko jest to możliwe, co powiązane jest również z coraz popularniejszą telepracą, o której wspomniano wcześniej. Ważne jest również, by nie tylko samodzielnie dbać o środowisko, ale również zachęcać do tego innych, swoich klientów czy partnerów biznesowych, co jest możliwe zwłaszcza w przypdku dużych korporacji, które mają do powiedzenie więcej niż zwykłe mikroprzedsiębiorstwa. Firmy takie jak Tieto wypracowują więc własne polityki środowiskowe, wedle których działają i przekonują do nich inne organizacje. Polityki takie są oczywiście monitorowane i odpowiednio aktualizowane.
Podsumowanie
Jak widać na przykładzie szwedzkiej korporacji Tieto, działającej także w Polsce, implementacja polityki związanej z ekologią nie jest rzeczą trudną, a na pewno opłacalną. Pomijam już fakt oszczędności pieniędzy. W dzisiejszych czasach firma, aby pozostać na rynku i dobrze prosperować, musi być konkurencyjna. Implementując strategię „zielonego IT” w organizacji wyprzedza się zdecydowanie konkurencję. Ważnym czynnikiem tu jest to, że to sami właściciele danych firm decydują o tempie wprowadzanych zmian (tam, gdzie jeszcze nie obowiązują formalne regulacje prawne). W tej dziedzinie można liczyć na wsparcie instytucji rządowych oraz środowiska lokalnego, które będzie postrzegać firmę jako nowoczesną, przyjazną środowisku i odpowiedzialną, a co za
82
9/2010
Make IT Green!
tym idzie, konkurencyjną na rynku nie tylko lokalnym, ale także międzynarodowym. Według sondażu Zrównoważone IT 2008 zleconego przez BEA w I kwartale 2008r., ponad 2/3 europejskich firm ma już stworzony i działający plan zmniejszenia zużycia energii oraz emisji gazów cieplarnianych spowodowanych korzystaniem z urządzeń informatycznych; ponad 30% organizacji w chwili prowadzenia sondażu wdrażało lub było w trakcie opracowywania strategii „Green IT”. Europa zatem całkiem nieźle sobie radzi z wprowadzaniem innowacji związanych z IT. Jednak co z Polską? Niestety tu raporty nie są zbyt zachwycające. Już sam fakt, że gdy w wyszukiwarkę wpisuje się termin„Green IT” i pojawiają się same anglojęzyczne strony, świadczy o tym, że w naszym kraju świadomość ekologiczna firm jest niska. W Polsce, miejmy nadzieję, że tylko na razie, nie kładzie się nacisku na aspekty ekologiczne w przypadku urządzeń. Przedsiębiorcy co najwyżej zwracają uwagę na ekologię np. w przypadku papieru - część swoich prac drukują na papierach ekologicznych. Jednakże w przypadku urządzeń pomijane są aspekty związane ze zużyciem energii czy materiałów, z jakich wykonano urządzenie. Na początek jednak, dobre i to – oby tylko na tym się nie skończyło. Jak wynika z badań D-Link Technology Trend, przeprowadzonych wśród polskich firm sektora MŚP, przy zakupie sprzętu IT ekologiczne aspekty stanowią marginalną rolę. Mimo wysokiej świadomości ekologicznej oraz świadomości korzyści wynikających z używania energooszczędnych urządzeń, firmy przy zakupach kierują się przede wszystkim ceną. Prawie wszyscy ankietowani (94%) zgodzili się co do tego, że wykorzystanie energooszczędnych urządzeń przyczynia się do dbałości o środowisko naturalne, ale przy zakupie sprzętu na posiadane przez producentów certyfikaty związane z ochroną środowiska zwraca uwagę niecała połowa (49%) z nich. Jeszcze mniejszy odsetek firm (36%) zwraca uwagę na poszanowanie środowiska przy produkcji sprzętu.
Badanie te pokazują, że w Polsce świadomość, że o środowisko należy dbać, jest duża, a to stanowi ogromny plus. Minusem jednak jest fakt, że firmy oszczędzają na rozwiązaniach ekologicznych. Przyczyną takiego stanu rzeczy jest niska świadomość polskich przedsiębiorców. W mediach niewiele wspomina się o realnych korzyściach z implementacji rozwiązań Green IT w firmie. Na koniec jeszcze trochę o producentach sprzętu elektronicznego, którzy także należą do branży IT, i którzy również znają pojęcie „Zielone IT”. Niestety dużo z tych przedsiębiorstw uważa, że mogą uchodzić za „zielone”, jeżeli zaczną oferować energooszczędne produkty i usługi. Jednakże nie o to tylko w tym wszystkim chodzi. Producenci z branży IT wprowadzają bardzo wiele innowacji proekologicznych: jedni ograniczają w swych towarach ilość toksycznych chemikaliów, drudzy dążą do zapewnienia skuteczniejszego wykorzystania energii, wydłużenia cyklu życia produktu, a inni usprawniają proces recyklingu. Jednak, aby produkt był w pełni ekologiczny, należy połączyć wszystkie te działania.
ROGER ZACHARCZYK Pracuje jako programista gier komputerowych, studiuje na piątym roku informatyki na wydziale Informatyki i Zarządzania Politechniki Wrocławskiej. Zainteresowania: języki programowania, webserwisy, opensource (od 2000 roku). Kontakt z autorem: roger.zacharczyk@gmail.com
Reklama
www.sdjournal.org
83
KLUB PRO INFOTEX SP.J Śmietanowski i Wsp.
TTS Company Sp. z o.o.
http://www.infotex.com.pl
http://www.OprogramowanieKomputerowe.pl
Dystrybutor XP Unlimited – Serwer Terminali dla Windows XP i VISTA. Program umożliwia łączenie się z dowolnego klienta Windows, Linux z wykorzystaniem protokołu RDP. Cena wersji Classic dla 5 użytkowników - 165€, dla nieograniczonej liczby - 235€. Ponadto oferujemy opiekę serwisową i aplikacje internetowe na zamówienie.
Sprzedaż i dystrybucja oprogramowania komputerowego. Import programów na zamówienie. Ponad 200 producentów w standardowej ofercie. Chcesz kupić oprogramowanie i nie możesz znaleźć polskiego dostawcy? Skontaktuj się z nami – sprowadzimy nawet pojedyncze licencje.
Softline rozwiązania mobilne Volantis jest uznanym na całym świecie dostawcą rozwiązań mobilnych dla firm udostępniających informacje oraz dane przez Internet (operatorów telefonii komórkowej, stacji tv, czasopism internetowych). Dzięki zasadzie „stwórz raz, uruchamiaj gdziekolwiek” nasze rozwiązania zmniejszają złożoność, koszt i czas dostarczenia na rynek serwisów i aplikacji. Volantis jest członkiem organizacji W3C, a naszymi klientami są światowi potentaci telekomunikacyjni.
Proximetry Poland Sp. z o.o.
Proximetry Poland Sp. z o.o. jest polskim oddziałem amerykańskiej firmy Proximetry Inc. – dostawcy systemów zarządzania sieciami bezprzewodowymi 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 najlepszych i zostań członkiem naszej ekipy! http://www.proximetry.com
Opera Software
Opera Software’s vision is to deliver the best Internet experience on any device. We are offering browser for PC/desktops and embedded products that operates across devices, platforms and operating systems. Our browser can deliver a faster, more stable and flexible Internet experience than its competitors.
Wiodący producent systemów mobilnych, dostawca aplikacji użytkowych dla biznesu (Symbian OS, Windows Mobile, J2ME ) zaprasza do współpracy. Zostań naszym partnerem. Dołącz do zespołu. http://www.softline.com.pl
Systemy bankowe, ISOF
HEUTHES istnieje na rynku od 1989 r. Obok systemów informatycznych dla banków, oferuje nowoczesne oprogramowanie do obsługi firm. System ISOF jest udostępniany klientom w trybie SaaS lub licencji. Pracuje na platformie Linux i zawiera m.in. takie moduły jak CRM, DMS, Magazyn, Sprzedaż, Logistyka oraz Rachunkowość. http://www.isof.pl
Architektury systemów IT
http://www.opera.com
Twórca frameworków JUVE i serwera aplikacji AVAX oferuje usługi, doradztwo, rozwiązania do tworzenia nowoczesnych, dużych systemów i rozwiązań informatycznych/internetowych, integrujące architektury ery post-J2EE/.NET, wykorzystujące MDD/MDA dla dziedzin – bankowość, telekomunikacja, handel, e-commerce, ERP/Workflow/CRM, rozwiązania internetowe, portalowe. www.mpsystem.com mpsystem@mpsystem.com
Kei.pl
Future Processing
http://www.kei.pl
http://www.future-processing.pl
Kei.pl działa na rynku usług hostingowych od 2000 roku. Do naszych zadowolonych Klientów z dumą możemy zaliczyć wiele przedsiębiorstw sektora MSP, instytucji oraz osób prywatnych. W ofercie Kei.pl znajdują się pakiety hostingowe, a także usługi dla wymagających Użytkowników – platformy e-Biznes oraz serwery fizyczne.
Playsoft
Playsoft jako lider portowania aplikacji na platformy mobilne wciąż powiększa bazę swoich klientów: EA Mobile, Sega, THQ, Konami. W ramach rozszerzania swojej działalności, poszukujemy doświadczonego programisty, który byłby odpowiedzialny za tworzenie aplikacji na platformy Iphone, Windows Mobile, Android. http:// www.playsoft.fr
Future Processing to dynamiczna firma technologiczna działająca na globalnym rynku oprogramowania. Jesteśmy zespołem wysokiej klasy specjalistów posiadających wiedzę i doświadczenie niezbędne do realizacji ambitnych projektów informatycznych. Jeśli programowanie to Twoja pasja dołącz do nas! (możliwość pracy zdalnej).
WSISiZ w Warszawie INFORMATYKA ZARZĄDZANIE
studia stopnia I i II (stacjonarne i niestacjonarne) specjalności: inżynierskie, magisterskie i licencjackie. Szczegółowe plany studiów, opisy poszczególnych specjalności – zapraszamy na stronę uczelni. http://www.wit.edu.pl