You are on page 1of 60

REDAKCJA

7/2011 (199)

BIBLIOTEKA MIESIĄCA Programowanie Tcl

4 Grafy i algorytmy grafowe. T­ cl: wirtualne systemy plików.


Biblioteka boost::graph 24 Część II: Skrypty Tcl jako aplikacje
Robert Nowak, Andrzej Michałowski wykonywalne
Grafy są strukturą danych, która pozwala opisać zło- Piotr Bełtowski, Wojciech Kocjan
żone zależności z otaczającego nas świata. W artykule Tcl/Tk to dosyć interesujący język. Od 20 lat Tk po-
omawiamy bibliotekę do reprezentacji grafów, wchodzą- zwala na tworzenie budowanie interfejsów graficznych
cą w skład kolekcji boost. działających na różnych systemach operacyjnych – wy-
korzystywane między innymi przez języki Perl oraz Py-
KLUB TECHNICZNY thon. Od 11 lat Tcl pozwala na pakowanie całej aplika-
cji do pojedynczego pliku wykonywalnego – co prak-
Po drugiej stronie ekranu.
10 Czyli od kampera do game
tycznie eliminuje problemy z dystrybucją aplikacji oraz
ich uaktualnianiem. W dzisiejszym artykule przybliżymy
developera. ten proces.
Adrian Zając
Niewiele osób zdaje sobie sprawę, że praca przy tworze- Tcl: wirtualne systemy plików.
niu gier komputerowych stała się w ostatnich latach jak 34 Część III: System budujący TABS
najbardziej realnym źródłem dochodów w naszym kra- Piotr Bełtowski, Wojciech Kocjan
ju. Młodzieńcze pasje mogą nie tylko znaleźć swe ujście Programiści Javy od lat z powodzeniem korzystają ze
w nowo otwartych kierunkach studiów, lecz otworzyć sprawdzonego i popularnego rozwiązania, jakim jest
przed nami drogę do jednego z najbardziej dochodowe- środowisko budujące Ant. Przyjęta filozofia definiowania
go segmentu rynku. projektów jest na tyle wygodna i elastyczna, że docze-
kała się analogicznych narzędzi dla innych języków. Rów-
Programowanie Java nież Tcl może poszczycić się systemem TABS, który opi-
szemy w niniejszym artykule.
18 Analiza wydajności aplikacji Java
dla opornych. Jak diagnozować
i rozwiązywać problemy z Garbage
Collectorem w Javie?
Daniel Witkowski, Paweł Wojtanka

Miesięcznik Software Developer’s Journal (12 numerów w roku) ul. Bokserska 1, 02-682 Warszawa, Polska
jest wydawany przez tel. +48 22 427 36 91, fax +48 22 224 24 59
Software Press Sp. z o.o. SK
www.sdjournal.org
Prezes: Paweł Marciniak cooperation@software.com.pl

Dyrektor wydawniczy: Natalia Sieniutowicz Dział reklamy: adv@software.com.pl


Redakcja dokłada wszelkich starań, by publikowane w piśmie
Redaktor naczelny: Łukasz Łopuszański i na towarzyszących mu nośnikach informacje i programy były
lukasz.lopuszanski@software.com.pl poprawne, jednakże nie bierze odpowiedzialności za efekty
Skład i łamanie: Tomasz Kostro wykorzystania ich; nie gwarantuje także poprawnego działania
www.studiopoligraficzne.com programów shareware, freeware i public domain.
Kierownik produkcji: Andrzej Kuca Wszystkie znaki firmowe zawarte w piśmie są własności
andrzej.kuca@software.com.pl odpowiednich firm.
Zostały użyte wyłącznie w celach informacyjnych.

Adres korespondencyjny: Osoby zainteresowane wspópracą prosimy o kontakt:


Software Press Sp. z o.o. SK, cooperation@software.com.pl

2 7/2011
Spis treści

su, że się nie opłaca.Wszystkie te osoby mają coś wspól-


­E-Commerce nego, w praktyce prawie nikt tego nie robi. Głównie dla-
tego, że to kosztuje. Czy na pewno?
Wiem czego chcesz. Systemy
42 rekomendacji produktów Skuteczne wdrażanie w projekt
Piotr Płoński 56 Michał Kapłon
Współcześnie trudno jest znaleźć w sieci, film, książ- Wszyscy wiedzą, jak to jest z nowymi projekta-
kę, piosenkę – produkt, który będzie się nam podobał. mi. Niezależnie od tego czy są ciekawe czy nudne, łatwe
W artykule opiszę dwa algorytmy stosowane najczęściej czy wymagające, skomplikowane technologicznie czy da-
w serwisach internetowych, takich jak np. Amazon.com jące się realizować za pomocą kartki papieru i ołówka,
lub YouTube.com, do polecania produktów. Systemy re- jedną przynajmniej cechę mają wspólną. Dla ludzi, któ-
komendacji pozwalają użytkownikowi znaleźć szybciej rzy dołączają do zespołu są nowe. Nowi programiści, za-
interesujący go produkt, a właścicielom serwisów osią- nim w pełni rozwiną swe „koderskie” skrzydła, muszą
gać większe zyski. nauczyć się wielu reguł, faktów, zależności – słowem, niu-
ansów nowej domeny. Rolą mentorów jest umożliwie-
INŻYNIERIA OPROGRAMOWANIA nie im tego w jak najmniej bolesny sposób. Rolą ich sa-
mych jest świadome uczenie się rzeczy istotnych, najbar-
Naturalny porządek refaktoryzacji dziej potrzebnych.
46 Michal Bartyzel, Mariusz Sieraczkiewicz
Są tacy, którzy wiedzą, że trzeba refaktoryzować.
Są tacy, którzy nie wiedzą, że trzeba refaktoryzować.
Są tacy, którzy uważają, że refaktoryzowanie nie ma sen-

Reklama

www.sdjournal.org 3
BIBLIOTEKA MIESIĄCA

Grafy i algorytmy grafowe


Biblioteka boost::graph library
Grafy są strukturą danych, która pozwala opisać złożone zależności
z otaczającego nas świata. W artykule omawiamy bibliotekę
do reprezentacji grafów, wchodzącą w skład kolekcji boost.

Dowiesz się: Powinieneś wiedzieć:


• Jak reprezentować grafy w C++; • Jak pisać proste programy w C++;
• Co oferuje biblioteka boost::graph; • Co to jest graf.
• Jak używać algorytmów grafowych oferowanych przez
tę bibliotekę.

cje ze standardowej biblioteki szablonów (patrz ramka).


Biblioteka boost::graph Graf reprezentowany listą sąsiedztwa generuje się uży-
Grafy, czyli zbiory wierzchołków powiązane krawędzia- wając szablonu adjacency_list, tak jak pokazano na Li-
mi (patrz ramka), są bardzo często wykorzystywane do stingu 1. Trzy pierwsze parametry są nazwami typów,
przetwarzania informacji. Są one bardzo ogólną struk- które definiują kolekcje wykorzystane do przechowy-
turą danych, inne powszechnie używane struktury da- wania krawędzi i wierzchołków oraz rodzaju grafu, na-
nych (drzewa, listy) są pewnymi szczególnymi przypad- tomiast trzy kolejne są typami związanymi z wierzchoł-
kami grafów. kiem, krawędzią i grafem. Znaczenie tych parametrów,
Biblioteka BGL (ang. Boost Graph Library), wchodząca oraz typowe wartości podano na Listingu 1. Biblioteka
w skład bibliotek boost, zawiera szablony reprezentu- wykorzystuje typ struct no_property {}, który oznacza,
jące grafy oraz zbiór kilkudziesięciu algorytmów grafo- że nie przechowujemy obiektów związanych z wierz-
wych. Grafy są dostarczane w postaci generycznej, dzię- chołkiem, krawędzią lub grafem.
ki czemu z wierzchołkiem, krawędzią lub całym grafem Graf może być reprezentowany także przez macierz
można związać obiekt lub obiekty dowolnego typu. Na sąsiedztwa (szablon adjacency_matrix) albo w postaci
rysunku 1 pokazano schematycznie graf przechowywany skompresowanej (szablon compressed_sparse_row_graph),
w takiej postaci, gdzie z wierzchołkiem są związane kra- te sposoby nie są wykorzystywane w tym artykule.
wędzie z niego wychodzące. W najprostszym przypadku, gdy krawędzie są przecho-
Szablony z biblioteki boost::graph wykorzystują kolek- wywane w wektorze, identyfikatorem wierzchołka jest

Szybki start
Aby uruchomić przedstawione przykłady, nale-
ży mieć dostęp do kompilatora C++ oraz edyto-
ra tekstu. Przykłady wykorzystują biblioteki boost
(www.boost.org). Aby poprawnie je skompilować
należy dodać odpowiednie zależności wykorzysty-
wane podczas konsolidacji; dla konsolidatora g++
należy dodać opcje: -lboost _ graph; dla konsoli-
datora Visual Studio (program link) biblioteki bo-
ost są dodawane automatycznie. Na wydrukach
pominięto dołączanie odpowiednich nagłówków
oraz udostępnianie przestrzeni nazw, pełne źródła
umieszczono jako materiały pomocnicze.
Rysunek 1. Przykładowy graf

4 7/2011
Grafy i algorytmy grafowe

liczba całkowita (indeks). W takim przypadku graf można


utworzyć dostarczając liczbę wierzchołków oraz tablicę Grafy
krawędzi, gdzie krawędź to para liczb: indeks wierzchoł- Grafy to zbiory wierzchołków powiązane krawę-
dziami. Każda krawędź zaczyna się i kończy w jed-
ka z którego krawędź wychodzi oraz indeks wierzchołka nym z wierzchołków. Grafy dzielimy na skierowa-
do którego krawędź wchodzi. Przykład konstrukcji grafu ne (krawędzie mają określony kierunek) oraz nie-
zawiera Listing 2. Reprezentacja wewnętrzna jest sche- skierowane. Przykład grafu pokazano na Rysunku
matycznie przedstawiona na Rysunku 2. 1. Specjalnym rodzajem grafów są drzewa, którymi
Dodawanie, usuwanie wierzchołków oraz krawędzi nazywamy grafy nie zawierające dróg zamknię-
tych (czyli cykli).
jest możliwe dla grafów utworzonych za pomocą sza- Grafy są bardzo często wykorzystywane do opi-
blonu adjacency_list. Wymienione modyfikacje grafu sywania różnych zależności z otaczającego nas
wykonuje się za pomocą funkcji add_vertex , add_edge, świata; przykładem jest opis sieci połączeń pomię-
remove_vertex oraz remove_edge. Szczególną uwagę nale- dzy miastami, wtedy wierzchołki mogą opisywać
ży zwrócić na usuwanie wierzchołków (remove_vertex), miasta, zaś krawędzie – drogi.
powinno się najpierw usunąć wszystkie krawędzie wcho-
dzące i wychodzące z usuwanego wierzchołka. Bibliote-
ka zawiera funkcję clear_vertex, która upraszcza to za- Standardowa biblioteka szablonów
danie. Zbiór kontenerów jednowymiarowych (tablice, listy,
Do grafu, pokazanego na Rysunku 1 dodawany jest no- słowniki), algorytmów i iteratorów, wchodzi w skład
wy wierzchołek. Następnie tworzona jest krawędź po- biblioteki standardowej języka C++. Jest bardzo
między wierzchołkiem A, a tym dodanym; później usu- wydajna i uniwersalna (wykorzystuje szablony).
wane są wszystkie krawędzie związane z wierzchołkiem Więcej informacji http://www.sgi.com/tech/stl/.
D (wchodzące i wychodzące). Na koniec usuwany jest

Listing 1. Szablon tworzący graf

adjacency_list<VertexList, //kolekcja przechowująca wierzchołki, znaczenie jest następujące:


// vecS - std::vector
// listS - std::list
// setS - std::set
// multisetS - std::multiset
OutEdgeList,// kolekcja przechowująca krawędzie - parametr ma wartości takie jak
VertexList
Directed, // rodzaj grafu, znaczenie:
// directedS - graf skierowany
// undirectedS - graf nieskierowany
VertexProperties, // typ obiektu związanego z wierzchołkiem, domyślnie no_property
EdgeProperties, // typ obiektu związanego z krawdzią, domyślnie no_property
GraphProperties> //typ obiektu zwizanego z caym grafem, domyślnie no_property

Listing 2 . Tworzenie i modyfikacja grafu

typedef adjacency_list<vecS, vecS, directedS> Graph; //typ grafu


enum { A, B, C, D, E, N }; //identyfikatory wierzchołków, N – liczba wierzchołków
typedef std::pair<int, int> Edge; //para liczb - reprezentuje krawędź
const Edge EDGE_ARRAY[] = { Edge(A,B), Edge(A,E),
Edge(B,A), Edge(B,C), Edge(B,D),
Edge(D,E), Edge(E,B) };
const int NUM_EDGES = sizeof(EDGE_ARRAY)/sizeof(EDGE_ARRAY[0]);
Graph g(EDGE_ARRAY, EDGE_ARRAY + NUM_EDGES, N);
Graph::vertex_descriptor v = add_vertex(g); //dodaje nowy wierzchołek
add_edge(A, v, g); //dodaje nową krawędź
clear_vertex(D, g); //usuwa krawędzie związane z wierzchołkiem D
remove_vertex(D, g); //usuwa wierzchołek

www.sdjournal.org 5
BIBLIOTEKA MIESIĄCA

ten wierzchołek. Po tych modyfikacjach będziemy prze-


chowywali graf pokazany na Rysunku 3.

Własne dane opisujące wierzchołki


i krawędzie
Jeżeli istnieje potrzeba dołączenia własnych danych, któ-
re opisują wierzchołek lub krawędź i które mają być za-
rządzane (tworzone i usuwane) przez klasy reprezen-
tujące wierzchołek lub krawędź, należy dostarczyć od-
powiedni typ jako parametr szablonu opisującego graf.
Poniżej pokazano graf, który przechowuje struktu-
rę CityData wraz z wierzchołkami oraz RoadData wraz Rysunek 2 . Graf przechowywany jako lista
z krawędziami. sąsiedztwa
Zamiast tworzyć własne typy, takie jak CitiData czy
RoadData, możemy wykorzystać zbiór etykiet dostarcza-
ny przez bibliotekę. Wtedy odpowiedni parametr szablo-
nu generujemy wykorzystując szablon property, przykład
pokazano na Listingu 4, gdzie w ten sposób dostarcza się
liczbę całkowitą przechowywaną w każdej krawędzi.

Znajdowanie najkrótszych ścieżek


o wspólnym początku – Algorytm Dijkstry
Mając graf składający się z wierzchołków i krawędzi łą-
czących te wierzchołki możemy przyporządkować po-
szczególnym krawędziom etykiety (liczby) nazywane wa-
gami. Etykiety te oznaczają koszt przejścia pomiędzy
wierzchołkami połączonymi krawędzią. Jednym z typo-
wych problemów grafowych jest problem znajdowania Rysunek 3. Graf pokazany na Rysunku 1 po
najkrótszych ścieżek (o najmniejszej wadze łącznej) z da- modyfikacjach
nego wierzchołka, zwanego źródłem, do wszystkich po-
zostałych wierzchołków w grafie. Problem ten rozwią- długość tej drogi, to wybierając dane miasto i stosując al-
zuje się zarówno dla grafów skierowanych, jak i nieskie- gorytm do znajdowania najkrótszych ścieżek otrzymamy
rowanych. Będziemy rozwiązywać ten problem przy po- wykaz najkrótszych dróg z zadanego miasta do wszyst-
mocy biblioteki boost::graph. kich pozostałych. Należy odnotować że waga krawędzi
Jeżeli wierzchołek będzie reprezentował miasto, kra- nie musi mieć czysto geometrycznej interpretacji (jaką
wędź – drogę pomiędzy miastami, zaś waga krawędzi to jest odległość między miastami), wagą krawędzi może

Listing 3. Graf przechowujący obiekty użytkownika w wierzchołkach i krawędziach

struct CityData { //obiekty związane z wierzchołkiem


CityData() : name(""), population(0) {}
string name;
int population;
};
struct RoadData { //obiekty związane z krawędzią
RoadData() : length(0) {}
int length;
};
//graf przechowujący w wierzchołkach obiekty typu CityData oraz obiekty typu RoadData w krawędziach
typedef adjacency_list<vecS, vecS, directedS, CityData, RoadData> Graph;
Graph g(3); //obiekt grafu (trzy wierzchołki, brak krawędzi)
Graph::vertex_descriptor v = *vertices(g).first; //identyfikator pierwszego wierzchołka
g[v].name = "Nowe Miasto"; //g[v] zwraca referencję na obiekt CityData
g[v].population = 2000;

6 7/2011
Grafy i algorytmy grafowe

Tabela 1: Algorytmy znajdowania najkrótszych ścieżek


Nazwa algorytmu W bibliotece BGL Kiedy stosujemy
Dijkstra dijkstra_shortest_paths wagi krawędzi dodatnie
Bellmana-Forda bellman_ford_shortest_path wagi krawędzi mogą być ujemne
Przeszukiwanie wszerz (BFS) breadth_first_search wagi krawędzi równe 1

Listing 4. Tworzenie grafu z wagami krawędzi.

typedef adjecency_list<
vecS,
vecS,
directedS,
no_property, // brak dodatkowych właściwości dla wierzchołków
property<edge_weight_t, unsigned int> // dodatkowa właściwość dla krawędzi
> Graph;
/* tutaj inicjacja tablicy EDGE_ARRAY tak jak pokazuje Listing 2 */
unsigned int weights[] = { /* tu podajemy wagi krawędzi */ };
Graph graph(
EDGE_ARRAY,
EDGE_ARRAY + NUM_EDGES,
weights, // tablica wag krawędzi
N);

Reklama

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

�������������������������������������������������������������������������
BIBLIOTEKA MIESIĄCA

Listing 5. Obliczanie najkrótszych ścieżek.


ną zapisane. Po takich przygotowaniach możemy wywo-
łać funkcję dijkstra_shortest_paths, obliczającą najkrót-
vector<int> distance(NUM_VERTICES); sze odległości co zostało pokazane na Listingu 5. Obli-
const int START_VERTEX = C; czone najkrótsze odległości zostaną zapisane do przeka-
dijkstra_shortest_paths( zanego funkcji kontenera. Pozostaje wypisać efekty dzia-
graph, łania algorytmu.
vertex(START_VERTEX, graph),
distance_map(&distance[0]) Podsumowanie
); Biblioteka boost::graph zawiera generyczną reprezen-
for(int i = 0; i < NUM_VERTICES; ++i) tację grafu oraz zbiór kilkudziesięciu algorytmów grafo-
cout << ”Odleglość do wierzchołka” << wych, między innymi przeglądające grafy (wszerz, w głąb,
(char)(i+'A')<< ”wynosi” << wykorzystując heurystyki, topologicznie), znajdujące naj-
distance[i] << endl; krótsze ścieżki, minimalne drzewa rozpinające, badają-
ce przepływy, badające spójność i inne metryki, itd. Do-
stępne są rozszerzenia, m.in. biblioteka umożliwiająca
być też czas podróży, a wtedy rozwiązanie problemu za- współbieżną (rozproszoną) realizację algorytmów grafo-
wiera wykaz najkrótszych czasów połączeń między wy- wych. Istnieją także wersje tej biblioteki dostępne w in-
branym miastem, a wszystkimi pozostałymi miastami. nych językach programowania.
Istnieje wiele algorytmów rozwiązujących problem
znajdowania najkrótszych ścieżek, biblioteka boost::
graph udostępnia takie, jak przedstawiono w Tabeli 1.
ANDRZEJ MICHAŁOWSKI
Przedstawimy sposób wykorzystania algorytmu Dijk- Student Informatyki Wydziału Elektroniki i Tech-
stry dla prostego grafu. Algorytm ten możemy wyko- nik Informacyjnych Politechniki Warszawskiej
rzystywać dla grafów, w których wagi krawędzi są do- oraz Ekonomii Wydziału Nauk Ekonomicznych
datnie. Typ reprezentujący graf, przedstawiony na Li- Uniwersytetu Warszawskiego. Zainteresowania
stingu 2, modyfikujemy dodając składową typu unsigned to programowanie, sport, finanse.
int związaną z każdą krawędzią. Składowa ta będzie re- Kontakt z autorem:
prezentowała wagę krawędzi. Wykorzystujemy dostar- a.m.michalowski@gmail.com
czany przez bibliotekę szablon property oraz tag edge_
weight_t.
Następnie tworzymy tablicę liczb całkowitych zawie-
rających, wagi krawędzi, w następujący sposób: i-ta war- ROBERT NOWAK
Adiunkt w Zakładzie Sztucznej Inteligencji In-
tość tablicy wag odpowiada i-tej krawędzi w tablicy kra-
stytutu Systemów Elektronicznych Politechni-
wędzi EDGE_ARRAY, wykorzystywanej przy tworzeniu gra- ki Warszawskiej, zainteresowany tworzeniem
fu. Tablice wag krawędzi przekazujemy jako parametr aplikacji wykorzystujących algorytmy sztucz-
podczas tworzenia grafu, co zostało pokazane na Listin- nej inteligencji i fuzji danych. Autor bibliote-
gu 4. ki faif.sourceforge.net. Programuje w C++ od
W celu obliczenia najkrótszych odległości, musimy wy- ponad 15 lat.
brać wierzchołek startowy, a także stworzyć dodatko- Kontakt z autorem:rno@o2.pl
wy kontener, w którym te najkrótsze odległości zosta-

W Sieci
• http://www.boost.org – dokumentacja bibliotek boost, w tym boost::graph;
• http://home.agh.edu.pl/~horzyk/lectures/pi/ahdydpiwykl9.html – opis różnych rodzajów grafów;
• http://osl.iu.edu/~dgregor/bgl-python/ – interfejs do boost::graph z języka Python;
• http://jung.sourceforge.net/ – biblioteka do grafów w Javie.

Więcej w książce
Omówienie współcześnie stosowanych technik, wzorce projektowe, programowanie generyczne, prawidło-
we zarządzanie zasobami przy stosowaniu wyjątków, programowanie wielowątkowe, ilustrowane przykłada-
mi stosowanymi w bibliotece standardowej i bibliotekach boost, opisano w książce Robert Nowak, Andrzej
Pająk ,,Język C++: mechanizmy, wzorce, biblioteki'', BTC 2010.

8 7/2011
KLUB TECHNICZNY

Po drugiej stronie ekranu


– czyli od kampera do game developera
Niewiele osób zdaje sobie sprawę, że praca przy tworzeniu gier
komputerowych stała się w ostatnich latach jak najbardziej realnym źródłem
dochodów w naszym kraju. Młodzieńcze pasje mogą nie tylko znaleźć swe
ujście w nowo otwartych kierunkach studiów, lecz otworzyć przed nami
drogę do jednego z najbardziej dochodowego segmentu rynku.

Dowiesz się:
• Jak prężnym segmentem światowego rynku jest elektroniczna rozrywka;
• Jakie realne możliwości otwiera przed graczami praca przy produkcji gier;
• Dlaczego EAG i GSA są idealnym rozwiązaniem dla przyszłych developerów gier.

Na skrzydłach marzeń Nie pomyl drogi


Powiadają, że marzenia są skrzydłami duszy. Dzięki To zdumiewające jak dziecięce pasje potrafią ukształ-
nim potrafimy wznieść się na wyżyny swoich możliwo- tować dorosłe życie człowieka. Niestety z biegiem cza-
ści i pokonać własne słabości. Marzenia nadają także su i upływem kolejnych lat bardzo często rezygnujemy
naszemu życiu sens, którego tak wiele osób poszuku- z pełnych optymizmu planów podboju świata. Życie ko-
je, a przecież cel naszego życia ukryty jest w nas, w na- ryguje nasze beztroskie wyobrażenia o przyszłej karie-
szej chęci odkrywania, poznawania, potrzebie zrozu- rze zawodowej. W pewnym sensie, zjawisko to należy
mienia i znalezienia odpowiedzi. Cel w życiu to kieru- zaliczyć do pozytywnych, gdyż sprawia, że lista zawo-
nek na płaszczyźnie możliwości, który sami sobie na- dów w naszym kraju nie ogranicza się w większości do
dajemy. Wznosząc się w przestworza odkrywamy nie piłkarzy i kosmetyczek, chociaż w pierwszym przypad-
tylko nowe możliwości, lecz w namacalny sposób po- ku mile widziana byłaby drobna zmiana jakościowa…
szerzamy swoje horyzonty i dostrzegamy kolejne per- Niestety bardzo często ceną takiego wyboru jest rezy-
spektywy. Poznajemy także siebie samego pokonu- gnacja z własnej pasji, odstąpienie od młodzieńczej po-
jąc własne słabości, niejednokrotnie będąc zaskoczo-
nym na jak wiele nas stać. Jednakże bierne zagłębianie
się w sferę marzeń staje się ucieczką od własnego ży-
cia, jeżeli nie jest połączone z determinacją. Bez goto-
wości do realnego osiągnięcia celu, nawet najbardziej
wzniosłe idee okażą się tylko powolnym opadaniem
w dół. Kolejne okazje będą bezszelestnie przelatywać
nam nad głowami, a linia horyzontu zacznie zaciskać
się wokół nas, pochłaniając kolejne obszary nowych
możliwości. Każdy z nas ustawicznie poszukuje swojej
ścieżki, która tak naprawdę znajduje się tuż przed na-
mi, a jej szlak wyznaczają drogowskazy z naszych wła-
snych marzeń. Wystarczy tylko nią podążyć, pokonu-
jąc rozdroża wątpliwości i ostre zakręty zagubienia, bo
chociaż niejeden raz potkniemy się o kamień własnych
słabości, to wysiłek wart jest swej nagrody. Marzenia Rysunek 1. Malarstwo, literatura, kinematografia,
są na wyciągnięcie ręki. muzyka – bez tych elementów nie mogłyby
istnieć dzisiejsze gry

10 7/2011
Po drugiej stronie ekranu – czyli od kampera do game developera

goni za ideałami i realizacji własnych marzeń. Przyczy- jednokrotnie miała swój wkład w proces wychowaw-
ną zaniechania podążania własną ścieżką jest najczęściej czy młodych ludzi, niemniejszy niż sama telewizja. Pew-
brak wiary we własne siły, bezpodstawne pozbawianie nie każda osoba, zafascynowana tym tematem zdała so-
się szans już na samym początku, jeszcze w fazie plano- bie sprawę, że gry wideo dorastały razem ze swoimi
wania, bądź też fałszywe przekonanie o braku realnej odbiorcami, a ich fenomen był impulsem do chęci zre-
możliwości osiągnięcia celu. To kluczowe, aby właśnie alizowania marzenia o stworzeniu swojego własnego
w okresie największej elastyczności w wyborze swojej cybernetycznego świata. Wyprodukowany na począt-
przyszłości, czyli w czasie, gdy decydujemy o kierun- ku lat 80' film „TRON”, który dzisiaj należy już do kla-
ku naszych studiów, uzmysłowić sobie, że każda ścież- syki gatunku, był właśnie zobrazowaniem tych marzeń,
ka jest otwarta, a każde marzenie możliwe do spełnie- niestety wtedy jeszcze praktycznie nieosiągalnych. Każ-
nia, jeżeli tylko stoi za tym pragnienie podjęcia próby dy chciał być jak Kevin Flynn, przemierzający bezgra-
i przetestowania własnych sił. niczną planszę cyfrowego wszechświata, mogący nie
tylko go odkrywać, ale także brać czynny udział w ak-
Gra o „TRON” cie jego tworzenia. Wizja ta była wtedy tak nowator-
Żyjemy w czasach, gdy zawody dawniej uważane w Pol- ska, a zastosowane w jej realizacji efekty komputerowe
sce bardziej za ciekawostkę niż źródło zarobku, lub bę- wyprzedzały swoje czasy do tego stopnia, iż obraz zo-
dące całkowicie zdominowane przez kraje zachodnie, stał wykluczony z wyścigu o Oscara za efekty specjal-
dzisiaj są bardziej pożądane na naszym rynku pracy, ne, gdyż uważano, że „triki komputerowe” są sprzecz-
a kolejne uniwersytety umożliwiają zdobycie kwalifika- ne z regulaminem. Dzisiaj wszechobecne zastosowanie
cji do ich wykonywania. Przykładem tego jest właśnie narzędzi cyfrowych nie tylko w produkcji kinowych hi-
możliwość pracy przy produkcji gier komputerowych. tów stało się już standardem. Najwspanialsze jest jed-
Obecne pokolenie na stałe kojarzyć będzie swoje dzie- nak to, że teraz każdy ma możliwość zaspokoić pra-
ciństwo właśnie z elektroniczną rozrywką, która nie- gnienia rozbudzone przez film Steven'a Lisberger'a, sta-
jąc się nie tylko realnym gościem binarnego świata, ale
także jego twórcą. Sam proces tworzenia gier to czysty
akt twórczy, praktycznie niczym nieograniczony, dający
ogromne pole do popisu dla naszej wyobraźni. Możli-
wości te wykraczają daleko poza potencjał twórczy to-
warzyszący pisaniu książek, kręceniu filmów, malowa-
niu obrazów, czy nawet komponowaniu muzyki. Inter-
dyscyplinarność gier sprawia, iż wszystkie te dziedziny
tworzą w nich harmoniczną całość, dzięki czemu koń-
cowy efekt otrzymuje nieosiągalny nigdzie wcześniej
charakter wielowymiarowości.
Obecnie gry wideo pretendują nawet do zdobycia
miana sztuki, co w przypadku wielu wybitnych tytułów
jest wyraźnie uzasadnione. Istnieje jednak bardzo waż-
ny czynnik, który odróżnia gry komputerowe od wy-
mienionych wcześniej dzieł twórczych, a mianowicie
interaktywność. Pisząc książkę, lub kręcąc film z gó-
ry narzucamy odbiorcy jedną, jedyną ścieżkę odbioru
utworu, przez co treść w nim przedstawiona jest wy-
bitnie liniowa. Pozbawiając odbiorcę jakiejkolwiek moż-
liwości ingerencji w zawartość dzieła, ogranicza się go
wyłącznie do biernego odbioru prezentowanego utwo-
ru. Gry komputerowe są uosobieniem interaktywno-
ści, pozwalającej nie tylko na bardzo liczną, lecz cza-
sami wręcz nieskończoną ilość sposobów postrzega-
nia przedstawionego w niej świata. Twórcy otrzymują
ogromne możliwości w przenoszeniu na „cybernetycz-
ny papier” swoich pomysłów, a elastyczność i stopień
zaawansowania używanych narzędzi umożliwia cho-
ciażby tworzenie własnych zasad fizyki, obowiązujących
Rysunek 2. Powyżej grafika koncepcyjna z gry w stworzonej przez nas grze. Dodatkowo możliwość
Disturb wcielenia się w wirtualną postać i indywidualne pokie-

www.sdjournal.org 11
KLUB TECHNICZNY

rowanie jej losami, oferuje niespotykaną dotąd nigdzie salność, elastyczność, lub wręcz wszechobecność sto-
immersję w wykreowany świat, a sposób jego odbio- sowanych rozwiązań. Potencjał rozwojowy jest ogrom-
ru nabiera niezwykle osobistego charakteru. Jeszcze do ny, a ilość dostępnych narzędzi sprawia, że każdy bę-
niedawna drzwi do tych wszystkich możliwości znajdo- dzie mógł znaleźć odpowiednią dla siebie specjalizację,
wały się poza granicami naszego kraju. Dzisiaj stoją one bez względu na to czy zajmuje się informatyką, muzyką,
szeroko otworem dla każdego z nas. sztuką, czy naukami humanistycznymi. Gry komputero-
we nie ograniczają się wyłącznie do komputerów oso-
Realny pieniądz wirtualny bistych, lecz tworzą trzon potężnego rynku konsolo-
Przez wiele lat utrzymywało się bardzo błędne prze- wego, zarówno dla ich stacjonarnych odpowiedników
konanie, iż gry komputerowe są jedynie mało poważ- jak Xbox 360 i PlayStation 3, czy handheldów pokroju
ną formą rozrywki przeznaczoną głównie dla dzieci. Nintendo 3DS i PlayStation Portable. Gry wideo stały
Świat jednak niestrudzenie szedł do przodu, a osoby się także nieodłączną częścią telefonów komórkowych,
bagatelizujące elektroniczną rozrywkę zapewne nie- a gigantyczny sukces gry „Angry Birds” dowodzi tylko
jeden raz zakrztusiły się swoimi mylnymi poglądami. z jak potężnym gronem odbiorców mamy do czynienia.
Oficjalny przełom nastąpił kilka lat temu, gdy świato- Wszyscy szukający innowacyjnych rozwiązań i nowych
we media obiegła wiadomość, że rynek gier kompute- technologii zapewne zainteresują się nowymi trenda-
rowych zaczął w niektórych krajach przynosić docho- mi w branży wkraczającymi do domów zwykłych gra-
dy przekraczające zyski z produkcji filmów. Doskona- czy, jak chociażby stereoskopowe wyświetlanie obrazu
łym dowodem tego jest seria Call of Duty, której naj- dające złudzenie trójwymiarowości, czy kontrolery ru-
nowsze odsłony – Modern Warfare, Modern Warefa- chowe pokroju PS Move i Kinect.
re 2 i Black Ops, biją kolejne rekordy zarówno w wyni-
kach sprzedaży, jak i kwot przeznaczanych na ich kam- Polacy nie gęsi i swój joystick mają
panie reklamowe, przynosząc swojemu wydawcy, Ac- Jeżeli należysz do osób, które cechuje niestety dość
tivision, kosmiczne zyski. Każdy, kto nie widzi poten- powszechna w naszym kraju mentalność, nakazują-
cjału znajdującego się w rynku produkcji gier kompute- ca sądzić, iż wszystko co zagraniczne musi być lepsze,
rowych zapewne już został w tyle za pędzącym postę- to nawet nie zdajesz sobie sprawy, jak bardzo w przy-
pem technologicznym i jeszcze niejednokrotnie przega- padku gier komputerowych możesz się mylić. Dziedzi-
pi okazję, aby dostosować się do dzisiejszych standar- na ta niejednokrotnie dowiodła, że nie liczy się ilość
dów rynkowych. Wszyscy zainteresowani tą tematy- wydawanych gier, lecz ich jakość, a w ostatnich latach
ką, jako potencjalnym sposobem zarobku, powinni zda- rdzennie polskie produkcje mogą już świadczyć o roz-
wać sobie sprawę nie tylko ze złożoności procesu po- poczęciu podboju światowych rynków oraz zapewnie-
wstawania gier i jego wielowątkowości, o czym pisałem niu swojej marce uznania w licznych szeregach odbior-
wcześniej, ale także istotne jest, aby dostrzec uniwer- ców. Dla przykładu wystarczy podać reklamowaną, ja-
ko „największą polską produkcję”, multiplatfor-
mową grę Bulletstorm, powstałą przy współpra-
cy z Epic Games, które odpowiedzialne jest za
takie tuzy gatunku jak chociażby seria Gears of
War. Produkcja polskiego studia People Can Fly
dokonała tego, co tak bardzo potrzebne jest dzi-

Rysunek 3. Tworzenie gier to


niezwykle złożony proces. Powyżej
projekt poziomów w programie UDK

12 7/2011
Po drugiej stronie ekranu – czyli od kampera do game developera

siaj na rynku FPS’ów, czyli powiew inno-


wacji i świeżości w gatunku. Gra stoi na
najwyższym światowym poziomie, a mo-
ment, gdy w napisach końcowych poja-
wiają się praktycznie same polskie na-
zwiska, jest wręcz bezcenny. Warto też
wspomnieć o będącym w produkcji De-
ad Island studia Techland, którego trailer
swego czasu wstrząsnął posadami świata
gier, a o jego wykonaniu wypowiadał się
w samych superlatywach nawet sam Hi-
deo Kojima. Rynek gier dla komputerów
klasy PC posiada jeszcze większy polski
wkład w jego zawartość, a przykładem
Rysunek 4. Monocular – model postaci stworzony na potrzeby
niech będą ostatnie dni, które wręcz za- projektu Disturb
lewają nas kolejnymi doniesieniami na te-
mat premiery drugiej części flagowej polskiej produkcji, ce w branży, a więc posiadające bezcenne doświadcze-
czyli Wiedźmin 2: Zabójcy Królów. Już teraz pojawiają nie zawodowe.
się głosy w zagranicznej prasie, że najnowsze przygody Obecnie EAG, idąc naprzeciw oczekiwaniom studen-
Geralta mogą zostać uznane za perełkę gier typu RPG, tów, oferuje w ramach Projektu magisterskie studia sta-
na którą wszyscy gracze tak bardzo czekali. cjonarne (3 kierunki) oraz niestacjonarne II stopnia (2
kierunki). Wszyscy pragnący podjąć naukę mają do wy-
Polska Dolina Krzemowa boru 3 nowe specjalizacje: Modelowanie i animacja 3D
oraz Produkcja gier wideo, realizowane na Wydziale
Fizyki, Astronomii i Informatyki Stosowanej UJ, a także
Projektowanie gier wideo, prowadzone przez Wydział
Zarządzania i Komunikacji Społecznej UJ. Nowe specja-
lizacje są finansowane z projektu „Wiedza i kompeten-
cje z fizyki, chemii i informatyki na potrzeby gospodarki
– WIKING” współfinansowanego ze środków Unii Eu-
ropejskiej w ramach Europejskiego Funduszu Społecz-
nego. Pierwsze dwie oferty przeznaczone są głównie
EAG umożliwia zdobycie wiedzy i doświadczenia dla osób o zainteresowaniach i umiejętnościach pro-
niezbędnych do rozpoczęcia pracy w branży gramistycznych, ostatnia zaś skierowania jest w stronę
elektronicznej rozrywki osób o humanistycznym wykształceniu. Student wybie-
rając Modelowanie będzie mógł pracować w przyszło-
Dostrzegając istotę zachodzących przemian, skalę moż- ści jako programista grafiki, dzięki znajomości narzędzi
liwości oraz ogromne zapotrzebowanie polskiego ryn- m.in. do renderingu scen, zaś absolwent Produkcji znaj-
ku na specjalistów z sektora elektronicznej rozryw- dzie zatrudnienie jako główny programista gry, a więc
ki, krakowskie uczelnie podjęły inicjatywę stworze- osoba gotowa do pokierowania zespołem osób two-
nia pierwszej w Polsce, profesjonalnej szkoły tworze- rzących kod programu. Kończąc projektowanie gier
nia gier wideo. Dzięki połączonym siłom Uniwersy- zdobędziemy zdolności i wiedzę m.in. z zakresu ludo-
tetu Jagiellońskiego i Akademii Górniczo-Hutniczej logii oraz pisania scenariuszy. Chcąc się prężnie rozwi-
oraz współpracy wielu firm tworzących gry kompute- jać, EAG ściśle współpracuje z firmami w ramach Eu-
rowe (m.in. CD Projekt, Reality Pump czy Blooberte- ropejskiego Centrum Gier, a także prowadzi wykłady
am), w 2008 roku powstała Europejska Akademia Gier popularyzujące na konferencjach i w szkołach. Studen-
(EAG). Początkowo oferowała ona 6 kierunków na stu- ci Akademii mają dostęp do nowoczesnego i zaawan-
diach podyplomowych, które w końcu zostały połączo- sowanego sprzętu, głównie dzięki utworzeniu Zakładu
ne w 3 specjalizacje. Jej główną cechą była możliwość Technologii Gier (ZTG UJ) na Wydziale FAIS, posiada-
kształcenia w wybranej przez siebie specjalności, z na- jącego dwie pracownie. Pracownicy zakładu naukowe-
ciskiem na praktyczną stronę zajęć, co kontrastowało go podejmują tematykę związaną z tworzeniem gier wi-
z powszechnym na dzisiejszych uczelniach zjawiskiem deo, obejmującą głównie bezdotykowe interfejsy kom-
zbyt dużej liczby przedmiotów o charakterze ogólnym. puterowe, interakcję człowiek-komputer (HCI), inter-
Fundamentem uczelni oraz jej największym atutem jest fejsy mózg-komputer (BCI), programowanie kart gra-
kadra wykładowa, na którą składają się osoby pracują- ficznych czy symulację fizyki czasu rzeczywistego. EAG

www.sdjournal.org 13
KLUB TECHNICZNY

planuje ciągłe poszerzanie swojego zaplecza sprzęto-


wego, mając w planach stworzenie najbardziej nowo-
czesnych i profesjonalnych laboratoriów dedykowa-
nych technologiom tworzenia gier wideo. Do swoje-
go dorobku Akademia może dołączyć także zorgani-
zowanie środowiskowego Seminarium EAG, na któ-
rym odbyło się już 35 prezentacji, a także zakup z fun-
duszu Ars Docendi podręczników dla studentów spe-
cjalizacji o tematyce gier wideo. Rozwijana jest także
strona EAG WIKI, która ma tworzyć swoistą bazę in-
formacji o grach komputerowych. Już teraz można na
niej znaleźć szereg przydatnych informacji, jak chociaż- Gry to nie tylko wirtualne światy, ale także rzesze
by zarys najpopularniejszych zawodów w branży, histo- graczy, których łączy wspólna pasja
rię gier i platform, zastosowanie sztucznej inteligencji
w grach, czy popularyzujący się obecnie cloud gaming. ści rozwijania własnych zainteresowań, a charakter te-
EAG to niespotykana jak dotąd w naszym kraju szan- go zjawiska i obecny postęp technologiczny pozwalają
sa dla wszystkich pasjonatów elektronicznej rozryw- robić to na niespotykaną dotąd skalę. Ludzie zaurocze-
ki, którzy marzą o poznaniu tego fascynującego, a zara- ni tematyką gier wideo stanowią siłą napędową dla roz-
zem niezwykle złożonego procesu, jakim jest tworze- woju elektronicznej rozrywki, a ich zapał, innowacyjne
nie gier wideo. pomysły i zdolności wytyczają nowe ścieżki tej dziedzi-
ny. Efektem takiej pasji jest właśnie pierwsza w Polsce,
Gdy pasja przybiera kszta otwarta organizacja zrzeszająca osoby zainteresowa-
Gry komputerowe to nie tylko niezwykle prężnie roz- ne tematyką gier wideo - Gamedev Students Associa-
wijająca się gałąź rynku nowoczesnych technologii tion (GSA). Organizacja ta powstała w 2008 roku, za-
i pole do rozwoju kariery zawodowej. Gry to przede raz po narodzinach EAG, która jest jej patronem wraz
wszystkim rzesze odbiorców, rozsianych po wszystkich z ZTG UJ, i początkowo działała na Uniwersytecie Ja-
zakątkach globu graczy, których pomimo dzielących ich giellońskim. Obecnie GSA ma charakter ogólnopolski,
odległości połączyła miłość do wspólnej pasji. Ten ogól- jednakże zamiarem tej niezwykle prężnej inicjatywy jest
noświatowy fenomen stwarza zupełnie nowe możliwo- osiągnięcie ogólnoświatowego charakteru. Organizacja

Rysunek 5. Studenci EAG mają dostęp do zaawansowanego sprzętu i specjalistycznego


oprogramowania. Dzięki tym możliwościom powstaje gra GobWar

14 7/2011
Po drugiej stronie ekranu – czyli od kampera do game developera

jest otwarta dla wszystkich pasjonatów gier i nie ogra-


nicza się wyłącznie do studentów, dzięki czemu możli-
we jest osiągnięcie jej głównego celu, a więc stworzenia
związanej z GSA społeczności ludzi, mogących nie tyl-
ko swobodnie dzielić się z innymi swoją pasją, ale tak-
że rozwijać swoje umiejętności, a nawet zadbać o swo-
ją karierę zawodową. Interdyscyplinarny charakter or-
ganizacji sprawia, że w jej szeregi może przystąpić każ-
dy, bez względu na dziedzinę swojego wykształcenia.
Ideą przewodnią tego koła naukowego jest stworzyć
przestrzeń umożliwiającą współpracę dla tzw. 3 poko-
leń rynku pracy, a więc uczniów, studentów oraz ab-
solwentów pracujących w branży. Pozwoli to nie tyl-
ko pomóc młodszej części graczy w ukierunkowaniu
swego zainteresowania dzięki radom starszych, bar-
dziej doświadczonych członków, ale także bliżej zro- Rysunek 7. Dzięki akredytacjom medialnym ekipa
zumieć aktualne trendy i potrzeby potencjalnych od- SAGE mogła przeprowadzić dziennikarską relację
z krakowskiego Game Fusion
biorców gier. Realna i ogólnodostępna możliwość za-
sięgnięcia opinii i otrzymania informacji od osób, któ-
re znają proces tworzenia gier „od drugiej strony ekra- jekcie. W tym właśnie tkwi duch organizacji, czyli za-
nu” jest w naszym kraju czymś unikatowym. Dostępne chęcanie użytkowników do własnej inicjatywy i sponta-
dla jej członków forum dyskusyjne jest idealnym roz- niczności, gdyż celem GSA nie jest stworzenie systemu
wiązaniem dla wszystkich tych, którzy chcą na bieżą- zarządzającego projektami, lecz narzędzia umożliwiają-
co uczestniczyć w życiu społeczności graczy. Centrum cego realizację własnych przedsięwzięć. Możliwość or-
GSA jest jej strona internetowa, stanowiąca swoistą ganizacji takich projektów pozwoli na zdobycie cenne-
bazę profili. Jej celem jest przeniesienie polskiej sce- go doświadczenia, które odgrywa kluczową rolę dla
ny developerskiej na zupełnie nowy poziom, a pomóc przyszłych pracodawców. Dla nich istnienie organiza-
ma w tym praktyczny system podziału użytkowników cji również przynosi wymierne korzyści, gdyż każdy jej
w bazie według ich kompetencji.. Pragnąc przystąpić członek posiada stosowny profil, określający nie tylko
do organizacji na stronie GSA, użytkownik wypełnia jego kompetencje czy doświadczenie, ale także prezen-
formularz, określając swoje zainteresowania, stopień tujący portfolio. Umożliwia to hosting projektów użyt-
umiejętności i preferencje odnośnie udziału w przy- kowników na stronie GSA, dzięki czemu ich promocja
szłych projektach. W ten sposób każda zarejestrowa- staje się wyraźnie łatwiejsza. Obecnie członkowie or-
na osoba w prosty i łatwy sposób będzie mogła wyszu- ganizacji pracują nad otwartym projektem gry Disturb,
kać potencjalnych członków swojego zespołu i wysłać prototypowego shootera FPP wykorzystującego moż-
stosowne zaproszenie do udziału w realizowanym pro- liwości silnika fizycznego PhysX. Całość ma charakter
edukacyjny, dzięki czemu każdy ma możliwość wzię-
cia udziału w tworzeniu jej poszczególnych elemen-
tów, od grafik koncepcyjnych, na warstwie dźwięko-
wej kończąc. Nadmienić należy, że charakter organi-
zacji nie ogranicza się jedynie do wirtualnego aspek-
tu przedsięwzięcia, lecz umożliwia fizyczne zrzeszanie
się jej członków w stworzone przez nich sekcje. Każ-
dy może być inicjatorem takiej grupy, a fakt, że GSA ja-
ko jedyna organizacja studencka UJ ma dostęp do wy-
posażonych w zaawansowany sprzęt laboratoriów Eu-
ropejskiej Akademii Gier, otwiera przed jej członkami
wyjątkowe możliwości. Obecnie działają 3 sekcje tema-
tyczne, spotykające się regularnie na Wydziale Fizyki,
Astronomii i Informatyki Stosowanej UJ.
Sekcja LEGO Team skupia się wokół tematu roboty-
ki, jednakże w jej najbardziej przystępnej formie. Dzię-
Rysunek 6. GSA ciągle poszerza bazę swoich ki połączeniu klocków LEGO ze zdobyczami najnowo-
tytułów, mając w planach stworzenie cyfrowej cześniejszych technologii cyfrowych została stworzona
biblioteki gier seria produktów Mindstorms. Członkowie sekcji mają

www.sdjournal.org 15
KLUB TECHNICZNY

dostęp do zestawów LEGO Mindstorms NXT 2.0, po- ny cel postawili sobie stworzenie wszystkich elementów
zwalających konstruować i w łatwy sposób programo- gry, od modeli po animacje, na muzyce kończąc.
wać własne roboty. Dzięki załączonym czujnikom odle- Sekcja Analizy Gier EAG (SAGE) to grupa pasjona-
głości, dotyku, koloru oraz napędowi w postaci serwo- tów gier wideo, którzy poszerzają swoją merytoryczną
motorów, a także możliwości sterowania za pośred- wiedzę o grach i aktualnych trendach w branży. Sekcja
nictwem komputera, każdy ma możliwość zbudowa- ma dostęp do ciągle poszerzanej biblioteki najnowszych
nia własnego unikatowego i zaawansowanego mode- tytułów, dzięki czemu ma możliwość realizacji jednego
lu robota. Sekcja ma za zadanie organizowanie Zawo- ze swych głównych celów, a więc analizy gier pod ką-
dów Robotów Walczących oraz formowanie reprezen- tem pisanych później recenzji. Zdolności nabyte przez
tacji GSA dla tego typu imprez. Zdolności inżynierskie członków SAGE wykorzystywane są chociażby podczas
członków LEGO Team z każdym miesiącem wzbogaca- tworzenia relacji z imprez o tematyce gier wideo. Jako
ją kolekcję skonstruowanych przez nich robotów o ko- najnowszy przykład można podać udział członków sek-
lejne modele. cji w krakowskim Game Fusion. Do zadań Sekcji Anali-
Sekcja Unreal Development Kit (UDK) rozwija swo- zy Gier należą także organizacje turniejów, SAGE ofe-
je zainteresowania obracające się wokół niezwykle dziś ruje również odbycie w jej ramach studenckich prak-
popularnego silnika gier Unreal Engine. Główny projekt tyk. Grupa planuje współpracę zarówno z prasą i por-
grupy opiera się na stworzeniu gry typu hack & slash talami internetowymi, jak i studiami developerskimi,
o nazwie GobWar – Weź dwa! Gra osadzona zostanie dlatego obecnie poszukuje partnerów medialnych.
w wykreowanym przez 6 osobowy zespół świecie fanta-
sy, a jej główny bohater, niezadowolony z polityki lokal- Jutro zaczyna się dzisiaj
nego możnowładcy postanawia wziąć sprawy w swoje Marzeniem twórców Gamedev Students Association
ręce. Przedstawiona historia będzie mieć charakter hu- jest tworzenie podobnych kół zainteresowań w szko-
morystyczny, a sam protagonista, lekko podpity, dzier- łach współpracujących z organizacją, co ma miejsce
żący tulipana w ręce Goblin, musi uważać, aby zbytnio w krajach będących pionierami elektronicznej rozrywki,
nie wytrzeźwieć, co może negatywnie odbić się na za- jak chociażby w Japonii, gdzie profesjonalna nauka two-
dawanych przez niego obrażeniach. Z tego też powodu
istotnym elementem gry będzie zdobywanie kolejnych
kufli „złotego napoju”, a sam bohater nie będzie miał
czasu ani na odpoczynek, ani na kaca. Autorzy za głów-

Rysunek 10. Z myślą o następnej


generacji konsol, już od 7 lat powstaje
Unreal Engine 4

16 7/2011
Po drugiej stronie ekranu – czyli od kampera do game developera

Rysunek 11. Disturb to otwarty, edukacyjny


projekt, w tworzenie którego może zaangażować
się każdy

rzenia gier rozpoczyna się już w szkołach średnich. GSA rów, którzy rozumiejąc potencjał drzemiący w organiza-
obecne też będzie na Europejskich Finałach World Cy- cji, będą gotowi przyłączyć się do zrewolucjonizowania
ber Games, największej światowej imprezie pretendu- polskiej sceny elektronicznej rozrywki. Przyszłość pol-
jącej do miana komputerowego odpowiednika igrzysk skich gier komputerowych zaczyna się w Krakowie.
olimpijskich. Na odbywającej się w Warszawie imprezie, Szanowny graczu, pamiętaj, że każdy cel i każde ma-
UDK zorganizuje warsztaty z tworzenia gier, natomiast rzenie jest możliwe do zrealizowania, jeżeli tylko tra-
SAGE przeprowadzi dziennikarską relację z cyberolim- fisz pod właściwy adres. Tak więc, gdy masz wątpliwo-
piady. W najbliższych planach na EAG ma powstać ba- ści i chcesz coś przemyśleć odwiedź Przemyśl, jeżeli
za nowoczesnych technologii z większością najpopular- szukasz ukrytego głęboko piękna natury, to zawitaj do
niejszych konsol stacjonarnych i przenośnych, oraz pra- Zakopanego, jeżeli pragniesz w życiu odmiany to jedź
cownia mobilnych urządzeń, posiadająca m.in. stół Mi- do Poznania, a wrócisz nie-do-poznania, natomiast, je-
crosoft Surface, rękawice cybernetyczne i najnowsze te- śli chcesz być w centrum społeczności graczy i szukasz
lefony komórkowe. Zaplecze to ma być dostępne także drogi do kariery w branży elektronicznej rozrywki, nie
dla członków GSA. W chwili obecnej za główny cel or- miej wątpliwości – wybierz Kraków.
ganizacja stawia sobie stworzenie corocznej konferen-
cji, na której członkowie będą mieli możliwość osobi-
stego spotkania się, oraz przedstawiania swoich projek-
ADRIAN ZAJĄC
Jest studentem III roku Informatyki na Wydzia-
tów. Dzięki obecności firm z branży gier, które już teraz
le Fizyki, Astronomii i Informatyki Stosowanej
wyraziły ogromne zainteresowanie projektem, uczestni- UJ. Oprócz gier komputerowych, pasjonuje się
cy będą mieli szanse zaprezentowania się swoim przy- również podróżami i dziennikarstwem. Jest re-
szłym pracodawcom, a sama konferencja ma szansę stać daktorem SAGE, organizacji GSA.
się jednym z największych wydarzeń branżowych roku. Kontakt z autorem: adrian.zajac@uj.edu.pl
Jednakże, aby było to możliwe GSA poszukuje partne-

www.sdjournal.org 17
PROGRAMOWANIE JAVA

Analiza wydajności
aplikacji Java dla opornych
Jak diagnozować i rozwiązywać problemy
z Garbage Collectorem w Javie?

Dowiesz się Powinieneś wiedzieć


• Jak efektywnie diagnozować problemy przy migracji • Znać podstawy języka Java oraz serwerów aplikacyjnych;
rozwiązań ze środowisk testowych na produkcyjne; • Znać podstawy wykorzytania narzędzi testowych
• W jaki sposób analizować logi procesu Garbage Col- (JMeter).
lectora;
• Jak zmienić implementację JVM dla aplikacji.

Tabela 1.
Parametr Wartość
Jak analizować wydajność systemu? Czas trwania testu 180 minut
Bardzo często osoby odpowiedzialne za dostarczenie
Warm-up time 60 minut
systemu informatycznego nie przykładają odpowiedniej
wagi do różnego rodzaju testów wydajnościowych i ska- Liczba równoległych użytkowników 100
lowalnościowych. Wynika to przeważnie z braku czasu, Średni czas odpowiedzi < 1 sek
niedoszacowania zasobów lub błędnego określenia funk- 99 percentyl < 2 sek
cjonalności. O ile brak konkretnego przypadku użycia zo-
stanie wychwycony od razu, to określenie, czy aplikacja Tabela 2.
posiada odpowiednią wydajność jest dość trudne... do Parametr Wartość
czasu, gdy jest już za późno. Chcemy pokazać, jak moż- Liczba równoległych użytkowników 100
na szybko wykryć potencjalne problemy nawet wtedy,
Średni czas odpowiedzi 0,75 sek
gdy na przeprowadzenie testów wydajnościowych ma-
my mało czasu. Mediana czasów odpowiedzi 0,4 sek

Załóżmy, że udało nam się


przeprowadzić testy i uzy-
skane wyniki nas satysfakcjo-
nują. Wymagania dotyczą-
ce testów przedstawione są
w tabeli nr 1, natomiast wy-
niki w tabeli nr 2. Dodatko-
wo wykres nr 1 przedstawia
rozkład czasów odpowiedzi.
Użytkownik, który “ręcz-
nie” klikał w aplikację ra-
portuje nam, że miał bardzo
złe czasy odpowiedzi i sys-
tem wg. niego „nie działał”.
Na co w tym przypadku na-
leży zwrócić uwagę? Gdzie
Wykres 1. szukać problemów? Od-

18 7/2011
Analiza wydajności aplikacji Java dla opornych

powiedź jak zwykle w takich sytuacjach zależy od wielu • Wiedza na temat GC


czynników. W tym artykule chciałbym skupić się na pro- • Umiejętność wytworzenia powtarzalnego testu,
cesie zarządzania pamięcią, czyli Garbage Collectorze w celu weryfikacji postępu prac
(GC), więc na potrzeby sytuacji w tym przypadku win- • Umiejętność tuningu lub zmiany GC
nym okaże się GC. Więcej o samym procesie GC napi-
sane jest w sekcji kolejnej, najpierw przeanalizujmy sam Co to jest Garbage Collector?
problem, z którym musimy się uporać. Zrobimy symula- Garbage Collector (GC), czyli tak zwane „odśmiecanie
cję rozwiązania, które jest możliwe, choć mało prawdo- pamięci”, to jedna z metod automatycznego zarządzania
podobne. Przyjmijmy, że maksymalne pauzy na procesie dynamicznie przydzielaną pamięcią. Za zwalnianie pamięci
GC są rzędu powyżej 120 sekund. W realnych projek- ze zbędnych danych (nieużywanych obiektów) odpowie-
tach często występują pauzy 30 sekund, które są akcep- dzialny jest proces Garbage Collectora.
towane przez testerów i właścicieli biznesowych aplika- Przyjrzyjmy się teraz, które dane z punktu widzenia
cji, więc nie jest to drastyczne nadużycie. Załóżmy sytu- optymalizacji zajmowanej pamięci są uważane za niepo-
ację, w której awarii uległ system zewnętrzny i każde za- trzebne (diagram nr 1). W przypadku stworzenia obiek-
pytanie do tego systemu kończy się timeoutem (ta sytu- tu klasy Dane o nazwie punkt zostaną wpisane do pamię-
acja jest typowa przy wielu zewnętrznych systemach czy ci dwie zmienne x i y o wartości 0. Stworzono także dru-
bazach danych). Wróćmy jednak na chwilę do procesu. gi obiekt o tej samej nazwie, lecz ze zmiennymi o warto-
Na histogramie mamy jeden niewielki słupek przy warto- ściach 1, co ilustruje poniższy fragment kodu:
ściach powyżej 2 sekund. Przy szczegółowej analizie oka-
zuje się, że te czasy odpowiedzi są równe 120 sekund, Dane punkt = new Dane (0,0);
co jest ustawione jako timeout dla narzędzia testującego. punkt = new Dane (1,1);
Przez 33% czasu, czyli 60 minut ze 180 minut testu, sys-
tem nie działał. Tłumaczy to negatywny odbiór użytkow- Gdy zabraknie pamięci, pierwszy obiekt o nazwie punkt
nika. Skąd jednak wzięły się tak dobre wyniki testu? Po- (0,0) zostaje przeznaczany do usunięcia przez proces
liczmy. Przez 60 minut 100 wątków wykonywało trans- Garbage Collectora – obiekt zajmuje obszar w pamię-
akcje, które trwały 120 sekund. W tym czasie wykonało ci, ale nie możemy się do niego odwołać przez referen-
się 3000 nieudanych transakcji. W czasie pozostałych 120 cję. Sytuacja ta została zilustrowana na diagramie nr 1.
minut testu te same wątki wykonały 1 797 000 transak- Proces ten jest uruchamiany automatycznie w przypad-
cji (przy średnim czasie <1 sek). W tym przypadku 3000 ku braku pamięci, lecz może być także być wywołany
nieudanych transakcji stanowi zaledwie 0,17% mimo, że w trybie ręcznym:
system praktycznie przez 33% czasu nie działał. Jaki z te-
go wniosek? Nie dajmy się zwieść narzędziom i szczegó- System.gc();
łowo przyjrzyjmy się każdemu niestandardowo wygląda-
jącemu wynikowi. Jednym z interesujących narzędzi god- Wywołanie powyższej metody nie jest równoznaczne
nych polecenia jest JitterMeter, dostarczany jako narzę- z uruchomieniem GC, lecz stanowi sugestię dla Wir-
dzie open-source przez firmę Azul Systems, które jest tualnej Maszyny Javy (JVM), że z punktu widzenia pro-
w stanie analizować działający JVM pod kątem takich sy- gramisty jest to dobry moment na uruchomienie pro-
tuacji. Teraz zastanówmy się, co możemy zrobić, aby te cesu GC. Decyzja o uruchomieniu tego procesu zale-
pauzy wyeliminować. W tym celu wymagane są następu- ży jednak wyłącznie od JVM. Stanowi to główną wa-
jące rzeczy: dę GC - brak przewidywalności, w którym momen-
cie mechanizm GC zostanie uruchomiony. Negatyw-
nym aspektem jest także konieczność czasowego za-
wieszenia działania aplikacji podczas jego uruchomienia,
co może wpłynąć negatywnie na czas odpowiedzi syste-
mu i znacznie utrudnia utrzymanie poziomu SLA na za-
danym poziomie.

Architektura systemu testowego


Testy wydajnościowe trzeba realizować w środowi-
sku odpowiadającym (lub porównywalnym ze środowi-
skiem produkcyjnym w znanym współczynniku) środowi-
sku produkcyjnemu. Na potrzeby tego artykułu stworzo-
no dedykowane środowisko testowe, w którym każdy
może sam zasymulować i odtworzyć sytuację opisywaną
Diagram 1. w niniejszym artykule. Do kompletu potrzebny jest:

www.sdjournal.org 19
PROGRAMOWANIE JAVA

JitterMeter (http://azulsystems.com/resources/tools/jittermeter)
Narzędzie open-source, udostępniane przez Azul Systems, które pozwala analizować wydajność i zachowa-
nie JVM pod kątem opóźnień widocznych z punktu widzenia klienta końcowego, często nazywanego też
użytkownikiem.

Fragger (http://azulsystems.com/resources/tools/fragger)
Narzędzie open-source, udostępniane przez Azul Systems, symulujące zużycie pamięci przez aplikacje, ana-
logicznie jak przy równoległej obsłudze wielu niezależnych użytkowników. Wykorzystanie tego narzędzie
umożliwia sprawdzenie zachowania systemu przy dużym (i możliwym do definicji) obciążeniu pamięci.

JMeter (http://jakarta.apache.org/jmeter/)
Narzędzie open-source, które umożliwia realizację testów funkcjonalnych i wydajnościowych w łatwy i
zautomatyzowany sposób. Udostępnia również WebProxy, które może nagrywać ruch w celu jego później-
szego odtworzenia.

• Serwer (przynajmniej 4 rdzenie oraz 16GB RAM; im zostaną na czterech wirtualnych maszynach Java, każda
więcej tym lepiej) od innego dostawcy i z inną implementacją procesu GC.
• VMWare ESX 4.x (do pobrania ze strony: http:// Przetestowany zostanie również nowy, eksperymental-
downloads.vmware.com/d/details/esx41u1/ZHcqYnRlQH- ny GC G1 stworzony przez SUN/Oracle.
BiZCpwdw==) Realizacja testu, w zależności od konfiguracji testowej
• Różne wersje JVM (różnej w zależności od wykorzystywanego sprzętu), po-
• Sun/Oracle JDK: http://www.oracle.com/ lega na odpowiednim dobraniu liczby równoległych wąt-
technetwork/java/javase/downloads/index.html ków, które wykonują zapytania do przykładów Tomca-
• Open JDK: http://openjdk.java.net ta, oraz przerw między każdym kolejnym wywołaniem.
• IBM JDK: http://www.ibm.com/developerworks/java/ Manipulacja tymi parametrami pozwala zmieniać równo-
jdk ległość przetwarzania po stronie Tomcata lub prędkość
• Zing JDK: http://www.azulsystems.com/products/ alokacji nowych obiektów. W celu zasymulowania pra-
zing/trial cy wielu użytkowników, wykorzystano open-source’o-
• Tomcat 6.x (http://tomcat.apache.org/download-60.cgi) we narzędzie Fragger. Dzięki temu możliwe było znaczne
• JMeter (http://jakarta.apache.org/jmeter/) zwiększenie wykorzystania pamięci przez aplikację i anali-
• Scenariusz testowy dla JMeter: http://wits.pl/scenariusz za jej zachowania w sytuacji, gdy system musi obsłużyć żą-
dania od wielu równoległych użytkowników. Przy wyeli-
Test polega na równoległym wy-
wołaniu standardowych przykła-
dów znajdujących się w każdej
dystrybucji Tomcata. Niestety,
przeważnie czas odpowiedzi bę-
dzie zbliżony do 1ms, jeżeli sys-
tem nie jest obciążony, bo przy-
kłady nie realizują żadnych funkcji
biznesowych. Jednakże nawet na
tak prostych przykładach można
zaobserwować fluktuacje czasów
odpowiedzi, w związku z działa-
niem procesu GC. W wersji do-
mowej można użyć jednego fi-
zycznego komputera do zasymu-
lowania całego środowiska, co
jest niewątpliwym plusem. Ar-
chitektura środowiska testowe-
go przedstawiona jest na diagra-
mie nr 2. Testy przeprowadzone Diagram 2.

20 7/2011
Analiza wydajności aplikacji Java dla opornych

minowaniu pauz między ko-


lejnymi wywołaniami moż-
liwe jest uzyskanie alokacji
danych na poziomie 20GB
na sekundę. Takich para-
metrów, poza Azul JVM, nie
jest w stanie wytrzymać ża-
den inny GC. Warto tutaj
dodać, iż testowana jest im-
plementacja Azul JVM dzia-
łająca na procesorach Intel
i na dokładnie takiej samej
platformie jak pozostałe wir-
tualne maszyny. Eliminujemy
więc przewagę sprzętowe-
go zarządzania JVM, która
była obecna w poprzednich
generacjach rozwiązań Azul Wykres 2.
(Urządzenia Przetwarzające
Azul Vega 3). Uzyskane wy-
niki pokazane są na wykre-
sach 2 i 3.

Wyniki
W czasie tego testu analizo-
wano czas odpowiedzi sys-
temu, standardowe odchy-
lenie oraz maksymalny czas
odpowiedzi. O ile czasy od-
powiedzi są na porówny-
walnym poziomie, co by-
ło oczekiwanym rezultatem,
to wartości odchylenia stan-
dardowego różnią się znacz-
nie, nawet o dwa rzędy wiel-
kości. Z wykresów długo-
Wykres 3.
ści pauz GC na poszczegól-
nych JVM, widzimy, że pauzy
często były dłuższe niż 1 se-
kunda. Takie wyniki, przy ta-
kiej konstrukcji testu jaką za-
proponowaliśmy, oznaczają,
że czas odpowiedzi, (w sy-
tuacji, gdy trafimy na pauzę
GC) zwiększa się z 1 ms do
ponad 1000 ms. Porównując
maksymalne czasy odpowie-
dzi poruszamy się pomiędzy
127ms dla Zing JVM a po-
nad 3 000 ms (3 sekundy)
dla SUN oraz OPEN JDK,
z pozostałymi konfiguracja-
mi plasującymi się w oko-
licach 1 000 ms. Zestawie-
nie to pokazuje wykres nr 4. Wykres 4.

www.sdjournal.org 21
PROGRAMOWANIE JAVA

W przypadku przebiegu bez Frag-


gera (wykres nr 5) widać, że pau-
zy występują co kilka minut, co nie
jest dużym problemem, ale też ta-
ki test nie odpowiada systemowi
działającemu pod dużym obciąże-
niem. Wykresy od 6 do 8 przed-
stawiają zachowanie systemu
z Fraggerem, czyli z symulowanym
dużym obciążeniem. W tych przy-
padkach nie dość, że częstotliwość
uległa zwiększeniu do kilkunastu
wystąpień na minutę, to i czasy
pauz znacznie wzrosły. Poza Azul
JDK, który został specjalnie zapro-
jektowany w celu eliminacji pauz
GC, pozytywnie wyróżnia się no-
wy GC SUN G1 oraz IBM JDK,
któremu przeważnie udaje się Wykres 5.
skończyć cykl GC poniżej 0,5 se-
kundy. GC G1 od SUN jest w sta-
nie dużą część pracy zrealizować
w sposób równoległy do aplikacji,
a pauzy typu stop-the-world są nie
większe niż 200ms. Oczekiwania
na maksymalne pauzy dla G1 usta-
wiono na 50 milisekund, czyli czte-
ry razy mniej niż zmierzone pauzy.
Wynik i tak jest dużo lepszy (prze-
ważnie 3 do 10 razy) niż rozwiąza-
nia IBM, Open JDK czy poprzednie
implementacje SUN.
Na wykresie nr 7 przedsta-
wiono dwa przebiegi z tym GC
i ustawieniem flag „rekomendu-
jących” JVM utrzymywanie pauz
poniżej 50ms w przedziałach 200 Wykres 6.
ms (G:0,2s) oraz 2 000 ms (G:2s).
Flagi te (m.in. -XX:MaxGCPause-
Millis=Xms oraz -XX:GCPause-
IntervalMillis=Xms) można uznać
za wysłanie oczekiwania do JVM,
aby próbował utrzymać wyni-
ki w zadanych parametrach. JVM

Narzędzia do analizy
JVM
• JDK (HotSpot)
• JVisualVM
• Jstat
• Jmap
• Jinfo
• Memory Analyzer (Eclipse)

Wykres 7.

22 7/2011
Analiza wydajności aplikacji Java dla opornych

jednak nie daje żadnej gwarancji, że to się uda. Mimo


ustawienia powyższych parametrów obserwowane pau- Narzędzia i opcje pomocne
zy były w okolicach 100-200 ms, co jest wynikiem gor- w diagnozowaniu i analizie logów GC
szym niż oczekiwano, ale lepszym niż konkurencja (nie Flagi JVM:
wliczając w to Azul JDK). Mimo znacznych różnic w cza- • -Xloggc:<PLIK>
sach GC między wynikami z SUN JDK G1 a Azul JDK, to • -XX:+PrintGCTimeStamps
maksymalne czasy są porównywalne. Wynika to z tro- • -XX:+PrintGCDetails
chę innej architektury rozwiązania AZUL JDK, gdzie • -verbose:gc
JVM uruchamiany jest w specjalnie do tego przeznaczo- Narzędzia:
nym obrazie na hypervisorze ESX. Przy czasach odpo-
wiedzi na poziomie pojedynczych milisekund komunika- • GCViewer (http://www.tagtraum.com/)
cja sieciowa wnosi zauważalne opóźnienia w sumarycz- • IBM Support Assistant Workbench wraz z IBM
Monitoring and Diagnostic Tools for Java
nym czasie odpowiedzi. Decyzja, jak mapować takie wy- • Analizator logów GC dostarczany wraz z Azul JDK
niki na wymagania biznesowe pozostaje w gestii osoby
dostarczającej rozwiązanie.
Nasz przykład jest drastyczny, z premedytacją przeja- nia kluczowych elementów, którym należy się szczegól-
skrawiony i uproszczony, ale nie różni się znacząco od nie głęboko przyjrzeć jest nie do przecenienia.
wymagań stawianych systemom obsługującym transakcje Kluczowy nacisk położony został na analizę proble-
na rynkach giełdowych, gdzie liczy się ten, kto pierwszy mów z Garbage Collectorem i zaprezentowanie różnic
zaakceptował ofertę, czy też w przypadku obsługi połą- między implementacjami GC różnych dostawców. Jeżeli
czeń telekomunikacyjnych, gdy operator musi sprawdzić nie chcemy uciekać się do komercyjnych rozwiązań ofe-
stan konta przed zestawieniem połączenia z telefonu ko- rowanych przez firmy Azul Systems czy IBM, to możemy
mórkowego. uzyskać dość dużą poprawę zachowania GC poprzez wy-
korzystanie eksperymentalnego (w chwili obecnej) GC
Wnioski G1 stworzonego przez firmę SUN (teraz Oracle).
Chcieliśmy przekazać, jak w łatwy i szybki sposób okre- Chcielibyśmy też zachęcić odbiorców do śledzenia no-
ślić, czy aplikacja ma szansę bezboleśnie przejść z fazy te- wych produktów w ofercie Azul Systems, jako, że firma
stów do fazy produkcyjnej. W rzeczywistym świecie jest w najbliższym czasie udostępni nową generację rozwiązań,
zapewne dużo więcej haczyków, na które należy zwró- która wyeliminują barierę wejścia (głównie pod kątem ar-
cić uwagę, ale posiadanie umiejętności szybkiego określe- chitektury) związaną z tą technologią.

DANIEL
WITKOWSKI
Lider Obszaru
St rategicz nego
w WORLDIT Sys-
tems. Zajmuje się rozwiąza-
niami optymalizacji syste-
mów IT i realizuje projekty au-
dytów technologicznych.

PAWEŁ
WOJTANKA
Pracuje w WORLDIT
Systems i specjalizu-
je się w technologii
Wykres 8. Azul Zing.

ESX i narzędzia monitorujące


(http://downloads.vmware.com/d/details/esx41u1/ZHcqYnRlQHBiZCpwdw==)
W celu analizy zachowania wirtualnych maszyn działających w ramach hypervisora ESX można wykorzystać
narzędzie ESXTOP, które jest dostarczane razem z platformą VMWare ESX. Pozwala ono na zapis i analizę pa-
rametrów CPU, pamięci, I/O (dyski, sieć) pod kątem każdego z działających systemów.

www.sdjournal.org 23
PROGRAMOWANIE TCL

Tcl: wirtualne systemy plików


Część II: Skrypty Tcl jako aplikacje wykonywalne
Tcl/Tk to dosyć interesujący język. Od 20 lat Tk pozwala
na tworzenie budowanie interfejsów graficznych działających
na różnych systemach operacyjnych – wykorzystywane między
innymi przez języki Perl oraz Python.
Od 11 lat Tcl pozwala na pakowanie całej aplikacji do pojedynczego
pliku wykonywalnego – co praktycznie eliminuje problemy
z dystrybucją aplikacji oraz ich uaktualnianiem. W dzisiejszym
artykule przybliżymy ten proces.

Dowiesz się: Powinieneś wiedzieć:


• Jak zamieniać skrypty Tcl na pliki wykonywalne; • Podstawy języka Tcl;
• Czym są i jak używać Tclkity, Starkity i Starpacki. • Jak działają wirtualne systemy plików (z poprzedniego
artykułu).

Geneza problemu
Możemy śmiało postawić tezę, że niemal każdy twór- ni przenośny – możemy go skopiować i uruchomić na
ca oprogramowania – niezależnie od używanych techno- dowolnym komputerze z systemem Windows.
logii - pragnie by dotarło ono do jak najszerszego grona W przypadku wielu innych technologii wymagane jest
odbiorców, i było postrzegane jako przyjazne dla użyt- jednak posiadanie tzw. „środowiska uruchomieniowego”
kownika. Oprócz oczywistych cech – jak funkcjonalność – na przykład maszyny wirtualnej Javy, czy interpreterów
i przydatność - oznacza to również, że tworzona aplika- takich języków skryptowych jak Python, Tcl, Perl, Ruby.
cja musi być łatwa w dystrybucji. Nie przez przypadek O ile jednak rozmiar natywnej aplikacji nie jest zwykle
coraz większą popularnością cieszą się przenośne pro- zbyt duży, to niejednokrotnie rozmiar całego środowi-
gramy typu portable, gdzie cały proces instalacji sprowa- ska może skutecznie zniechęcić do wypróbowania danej
dza się do rozpakowania ściągniętego archiwum, zaś mi- aplikacji w ogóle (Tabela 1).
gracja czy odinstalowanie są tak proste jak przeniesienie Jak widzimy, uruchomienie „Hello world” w dowol-
lub skasowanie katalogu. nym z tych języków pociąga za sobą bagaż wielu mega-
Nie bez znaczenia są również rozmiary czy ilość pli- bajtów maszyny wirtualnej lub interpretera. Niewielkim
ków potrzebnych do pomyślnego używania danej apli- pocieszeniem jest fakt że raz zainstalowane środowisko
kacji. W przypadku języków takich jak C/C++ możliwe uruchomieniowe może służyć do uruchamiania więcej
jest zbudowanie „natywnego” pliku wykonywalnego nie niż jednej aplikacji, gdyż często użytkownik chce uży-
posiadającego żadnych zależności. Do pełnego korzysta- wać akurat tylko jedną, której aktualnie potrzebuje. Ta-
nia z jego funkcjonalności wystarczy wtedy że użytkow-
nik uruchomi dany program – bez potrzeby instalacji do- Tabela 1. Rozmiar i ilość plików w popularnych
datkowego oprogramowania. Przyjrzyjmy się nieśmier- środowiskach uruchomieniowych
telnemu „Hello world”: Środowisko Wersja Rozmiar (MB, Ilość plików
Windows XP)
#include <stdio.h> ActiveTcl 8.5.9 8.5.9 40,4 MB 1478
main() ActivePerl 5.12.3 5.12.3 107,5 MB 5630
{ printf ("Hello World!\n"); }
Ruby 1.9.2 1.9.2 30,2 MB 851
Java 1.6 (JRE) 1.6 (JRE) 96,1 MB 633
Po skompilowaniu poleceniem gcc hello.c -o
hello.exe plik wynikowy ma rozmiar 22kB i jest w peł- ActivePython 2.7.1 65,9 MB 3840

24 7/2011
Tcl: wirtualne systemy plików

ka jest cena wygody i komfortu (czyli szybkości i łatwo-


ści pisania kodu) oferowanych przez języki wysokiego
poziomu. Twórcy języka Tcl/Tk znaleźli ciekawe roz-
wiązanie tego, i wielu innych problemów, poprzez wy-
korzystanie opisanej w poprzednim artykule koncepcji
wirtualnych systemów plików. W dzisiejszym odcinku
dowiemy się jak zbudować analogiczne hello.exe w opar-
ciu o język Tcl.
Podkreślić w tym miejscu należy, że budowanie w uję-
ciu Tclowym nie ma nic wspólnego z kompilowaniem.

Przykładowa aplikacja
Nasz przykładowy program będzie nieco bardziej uroz-
maicony niż standardowe „Hello world” i będzie to pro-
sty acz działający zegarek, przedstawiony na Rysunku 1.
Kod umieścimy w pakiecie clock, co pozwoli nam w dal-
szej części tekstu zademonstrować dostęp do pakietów
Tcl. Struktura tego pakietu to katalog clock zawierają-
cy 2 pliki:

• clock.tcl w którym znajduje się implementacja zega-


ra, przedstawiony na Listingu 1 Rysunek 1. Przykładowa aplikacja w Tcl/Tk

Listing 1. Moduł clock (plik clock.tcl)

package provide clock 1.0

proc tick {c h m s} {
foreach {hours minutes seconds} [clock format [clock seconds] -format "%H %M %S"] {
wm title . "$hours:$minutes:$seconds"
$c itemconfigure $s -extent 0 -start [expr -([scan $seconds %d]*6-90)%360]
$c itemconfigure $m -extent 0 -start [expr -([scan $minutes %d]*6-90)%360]
$c itemconfigure $h -extent 0 -start [expr -(([scan $hours %d]*30+[scan $minutes %d]/2)-90)%360]
}
after 1000 tick $c $h $m $s
}

package require Tk
canvas .c -height 220 -width 220 -bg white
for {set i 0} {$i <= 360} {incr i 6} {
.c create arc 10 10 210 210 -extent 0 -start $i -outline black -width [expr {1+4*((($i-1)%30)/29)}]
}

.c create oval 20 20 200 200 -fill white -outline white


.c create oval 102 102 118 118 -fill black
set h [.c create arc 60 60 160 160 -extent 1 -start 0 -outline black -width 10]
set m [.c create arc 30 30 190 190 -extent 1 -start 0 -outline black -width 6]
set s [.c create arc 25 25 195 195 -extent 1 -start 0 -outline black -width 2]
tick .c $h $m $s
pack .c
wm resizable . 0 0

www.sdjournal.org 25
PROGRAMOWANIE TCL

• pkgIndex.tcl definiujący moduł clock : niewielki podzbiór oferowanej funkcjonalności, co po-


package ifneeded clock 1.0 [list source [file join zwalało by na znaczne odchudzenie środowiska. Ponie-
$dir clock.tcl]] waż jednak środowisko takie jest współdzielone, rzad-
ko mamy pewność które z bibliotek mogą być usunię-
Plik ten opisuje pakiety dostępne w danym katalogu te, gdyż aplikacja B może mieć zupełnie inne zależności
– w tym przypadku informuje Tcl, że dany katalog za- od aplikacji A.
wiera pakiet clock 1.0 oraz jaką akcję należy wykonać, Czym jest Tclkit ? Jest to kompletne środowisko Tcl
by dany pakiet załadować (więcej informacji pod adre- dostępne w formie pojedynczego pliku o niewielkich
sem: http://wiki.tcl.tk/pkgIndex.tcl). rozmiarach. Typowy Tclkit zawiera:
Celowo pomijamy szczegółową analizę pliku clock.tcl,
zostawiając ją poniekąd jako zadanie domowe dla czy- • interpreter Tcl
telników. • bibliotekę Tk pozwalającą na tworzenie GUI
Uruchomienie przykładu jest proste – naszym skryp- • bibliotekę IncrTcl dostarczającą obiektowość
tem startowym będzie main.tcl przedstawiony na Listin- w skryptowym języku Tcl
gu 2. Najpierw ustalamy lokalizację tego skryptu, następ- • bibliotekę TclVFS oraz bazę danych Metakit (omó-
nie zapewniamy by moduły (jednym z nich będzie clock) wione w poprzednim artykule)
z podkatalogu lib były automatycznie widoczne dla in-
terpretera, poprzez dodanie odpowiedniej ścieżki do Tclkity są dostępne pod różne systemy takie jak Win-
zmiennej auto_path. W kolejnej linijce ładujemy mo- dows, Linux, MacOS X czy Solaris. Typowy rozmiar pli-
duł clock, co automatycznie spowoduje pojawienie się ku to kilka MB, przykładowo wersja pod Windows, na
okienka z zegarem, ostatnie polecenie zaś konfiguruje której skupimy się w dzisiejszym artykule - tclkit-8.5.8-
plik res/clock.ico jako ikonę okienka. Katalogi lib i res znaj- win32.upx.exe - ma 1.2 MB. Z nazwy pliku możemy wy-
dują się w tej samej lokalizacji co main.tcl. Samo odpale- wnioskować że zawiera Tcl w wersji 8.5.8, jest skompi-
nie sprowadza się do komendy: lowany 32-bitowo i spakowany UPXem (kompresorem
plików wykonywalnych).
C:\>wish sciezka/do/main.tcl Do czego służy Tclkit? Jak wspomnieliśmy jest to go-
towy do użycia interpreter Tcla, zatem jego funkcjonal-
Wish jest wersją interpretera Tcl z domyślnie załadowa- ność jest oczywista – wykonywanie skryptów Tclowych.
nym Tk. Teraz gdy mamy działający przykład, resztę ar- Przykładowo możemy za jego pomocą uruchomić nasz
tykułu poświęcimy sposobom zbudowania pliku wyko- program z zegarem:
nywalnego clock.exe o identycznej funkcjonalności.
C:\>tclkit-8.5.8-win32.upx.exe sciezka/do/main.tcl
Tclkit – środowisko Tcl jako pojedynczy plik
W Tabeli I. podaliśmy zarówno rozmiary jak i liczbę pli- Trzeba przyznać że jest to już znaczące ułatwienie
ków przychodzących z każdym środowiskiem – co naj- – zamiast instalować pełną dystrybucję Tcla, wystarczy
mniej kilkaset, a nierzadko kilka tysięcy. Środowiska te nam jeden plik, niestety wciąż nasza aplikacja występuje
bowiem zawierają wiele bibliotek i dodatków, przypomi- w formie grupy plików. Jak jednak za chwilę zobaczymy,
nając tym samym szwajcarski scyzoryk. Typowa aplikacja zalet płynących z faktu „spakowania” interpretera do
napisana w jednym z tych języków wykorzystuje tylko pojedynczego pliku jest znacznie więcej. Ponieważ na-

Listing 2. Główny skrypt przykładowego programu (plik main.tcl)

set currentDir [file normalize [file dirname [info script]]]


lappend auto_path [file join $currentDir lib]
package require clock
wm iconbitmap . -default [file join $currentDir res clock.ico]

Tclkit a system Windows


W przypadku systemów Windows istnieje możliwość (a wręcz bywa to konieczne) skorzystania z mniejszej,
konsolowej wersji Tclkit, okrojonej o bibliotekę Tk. Typowy rozmiar takiego pliku to około 700kB.
Rozdział na 2 wersje wynika z faktu, iż graficzne aplikacje w systemie Windows nie mogą korzystać z konsoli tek-
stowej w ramach standardowego wejścia/wyjścia. Wersja Tclkit bez Tk pozwala tworzyć aplikacje tekstowe, zaś
wersja z Tk – graficzne. Na innych systemach, gdzie wspomniany problem nie występuje (np. pod Linuxem pro-
gramy mające GUI mogą bez przeszkód korzystać z konsoli), możemy z powodzeniem używać tylko wersji z Tk.

26 7/2011
Tcl: wirtualne systemy plików

Słowniczek
• Metakit – baza danych o specyficznych właściwościach; wg autora „wypełnia lukę pomiędzy bazami
obiektowymi, relacyjnymi, drzewiastymi i typu flat-file”. Dzięki odpowiedniemu providerowi bazę danych
Metakit można traktować jak wirtualny kontener VFS.
• Tclkit – interpreter Tcl skompilowany do pojedynczego pliku; potrafi obsługiwać Starkity.
• Cookit – interpreter Tcl podobny do Tclkit, ale oparty na nowocześniejszej technologii cookfs (opisanej
szczegółowo w następnym artykule).
• Starkit – wirtualny kontener plików, najczęściej oparty na Metakit (dzięki providerowi TclVFS mk4) , stano-
wiący jednocześnie format dystrybucji oprogramowania. Do uruchomienia zawartego w nim programu
potrzebny jest Tclkit lub inny interpreter Tcl z obsługą Starkit. Zwyczajowo rozszerzeniem pliku jest .kit.
• Starpack – Tclkit + Starkit, czyli pojedynczy plik wykonywalny utworzony z interpretera Tcl i dołączonego
wirtualnego kontenera z plikami tworzącymi daną aplikację.

zwa pliku Tclkit jest zazwyczaj dość długa, dla uprosz- Starkity i Starpacki
czenia w dalszej części tekstu będziemy używać skró- – wszystko w jednym pliku
conej wersji: tclkit.exe. Tclkit jest tylko pierwszym krokiem zmierzającym do
Dużą zaletą jest zakres wspieranych platform; w końcu radykalnego uproszenia dystrybucji programów napisa-
to przenośność kodu stanowi jeden z mocnych atutów nych w Tclu. Jego dopełnieniem są Starkity. Jest to nic
języków skryptowych. Z istotniejszych platform są to: innego jak wirtualny kontener plików (VFS) zawierają-
cy w środku skrypty Tcl i inne pliki (zasoby) składające
• Windows się na naszą aplikację. Zwyczajowo pliki Starkit posiada-
• Linux ją rozszerzenie .kit. Jest to sposób dystrybucji podobny
• Mac OS X do archiwum zip zawierającego gotowy do uruchomie-
• Solaris nia program, ma jednak pewne różnice:
• AIX
• HP-UIX • Aby uruchomić aplikację, nie trzeba rozpakowywać
Starkita. Należy użyć Tclkita, np.: tclkit.exe moja _
Skąd można wziąć Tclkita ? Oczywiście – jak wszyst- aplikacja.kit . Ogólnie pliki .kit możemy traktować
ko dziś – z internetu. Wytrawnym użytkownikom wy- jak gotowe do uruchomienia aplikacje Tcl, lecz po-
szukiwarki odnalezienie go nie sprawi problemu, jednak zbawione kodu interpretera.
dla ułatwienia podajemy adres: http://code.google.com/p/ • Wystarczy tylko jeden Tclkit w systemie, by urucha-
tclkit/ (dawniej http://equi4.com/tclkit/). miać dowolną ilość Starkitów. Jest to analogiczne do

Wewnętrzna budowa Starkitów i Starpacków


Plik .kit zawiera kontener VFS, musi być on jednak poprzedzony tekstową częścią (nagłówkiem) zawierającą
przynajmniej Tclowe komendy inicjalizacyjne. Dzieje się tak dlatego, że na początku wykonywania tego pliku
Tclkit (lub inny użyty interpreter) nie zważa na rozszerzenie (a więc mogłoby być ono dowolne, .kit jest jedy-
nie przyjęta konwencją) i traktuje go jak zwykły skrypt Tcl (nie wie bowiem że ma do czynienia z kontenerem
VFS). W przypadku Starkitów nagłówek ma najczęściej następującą postać:

package require starkit


starkit::header mk4 -readonly
(ctrl+z)

Komendy te są wykonywane przez interpreter Tcl aż do napotkania znaku Ctrl+z (\u001a) oznaczającego dlań
koniec pliku, i powodują zainicjalizowanie i uruchomienie danego pliku .kit już jako Starkit. W szczególności, po
lecenie starkit::header mk4 -readonly otwiera archiwum w obecnie czytanym pliku, korzystając z formatu
podanego jako 1szy argument - w tym przypadku mk4, a następnie czytany jest plik main.tcl z tego archiwum.
Po znaku \u0001a następuje binarny ciąg danych stanowiący kontener VFS. Więcej światła na tą strukturę mo-
że rzucić także Listing 5.
W jaki sposób Tcl jest w stanie poprawnie zidentyfikować początek obszaru danych w pliku będący wspo-
mnianym kontenerem? W przypadku baz danych Metakit, ich rozmiar umieszczony jest na samym końcu.
Dzięki temu plik z taką bazą może zawierać całkowicie dowolne dane pod warunkiem że po ciągu danych
będących bazą zawierająca strukturę VFS nie ma już nic więcej (a tak jest właśnie w przypadku plików Star-
kit czy Starpack). Wtedy używając jej rozmiar jako ujemny offset względem końca pliku możemy precyzyjnie
określić początek archiwum i odczytać dane z bazy (a w tym przypadku - pliki z wirtualnego kontenera).
W przypadku Starpacków, wspomniany nagłówek Tclowy zastąpiony jest kodem binarnym, jednak zasady
pozostają niezmienione.

www.sdjournal.org 27
PROGRAMOWANIE TCL

Rysunek 2. Wewnętrzna struktura plików Starpack. Obszar A odpowiada Tclkitowi, a obszar B - Starkitowi

scenariusza: jedna maszyna wirtualna Javy + wiele wcześniej wspomniano, aby uruchomić daną aplikację
programów w Javie. dostarczoną w formie Starkita, potrzebne są 2 pliki:

Specyfikacja Starkit określa kilka niezbędnych elemen- • plik wykonywalny (tclkit.exe) zawierający interpreter Tcl
tów, które musi zawierać dany VFS: • plik .kit zawierający kod Tcla i inne zasoby

• Zazwyczaj kontener VFS zbudowany jest na bazie Okazuje się, że te 2 pliki można „skleić” w pojedynczy
Metakit, z wykorzystaniem sterownika (providera
VFS) mk4vfs. Jak pokażemy w późniejszej części roz-
działu, możliwe jest wykorzystanie innego typu VFS,
na przykład zip.
• W katalogu głównym kontenera musi znajdować się
skrypt main.tcl. Jest on automatycznie wywoływany
jako pierwszy.
• Katalog lib (oczywiście znajdujący się w środku na-
szego kontenera VFS) zwyczajowo zawiera dodat-
kowe moduły potrzebne dla naszego kodu. Kata-
log ten nie jest jednak automatycznie dodawany do
zmiennej auto _ path , dlatego też w skrypcie main.tcl
wymagany jest następujący kod inicjalizacyjny:
package require starkit
starkit::startup

• Te 2 linijki odpowiednio modyfikują zmienną


auto _ path oraz ustawiają zmienną starkit::topdir
tak, by wskazywała punkt montowania kontenera
VFS.
• Do tego momentu stosowaliśmy uproszczone zało-
żenie że plik .kit jest kontenerem VFS zbudowanym
w oparciu o Metakit. W rzeczywistości jego struk-
tura jest bardziej złożona – patrz ramka.

O Starkitach można by pisać jeszcze długo, prawdzi- Rysunek 3. Wewnętrzna struktura przykładowego
wie ciekawy temat jest jednak dopiero przed nami. Jak pliku clock.exe

28 7/2011
Tcl: wirtualne systemy plików

plik .exe – efekt tej operacji jest określany jako Starpack


Listing 3. Główny skrypt (plik main.tcl)
i ma następujące cechy: przystosowany do użycia w Starkicie/
Starpacku
• Jest to nadal plik wykonywalny, gdyż z punktu wi-
dzenia systemu operacyjnego jedynie wydłużyliśmy package require starkit
obszar danych znajdujący się na końcu tego pliku. starkit::startup
Tclkit jest na tyle „sprytny” że zauważy dołączoną package require clock
strukturę VFS i automatycznie wykona plik main.tcl. wm iconbitmap . -default [file join $starkit::
• Aplikacja dystrybuowana w tej formie ma oczywi- topdir res clock.ico]
ście większy rozmiar od pliku .kit
• Do uruchomienia tejże aplikacji nie jest wymagane
nic więcej! Innymi słowy, mamy pełnoprawny plik Listing 4. Skrypt budujący (build.tcl) plik
wykonywalny pozbawiony zewnętrznych zależności. wykonywalny clock.exe
Możemy go dać użytkownikom którzy nawet nie
będą świadomi, że językiem programowania jest Tcl. set targetname clock.exe
set exename [file tail [info nameofexe]]
Opisaną powyżej strukturę Starkitów i Starpacków ilu-
struje Rysunek 2. vfs::filesystem unmount $exename
Tyle teorii, przyjrzyjmy się teraz w praktyce jak same- file copy -force $exename $targetname
mu zbudować plik wykonywalny (funkcjonuje też ter-
min „spakować aplikację”) . Naszym celem będzie utwo- vfs::mk4::Mount $targetname $targetname
rzenie pliku clock.exe i chcemy by po jego uruchomie- file copy -force clock.vfs/main.tcl $targetname
niu użytkownik ujrzał okienko zawierające wspomnia- file copy -force clock.vfs/res $targetname
ny wcześniej „zegarek” z Rysunku 1. Strukturę pliku file copy -force clock.vfs/lib $targetname
clock.exe ilustruje Rysunek 3.
Kod aplikacji pozostanie bez zmian, z wyjątkiem pli- vfs::unmount $targetname
ku main.tcl który obecnie przyjmie postać jak na Listin-
gu 3. Dodane zostało wywołanie wyżej opisanego pole-
cenia starkit::startup, oraz użyto zmiennej $starkit:: spakowaniem ich do postaci archiwum lub pliku wyko-
topdir do określenia lokalizacji pliku z ikoną. nywalnego.
Ten i pozostałe pliki umieścimy w specjalnym katalo-
gu, odzwierciedlającym docelową strukturę kontenera Samodzielne budowanie pliku .exe
VFS. Niepisaną konwencją jest by katalog ten nazywał się Pierwszym sposobem jest własnoręczne zbudowanie pli-
identycznie jak docelowy plik, lecz z rozszerzeniem .vfs ku. Jak już wiemy, cała operacja sprowadza się do prze-
– w naszym przypadku będzie to zatem katalog clock.vfs niesienia zawartości katalogu clock.vfs do wewnętrznego
ukazany na Rysunku 4. kontenera VFS docelowego pliku clock.exe. Pracę tę wy-
Warto w tym momencie podkreślić, że plik main.tcl kona dla nas skrypt z Listingu 4.
w tej postaci nadaje się również do uruchomienia ja- Do zbudowania aplikacji potrzebny jest tclkit.exe (uwa-
ko zwykły skrypt Tclowy, poza środowiskiem Starkit/ ga! Ponieważ nasz program zawiera elementy graficzne,
Starpack. Pozwala to wygodnie testować aplikacje przed należy użyć Tclkita z wbudowaną obsługą Tk), ponie-

Tclkit to także Starpack!


Warto podkreślić, że „goły” Tclkit również jest Starpackiem. Oznacza to nie mniej, nie więcej, tylko fakt, że ma
on dołączony wirtualny kontener zawierający pliki – głównie katalog lib z kilkoma istotnymi modułami. Moż-
na to bardzo łatwo zweryfikować poprzez jego uruchomienie – ukaże się konsola Tclowa – i wpisanie komen-
dy puts $auto _ path. Wypisze ona wszystkie lokacje, w których interpreter będzie poszukiwał modułów, i ła-
two zauważymy tam wpisy odnoszące się do wewnętrznej zawartości Tclkita:

C:/tclkit-8.5.8-win32.upx.exe/lib/tcl8.5
C:/tclkit-8.5.8-win32.upx.exe/lib
C:/tclkit-8.5.8-win32.upx.exe/lib/tk8.5
C:/tclkit-8.5.8-win32.upx.exe/lib/tk8.5/ttk

Zgodnie z przyjętą konwencją, kontener VFS jest automatycznie podmontowany jako udział o tej samej nazwie
co plik w którym się znajduje – w tym przypadku jest to tclkit-8.5.8-win32.upx.exe.
Zbudowanie Starpacka z własną aplikacją oznacza de facto dogranie dodatkowych plików do wspomnia-

www.sdjournal.org 29
PROGRAMOWANIE TCL

waż clock.exe będzie składał się z tego właśnie pliku wraz Samodzielne budowanie pliku .kit
z „dodatkami”. Aby nie mnożyć „bytów”, przygotowali- Mówiąc o clock.kit, aż do tej chwili skrzętnie pomijaliśmy
śmy skrypt budujący w taki sposób, aby mógł być urucho- sposób budowania Starpacków. Ręczne tworzenie jest
miony z użyciem tego samego tclkit.exe (inne rozwiązania raczej kłopotliwe z powodu konieczności zadbania o od-
często wymagają osobnej kopii Tclkita przeznaczonej do powiedni nagłówek pliku, co ilustruje Listing 5. Znacznie
zapakowania w docelową aplikację), dlatego też proces lepiej wykorzystać do tego zadania narzędzie SDX.
budowania powinien być uruchomiony poleceniem:
Starkit oparty na kompresji ZIP
C:\>tclkit.exe build.tcl Do tego momentu jedynym używanym przez nas typem
wirtualnego kontenera VFS był mk4. Powód ku temu jest
Przyjrzyjmy się pobieżnie skryptowi budującemu. Na prosty – jest on praktycznie najlepszym rozwiązaniem
początku ustalana jest wartość 2 zmiennych. Pierwsza z istniejących. Specyfikacja Starkit jest jednak na tyle ela-
z nich – targetname – określa plik wynikowy. styczna, że teoretycznie możliwe jest użycie innego ro-
Zmienna exename zawierać będzie nazwę użytego Tcl-
kita (w naszym przykładzie – tclkit.exe). Zaraz po uru- Listing 5. Skrypt budujący plik clock.kit
chomieniu jest to punkt montowania (jak wspomnie-
liśmy, Tclkit również zawiera wewnętrzny VFS), dla- set target clock.kit
tego następne polecenie odmontowuje ten wirtual-
ny kontener. Dzięki temu $exename wskazuje teraz na #tworzy nagłówek Starkit
plik tclkit.exe, który możemy przekopiować pod nazwę set channel [open $target w]
clock.exe (próba skopiowania bez odmontowania udzia- fconfigure $channel -translation binary
łu spowodowałaby wykopiowanie zawartości kontene- puts $channel "package require starkit"
ra VFS). puts $channel "starkit::header mk4 -readonly"
W następnym kroku clock.exe jest podmontowany ja- puts $channel "\u001a"
ko kontener VFS typu mk4 , i „wzbogacony” poprzez close $channel
dokopiowanie zawartości katalogu clock.vfs.
Ostatnie polecenie odmontowuje ten kontener. Te- # mk4 dodaje bazę Metakit na końcu pliku
raz możemy już cieszyć oczy działającym programem vfs::mk4::Mount $target $target
clock.exe. file copy -force clock.vfs/main.tcl $target
Rozmiar pliku wynikowego to 1.2 MB i generalnie jest file copy -force clock.vfs/res $target
w całości podyktowany rozmiarem użytego Tclkita (roz- file copy -force clock.vfs/lib $target
miar pliku clock.kit to zaledwie 1.9 kB). vfs::unmount $target

Listing 6. Skrypt (build_zip.tcl) budujący plik


clock_zip.kit

set targetname clock_zip.kit

# wczytuje clock.zip do pamięci


set channel [open clock.zip]
fconfigure $channel -translation binary
set kit [read $channel]
close $channel

# tworzy nagłówek Starkit


set channel [open $targetname w]
seek $channel 0 start
puts $channel "package require starkit"
puts $channel "starkit::header zip"
puts $channel "\u001a"
fconfigure $channel -translation binary
puts -nonewline $channel $kit
Rysunek 4. Katalog clock.vfs zawiera aplikację close $channel
przygotowaną do spakowania do pliku clock.exe

30 7/2011
Tcl: wirtualne systemy plików

dzaju kontenera. Warunek konieczny to obsługa danego C:\>tclkit.exe build_zip.tcl


typu przez interpreter Tcl użyty do jego uruchomienia.
Listing 6. ilustruje sposób budowania pliku .kit w opar- Powstały plik możemy uruchomić interpreterem z ob-
ciu o kompresję zip. Zasada jest analogiczna, w pliku wy- sługą zip (patrz ramka):
nikowym najpierw umieszczamy odpowiedni nagłówek,
następnie dołączamy zawartość przygotowanego wcze- C:\>tclkit.exe clock_zip.kit
śniej archiwum clock.zip zawierającego zawartość kata-
logu clock.vfs (tak by main.tcl był w głównym katalogu te- Narzędzie SDX
go archiwum). Warto zwrócić uwagę na fakt, iż tym ra- W celu ułatwienia procesu pakowania aplikacji, twórcy
zem komenda starkit::header będzie wykonana z argu- omawianych rozwiązań udostępnili narzędzie SDX, dys-
mentem zip. trybuowane – a jakże inaczej – jako Starkit sdx.kit. Z uży-
Skrypt budujący możemy uruchomić na przykład za ciem tego narzędzia stworzenie pliku clock.exe sprowa-
pomocą Tclkita: dza się do polecenia:

Naprawa obsługi ZIP w Tclkit i ActiveTcl


Starsze wersje implementacji vfs::zip mają błąd, przez co wersja obsługa zip może nie działać poprawnie.
Ambitniejsi czytelnicy mogą sami łatwo naprawić ten błąd, podmieniając plik zipvfs.tcl (który należy pobrać
z http://tclvfs.cvs.sourceforge.net/viewvc/tclvfs/tclvfs/library/zipvfs.tcl i zapisać np. w katalogu C:\temp) we-
wnątrz Tclkita którego zamierzamy używać:

c:\temp>copy tclkitsh.exe temp.exe


1 file(s) copied.

c:\temp>temp.exe
% vfs::mk4::Mount tclkitsh.exe tclkit
mk4vfs1
% file copy -force C:/temp/zipvfs.tcl tclkit/lib/vfs1.4
23292
% vfs::unmount tclkit
% exit

c:\temp>del temp.exe

Po tej operacji tclkitsh.exe powinien bezproblemowo obsługiwać zip.


ActiveTcl natomiast jest dość często aktualizowany, tak więc najnowsza wersja powinna być pozbawiona te-
go błędu; jeśli nie, należy odszukać plik zip-1.0.3.tm i nadpisać go plikiem zipvfs.tcl.

Nagłówek „Shebang”
Terminem Shebang określana jest sekwencja znaków #! pozwalająca uruchomić dany plik jako skrypt na sys-
temach uniksopodobnych. W przypadku Starkitów często spotyka się następujący nagłówek:

#!/bin/sh
# \
exec tclkit "$0" ${1+"$@"}
package require starkit
starkit::header mk4 -readonly
(ctrl+z)

Pierwsza linijka jest typowa – jako interpreter pliku ustawiany jest /bin/sh. Dwie następne linijki stanowią swoistą
„magię”:

• interpreter sh zignoruje linijkę drugą i wykona trzecią, czyli uruchomi tclkit z nazwą bieżącego pliku jako
pierwszym argumentem i zakończy przetwarzanie tego pliku. Oczywiście tclkit nie musi byćtak na prawdę
Tclkitem – równie dobrze może to być dowiązanie symboliczne do tclsh czy Cookita. Warunkiem koniecz-
nym jest by tclkit miał atrybut wykonywalności i był dostępny w zakresie ścieżki systemowej PATH.
• interpreter Tcl ignoruje wszystkie linijki zaczynające się od znaku #. Ponieważ druga linijka kończy się zna-
kiem kontynuacji \, Tcl uzna trzecią linijkę za dokończenie poprzedniej, i w efekcie również zignoruje.

Kolejne wiersze to opisany wcześniej nagłówek pliku .kit, i są już wykonywane przez interpreter Tclw celu inicjali-
zacji i uruchomienia danego Starkita.

www.sdjournal.org 31
PROGRAMOWANIE TCL

C:\>tclkit.exe sdx.kit wrap clock.exe -runtime • Zbudowane pliki wykonywalne nie mają żadnych za-
tclkit.copy.exe leżności. Odbiorca docelowy nie musi instalować
żadnych dodatkowych programów czy bibliotek.
SDX nie jest tak sprytny jak nasz skrypt, przez co wy- Dla porównania, w przypadku niektórych rozwią-
maga utworzenia kopii Tclkita. W przypadku pominięcia zań dla Javy, pliki .exe wciąż wymagają zainstalowa-
opcji -runtime , wynikowy plik byłby zwykłym Starkitem: nej na dysku maszyny wirtualnej JRE.
• Mały rozmiar. Zbudowany przez nas clock.exe ma za-
C:\>tclkit.exe sdx.kit wrap clock.kit ledwie 1.2 MB, a zawiera w środku w pełni funkcjo-
nalny interpreter Tcl.
Zgodnie ze wspomnianą wcześniej konwencją, SDX • Wsparcie dla wielu platform i systemów operacyj-
oczekuje że pakowana aplikacja znajduje się w katalo- nych. Chociaż w artykule skupiamy się na środowi-
gu <nazwa_pliku_docelowego>.vfs. Pliki .kit wygenero- sku Windows, analogiczne pliki wykonywalne może-
wane tym narzędziem posiadają standardowy nagłówek my zbudować dla każdej z platform, dla której ist-
(tzw. Shebang – patrz ramka),pozwalający na urucha- nieją Tclkity (lub Cookity). Dzięki temu Linux, Sola-
mianie ich jak zwykłych programów na systemach unik- ris czy MacOS stoją przed nami otworem.
sopodobnych. Również sam SDX może być uruchomio- • Łatwość tworzenia. Do zbudowania wystarczy nam
ny w następującej formie: zaledwie TclKit, i nic więcej. Dodatkowo, nie musi-
my nawet dysponować platformą na którą piszemy
$ ./sdx.kit wrap clock.kit program – pliki pod Windows możemy tworzyć na
Linuxie, i tak dalej. Jedyne co musimy mieć, to Tcl-
SDX pozwala również na szereg innych operacji, jak na Kit na obie platformy (roboczą i docelową). Prze-
przykład rozpakowanie danego pliku. Szczegółową listę cież dobrego kodu nie trzeba testować :)
komend znajdziemy na stronie http://equi4.com/starkit/ • Plik wynikowy nie jest 'czarną skrzynką”. W każdej
sdx.html. chwili możemy uzyskać dostęp do jego wewnętrznej
struktury plików, chociażby w celu poprawek i ak-
Tcl Automated Build System tualizacji. Należy tu podkreślić że może być to po-
Na koniec pozostawiliśmy najbardziej użyteczne roz- strzegane jako wada w przypadku, gdy zależy nam na
wiązanie - Tcl Automated Build System (TABS) to narzę- całkowitym zabezpieczeniu kodu źródłowego przed
dzie do budowania archiwów oraz plików wykonywal- niepowołanym wzrokiem. Z drugiej zaś strony, do-
nych podobne do SDX. Założenia TABS są podobne do celowy odbiorca musiałby wiedzieć że dany plik zo-
rozwiązań typu ant oraz make – możliwość definiowa- stał akurat zbudowany z użyciem tej technologii.
nia i budowania celów, składających się z poszczegól-
nych zadań i zależności pomiędzy nimi. Z powodu złożo- Cookit – rzut oka
ności i mnogości oferowanych cech, system ten opisze- W tym artykule skoncentrowaliśmy się na rozwiązaniach
my w osobnym artykule. opartych o Tclkit. Już wkrótce opiszemy nieformalnego na-
stępcę, bardziej zaawansowany Cookit oparty o VFS cookfs.
Tcl a inne języki Cookit to przede wszystkim mniejsze rozmiary plików oraz
Pomijając ze zrozumiałych względów języki natywne, Tcl lepsza wydajność. To wszystko już w kolejnym artykule!
nie jest jedynym językiem, który pozwala na tworzenie
plików wykonywalnych. Przykładowo szereg rozwiązań PIOTR BEŁTOWSKI, WOJCIECH KOCJAN
istnieje dla Javy, zaś użytkownicy Pythona mogą skorzy- Autorzy książki „Tcl 8.5 Network Programming”
stać z narzędzia py2exe. Mimo to, w subiektywnej ocenie Piotr Bełtowski – od 5 lat pracuje dla IBM,
autorów żaden z pozostałych języków nie oferuje cho- wcześniejsze doświadczenie obejmuje m.in.
ciażby zbliżonego komfortu, prostoty, elegancji i elastycz- Ericsson España i Ericpol. Współautor kilku pa-
ności jak Tcl. Przemawiają za tym następujące fakty: tentów i publikacji.
Wojciech Kocjan jest programistą z ponad 10
letnim doświadczeniem z językiem Tcl. Pra-
Linki cował m.in. dla firm IBM, Motorola, obecnie
• http://equi4.com/tclkit współpracuje z firmą BitRock. Jego aktywność
i http://code.google.com/p/tclkit open source dotyczy m.in. tworzenia narzę-
• http://equi4.com/starkit dzi cookfs, cookit, tabs oraz współpracy przy
• http://equi4.com/metakit pierwszej wersji Tclkit na system Microsoft Win-
• http://www.endorser.org/cookit dows budowanej za pomocą narzędzi MinGW.
• http://www.endorser.org/tabs Kontakt z autorami: piotr.beltowski@gmail.com,
oraz http://sourceforge.net/projects/tabs
wojciech@kocjan.org

32 7/2011
�������������������������������������
����������������������������
����������
������������������������
�����������������

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

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

������������������������������������
PROGRAMOWANIE TCL

Tcl: wirtualne systemy plików


Część III: System budujący TABS

Programiści Javy od lat z powodzeniem korzystają ze sprawdzonego


i popularnego rozwiązania, jakim jest środowisko budujące Ant.
Przyjęta filozofia definiowania projektów jest na tyle wygodna
i elastyczna, że doczekała się analogicznych narzędzi dla innych
języków. Również Tcl może poszczycić się systemem TABS, który
opiszemy w niniejszym artykule.

Dowiesz się: Powinieneś wiedzieć:


• Jak wygodnie operować na różnych typach archiwów • Podstawy Tcla;
związanych z językiem Tcl; • Jak działają wirtualne systemy plików (I artykuł cyklu);
• Jak budować pliki wykonywalne ze skryptów Tcl • Na czym polega proces zwijania aplikacji do pliku wy-
w oparciu o system TABS; konywalnego (II artykuł cyklu).
• Jak tworzyć konfiguracje budowy w oparciu o zadania
i cele.

wane są w systemach kontroli wersji – TABS nie będzie


wtedy kopiował katalogów CVS, .svn czy .git. TABS ofe-
Tcl Automated Build System ruje dwa tryby pracy:
W poprzednim artykule opisaliśmy zwijanie aplikacji sa-
modzielnie, lub z użyciem prostego narzędzia SDX, po- • wykonywanie pojedynczych poleceń – podobnie jak
zostawiając opisanie systemu TABS aż do tej chwili. Tcl SDX, wykonuje jedną operację; na przykład:
Automated Build System to narzędzie do budowania ar-
chiwów oraz plików wykonywalnych podobne do SDX. tabs wrap -binary tclkit.exe -output app.exe -copy
Tak jak jego pierwowzór, pozwala na pakowanie oraz "app.vfs/*"
rozpakowywanie archiwów. Założenia TABS są również
podobne do rozwiązań typu ant oraz make – możliwość Jest to idealne rozwiązanie do budowania prostych
definiowania i budowania celów, składających się z po- programów – w przypadku, gdy nasza aplikacja po pro-
szczególnych zadań i zależności pomiędzy nimi. stu wymaga spakowania plików z jednego lub więcej ka-
Największą różnicą w porównaniu z SDX jest wspar- talogów
cie dla wielu formatów archiwów – zip, mk4 oraz cookfs.
Dla każdego z nich TABS pozwala na precyzyjną konfi- • definiowanie celów oraz zadań w pliku Tabsfile – po-
gurację poprzez przekazywanie dodatkowych opcji. Gdy dobnie jak w przypadku ant/make, TABS czyta de-
jest to możliwe, format archiwum wybierany jest auto- finicje poszczególnych celów, zależności i wykonuje
matycznie – np. w przypadku budowania plików wyko- poszczególne operacje w oparciu o cele do zbudo-
nywalnych w oparciu o Tclkit, formatem będzie mk4, wania oraz zależności pomiędzy nimi. Ten tryb jest
a dla Cookit będzie to cookfs. wygodniejszy w sytuacji, gdy budujemy kilka plików
Inną zaletą systemu TABS jest elastyczne definiowa- wynikowych oraz w przypadku większych zależno-
nie zadań. Poszczególne zadania oferują szeroki wa- ści pomiędzy nimi.
chlarz dodatkowych opcji – takich jak kopiowanie pli-
ków z wielu katalogów do jednego docelowego archi- Opis systemu zaczniemy od trybu wykonywania poje-
wum lub pliku wykonywalnego. Ponadto istnieje moż- dynczych poleceń, omawiając każde z nich. Następnie
liwość podania nazw plików i katalogów, które powin- przejdziemy do definiowania pliku Tabsfile, celów, za-
ny być ignorowane podczas kopiowania – jest to przy- leżności między nimi oraz poleceń, które należy wy-
datne przy np. budowaniu projektów, które przechowy- konać.

34 7/2011
Tcl: wirtualne systemy plików

Instalacja i uruchamianie Aby uruchomić poszczególne polecenie, wystarczy


Analogicznie do SDX, TABS dystrybuowany jest jako uruchomić tabs.tcl podając nazwę polecenia oraz ar-
jednoplikowe narzędzie. Można go pobrać ze strony gumenty w postaci par nazwa-wartość. Na przykład ko-
projektu – http://sf.net/projects/tabs/files/tabs/1.2/ (obec- menda:
ną wersją jest 1.2). W związku z obsługą różnych for-
matów, pobrać można trzy wersje pliku (zasadniczo $ tclkit tabs.tcl copy -copy "app.vfs/*" -output
każda z nich jest Starkitem o różnym typie użytego testdir
kontenera VFS):
powoduje uruchomienia polecenia copy, podając opcje -
• tabs-cli-zip.tcl – archiwum (kontener) w formacie zip; copy oraz -output .
uruchamiany działa poprawnie w większości dystry-
bucji, na przykład Tclkit i ActiveTcl (tak jak opisali- System pakietów w TABS
śmy w poprzednim artykule, koniecznym okazać się TABS wprowadza również koncepcję pakietów, czyli ze-
może podmiana implementacji vfs::zip na najnow- stawów plików gotowych do osadzenia w innych apli-
szą wersję, celem wyeliminowania błędów) oraz kacjach. Z technicznego punktu widzenia są to po pro-
Cookit (tylko wersja z Tcl 8.6) oraz. stu archiwa w formacie mk4, zip lub cookfs (o rozsze-
• tabs-cli.tcl – archiwum w formacie mk4, obsługiwane rzeniach .mk4pkg, .zippkg lub .cfspkg), które zawierają
poprawnie przez ActiveTcl oraz Tclkit. wszystkie potrzebne pliki.
• tabs-cli-cfs.tcl – archiwum w formacie cookfs, obsłu- Przykładowo, pakiet sqlite3 pod system operacyjny Li-
giwane poprawnie przez dystrybucje ActiveTcl oraz nux zawiera następujące pliki:
Cookit;
• lib/sqlite3.7.2/libsqlite3.7.2.so – biblioteka binarna
Rozszerzenie może być nieco mylące - nie są to czyste • lib/sqlite3.7.2/pkgIndex.tcl – standardowy deskryptor
skrypty Tclowe – lecz jak wspominaliśmy w poprzed- pakietu Tcl
nim artykule, interpreter Tcla nie patrzy na rozszerze-
nie i początkowo każdy plik traktuje jako skrypt, wyko- Pakiety mogą być uniwersalne, lub dedykowane dla
nując komendy z nagłówka inicjalizacyjnego. danej platformy. Na przykład pakiet zawierający je-
Po pobraniu, zalecamy zmianę nazwy na tabs.tcl – bę- dynie skrypty Tcl – taki jak tcllib – możemy osadzać
dzie ona wykorzystywana we wszystkich późniejszych na dowolnej platformie, natomiast pakiet z bibliote-
przykładach. Archiwum posiada standardowy nagłó- ką sqlite3 budowany jest osobno dla każdej platfor-
wek Shebang, a więc na systemach typu Unix nadanie mu my.
praw wykonywania i uruchomienie spowoduje urucho- Pakiet może być w dowolnym formacie obsługiwanym
mienie interpretera Tclkit (oczywiście pod warunkiem przez interpreter Tcl, za pomocą którego uruchamiany
że plik wykonywalny tclkit znajduje się gdzieś na ścieżce jest TABS. Zalecanym formatem jest zip, ponieważ jest
systemowej) z danym skryptem. on czytany przez praktycznie wszystkie interpretery Tcl
Aby sprawdzić czy skrypt działa, wystarczy uruchomić – Tclkit, Cookit oraz ActiveTcl.
go z opcją -help: Projekt Cookit dostępny pod adresem http://
endorser.org/cookit oferuje dla głównych systemów ope-
$ tclkit tabs.tcl -help racyjnych wiele gotowych pakietów. Każdy z nich do-
stępny jest w wielu formatach – zip, mk4, cookfs oraz co-
Polecenie to powinno wypisać pomoc dotyczącą obsłu- okfs wykorzystujący kompresję bz2.
gi TABS jak i wszystkich dostępnych poleceń. W przy- Sami oczywiście również możemy budować pakiety
padku jakichkolwiek problemów, otrzymamy komuni- z naszymi aplikacjami wykorzystując polecenie wrap, opi-
kat o błędzie. sane w następnych sekcjach tego artykułu.

Tabela 1. Opcje polecenia copy


Opcja Domyślnia Opis
wartość
-copy Lista plików i katalogów do skopiowania; podana jako plik/katalog lub lista Tcl w postaci:
{ścieżka-źródłowa katalog-docelowy}
-output Katalog docelowy
-excludedirectories CVS .svn Lista nazw katalogów, które powinny być ignorowane podczas kopiowania
-excludefiles core Lista nazw plików do zignorowania
-packages Lista pakietów, które powinny zostać podmontowane i skopiowane do katalogu docelowego

www.sdjournal.org 35
PROGRAMOWANIE TCL

Polecenie copy Powyższe linijka wykona kilka operacji:


Jednym z podstawowych jest zadanie copy. Służy ono do
kopiowania plików lub katalogów do podanego katalo- • skopiuje pliki i katalogi z libraries do destdir/lib
gu docelowego. Polecenie to nie tworzy archiwów lub • skopiuje pliki i katalogi z clock.vfs do destdir
plików wykonywalnych, jest natomiast wykorzystywane • skopiuje zawartość pakietów tclx-8.4.cfspkg oraz sqli-
również w zadaniu wrap. te3-3.7.2.zippkg do katalogu destdir.
Tabela 1 pokazuje dostępne opcje tego polecenia.
Polecenie copy może służyć do operacji na plikach nie Polecenie wrap
związanych z językiem Tcl. Na przykład polecenie: Następne polecenie – wrap - służy do składania archi-
wum lub plików wykonywalnych. Wewnętrznie wyko-
$ tclkit tabs.tcl copy -output destdir -copy "cvs- rzystuje copy, przez co obsługuje identycznie opcje takie
head/*" jak -copy, -excludefiles oraz -excludedirectories.
Zmienia się natomiast zastosowanie opcji -output – po-
automatycznie pominie podczas kopiowania pliki przednio była to nazwa katalogu docelowego, w tym przy-
i katalogi związane z np. repozytorium CVS lub Sub- padku jest to nazwa docelowego archiwum lub pliku wy-
version. Możliwe też jest dodanie dodatkowych fil- konywalnego. Opcje -binary, -executionlevel, -fileinfo,
trów: -icons oraz -starkit definiują format pliku docelowego
oraz pozwalają dostosować pliki wykonywalne – głównie
$ tclkit tabs.tcl copy -output destdir -copy "cvs- w przypadku systemu operacyjnego Microsoft Windows.
head/*" \ Tabela 2 pokazuje dostępne opcje tego polecenia.
-excludefiles "*~ *.bak *.tmp" Najprostszy przykładem jest odpowiednik polecenia
wrap z SDX:
co spowoduje automatyczne omijanie plików tymczaso-
wych oraz kopii zapasowych. Oczywiście możemy do- $ tclkit tabs.tcl wrap -output clock.mk4 -driver mk4
stosować filtry do plików, które chcemy pominąć. -starkit 1 \
Polecenie potrafi również kopiować pliki z kilku miejsc -copy "clock.vfs/*"
do jednego katalogu docelowego:
Spowoduje to zbudowanie clock.kit jako mk4 ze stan-
$ tclkit tabs.tcl copy -output destdir -copy dardowym nagłówkiem pozwalającym na załadowanie
"{libraries/* lib} clock.vfs/*" \ tej aplikacji jako skrypt Tcl. Możemy również zbudo-
-packages "pkgs/tclx-8.4.cfspkg pkgs/sqlite3- wać archiwum w formacie ZIP – należy jedynie dodać
3.7.2.zippkg" -driver zip :

Tabela 2. Opcje polecenia wrap


Opcja Domyślna Opis
wartość
-binary Jeśli podany, plik docelowy będzie dołączony do tego pliku; wykorzystywane do tworze-
nia samodzielnych plików wykonywalnych
-driver Typ archiwum VFS, którym archiwum ma być przepakowane; jeśli nie podany, zostanie
użyty format z pliku -binary, jeśli ten argument został podany
-driveroptions Opcje do przekazania podczas podmontowywania archiwum
-executionlevel Dla aplikacji pod Microsoft Windows, zmienia zawartość requestedExecutionLevel
-fileinfo Pozwala na zmianę informacji o pliku wykonywalnym dla systemów Microsoft Windows,
opisany poniżej
-icons Pozwala na podanie 1 lub więcej plików z ikonami, które zastąpią
standardowe ikony Tclkit lub Cookit dla pliku wykonywalnego
-output Plik docelowy
-starkit false Czy archiwum ma mieć standardowy nagłówek Shebang
-copy Lista plików i katalogów do skopiowania; podana jako plik/katalog lub lista Tcl w postaci {}
-excludedirectories CVS .svn Lista nazw katalogów, które powinny być ignorowane podczas kopiowania
-excludefiles core Lista nazw plików, które powinny
-packages Lista pakietów, które powinny zostać podmontowane i skopiowane do katalogu docelo-
wego

36 7/2011
Tcl: wirtualne systemy plików

$ tclkit tabs.tcl wrap -output clock.zip -driver zip Podobnie jak SDX, TABS może również tworzyć pli-
-starkit 1 \ ki wykonywalne. Wystarczy w tym celu podać opcję -
-copy "clock.vfs/*" binary, która wskazuje plik wykonywalny, w oparciu
o który chcemy stworzyć docelową aplikację. Na przy-
Podobnie jak w przypadku polecenia copy, możemy po- kład:
dawać wiele katalogów lub plików źródłowych oraz pa-
kiety do osadzenia w docelowym archiwum: C:\>tclkit.exe tabs.tcl wrap -binary tclkit.exe -
output clock.exe \
$ tclkit tabs.tcl wrap -output clock.mk4 -driver mk4 -copy "clock.vfs/*"
-starkit 1 \
-copy "{libraries/* lib} clock.vfs/*" \ Powyższy przykład stworzy plik wykonywalny w opar-
-packages "pkgs/tclx-8.4.cfspkg pkgs/sqlite3- ciu o tclkit.exe oraz skrypty w katalogu clock.vfs. W po-
3.7.2.zippkg" dobny sposób możemy stworzyć pliki wykonywal-
ne pod inne platformy – oczywiście możemy budować
Operacje wykonane w tym przykładzie są analogiczne aplikacje dla dowolnych systemów operacyjnych z każ-
do operacji w przykładzie z polecenia copy, kopiując je- dego innego systemu – np. programy pod Windows
dynie pliki do archiwum zamiast katalogu docelowego. można budować pod Linuxem lub Mac OS X.
Opcje -driver oraz -driveroptions pozwalają konfi- TABS oferuje możliwość modyfikacji plików wykony-
gurować rodzaj VFS oraz dodatkowe opcje. Jeśli nie po- walnych specyficznych dla systemu Windows. Opcja -
damy opcji -driver, TABS wybierze go automatycznie icons pozwala na podanie 1 lub więcej plików z ikona-
jeśli podamy opcję -binary – np. dodając pliki do Tcl- mi, które zastąpią standardowe ikony Tclkit/Cookit. Na
kit będzie to mk4, do Cookit – cookfs. Jeśli nie poda- przykład:
my opcji -binary, trzeba podać format VFS, który ma
zostać użyty. C:\> tclkit.exe tabs.tcl wrap -binary tclkit.exe
Opcja -driveroptions podaje parametry przekazywa- -output clock.exe -copy (...) -
ne podczas otwierania VFS. Obecnie jedynie cookfs po- icons "icons16.ico icons32.ico
zwala na konfigurowanie parametrów w ten sposób – na icons48.ico icons64.ico"
przykład możemy wyłączyć kompresję plików:
Wszystkie pliki wykonywalne Tclkit/Cookit zawierają
$ tclkit tabs.tcl wrap -output clock.tcl -starkit 1 \ ikony, które są wymagane wewnątrz archiwum na koń-
-driver cookfs -driveroptions "-compression none" cu pliku. W celu sprawdzenia jakich ikon należy dostar-
-copy (...) czyć dla danego pliku, należy rozpakować dany plik wy-
konywalny (np. za pomocą polecenia unwrap ) i spraw-
Dokładne informacje o akceptowanych opcjach może- dzić rozdzielczości oraz ilości kolorów wszystkich ikon
my znaleźć w dokumentacjach do poszczególnych mo- w pliku tclkit.ico lub cookit.ico.
dułów VFS – dla cookfs jest to http://www.endorser.org/ Opcja -fileinfo pozwala na zamianę informacji o apli-
cookit/cookfs/manpage. kacji – dostępnych np. we właściwościach pliku pod sys-
temem Microsoft Windows. Informacje te podawane są
Tabela 3. Atrybuty możliwe do skonfigurowania jako listy Tcl, w postaci dwuelementowej listy nazwa-
za pomocą -fileinfo wartość. Na przykład:
Właściwość Przykładowa wartość
C:\>tclkit.exe tabs.tcl wrap -binary clock.exe -
FileDescription Sample Clock
output app.exe -copy (...) -
FileVersion 1.2-bld14
fileinfo "FileDescription {Sample
OriginalFilename clock.exe Clock} FileVersion 1.2-bld14"
InternalName SampleClock
LegalCopyright © 2011 Jan Kowalski S.C. Tabela 3 przedstawia wszystkie informacje, które moż-
LegalTrademarks © 2011 Jan Kowalski S.C. na podać w opcji -fileinfo.
CompanyName Jan Kowalski S.C. Pole ProductVersionBinary definiuje wersję i należy
podać je w formie A.B.C.D, gdzie A, B, C i D to liczby
ProductName Clock
całkowite pomiędzy 0 a 65535. Pozostałe pola są polami
ProductVersion 1.2-bld14
tekstowymi i przyjmują dowolną informację – włącznie
ProductVersionBinary 1.2.0.14 z wszystkimi znakami Unicode.
Comments Sample clock application for artic- Dla plików wykonywalnych Cookit (od wersji 1.2),
le purporse możliwe jest zdefiniowanie trybu wykonywania (requ-

www.sdjournal.org 37
PROGRAMOWANIE TCL

estedExecutionLevel) dla systemów Windows Vista, Polecenie repack


Windows 7 oraz Windows Server 2008. Pozwala to Ostatnie opisywane polecenie pozwala na ponowne zbu-
zdefiniować czy program powinien być wykonywany ja- dowanie istniejącego archiwum. Jest to przydatne w kil-
ko administrator jeśli tryb UAC jest włączony. W tym ku zastosowaniach – zmniejszyć rozmiar archiwum lub
celu należy podać opcję -executionlevel. Przyjmuje ona zmienić format archiwum.
następujące wartości: Aby przepakować archiwum bez żadnych zmian wy-
starczy uruchomić:
• asInvoker – plik nie wymaga praw administratora
• requireAdministrator – plik wymaga praw admini- C:\>tclkit.exe tabs.tcl repack -file myapp.exe
stratora
• highestAvailable – plik wymaga najwyższych dostęp- Spowoduje to przepakowanie pliku wykonywalnego za-
nych uprawnień chowując jego część binarną. Jest to głównie przydatne
gdy pliki wewnątrz archiwum zostały skasowane – w ta-
W przypadku większości zastosowań należy poda- kiej sytuacji często część archiwum z usuniętymi plikami
wać asInvoker lub requireAdministrator. Na przy- pozostaje nieużyta, ale zajmuje miejsce i zwiększa rozmiar.
kład: Wykonanie polecenia repack rozwiązuje ten problem.
Druga możliwość to zmiana formatu archiwum.
C:\>tclkit.exe tabs.tcl wrap -binary cookit.exe W prosty sposób możemy przepakować archiwum zip
-output admin.exe -copy (...) do mk4 wykonując:
-fileinfo (...) -executionlevel
requireAdministrator C:\>tclkit.exe tabs.tcl repack -file clock.zip -output
C:\>tclkit.exe tabs.tcl wrap -binary cookit.exe - clock.mk4 -driver mk4
output frontend.exe -copy (...)
-fileinfo (...) -executionlevel Podobnie możemy zmienić format pakietów:
asInvoker
C:\>tclkit.exe tabs.tcl repack -driver zip -file tclx-
Polecenie unwrap 8.4.cfspkg -output tclx-8.4.zippkg
Następne polecenie jest odwrotnością wrap – pozwa-
la skopiować pliki z archiwum do katalogu docelowego. Tabela 5 pokazuje dostępne opcje, domyślne wartości
Aby rozpakować aplikację clock.exe do katalogu clock.vfs oraz ich opis.
należy wykonać następujące polecenie:
Budowanie złożonych aplikacji
C:\>tclkit.exe tabs.tcl unwrap -file clock.exe -output TABS pozwala również na wykonywanie bardziej skom-
clock.vfs plikowanych operacji. Czasem potrzebujemy zbudować
kilka plików naraz, zbudować rzeczy w określonej kolej-
Dostępne opcje są wyszczególnione w Tabeli 4. ności lub uruchomić skrypt lub aplikację przed budowa-
Podobnie jak poprzednie polecenie, unwrap wykorzy- niem faktycznych plików wynikowych.
stuje wewnętrznie polecenie copy – co pozwala na po- TABS oferuje prosty w użyciu system celów – czyli
minięcie niektórych plików. Jeśli chcemy pominąc rozpa- rzeczy których chcemy wykonywać oraz zależności po-
kowywanie bibliotek, możemy wykonać: między nimi. Aby wykonać bardziej rozbudowane ope-
racje musimy jedynie stworzyć plik Tabsfile, zdefiniować
C:\>tclkit.exe tabs.tcl unwrap -file clock.exe -output w nim 1 lub więcej zadań i uruchomić TABS. Plik Tabsfi-
clock.vfs \ le jest skryptem Tcl. Cele definiuje się wołając polecenie
-excludefiles "*.so *.dylib *.dll" target. Na przykład:

Spowoduje to pominięcie bibliotek i rozpakowanie po- target clock.exe -body {


zostałych plików i katalogów. runjob wrap -binary tclkit.exe -output clock.exe \

Tabela 4. Opcje polecenia unwrap


Opcja Domyślna wartość Opis
-file Plik do rozpakowania
-output Katalog docelowy
-excludedirectories CVS .svn Lista nazw katalogów, które powinny być ignorowane podczas kopiowania
-excludefiles core Lista nazw plików, które powinny

38 7/2011
Tcl: wirtualne systemy plików

Tabela 5. Opcje polecenia repack


Opcja Domyślna wartość Opis
-file Plik binarny lub archiwum do spakowania ponownie
-output Plik docelowy; jeśli nie podany, plik z -file zostanie nadpisany
-driver Typ archiwum VFS, którym archiwum ma być przepakowane; jeśli nie podany, zosta-
nie użyty format z pliku -file
-driveroptions Opcje do przekazania podczas podmontowywania archiwum
-excludedirectories CVS .svn Lista nazw katalogów, które powinny być ignorowane podczas kopiowania
-excludefiles core Lista nazw plików, które powinny

-copy "clock.vfs/*" jest odpowiednikiem wcześniejszego przykładu użycia


} polecenia wrap.
Nasz plik Tabsfile może zawierać więcej niż jeden cel:
Powyższy przykład jest kompletnym plikiem Tabsfile.
Aby zbudować clock.exe musimy jedynie uruchomić: target clock.exe -body {
runjob wrap -binary tclkit.exe -output clock.exe \
C:\>tclkit.exe tabs.tcl make clock.exe -copy "clock.vfs/*"
}
Wywołując polecenie make należy podać jeden lub target clock.tcl -body {
więcej celów do zbudowania. runjob wrap -output clock.tcl -driver mk4 -starkit
Poleceniu target podajemy nazwę celu jako pierwszy 1 \
argument. Pozostałe argumenty są w postaci par nazwa- -copy "clock.vfs/*"
wartość. Warto wspomnieć, że nazwa celu nie musi być }
równoznaczna z nazwą pliku, który dany cel buduje. Na-
tomiast dla wygody warto trzymać się konwencji, że ce- Możemy teraz zbudować oba pliki naraz wykonując:
le, które budują aplikację lub archiwum, otrzymują taką
nazwę, jak nazwa pliku docelowego. C:\>tclkit.exe tabs.tcl make clock.exe clock.tcl
Opcja -body to skrypt Tcl, który należy wykonać aby
zbudować dany cel. Zazwyczaj będzie to jedno lub wię- Kolejną opcją, którą możemy podać do definicji celu
cej wywołań polecenia runjob – które wewnętrznie jest -depends. Jest to lista celów, które muszą zostać
wykonuje poszczególne polecenia. Powyższy przykład wykonane przed wykonaniem tego celu.

Listing 1.

target tclkit-common.exe -body {


runjob wrap -binary tclkit.exe -output tclkit-common.exe \
-packages {pkgs/win32/sqlite3-3.7.2.cfspkg} \
-copy "common.vfs/*" \
-checkuptodate 1
}
target server.exe -depends {tclkit-common.exe} -body {
runjob wrap -binary tclkit-common.exe -output server.exe \
-fileinfo (...) -icons (...) \
-copy "server.vfs/*" \
-checkuptodate 1
}
target client.exe -depends {tclkit-common.exe} -body {
runjob wrap -binary tclkit-common.exe -output client.exe \
-fileinfo (...) -icons (...) \
-copy "client.vfs/*" \
-checkuptodate 1
}

www.sdjournal.org 39
PROGRAMOWANIE TCL

Tabela 6. Opcje zarządzania zadaniami


Opcja Domyślna wartość Opis
-fail true Czy błąd podczas wykonywania tej operacji ma generować błąd i przerwać budo-
wę pozostałych zadań?
-checkuptodate false Czy zadanie ma zostać wykonywane jedynie jeśli pliki źródłowe uległy zmianie?

Typowym przykładem jest budowanie aplikacji, która runjob wrap -fail 0 -driver zip -output clock-
składa się z wielu komponentów. Na przykład jeśli chce- zip.tcl (...)
my budować aplikację klient-serwer, możemy osadzać runjob wrap -fail 0 -driver mk4 -output clock-
kod wspólny dla obu celów oraz specyficzny dla każde- mk4.tcl (...)
go z nich. }
Możemy wtedy budować wspólny plik początkowy
oraz poszczególne wersje końcowe (Listing 1). Powyższy przykład buduje aplikację dla wszystkich
Powyższy przykład wykorzystuje również flagę - obsługiwanych typów archiwum. W przypadku, gdy
checkuptodate, omówioną dokładniej później w tej część z nich nie jest dostępna, błąd zostanie zignoro-
sekcji. Pozwala ona uniknąć budowania plików po- wany.
nownie jeśli żaden z plików źródłowych nie zmienił Opcja -checkuptodate sprawia, że zadanie wykona się
się. jedynie jeśli jeden z plików źródłowych jest starszy niż
Metoda ta znacznie przyspiesza budowanie aplika- plik docelowy. Wróćmy na chwilę do pierwszego przy-
cji, zwłaszcza jeśli pliki wspólne i ewentualne biblioteki kładu:
są dużych rozmiarów – plik pośredni tclkit-common.exe
pozwala uniknąć kompresowania pakietów oraz plików target clock.exe -body {
z common.vfs przy każdym budowaniu projektu. runjob wrap -binary tclkit.exe -output clock.exe \
Możliwe jest również definiowanie celów wirtualnych -checkuptodate 1 -copy "clock.vfs/*"
– posiadających jedynie zależności, nie wykonujących sa- }
memu żadnych operacji. Na przykład:
Spowoduje to, że plik clock.exe zostanie zbudowany od
target all -depends {clock.tcl clock.exe} nowa jedynie w sytuacji, gdy jeden z plików w katalo-
gu clock.vfs zmieni się od ostatniego budowania aplika-
Powyższy przykład definiuje cel all, który spowodu- cji. Zmiany w plikach w podkatalogach – jak np. zmia-
je zbudowanie clock.tcl oraz clock.exe. Wtedy wystar- na w clock.vfs/lib/clock/clock.tcl – również powodują po-
czy uruchomić: nowne zbudowanie aplikacji.

C:\>tclkit.exe tabs.tcl make all

TABS oferuje również kilka dodatkowych opcji,


które pozwalają zarządzać zadaniami -fail oraz PIOTR BEŁTOWSKI, WOJCIECH KOCJAN
-checkuptodate (Tabela 6). Autorzy książki „Tcl 8.5 Network Programming”
Opcja -fail pozwala na zdefiniowanie czy błąd przy Piotr Bełtowski – od 5 lat pracuje dla IBM,
wykonywaniu danego polecenia powoduje przerwanie wcześniejsze doświadczenie obejmuje m.in.
całego procesu budowania. Ericsson España i Ericpol. Współautor kilku pa-
tentów i publikacji.
target clock-all -body { Wojciech Kocjan jest programistą z ponad 10
runjob wrap -fail 0 -driver cookfs -output clock- letnim doświadczeniem z językiem Tcl. Praco-
cfs.tcl (...) wał m.in. dla firm IBM, Motorola, obecnie
współpracuje z firmą BitRock. Jego aktyw-
ność open source dotyczy m.in. tworzenia
narzędzi cookfs, Cookit, Tabs oraz współpra-
Linki cy przy pierwszej wersji Tclkit na system Micro-
• http://endorser.org/tabs soft Windows budowanej za pomocą narzędzi
• http://endorser.org/cookit MinGW.
• http://equi4.com/tclkit oraz Kontakt z autorami:
http://code.google.com/p/tclkit piotr.beltowski@gmail.com,
• http://equi4.com/starkit wojciech@kocjan.org

40 7/2011
E-COMMERCE

Wiem czego chcesz


Systemy rekomendacji produktów
Współcześnie trudno jest znaleźć w sieci, film, książkę, piosenkę
– produkt, który będzie się nam podobał. W artykule opiszę dwa
algorytmy stosowane najczęściej w serwisach internetowych, takich
jak np. Amazon.com lub YouTube.com, do polecania produktów.
Systemy rekomendacji pozwalają użytkownikowi znaleźć szybciej
interesujący go produkt, a właścicielom serwisów osiągać większe zyski.

Dowiesz się: Powinieneś wiedzieć:


• Co to jest system rekomendacji produktów? • Podstawy programowania w dowolnym języku.
• Jak działa system do polecania produktów?
• Jak zaimplementować system polecania produktów na
podstawie podobieństwa pomiędzy użytkownikami lub
produktami? mi w systemie np. wagi użytkownika opisują jego prefe-
rencje do określonych gatunków filmów natomiast wa-
gi filmu opisują przynależność do rodzaju filmu. Do me-
tod tych należą między innymi metody wykorzystujące

W
dzisiejszych czasach internetowe serwisy sieci neuronowe, rozkład na wartości osobliwe (SVD)
oferują nam ogromne ilości różnych pro- lub różne techniki klasteryzacji. Drugie podejście wyko-
duktów. Znalezienie ciekawej książki, fajne- rzystywane w SR to metody pamięciowe (ang. memory
go filmu lub piosenki, która się nam spodoba może oka- based). Metody te przy predykcji polecanego produktu
zać się niełatwym zadaniem, na które trzeba będzie po- używają całej historycznej informacji zapisanej w syste-
święcić sporo czasu. Wiele serwisów internetowych mie. Trzecia grupa metod, to metody hybrydowe które
takich jak np. Amazon.com czy YouTube.com oferu- wykorzystują połączenie metod z modelem i metod pa-
je swoim użytkownikom listy polecanych produktów. mięciowych. W artykule przedstawię dwa algorytmy na-
W artykule tym opiszę dwa najpopularniejsze i najła- leżące do grupy drugiej. Oba algorytmy jako wynik dzia-
twiejsze algorytmy stosowane w systemach rekomen- łania zwracają listę N produktów, które będą intereso-
dacji produktów. Ich implementacja oraz używanie po- wać najbardziej użytkownika – takie algorytmy nazywają
zwoli zadowolić użytkowników, którym będą podsuwa- się ang. top-N recommendation.
ne ciekawe produkty oraz właścicieli, którzy będą osią-
gać większe zyski. Reprezentacja danych
W systemie przechowywane są dane opisujące prefe-
Systemy rekomendacji rencje użytkowników do produktów. Zakładamy, że
Systemy rekomendacji (SR), nazywane też ang. collabora-
tive filtering (CF), bazując na zebranych danych historycz-
Tablica 1. Przykładowa macierz R z oddanymi
nych potrafią zasugerować z dużym prawdopodobień-
głosami – wiersze opisują użytkowników,
stwem jakie produkty mogą podobać się zalogowane-
a kolumny oznaczją produkty w systemie.
mu użytkownikowi (ang. active user). Bazują one na ob- Wartości w macierzy to oddane głosy.
serwacji, iż użytkownicy którzy kupili podobne produkty
mają zbliżone gusta, co za tym idzie w przyszłości będą P1 P2 P3 P4 P5
dokonywać podobnych zakupów. Algorytmy stosowane U1 - 3 7 8 8
w systemach rekomendacji można podzielić na trzy gru- U2 2 3 - 7 9
py. Pierwsza z nich, to metody modelowe (ang. model ba- U3 8 9 3 5 2
sed), które opierają się na budowaniu modeli użytkow-
U4 9 - - 3 3
nika i produktu w postaci wektora wag. Wagi te opisu-
ją wzajemne zależności pomiędzy bytami występujący- U5 1 4 9 7 ?

42 7/2011
Wiem czego chcesz – systemy rekomendacji produktów

użytkownik może wyrazić swoją opinię o produkcie gło- Natomiast odległość wykorzystująca korelację Pearso-
sując na niego. Załóżmy również, iż głosy są liczbami na- na podana jest poniżej:
turalnymi z zakresu [0, 10], gdzie 0 oznacza “nienawidzę
tego produktu”, a 10 - “uwielbiam ten produkt”. Odda-
ne głosy możemy przedstawić jako macierz R - (tablicę
dwuwymiarową). Wiersze macierzy będą opisywać nu-
mer użytkownika, a kolumny będą przedstawić numer
produktu. Wartość w macierzy będzie określać odda-
ny głos. Przyjmijmy również, że macierz ma M wierszy
(liczba użytkowników), oraz L kolumn (liczba produk- [2]
tów). Oznaczmy użytkowników indeksami p, q nato- Odległość Pearsona jest trochę bardziej skompli-
miast produkty jako i, j. Zmienna Rpi przedstawiać będzie kowana od odległości cosinusowej, i do jej oblicze-
notę wystawioną produktowi numer i przez użytkowni- nia potrzebna jest znajomość średniej głosów od-
ka o indeksie p. W tablicy nr 1 przedstawiono przykła- danej przez użytkownika o indeksie p – rp i średniej
dową macierz oddanych głosów. Dla przykładu, z tabli- głosów użytkownika q - rq. To, którą definicję me-
cy nr 1 widzimy, że R11='-' co znaczy, że użytkownik U1 tryki podobieństwa wybrać najlepiej sprawdzić em-
nie głosował na produkt P1 i np. że R34=5 co znaczy że pirycznie. Wiedząc, jak obliczyć podobieństwo po-
użytkownik U3 zagłosował na produkt P4, wystawiając mu między użytkownikami, szukamy K najbliższych użyt-
notę o wyskości 5. Natomiast R55='?' znaczy, że chcemy kowników do aktywnego użytkownika Ua (zalogowa-
wyznaczyć przewidywaną notę jaką odda użytkownik U5 nego). Zbiór K najbliższych użytkowników oznaczmy
na produkt P5. jako K(Ua). Następnie dla każdego produktu, na który
Warto zwrócić uwagę, że użytkownik nie musi zagło- nie zagłosował użytkownik Ua, przewidujemy ocenę na
sować na każdy produkt w systemie. W rzeczywistych podstawie równania:
systemach rekomendacji macierz R jest w około 99%
pusta. Trafność proponowanych produktów w dużej
mierze zależy od tego, na ile produktów użytkownik za-
głosował. Im więcej użytkownik oddał głosów, tym traf-
niejsze okażą się zaproponowane później produkty.
W artykule opiszę dwa podejścia w wyznaczaniu prze-
widywanej liczby głosów. Pierwsze podejście bazuje na
podobieństwie pomiędzy użytkownikami (ang. user ba- [3]
sed). Polega ono na znalezieniu w systemie użytkowni- Gdzie rj oznacza średnią ocenę jaką dostał produkt
ków, którzy podobnie głosowali w przeszłości. Opiera j. Wzór [3] można interpretować jako średnią wa-
się na obserwacji, iż skoro użytkownicy głosowali po- żoną głosów oddanych przez K sąsiadów. Następnym
dobnie w przeszłości to ich głosy w przyszłości powin- krokiem w algorytmie jest wybranie N produktów,
ny również być podobne. Drugie podejście, opiera się które dostały najwyższe noty. Wskazanych N pro-
na wyszukaniu podobnych do siebie produktów (ang. duktów jest wynikiem działania algorytmu. Wartość
item based). I tak, jak w pierwszym podejściu, zakłada, K najbliższych sąsiadów potrzebna w tym algorytmie
że produkty które były oceniane podobnie w przeszłości wyznaczana jest eksperymentalnie. Sprawdzając róż-
otrzymają przybliżone noty w przyszłości. ne wartości K wybieramy taką, dla której wartość błę-
du predykcji na zbiorze testowym będzie najmniej-
Algorytm bazujący na podobieństwie sza. Typowe wartości dla K zawierają się w przedzia-
użytkowników le [30, 50].
Do oceny podobieństwa pomiędzy dwoma użytkow- Podsumowując kroki algorytmu, można zapisać nastę-
nikami potrzebna jest metryka odległości między nimi. pująco:
Dwa najczęściej stosowane to odległość cosinusowa
i korelacja Pearsona. Odległość cosinusowa zdefiniowa- 1. Wyznacz odległość między aktywnym użytkowni-
na jest następująco: kiem, a wszystkimi użytkownikami w systemie.
2. Wybierz K użytkowników najbliższych do aktywne-
go użytkownika.
3. Korzystając ze zbioru K najbliższych użytkowników
wyznacz przewidywaną ocenę produktów na które
nie zagłosował aktywny użytkownik.
4. Wybierz N produktów z najwyższymi przewidywa-
[1] nymi ocenami.

www.sdjournal.org 43
E-COMMERCE

Algorytm bazujący
na podobieństwie produktów
Algorytm bazujący na podobieństwie produktów jest
bardzo podobny do wcześniejszego algorytmu, z tą róż-
nicą, że szukane są najbardziej pdobne produkty. Odle-
głość cosinusowa w tym podejściu zdefiniowana jest na-
stępująco:

[4]
Natomiast odległość wykorzystująca korelację Pearso- • problem nowego użytkownika lub produktu (ang.
na podana jest poniżej: cold star problem) – wprowadzając do systemu nowy
byt, nie mamy żadnej informacji o jego głosach;
• problem czarnej owcy (ang. black sheep problem)
– użytkownik oddaje specjalnie głosy inaczej niż
większość ludzi;
• problem sprawiedliwego oceniania – wiele użytkow-
ników ma tendencje do dawania tylko minimalnej
lub maksymalnej oceny.

[5] Mając zaimplementowany jako bazowy algorytm top-N


Zbiór K najbliższych produktów do produktu Pa recommendation możemy dodawać różne modyfikacje
oznaczmy jako K(Pa). Przewidywana ocena produktu ob- do naszego systemu by móc radzić sobie z tymi proble-
liczna jest na podstawie wzoru [6]. mami.

Podsumowanie
W artykule zostały przedstawione dwa podejścia wy-
korzystujące algorytm najbliższych sąsiadów do reko-
mendacji N produktów. Opisane metody są intuicyjne,
stosunkowo proste w implementacji i dają dobre wyni-
ki. Stosowanie systemów rekomendacji pozwala dostać
[6] dwie pieczenie na jednym ogniu – zadowolony użytkow-
Podobnie jak poprzednio po wyznaczeniu przewidy- nik, ponieważ podsuwane mu są ciekawe produkty tra-
wanych ocen dla produktów na które nie zagłosował za- fiające w jego gust oraz zadowolony właściciel serwisu,
logowany użytkownik wybierana jest lista N produktów gdyż potencjalnie wzrasta sprzedaż oferowanych przez
o największych estymowanych ocenach. niego produktów.

Problemy w systemch
rekomendacji
W rzeczywistych systemach rekomendacji często moż-
na spotkać się z następującymi problemami:
PIOTR PŁOŃSKI
• duża liczba użytkowników i produktów, przez co do Doktorant na Politechnice Warszawskiej, Wy-
działu Elektroniki i Technik Informacyjnych.
przechowywania ich potrzebna jest duża pojemność
Autor interesuje się sztuczną inteligencją,
pamięci RAM;
metodami analizy danych i bioinformaty-
• użytkownicy głosują tylko na małą część wszystkich ką. Ulubionym językiem programowania jest
produktów (ang. sparsity problem), a jakość przewi- C++.
dywanej oceny zależy od liczby oddanych głosów Kontakt: pplonski86@gmail.com
w systemie;

44 7/2011
�����
���������������������������
����������
�����������������������������������������������������
�������������������������������������������������
�������������������������������������������
������������������������������������������������

���������������� ����������������������������������������������
������������������������������������������ ����������������������������������������������
������������������������������������ ����������������������������
����������������������������������������������� �����������������������
������������������ ���������������������������������������
����������������� ���������������������������������������
������������������������������������������ ���������������������������������������
������������������������������������������������������� ������������������������������������������
�������������������������������������������������� ���������������������������������������
��������������������� ������������������������������������
���������������������������������������������� ���������������������������������������
�������������������������������������������������� �����������������������
����������������������������������������� ���������������������������������������������
��������������������� ������������������������������������������������
������������������������������������� �������������������������������������������������
�������������������������������������������
��������������������������������������������
���������������������
���������������������������������������������
������������������������������������ ���������������������������������������
�������������������������������������������� ������������������������������������������
�������������������������������������� ���������������������������������������
���������������������������������������� ������������������������������������������
����������������������������������������������� �������������������������������
��������� ����������������������
���������������������
���������������������������������������� ��������������������������������������
����������������������������������������������� �������������������������������������
��������� ������������������������
������������������������������� �������������������
�������������������������������� ����������������������������������
�������������������������������������������������� �����������
���������������������������������������������������� ��������������
�������������� �������������������������������������
����������������������� �����������������������������������������������������
INŻYNIERIA OPROGRAMOWANIA

Naturalny porządek refaktoryzacji


Jak pragmatycznie refaktoryzować?
Są tacy, którzy wiedzą, że trzeba refaktoryzować. Są tacy, którzy
nie wiedzą, że trzeba refaktoryzować. Są tacy, którzy uważają, że
refaktoryzowanie nie ma sensu, że się nie opłaca. Wszystkie te osoby
mają coś wspólnego, w praktyce prawie nikt tego nie robi. Głównie
dlatego, że to kosztuje. Czy na pewno?

Dowiesz się: Powinieneś wiedzieć:


• Kiedy brak refaktoryzacji się nie opłaca; • Czym jest refaktoryzacja;
• Jak pragmatycznie podejść do refaktoryzacji; • Znać podstawowe techniki refaktoryzacji oraz wzorce
• Jak refaktoryzować w zależności od głębokości zmian. projektowe.

Zawód – szambonurek... metr. Jedyną możliwością przetrwania w tym środowi-


Wyobraź sobie, że wprowadzasz się do nowego miesz- sku jest posiadanie specjalnego kombinezonu... szambo-
kania. Jednak postanowiłeś, że nie będziesz sprzątać. Za- nurka.
oszczędzisz trochę czasu. Będziesz mógł go wykorzystać I teraz sobie wyobraź tę całą górę śmieci w ca-
bardziej efektywnie. łym mieszkaniu i wyobraź sobie, że jesteś w sypialni
Czasami papierki, plastikowe butelki, puszki lądują na i chcesz przejść do kuchni, żeby zrobić sobie herba-
podłodze. Czasami ktoś z domowników zostawi skór- tę. Pomyśl, jak duży to wysiłek, żeby wykonać tak pro-
kę od banana albo ogryzek. Na początku nie stanowi stą czynność.
to większego problemu. Wystarczy patrzeć pod nogi. Jeśli jeszcze nie znajdujesz analogii między powyższą
Z czasem jednak śmieci jest coraz więcej, więc zaczy- sytuacją, a kosztem kiepskiego kodu, zrób sobie prze-
nasz przerzucać je w jedno miejsce. Tam starasz się nie rwę i przeczytaj ten tekst od początku.
zaglądać. Nawet boisz się zaglądać, bo nigdy nie wiado-
mo, co tam można znaleźć. Z czasem śmietnik zaczyna Ile to kosztuje?
„żyć” i choć na początku jest to obrzydliwe, zaczynasz Dużo. Posiadanie kiepskiego kodu kosztuje bardzo du-
się i do tego przyzwyczaić. żo. Nie podamy liczb, bo są one zależne od konkretne-
Przychodzi taki moment, że warstwa ma już kilkadzie- go projektu. Niech powyższa metafora będzie przybliże-
siąt centymetrów, po kolejnych tygodniach już ponad niem tego stanu.

Dług techniczny
Dług techniczny jest metaforą opracowaną przez Warda Cunninghama
Metafora ta oparta jest na idei długu finansowego, który jest korzystny jedynie w krótkim okresie czasu:

• zaciągając pożyczkę otrzymujemy w szybki sposób dodatkowe środki finansowe;


• do momentu, do którego nie spłacimy pożyczki w całości naliczane są odsetki;
• szybsza spłata gwarantuje mniejsze straty.

Dług finansowy znajduje swoje odzwierciedlenie w przypadku pisania kodu:

• pisanie kodu „na sztywno” pozwala na szybką realizację konkretnej funkcjonalności;


• do momentu, do którego nie poprawimy w całości elastyczności dotychczasowego kodu, pojawiają się
kolejne elementy wymagające przekształcenia.

46 7/2011
Naturalny porządek refaktoryzacji

Rysunek 1. Całościowa strategia procesu


refaktoryzacji

www.sdjournal.org 47
INŻYNIERIA OPROGRAMOWANIA

Listing 1a. Pierwsza prosta, dość rozbudowana implementacja.

public class TextManager


{
private TextManagerHelper _hlp = null;
// ...
public TextManager(TextManagerHelper _helper)
{
this._hlp = _helper;
}

private Random rnd = new Random();

public string Convert(string text)


{
String result = "";
List<TextPart> prts = _hlp.Convert(text);

for (int i = 0; i < prts.Count; i++)


{
if (prts[i].Type.Equals(TextPartType.WORD) && rnd.NextDouble() < 0.2)
{
if (i + 2 < prts.Count)
{
TextPart t = prts[i];
prts[i] = prts[i + 2];
prts[i + 2] = t;
}
}
}

for(int i1 = 0; i1 < prts.Count; i1++)


{
if (rnd.NextDouble() < 0.2)
{
prts.Insert(i1, new TextPart(" ", TextPartType.NONWORD)); i1++;
String[] wds = new String[] { "i", "a", "aczkolwiek", "poniekąd" };
int ind = rnd.Next(wds.Length);
prts.Insert(i1, new TextPart(wds[ind], TextPartType.WORD)); i1++;
prts.Insert(i1, new TextPart(" ", TextPartType.NONWORD));
}
}

String result2 = "";

foreach (TextPart part in prts)


{
result2 += part.Contents;
}

result = result2;
result = Regex.Replace(result, @"[\?!-\.,:;'\(\)]", "", RegexOptions.CultureInvariant);

String result1 = "";

for ( int i2 = 0; i2 < result.Split(' ').Length - 1; i2++)


{
if (rnd.NextDouble() < 0.5)
{

48 7/2011
Naturalny porządek refaktoryzacji

Listing 1b. Pierwsza prosta, dość rozbudowana implementacja.

char[] chs = new char[] { '.', ',', '!' };


intj = rnd.Next(chs.Length);
result1 += result.Split(' ')[i2] + chs[j];
}
else
{
result1 += result.Split(' ')[i2] + " ";
}
}
result1 += result.Split(' ')[result.Split(' ').Length - 1];
result = result1;

result = result
.Replace("ą", "a")
.Replace("ł", "l")
.Replace("ę", "e")
.Replace("ń", "n")
.Replace("ż", "z")
.Replace("ź", "z")
.Replace("ó", "o")
.Replace("ś", "s")
.Replace("ć", "c")
.Replace("Ą", "A")
.Replace("Ł", "L")
.Replace("Ę", "E")
.Replace("Ń", "N")
.Replace("Ż", "Z")
.Replace("Ź", "Z")
.Replace("Ó", "O")
.Replace("Ś", "S");

String result3 = "";


char[] tArray = result.ToCharArray();

foreach (char ch in tArray) {


if (rnd.NextDouble() < 0.3)
{
char? newCh = null;
if (Char.IsLower(ch))
{
newCh = Char.ToUpper(ch);
} else
{
newCh = Char.ToLower(ch);
}

result3 += newCh;
}
else
{
result3 += ch;
}
}
result = result3.Replace(" ", "");
return result;
}
}

www.sdjournal.org 49
INŻYNIERIA OPROGRAMOWANIA

Strategia refaktoryzacji
Jednak najczęściej nie wystarczy po prostu refaktory- Prywatne metody
Jeśli w klasie są znaczące prywatne metody, które
zać, bo łatwo wpaść w szał refaktoryzacji, który pole- mają długość więcej niż kilka wierszy, to prawdo-
ga na refaktoryzowaniu wszystkiego i za wszelką cenę. podobnie metoda ta powinna znaleźć się w innej
Przedstawimy poniżej strategię refaktoryzacji, która klasie – już istniejącej lub nowej.
w sposób systemowy pozwala podejść do tego często
niewdzięcznego zadania, jednocześnie przyczyniając
się do ewolucyjnego rozwoju projektu i architektury.
Podpowiada też, jak się zabrać za kod odziedziczony ność klasy. Przesuń metody, które realizują inne
i zacząć go refaktoryzować. Oto magiczne punkty: odpowiedzialności do bardziej odpowiednich dla
nich klas.
1. Zacznij od prostego rozwiązania, zgodnie zasadą 4. Z czasem zaczynasz dostrzegać, że w Twoich roz-
Keep it simple stupid. Nie myśl zbyt dużo o wzor- wiązaniach potrzeba elastyczności – zacznij wpro-
cach, o wprowadzaniu wszelkiej możliwej ela- wadzać wzorce projektowe, tam gdzie potrzeba.
styczności. 5. Raz na jakiś czas (raz na kilka miesięcy przy więk-
2. Z dużych metod zaczynaj wyodrębniać mniej- szych projektach), analizuj to, co dzieje się z Two-
sze składowe metody (refaktoryzacja Extract Me- im projektem. Architektura wymaga regularnego
thod). Dąż do realizacji wzorca Compose Method odświeżania i wprowadzania zmian, aby przysta-
– niech Twoja główna metoda składa się z serii wała do pojawiających się wymagań.
wywołań mniejszych metod.
3. Kiedy Twoje klasy będą składały się z dużej ilości Przyjrzymy się kolejnym krokom procesu na przykła-
małych metod, zacznij analizować odpowiedzial- dzie fragmentu kodu (Rysunek 1).

Keep it simple stupid


Pewnie niejednokrotnie słyszałeś, żeby tworzyć pro-
ste rozwiązania, ale nikt nie potrafił Ci powiedzieć, co
to znaczy. Najzwyczajniej w świecie zacznij od kodu,
który pierwszy przychodzi Ci do głowy. Nie sil się na
wzorce projektowe czy znamiona „być przygotowa-
nym na każdą ewentualność”. Stwórz zwykłe rozwią-
zanie, nawet w starym proceduralnym stylu. Jeśli bę-
dziesz tworzył je małymi krokami, to nie powinieneś
napotkać zbyt dużych problemów.
Innym punktem procesu wyjścia często jest kod
odziedziczony, który jest dość kiepski. Takim przykła-
dem się zajmiemy.
Załóżmy, że mamy napisaną klasę udostępniającą
metodą służącą do zaciemniania tekstu, będącego pa-
rametrem metody. Przykładowy kod znajdziesz na Li-
stingu 1.

Compose Method
Analiza metod takich jak przedstawiona na Listingu
1 najczęściej prowadzi nas do zrozumienia, jakie są
główne punkty algorytmu zawartego w metodzie. I to
jest właśnie kolejny krok – postaraj się podzielić dużą
metodę na mniejsze kroki wyodrębniając je do osob-
nym metod (refaktoryzacja Extract Method). Tym sa-
mym pierwotna metoda będzie się składać z sekwen-
cji wywołań metod składowych. Przy odpowiedniej
konwencji nazewniczej uzyskamy kod, który czyta się
jak książkę.
Przy okazji warto co nieco posprzątać – głównie
Rysunek 2. TextObfuscator po zastosowaniu wprowadzić zmiany w mało intuicyjnych nazwach.
Compose Method. Przykład znajdziesz na Listingu 2.

50 7/2011
Naturalny porządek refaktoryzacji

Wydzielanie klas W naszym przykładzie metody głównie skupia-


W następnym kroku przyglądamy się odpowiedzial- ją wokół pojedynczych operacji mających na ce-
nościom poszczególnych klas oraz metodom, pod ką- lu zaciemnianie tekstu oraz zapewniającym wykona-
tem dopasowania do odpowiedzialności klasy. Najle- nie operacji z pewnym prawdopobieństwem. Może-
piej przeanalizuj wszystkie metody oraz pogrupuj je pod my wyodrębnić odpowiadające tym operacjom klasy
kątem wykonywania podobnych operacji. Szukamy dla TextObfuscatorMethods oraz Probability. Kod po tej
nich miejsca w innych klasach lub w nowej klasie. Pamię- zmianie mógłby wyglądać tak jak na Listingu 3.
taj: jeśli w danej klasie istnieje znacząca metoda prywat-
na (dłuższa niż 3-4 wiersze), to metoda ta powinna zna- Refaktoryzacja do wzorców
leźć się w innej klasie. Stosując dotychczasowe kroki zaczynamy mieć coraz

Listing 2. Refaktoryzacja do Compose Method.

public class TextObfuscator .Replace("ż", "z")


{ .Replace("ź", "z")
// ... .Replace("ó", "o")
public string Obfuscate(string text) .Replace("ś", "s")
{ .Replace("ć", "c")
String result = ChangeWordsOrderRandomly(t .Replace("Ą", "A")
ext); .Replace("Ł", "L")
result = AddMeaninglessWordsRandomly(resu .Replace("Ę", "E")
lt); .Replace("Ń", "N")
result = RemoveSeparators(result); .Replace("Ż", "Z")
result = AddSeparatorsRandomly(result); .Replace("Ź", "Z")
result = ReplacePolishCharactersWithNonPoli .Replace("Ó", "O")
shCharacters(result); .Replace("Ś", "S");
result = ReplaceUpperAndLowerCharactersRand }
omly(result);
result = RemoveSpaces(result); public String ReplaceUpperAndLowerCharactersRand
return result; omly(String text)
} {
public String RemoveSpaces(String text) String result = "";
{ char[] textArray = text.ToCharArray();
return text.Replace(" ", "");
} foreach (char currentCharacter in textArray)
{
public String RemoveSeparators(String text) if (ShouldBeUpperAndLowerReplaced())
{ {
return Regex.Replace(text, SEPARATORS_REGEX, result += ReplaceLowerAndUpper(curr
"", RegexOptions.CultureInvaria entCharacter);
nt); }
} else
{
result += currentCharacter;
public String ReplacePolishCharactersWithNonPoli }
shCharacters(String text) }
{
return text return result;
.Replace("ą", "a") }
.Replace("ł", "l") // ...
.Replace("ę", "e") }
.Replace("ń", "n")

www.sdjournal.org 51
INŻYNIERIA OPROGRAMOWANIA

Listing 3a. Wydzielone klasy na bazie zasady analizy odpowiedzialności.


public class TextObfuscator
{
// ...
public string Obfuscate(string text)
{
List<TextPart> parts = methods.ParseTextForWordsAndNonWords(text);
methods.ChangeWordsOrderRandomly(parts);
methods.AddMeaninglessWordsRandomly(parts);
methods.RemoveSeparators(parts);
methods.AddSeparatorsRandomly(parts);
methods.RemoveSpaces(parts);
// ...
}
}

public class TextObfuscatorMethods


{
// ...
public virtual void RemoveSpaces(List<TextPart> parts)
{
for (int i = 0; i < parts.Count; i++)
{
RemoveSpacesFromTextPart(parts, i);
RemoveTextPartIfEmpty(parts, i);
}
}

private static void RemoveSpacesFromTextPart(List<TextPart> parts, int i)


{
parts[i] = parts[i].ReplaceContents(" ", "");
}

public virtual void RemoveSeparators(List<TextPart> parts)


{
for(int i = 0; i < parts.Count; i++)
{
RemoveSeparatorsFromTextPart(parts, i);
RemoveTextPartIfEmpty(parts, i);
}
}

public virtual void AddSeparatorsRandomly(List<TextPart> parts)


{
for (int i = 0; i < parts.Count; i++)
{
if (ShouldAddSeparator())
{
parts.Insert(i, TextPart.NewSeparator(DrawSeparator())); i++;
}
}
}

52 7/2011
Naturalny porządek refaktoryzacji

Listing 3b. Wydzielone klasy na bazie zasady analizy odpowiedzialności.


private bool ShouldAddSeparator()
{
return probability.ShouldBeDone(ADDING_SEPARATOR_PROBABILITY);
}
// ...
}

public class Probability


{
private Random random = new Random();

public bool ShouldBeDone(double probability)


{
if (probability < 0.0 || probability > 1.0)
{
throw new ProbabilityException("Probability should be in range [0.0, 0.1]");
}

return random.NextDouble() < probability;


}
}

bardziej kształtne rozwiązanie, jednak głównie to co Wersja z Budowniczym wyglądałaby jak na Listin-
otrzymujemy to metody pogrupowane w klasy. Nad- gu 4.
szedł czas na zastosowanie zasad obiektowych (np.
zebranych w SOLID). Analizujemy kod pod kątem po- Ewolucja architektury
wtarzalności, potrzeby elastyczności, zapachów ko- Dalszym krokiem, na dużo wyższym poziomie abs-
du i wprowadzamy wzorce projektowe. Często tam trakcji i wymagającym dogłębnego zrozumienia sys-
gdzie mamy wiele metod o zbliżonym schemacie bę- temu. Na bazie pojawiających się wzorców, rozwija-
dzie można zastosować Template Method lub Strate- jących się obiektów dziedzinowych po pewnym cza-
gy. Tam gdzie tworzymy złożone struktury, tam sto- sie dostrzegamy konieczność modyfikacji architektu-
sujemy wzorzec Builder. Tam gdzie mamy do czynienia ry. Z pomocą mogą nam przyjść wzorce architekto-
z nieskomplikowaną maszyną stanową wprowadzamy niczne lub wprowadzenie innych mechanizmów archi-
State. Tam gdzie potrzebujemy polimorficznego two- tektonicznych. Na tego typu przekształcenia może się
rzenia obiektów używamy Abstract Factory lub jej zde- składać m. in.:
generowanej postaci Simple Factory.
Jeśli przyjrzymy się klasie TextObfuscatorMethods • wprowadzanie warstw;
z przykładu, możemy zauważyć, że większość me- • wprowadzenie lub zmiana O/RM;
tod przyjmuje jako parametr przetwarzany tekst. • zmiana organizacji logiki biznesowej;
Jest to sygnał, że te metody powinny być w kla- • wprowadzenie lub zmiana szkieletu aplikacji.
sie, która ma pole zawierające przetwarzany tekst.
W zasadzie możemy odwrócić sytuację i w klasie Często w systemach przyjmuje się, że stworzo-
TextObfuscatorMethods umieścić pole typu przetwa- na raz architektura będzie doskonale spełniać swo-
rzany tekst, wtedy metody staną się praktycznie bez- je zadanie przez cały cykl życia produktu. Tymcza-
parametrowe. Tym samym klasa nabiera charakteru sem zmienność wymagań oraz trudność stworzenia
wzorca Builder. optymalnej architektury od samego początku powo-
Inną opcją, pod warunkiem, że chcielibyśmy uzy- duje, że założenia architektoniczne należy cały czas
skać możliwość dowolnego składania przekształceń monitorować oraz wprowadzać ewolucyjne zmiany,
zaciemniających tekst (stosować je wybiórczo, w do- tak aby powstające rozwiązania były proste. Sztyw-
wolnej kolejności, o czym chcielibyśmy decydować na, nie zmieniana architektura najczęściej prowadzi
w czasie wykonania), wtedy można by zastosować do powstawania rozwiązań trudnych w zrozumieniu,
wzorzec Decorator. naszpikowanych obejściami.

www.sdjournal.org 53
INŻYNIERIA OPROGRAMOWANIA

Listing 4. Wprowadzenie wzorca Builder.


public class TextObfuscator
{
private ObfuscatedTextBuilder builder = null;
// ...
public string Obfuscate(string text)
{
builder.NewText(text);

builder.ChangeWordsOrderRandomly();
builder.AddMeaninglessWordsRandomly();
builder.RemoveSeparators();
builder.AddSeparatorsRandomly();
builder.RemoveSpaces();
builder.ReplacePolishCharactersWithNonPolish();
builder.ReplaceUpperAndLowercase();

return builder.ToString();
}
}
public class ObfuscatedTextBuilder
{
// ...
private List<TextPart> textParts = new List<TextPart>();
public virtual void NewText(string text)
{
this.textParts = ParseTextForWordsAndNonWords(text);
}
// ...
public virtual void RemoveSpaces()
{
for (int i = 0; i < textParts.Count; i++)
{
RemoveSpacesFromTextPart(textParts, i);
RemoveTextPartIfEmpty(textParts, i);
}
}

public virtual void AddMeaninglessWordsRandomly()


{
for (int i = 0; i < textParts.Count; i++)
{
if (ShouldAddMeaninglessWords())
{
textParts.Insert(i, TextPart.SpaceSeparator); i++;
textParts.Insert(i, new TextPart(DrawMeaninglessWord(), TextPartType.WORD)); i++;
textParts.Insert(i, TextPart.SpaceSeparator);
}
}
}
// ...
}

54 7/2011
Naturalny porządek refaktoryzacji

Rysunek 3. Wyodrębnione klasy


TextObfuscatorMethods i Probability.

Ciągła refaktoryzacja i kosztowe. My to wiemy. Ty musisz sam się przeko-


Przedstawiony proces przedstawia koncepcję ciągłej nać. Wypróbuj zwyczajnie tę strategię przy najbliższej
refaktoryzacji, w której jest ona częścią prac projek- okazji!
towych na każdym poziomie – architektury, projek-
tu, kodu. Nie jest wydzieloną fazą, samodzielną czę-
ścią – jest częścią integralną prac. Chcemy zaznaczyć,
że powyższy proces (mimo, że tak został przedstawio-
ny) nie jest całkowicie liniowy. Często realizując je-
den z późniejszych kroków należy wielokrotnie wra- MICHAŁ BARTYZEL,
cać do kroków wcześniejszych. Przedstawiona stra- MARIUSZ SIERACZKIEWICZ
tegia przedstawia bardziej kierunek działań niż sztyw- Trenerzy i konsultanci w firmie BNS IT. Bada-
ny algorytm. ją i rozwijają metody psychologii programo-
Stosując przedstawione zasady mając na uwadze re- wania, pomagające programistom lepiej
wykonywać ich pracę. Na co dzień Auto-
guły dobrego programowania i projektowania obiek-
rzy zajmują się zwiększaniem efektywności
towego uzyskujemy kod, którego koszt utrzymania
programistów poprzez szkolenia, warsztaty
jest kilkukrotnie niższy niż w przypadku tradycyjne- oraz coaching i trening.
go podejścia. Ponadto testowanie takiego kodu na Kontakt z autorami:
poziomie jednostkowym staje się nieporównywal- m.bartyzel@bnsit.pl,
nie prostsze. m.sieraczkiewicz@bnsit.pl
Nie chcemy przekonywać Cię, że ten sposób pra-
cy długofalową przynosi duże korzyści jakościowe

www.sdjournal.org 55
INŻYNIERIA OPROGRAMOWANIA

Skuteczne wdrażanie w projekt


Wszyscy wiedzą, jak to jest z nowymi projektami. Niezależnie
od tego czy są ciekawe czy nudne, łatwe czy wymagające,
skomplikowane technologicznie czy dające się realizować za pomocą
kartki papieru i ołówka, jedną przynajmniej cechę mają wspólną.
Dla ludzi, którzy dołączają do zespołu są nowe. Nowi programiści,
zanim w pełni rozwiną swe „koderskie” skrzydła, muszą nauczyć się
wielu reguł, faktów, zależności – słowem, niuansów nowej domeny.
Rolą mentorów jest umożliwienie im tego w jak najmniej bolesny
sposób. Rolą ich samych jest świadome uczenie się rzeczy istotnych,
najbardziej potrzebnych.

Dowiesz się: Powinieneś wiedzieć:


• Jak wprowadzać nowych ludzi w nową dla nich tematy- • Jak wykorzystywać nasze własne predyspozycje
kę z zależności od ich własnego poziomu doświadczenia; w procesie nauki.
• Jak nie dać się przytłoczyć nadmiarowi informacji, jeśli
to Ty jesteś wdrażany.

le nie jest to proste zadanie. Im bardziej skomplikowa-


Wykorzystajmy ny projekt, tym więcej detali trzeba przekazać nowemu
nasze własne możliwości człowiekowi w stosunkowo krótkim czasie. Im szybciej
W poprzedniej części przyjrzeliśmy się dwóm poję- stanie się samodzielny, tym szybciej zacznie się zwra-
ciom, które – jeśli stosowane właściwie – pozwala- cać jako – brutalnie rzecz ujmując – inwestycja. Ro-
ją wydajnie przyswajać wiedzę dziedzinową. Model dzi się więc pytanie, czy każda nowa osoba jest w sta-
Dreyfusa wprowadza pewien całkiem racjonalny po- nie poradzić sobie z takim natłokiem informacji? Kolej-
dział zdobywanego doświadczenia na poziomy (patrz nym jest: w jaki sposób rzeczony natłok wiedzy sprowa-
ramka). Łatwo odnieść go do siebie i przekonać się, że dzić do strawnego, łatwo przyswajalnego zestawu rze-
faktycznie na początkowych etapach nauki zwracamy czy do nauczenia?
baczniejszą uwagę na gotowe, dostarczone nam z ze- Jak można zamienić ciężar przekopywania się przez
wnątrz zasady, których trzymamy się kiedy trzeba i nie nudne pokłady wiedzy dziedzinowej w ekscytującą po-
trzeba. Później, wraz z nowymi doświadczeniami zaczy- dróż do kopalni informacji przeznaczonych członkom
namy czuć system coraz lepiej, by wreszcie stać się je- zespołu projektowego?
go częścią jako ekspert. W poprzedniej części przeprowadziliśmy ekspery-
Deliberate Practice ([2], [3]) pokazuje z kolei na co ment, który pozwolił trochę wczuć się w rolę kandy-
należy zwracać uwagę w procesie uczenia, by zmaksy- data na eksperta z dziedziny programowania. Teraz
malizować zysk z wkładanej w naukę pracy. Wyjaśnia będziemy snuć podobne rozważania, ale w odniesie-
jak istotna jest rola mentora, o ile potrafi on właściwie niu do tematyki projektowej i na kilku różnych pozio-
pokierować tokiem nauczania. Pokazuje, których rze- mach. Przyjrzymy się jak radzi sobie z takim samym wy-
czy warto się uczyć, a które zostawić na później. A tak- zwaniem programista doświadczony oraz początkujący.
że ile trzeba włożyć w to wysiłku, by osiągnąć zamie- Następnie spróbujemy wskazać jakie warunki powinny
rzony cel. zostać spełnione, by również bardziej wymagający pro-
Wiedzę tę jak najbardziej można stosować w proce- ces wdrażania zakończył się sukcesem, zwłaszcza w od-
sie wdrażania nowego członka zespołu (Warto pamię- niesieniu do kolegów i koleżanek dysponujących mniej-
tać jednak, iż z punku widzenia mentora bardziej istotny jest szym doświadczeniem.
tu Dreyfus). Niejednokrotnie przekonujemy się, że wca- Zacznijmy od prostszego przypadku.

56 7/2011
Skuteczne wdrażanie w projekt

Nowy projekt, nowe możliwości... ludzi i muszę zostać wdrożony w projekt maksymal-
Wyobraźmy sobie, że właśnie zmieniam pracę. Z ob- nie szybko.
szarów dobrze poznanych, muszę wkroczyć w niezna- Po przedstawieniu powyższego zarysu przechodzi
ne rejony, być może w całkiem nowe technologie. Dla ów kolega do listowania wszystkich istotnych techno-
ułatwienia przyjmijmy, że jest to projekt webowy. Po- logii używanych zarówno w starym, jak i nowym stac-
wszechnie wiadomo bowiem, że webowe projekty są ku. Okazuje się, że aplikacja siedzi na bazie danych
najciekawsze, zaś podawanie ich jako przykład w rozwa- Oracle i korzysta z JPA. Jako providera używa Hiber-
żaniach daje nieskończone wręcz możliwości. nate w wersji 4.x, jednak nie wszędzie, bo starsza część
Załóżmy ponadto, że rzecz toczy się w krainie Ja- bazuje na układanych „na piechotę” zapytaniach reali-
vy Enterprise, a ja sam dysponuję doświadczeniem zowanych przez warstwę JDBC. Jako, że baza do naj-
dość dobrym, by radzić sobie śpiewająco z większo- mniejszych nie należy, mapowań encji po obydwu stro-
ścią trzy- i więcej-literowych skrótów rozpoczynają- nach ci u nas dostatek. Dochodzą do tego hordy klas
cych się od „J”. DAO i DTO. Żeby było bardziej zielono, obracamy się
Przybliżmy w kilku słowach charakterystyczne cechy w Springu w wersji 3.x. Warstwę UI realizuje nam to-
projektu. na widoków JSP osadzonych w Tiles'owych szablonach.
Projekt jest duży, rozwijany od X lat. Przez ten czas Nad bezpieczeństwem czuwa nieśmiertelne Spring Se-
przewinęło się przezeń masę kodu. Spora jego część curity ze swymi nieskończonej długości łańcuchami fil-
nadal istnieje i nazywa się legacy stuff, że się tak wyra- trów. Jako, że nie wszystko da się bądź opłaca się ob-
żę. Nikt nie chce tego oglądać z bliska, bo później śnią sługiwać w MVC, mamy jeszcze garść serwletów, ser-
się koszmary. Czasami jednak nie ma wyjścia. Ale jest wujących bardziej wymagające zasoby. Całości obrazu
też promyk światła w ciemności – oto heroicznym wy- dopełnia kilka pomniejszych aplikacji pomocniczych ko-
siłkiem zastępów programistów udało się zrefaktory- rzystających z innych baz danych, innych frameworków
zować część starych modułów i stworzyć nowe, ko- i pozostałych, znanych i lubianych specyfikacji na lite-
rzystające z bardziej cywilizowanych technologii. Te rę „J”, jak na przykład JSF, JMS, JMX czy nawet zmo-
nowe są rozwijane pod nazwą new stack. Dąży się do ra najwytrwalszych – JAAS. Na okrasę otrzymuję prze-
przeniesienia tam całej archaicznej, zardzewiałej funk- gląd wszystkich wersji wykorzystywanych kontenerów
cjonalności, ale biznes mówi, że jeszcze nie teraz, bo są serwletów i serwerów aplikacji razem z ciekawszymi
ważniejsze priorytety. Priorytety bywają zwykle waż- przykładami ich konfiguracji.
ne i ważniejsze, a biznes wie co mówi. Dowiedziałem Kolejny krok wprowadzenia to zaprezentowanie mi
się tego w rozmowie ze starszym (stażem i być może zasad biznesowych obowiązujących w tym zagmatwa-
wiekiem) kolegą. Wygląda na obeznanego w temacie, nym świecie. Z zasadami powiązane są pryncypia ar-
poza tym chyba lubi to co robi, bo wszystko opowia- chitektury, które muszę poznać wraz z obowiązującymi
da mi z niehamowanym, chaotycznym entuzjazmem. standardami kodowania, pracy w zespole, używania na-
Wyznaje widać zasadę, że jeśli nie powie mi wszyst- rzędzi, etc.
kiego naraz, wiedza ta najpewniej przepadnie wkrót- Na pierwszy rzut oka całkiem tego sporo. Samo zesta-
ce na wieki. wienie technologii mogłoby przyprawić o ból głowy, ale
Powód tegoż postępowania nie daje się nazbyt dłu- miałem to szczęście, że ze sporą częścią z nich zetkną-
go ukrywać. Zatrudniono mnie, bo firma potrzebuje łem się już wcześniej. Powiedzmy, że w Springu nie pisa-

Model Dreyfusa – dla przypomnienia


Model opisujący etapy zdobywania wiedzy. Wyróżnia pięć etapów, z których każdy cechuje inna zależność
od kontekstu:

• Novice – całkowite podporządkowanie regułom, bez znajomości kontekstu, w którym są one umiejsco-
wione razem z rozpatrywanym zagadnieniem. Nie czuje się częścią systemu.
• Advanced beginner – nadal stosuje reguły, lecz posiada już ograniczoną zdolność do znajdowania no-
wych miejsc ich zastosowania. Nie potrzebuje szerszego oglądu na zagadnienie, nad którym pracuje.
• Competent – posiada już całkiem pokaźny zestaw reguł. Potrafi je kategoryzować, by wiedzieć, kiedy któ-
rą należy stosować. Umie rozwiązywać problemy. Dostrzega kontekst problemu.
• Proficient – potrzebuje szerszego oglądu sytuacji. Potrafi samodzielnie poprawiać swoje błędy i doskona-
lić się. Działa w kontekście dziedziny.
• Expert – nie potrzebuje reguł. Działa intuicyjnie w kontekście dziedziny, udzielając od razu odpowiedzi na
stawiane pytanie. Czuje się częścią systemu, czuje się za niego odpowiedzialny.

Model został sformułowany przez braci Stuarta i Huberta Dreyfusów.


Więcej informacji można znaleźć w [1] i [4].

www.sdjournal.org 57
INŻYNIERIA OPROGRAMOWANIA

łem wiele, ale Bean-y to Bean-y, XML to XML a Depen-


dency Injection wszędzie wygląda podobnie. Nie przera-
ża mnie to, mimo że „mentor”, którego mi przydzielono
nie ma bladego pojęcia o zasadach propagowanych przez
Dreyfusa i zanudza mnie wszystkim, co mu tylko przyj-
dzie na myśl. Na swoje szczęście potrafię niepotrzebne
rzeczy szybko odfiltrowywać.
Teraz, kiedy przyjdzie mi zrobić pierwsze zadanie, bę-
dę wiedział mniej-więcej jak się w tym wszystkim poru-
szać. Oczywiście, dobrze by było pierwsze kroki stawiać
pod okiem któregoś z wtajemniczonych kolegów. Jeśli
takowego zabraknie, jest jeszcze Wiki, JavaDoc, debug-
ger, moja wiedza i jakaś tam podstawowa intuicja.
Podsumowując: zanudziłem się na śmierć słuchając
o wszystkim i o niczym jednocześnie. Część obrazu, ta
dająca się przełożyć bezpośrednio na moje wcześniej-
sze doświadczenia, zadomowiła się w umyśle od razu.
Reszta musi poczekać na swoją kolej i mieć nadzieję, że
wkrótce ją sobie przyswoję. W sumie – nie było wca-
le tak źle.
o mapowaniach kontrolerów w widoku, następnie nad-
Przypadek trudniejszy mienił coś o filtrach, by zaraz skoczyć do tematu o jakieś
Jak już wcześniej wspomniałem, to był ten łatwiejszy „bezpiecznej wiośnie” (W zrozumieniu tego zdania wydat-
przypadek. Okazało się, że wdrożenie przebiegło cał- nie może pomóc zapuszczenie automatycznej translacji na
kiem gładko, ale tylko dlatego, że ja sam byłem w stanie dokumentacji Spring Security).
w co trudniejszych momentach procesu "prostować" No i kto to jest, do diaska, ten DispatcherServlet??
swego "mentora". Zajmijmy się więc teraz, dla porów- Tym razem nie poszło już tak dobrze. Głównym po-
nania, przypadkiem dużo trudniejszym. Będziemy roz- wodem było niedostosowanie poziomu materiału wykła-
ważać wdrażanie pracownika bez doświadczenia. du do poziomu jego słuchacza. Cóż mi po tym, bowiem,
Załóżmy, że właśnie skończyłem studia, zaaplikowałem że dowiedziałem się jak wygląda łańcuch filtrów i które
na stanowisko (Junior) Software Developer i przeszedłem fazy powinienem wykorzystać przy implementacji takich
rekrutację. Trafiam przed oblicze tego samego kole- to a takich wymagań, jeśli ja mam zaledwie mgliste poję-
gi, który mojej bardziej doświadczonej instancji skłonny cie o tym co to jest filtr serwletu? Jak mogłem zapamię-
był wyjaśniać wszystkie problemy świata równocześnie. tać niuanse konfiguracji JBoss'a 5.0.1, kiedy nie wiem co
Zostałem więc zbombardowany tym wszystkim, o czym to jest serwer aplikacji?
mówiliśmy kilka akapitów temu. Jako, że programowanie Zbyt wiele danych w zbyt krótkim czasie. Zbyt wiele
aplikacji kojarzy mi się głównie z „Hello, World”, więk- chaotycznych informacji dla mojego chłonnego, lecz nie-
szość z tego, co usłyszałem w pierwszych godzinach wy- doświadczonego jeszcze technologicznie umysłu. Brak
kładu wpadła jednym, a wypadła drugim uchem. Stara- konkretnych przykładów potwierdzających teorię.
łem się wszystko zapamiętać, daję słowo, nawet robiłem Dreyfus nie byłby zadowolony. Ani jeden ani drugi,
notatki. Ale pan raz mówił mi o bazie danych, za chwilę zresztą.

Wydajność pair-programming
Programowania w parach to metoda zaczerpnięta z metodyki XP. Jest ona na tyle uniwersalna, że dopraw-
dy ciężko wyobrazić sobie przykład, gdzie mogłaby nie przynieść zauważalnego zysku. Oczywistym jest, że
gdy na ten sam fragment kodu patrzy często więcej niż jedna osoba jednocześnie, przepływ wiedzy o pro-
jekcie między członkami zespołu zauważalnie się zwiększa. Nie zawsze jednak oczywistym jest, że jeśli jest
przez wszystkich stosowana na porządku dziennym, zwiększa się także wydajność całego zespołu. Wyjaśnie-
nie tego fenomenu jest całkiem proste: co dwie głowy, to nie jedna. Dwóch programistów pracujących nad
tym samym kodem jest w stanie lepiej mobilizować się nawzajem do pracy niż gdy pracują osobno. Ponad-
to zmniejsza się ich wypadkowe „rozproszenie”, co implikuje mniej przypadkowego „błądzenia” w okolicach
poszukiwanego rozwiązania. Dzięki temu poprawia się też oczywiście jakość kodu.
Programujmy w parach codziennie!
Więcej informacji można znaleźć w [5].

58 7/2011
Skuteczne wdrażanie w projekt

Jeśli chcemy nauczyć, róbmy to z głową matem i powiększy pewność siebie. Zadanie nierozwią-
Powyższy przykład został wyolbrzymiony celowo. Wia- zywalne są całkowicie zabronione. Brak zadowalających
domo, że nikt rozsądny nie zatrudni zupełnego nowicju- rezultatów potrafi, jak powszechnie wiadomo, nad wy-
sza, kiedy spodziewa się szybkiego zwrotu z inwestycji. raz skutecznie demotywować.
Zwykle mamy do czynienia z przypadkami umiejscowio- Pamiętamy, że szybka informacja zwrotna to przecież
nymi gdzieś pomiędzy obydwoma przytoczonymi przy- kluczowy aspekt Deliberate Practice.
kładami. Skupmy się teraz na początkujących kandyda-
tach jako najbardziej wymagających. Oto kilka spostrze- Stosujmy jak najczęściej programowanie
żeń, które mogą pomóc w tym względzie potencjalnym w parach
mentorom. Nie dość, że jest to podejście zwiększające jakość kodu
i wydajność całego zespołu (patrz ramka), to jeszcze zna-
Dostosowujmy poziom komicie ułatwia dzielenie się wiedzą. Zaleca się stosowa-
Już po kilku minutach rozmowy z nowym członkiem ze- nie go jak najczęściej, niezależnie od poziomu posiadane-
społu widać jak na dłoni poziom jego umiejętności. Po- go doświadczenia.
starajmy się umiejscowić go w modelu Dreyfusa, a bę- Tych kilka prostych wytycznych rozwiązuje większość
dzie nam łatwiej się z nim komunikować. napotykanych przez początkujących członków zespo-
łu trudności. Przy odpowiednim zrozumieniu po oby-
Cierpliwe odpowiedzi na głupie pytania dwu stronach na pewno przyniosą one oczekiwane re-
Ktoś kiedyś powiedział, że nie ma głupich pytań – są tyl- zultaty. Największe korzyści możemy osiągnąć wyzwala-
ko głupie odpowiedzi. Bądźmy przygotowani na dziesiąt- jąc u młodszych stażem kolegów odpowiednią motywa-
ki pytań, począwszy od tych najbardziej elementarnych. cję. Jeśli podarujemy im cierpliwą pomoc, odpłacą zaan-
Wkrótce okaże się, że ilość pytań się zmniejsza, a zaufa- gażowaniem w projekt.
nie do zespołu rośnie. Wystarczy tylko pamiętać, że dla każdego z nas każdy
projekt, przy którym przyszło nam prawować, był kie-
Uczmy poprzez przykłady dyś nowy.
Pamiętajmy, że człowiek bardzo szybko przyswaja to,
co jest w stanie sam powtórzyć. Proste ćwiczenia re-
alizowane w trybie pair-programming są tu nieocenio-
ną pomocą. Można zacząć na przykład od demonstro-
wania stosowanych praktyk na przykładzie refaktoryza- MICHAŁ KAPŁON
Absolwent Kierunku Informatyka na Wydziałe
cji fragmentów określonych jako legacy code. Całkiem
Elektroniki Politechniki Wrocławskiej. Od roku
dobrze działa też rozwiązywanie Bug-ów. Idealnie, je- związany z firmą Tieto Poland Sp. z o. o., gdzie
śli da się to przeprowadzić z wykorzystaniem meto- pracuje na stanowisku Senior Java Developer
dyki TDD. przy ciekawym, lecz wymagającym projekcie
wykorzystującym technologie JEE. Posiada
Nie zasypujmy nowicjuszy zbędnymi szczegółami sześć lat doświadczenia w wytwarzaniu opro-
Nadmierna szczegółowość nie jest na początku potrzeb- gramowania, w większości w Javie. Przedsta-
na. Skupmy się na jednym prostym problemie za jednym wione wyżej idee stara się, w miarę możliwo-
razem, a efekt będzie o wiele lepszy. ści, wcielać w życie, by czerpać na co dzień
przyjemność ze swojej pracy i nie utrudniać
Rezultat musi być widoczny bardzo szybko życia innym, zwłaszcza młodszym kolegom,
Dobierajmy początkującym zadania tak, by widzieli ich których przyjdzie mu wdrażać w projekt.
efekt możliwie najszybciej. Zmniejszy to ich znużenie te-

Literatura
1. Pragmatic Thinking and Learning. Refactor Your “Wetware”, Andy Hunt, 2008, Pragmatic Bookshelf
2. What is Deliberate Practice? Mastering the Art of Intelligent Practice, Pervin Shaikh, 2009 [http://
www.suite101.com/content/deliberate-practice-a132437]
3. Secrets of Greatness. What it takes to be great, Geoffrey Colvin, 2006 [http://money.cnn.com/
magazines/fortune/fortune_archive/2006/10/30/8391794/index.htm]
4. Dreyfus model of skill acquisition, Wikipedia [http://en.wikipedia.org/wiki/Dreyfus_model_of_skill_acqu-
isition]
5. Pair Programming [http://www.extremeprogramming.org/rules/pair.html]

www.sdjournal.org 59

You might also like