<?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>xlab</title>
	<atom:link href="http://xlab.pl/feed/" rel="self" type="application/rss+xml" />
	<link>http://xlab.pl</link>
	<description>XSolve laboratory - dzielimy się tym co wiemy...</description>
	<lastBuildDate>Mon, 09 Jan 2012 15:29:06 +0000</lastBuildDate>
	<language>pl</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Efektywne programowanie w javie</title>
		<link>http://xlab.pl/efektywne-programowanie-w-javie/</link>
		<comments>http://xlab.pl/efektywne-programowanie-w-javie/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 15:51:06 +0000</pubDate>
		<dc:creator>pawel.henek</dc:creator>
				<category><![CDATA[Programowanie Java]]></category>
		<category><![CDATA[helion]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[joshua bloch]]></category>
		<category><![CDATA[książki java]]></category>
		<category><![CDATA[książki programowanie]]></category>
		<category><![CDATA[programiści java]]></category>
		<category><![CDATA[software engineering]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1901</guid>
		<description><![CDATA[Miałem ostatnio przyjemność studiować książkę autorstwa Joshuę Blocha &#8211; bardzo ciekawa postać świata javy, doktora informatyki z Carnegie Mellon University, aktualnie pracującego jako Java Chief Architect w Google. Od wielu lat realizujący projekty i badania głównie związane m.in. z javą, systemami rozproszonymi. Bogate doświadczenie akademickie, komercyjne (przed Google pracował w Sun&#8217;ie) oraz pochlebne opinie czytelników [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">Miałem ostatnio przyjemność studiować książkę autorstwa Joshuę Blocha &#8211;  bardzo ciekawa postać świata javy, doktora informatyki z Carnegie Mellon  University, aktualnie pracującego jako Java Chief Architect w Google.  Od wielu lat realizujący projekty i badania głównie związane m.in. z  javą, systemami rozproszonymi. Bogate doświadczenie akademickie,  komercyjne (przed Google pracował w Sun&#8217;ie) oraz pochlebne opinie  czytelników gwarantują, że każda książka której jest autorem nie schodzi  poniżej pewnego merytorycznego poziomu. Nie inaczej jest też w  przypadku książki Effective Java: Programming Language Guide (w Polsce  Java. Efektywne programowanie, Helion).</p>
<p><a class="alignleft" style="float: left; margin: 10px 10px 10px 0;" href="http://helion.pl/ksiazki/java-efektywne-programowanie-wydanie-ii-joshua-bloch,javep2.htm" target="_blank"><img class="alignleft size-medium wp-image-1917" title="Java. Efektywne Programowanie" src="http://xlab.pl/wp-content/uploads/2011/10/Obrazek-1-209x300.png" alt="" width="209" height="300" /></a>To czym zdecydowanie różnią  się książki Blocha od innych dotyczących programowania czy też javy,  jest to że w każdej z nich skupia się na pewnej niszy w temacie o którym  pisze. W przypadku efektywnego programowania, skupia się na  praktycznych aspektach tworzenia oprogramowania, dobrych, sprawdzonych  wzorcach postępowania przy jego projektowaniu oraz na specyficznych dla  javy zagadnieniach. Autor porusza 78 tematów, z którego każdy to kilku  stronnicowy artykuł szczegółowo omawiający problem. Materiał zawarty w  książce został skatagoryzowany według pewnych większych grup problemów,  które porusza.  Autor rozpoczyna od omawiania zagadnień związanych  z tworzeniem i usuwaniem obiektów, następnie przechodzi do tych  związanych z projektowaniem klas, w tym aspektów specyficznych dla javy.  Można tutaj dowiedzieć się m.in. dlaczego należy uważnie używać  singletonów, podstaw działania garbage collectora, jak definiować  prawidłowe metody hashCode czy equals, dlaczego warto stosować  interfejsy czy zastępować dziedziczenie kompozycją. Na uwagę zasługe  fakt, iż autor stara się być jak najbardziej obiektywny, dostrzega  zarówno zalety proponowanych przez siebie rozwiązań jak i ewentualne  wady.  W dalszej kolejności omawia takie konstrukcje jak  typy ogólne, wyliczeniowe i adnotacje. Udziela praktycznych wskazówek  jakich konstrukcji języka i praktyk programowania używać, a jakie są już  przestarzałe. W ostatnich rozdziałach omawia sposoby wydajnego i  rozsądnego korzystania z wyjątków,  dzieli się doświadczeniem w kwestii  współbieżności oraz serializacji.  Cała wiedza z książki jest  gdzieś pewnie rozsiana po internecie w postaci pojedynczych postów na  blogach czy artykułów. Wydaje mi się jednak iż warto takie kompendium  wiedzy nt problemów specyficznych dla javy mieć zawsze pod ręką i od  czasu do czasu odświeżyć swoją pamięć. Gorąco polecam książkę <a href="http://helion.pl/ksiazki/java-efektywne-programowanie-wydanie-ii-joshua-bloch,javep2.htm">Java. Efektywne programowanie</a> . Tymczasem uciekam do kolejnego dziecka Blocha &#8211; <a href="http://www.javapuzzlers.com/">Java puzzlers</a> .</p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/efektywne-programowanie-w-javie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zaprogramuj się na Softdevcon II &#8211; XSolve kolejny raz partnerem konferencji</title>
		<link>http://xlab.pl/xsolve-partnerem-konferencji-softdevcon/</link>
		<comments>http://xlab.pl/xsolve-partnerem-konferencji-softdevcon/#comments</comments>
		<pubDate>Tue, 11 Oct 2011 13:53:58 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Ogólne]]></category>
		<category><![CDATA[aplikacje na androida]]></category>
		<category><![CDATA[konferencje dla programistów]]></category>
		<category><![CDATA[konferencje it]]></category>
		<category><![CDATA[konferencje programistyczne]]></category>
		<category><![CDATA[metodologie it]]></category>
		<category><![CDATA[softdevcon]]></category>
		<category><![CDATA[softdevcon II]]></category>
		<category><![CDATA[spotkania it]]></category>
		<category><![CDATA[trendy it]]></category>
		<category><![CDATA[tworzenie aplikacji android]]></category>
		<category><![CDATA[wydarzenia branży it]]></category>
		<category><![CDATA[wydarzenia it]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1928</guid>
		<description><![CDATA[30 listopada 2011r. firma SQAM rozpoczęła cykl merytorycznych konferencji Softdevcon – wykładów i warsztatów skierowanych do zainteresowanych tematyką programowania . Po listopadowym sukcesie w Warszawie, Softdevcon wraz z zespołem światowej klasy specjalistów dotrze do Wrocławia. 31 stycznia 2012r. programiści, informatycy oraz pasjonaci oprogramowania staną przed niepowtarzalną szansą poznania najnowszych trendów, technik i kierunków rozwoju branży  programistycznej. Skillful [...]]]></description>
			<content:encoded><![CDATA[<p>30 listopada 2011r. firma SQAM rozpoczęła cykl merytorycznych konferencji Softdevcon – wykładów i warsztatów skierowanych do zainteresowanych tematyką programowania . Po listopadowym sukcesie w Warszawie, Softdevcon wraz z zespołem światowej klasy specjalistów dotrze do <strong>Wrocławia.</strong></p>
<p><strong>31 stycznia 2012r.</strong> programiści, informatycy oraz pasjonaci oprogramowania staną przed niepowtarzalną szansą poznania najnowszych trendów, technik i kierunków rozwoju branży  programistycznej. Skillful Software House XSolve objął patronatem medialnym cały cykl konferencji, widząc powiązanie pomiędzy branżą w jakiej na co dzień działa z tematyką poruszaną na poszczególnych imprezach Softdevcon.</p>
<p><strong>Prelekcje poruszą tematykę z obszaru Cloud Development.</strong></p>
<p>Lista prelekcji:</p>
<p>1. <strong>Analiza danych przy użyciu Apache Hive I Elastic MapReduce</strong><br />
(Radek Maciaszek / Krystian Nowak)<br />
2. <strong>Development for the Cloud – changing the team’s mindset</strong><br />
(Masha Belyakova)<br />
3. <strong>A cloud in your pocket</strong><br />
(Axel Quack)<br />
4. <strong>Testowanie chmury</strong><br />
(Rafał Sibilski )<br />
5. <strong>Komunikacja ze światem zewnętrznym z wykorzystaniem Windows Azure AppFabric</strong><br />
(Marcin Pytlik)<br />
6. <strong>How Telecom companies are reacting to Cloud and what are the typical Telecom cloud offers</strong><br />
(Alper Celik)</p>
<p>Siódma prelekcja należy do <strong>Sponsora Głównego</strong>.</p>
<div style="text-align: center;">
<p><img class="aligncenter size-medium wp-image-1931" title="softdevcon logo" src="http://xlab.pl/wp-content/uploads/2011/11/softdevcon_znak_500x129-300x77.png" alt="Logo konferencji Softdevcon" width="300" height="77" /></p>
<p style="text-align: left;">Testujesz aplikacje? Programujesz gry? Interesuje Cię Cloud Development? Chcesz wiedzieć więcej? A może chcesz się podzielić swoją wiedzą z innymi?  Wykorzystaj szansę, którą stawiamy przed Tobą. Przyjdź, dowiedz się, <strong>zgarnij</strong> nagrody i zaprogramuj swój sukces wraz z Softdevcon.</p>
<p style="text-align: left;"><strong>Rejestracja na konferencję trwa. </strong>Więcej informacji na <a href="http://softdevcon.pl/wydarzenia/612-Softdevcon_II_Wroclaw">http://softdevcon.pl/wydarzenia/612-Softdevcon_II_Wroclaw</a></p>
<p style="text-align: left;">Polecamy konferencje z cyklu Softdevcon jako drogę do zdobycia wiedzy, poznania nowych, interesujących ludzi oraz wymiany doświadczeń.</p>
<p style="text-align: left;"><strong><br />
</strong></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/xsolve-partnerem-konferencji-softdevcon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PFCongres 2011 &#8211; szybkie podsumowanie</title>
		<link>http://xlab.pl/pfcongres-2011-szybkie-podsumowanie/</link>
		<comments>http://xlab.pl/pfcongres-2011-szybkie-podsumowanie/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 17:15:17 +0000</pubDate>
		<dc:creator>adam.gegotek</dc:creator>
				<category><![CDATA[Programowanie PHP]]></category>
		<category><![CDATA[konferencja]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1880</guid>
		<description><![CDATA[W dniu siedemnastego września bieżącego roku, w holenderskim mieście Utrecht odbył się PFCongres 2011. Dla tych, którzy jeszcze nie wiedzą cóż to takiego, jest to konferencja poświęcona rozwojowi internetu skupiająca głównie entuzjastów PHP już ponad szósty raz z rzędu. Tegoroczna edycja została podzielona na dwie, dwujęzyczne, odbywające się równolegle części i gościła aż czternastu światowej [...]]]></description>
			<content:encoded><![CDATA[<p>W dniu siedemnastego września bieżącego roku, w holenderskim mieście Utrecht odbył się <a title="pfcongres" href="http://www.pfcongres.com/" target="_blank">PFCongres 2011</a>. Dla tych, którzy jeszcze nie wiedzą cóż to takiego, jest to konferencja poświęcona rozwojowi internetu skupiająca głównie entuzjastów PHP już ponad szósty raz z rzędu. Tegoroczna edycja została podzielona na dwie, dwujęzyczne, odbywające się równolegle części i gościła aż czternastu światowej sławy mówców wśród których znaleźli się:</p>
<p><em>Zeev Suraski</em> &#8211; izraelski programista PHP, współzałożyciel Zend Technologies. Z pomocą Andiego Gutmans&#8217;a w 1997 napisał PHP3, po czym dwa lata później stworzył Zend Engine.</p>
<p><em>Derick Rethans</em> &#8211; twórca mcrypt, input_filter, dbus i rozszerzeń typu date/time w PHP. Znany również z opieki nad projektem PHP&#8217;owego profilera Xdebug oraz z kilkuletniego zaangażowania w Apache Zeta Components.</p>
<p><em>Jouzas Kaziukenas</em> &#8211; założyciel i prezes firmy Web Species Ltd, mówca na konferencjach dotyczących technologii informatycznych, blogger.</p>
<p><em>Joshua Thijssen</em><strong> </strong>- starszy inżynier oprogramowania w Enrise/4Worx oraz właściciel prywatnej firmy NoxLogic.</p>
<p>Pomimo tego, iż byłem w stanie uczestniczyć tylko na przemówieniach w języku angielskim, muszę przyznać, że poruszono w nich kilka ciekawych tematów takich jak:</p>
<p>-<em> 15 porad dla użytkowników MySQL</em><br />
<em> -  Struktury danych SPL i ich złożoność</em><br />
<em>- Jak władać przestrzeniami nazw w PHP</em><br />
<em>- Nowa era frameworków w PHP</em><br />
<em>- Rozszerzenia w PHP, z czym i dlaczego ?</em></p>
<p>Oceniając je poprzez pryzmat programisty PHP, trzy pierwsze uważam za naprawdę wartościowe i godne uwagi.</p>
<p>Według mnie najciekawsze przemówienie wygłosił Joshua Thijssen, specjalista MySQL, który w zwięzły sposób pokazał kilkanaście sztuczek mogących znacznie przyspieszyć operacje na bazie danych. Uważam, że przejrzenie <a title="15 mysql protips" href="http://www.slideshare.net/jaytaph/15-protips-for-mysql-users-pfz" target="_blank">slajdów</a> z jego przemowy na pewno nauczy Was czegoś nowego. Pamiętajcie by nie ufać varchar&#8217;om! :)</p>
<p>Kolejnym, wybitnym przemówieniem popisał się Jurriën Stutterheim, który po krótkiej dygresji na temat złożoności algorytmów przeszedł do ciekawszej części poświęconej strukturom danych w PHP. Było naprawdę miło słuchać wykładu w którym dowodził, że prócz typowych tablic, PHP oferuje tak zaawansowane struktury jak: SplDoublyLinkedList, SplStack, SplQueue, SplHeap, SplMaxHeap, SplMinHeap, SplPriorityQueue, SplFixedArray i SplObjectStorage. Szczerze zachęcam do obejrzenia jego <a title="spl data structures" href="http://www.slideshare.net/norm2782/pf-congres20110917-datastructures" target="_blank">prezentacji</a>.</p>
<p>Chciałbym też wspomnieć o wystąpieniu Nicka Belhomme, który postanowił opowiedzieć o nowej funkcjonalności wprowadzonej do PHP dopiero w wersji 5.3. Jego tematem były oczywiście przestrzenie nazw (ang. namespaces), czyli abstrakcyjne kontenery stworzone do trzymania logicznie pogrupowanych unikatowych identyfikatorów. Jego <a title="mastering namespaces" href="http://www.slideshare.net/NickBelhomme/mastering-namespaces-pfcongres11" target="_blank">prezentacja</a> była szczególnie edukacyjna i istotna dla przyszłych projektów w PHP, obfitując przy tym dodatkowo w kilkanaście przykładów z kodami źródłowymi.</p>
<p>Na sam koniec chciałbym przytoczyć wypowiedź Jouzasa Kaziukenas&#8217;a. Starał się on ukazać zmiany jakie zaszły w świecie frameworków PHP&#8217;owych w przeciągu ostatnich sześciu lat. Muszę przyznać, że zrobił to wyjątkowo dobrze. Wymieniwszy kilka frameworków, w tym Symfony2, Zend Framework, Lithium, Alloy, Fuel, Fat-free oraz Flow3, jego uwagę na dłużej przykuło Symfony2. Przede wszystkim za sprawą innowacyjnych rozwiązań o których rozprawiał, takich jak: bundles, dependency injection oraz community driven development (GIT). Nie bez znaczenia okazały się również symfonowe interoperacyjność, szybkość i doskonała dokumentacja. Jouzas ponadto bardzo oczekiwał nowej, stabilnej wersji frameworka ZF2, którego premiery nie potrafił niestety określić. Jeśli w tym czasie chcielibyśmy czegoś z innej beczki, do wypróbowania zostają microframeworki. Pomimo tego, iż stworzone głównie dla małych projektów, z pewnością będą interesującą i godną uwagi alternatywą. Dla zainteresowanych, przytoczonym microframeworkiem został Silex.</p>
<p>Podsumowując konferencję PFCongres muszę przyznać, że uczestnictwo w niej było dla mnie bardzo cennym doświadczeniem. Miałem bowiem okazję poznać wiele ciekawostek i wodotrysków jak również zaznajomić się z nowinkami i przyszłymi trendami języka PHP. Miałem też okazję na własne oczy zobaczyć Tych, którzy wkładają ogromny wysiłek w jego rozwój. Co więcej, bardzo zmotywowało mnie ich entuzjastyczne podejście do dalszego rozwoju i udoskonalania owego języka. Liczę, że i w przyszłym roku zdołam stawić się na PFCongres, a jeśli i Ty czujesz się podobnie &#8222;wkręcony&#8221; w PHP, to serdecznie polecam i zapraszam Cie na to wydarzenie!</p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/pfcongres-2011-szybkie-podsumowanie/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Python &#8211; widziany okiem Javianina</title>
		<link>http://xlab.pl/python-widziany-okiem-javianina/</link>
		<comments>http://xlab.pl/python-widziany-okiem-javianina/#comments</comments>
		<pubDate>Thu, 22 Sep 2011 21:22:42 +0000</pubDate>
		<dc:creator>pawel.rychlik</dc:creator>
				<category><![CDATA[Ogólne]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[podstawy]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1855</guid>
		<description><![CDATA[Całkiem niedawno wpadł mi w ręce podręcznik do Pythona. Książka wyglądała na interesującą, więc długo nie zwlekając wziąłem się za czytanie, chwilę później już pisałem pierwsze Hello-world&#8216;y w dotąd zupełnie mi obcym języku. Z początku nie bardzo wiedziałem, którą wersje Pythona zainstalować &#8211; strona python.org oferuje multum możliwości, dostępne jest kilkanaście (kilkadziesiąt?) paczek, przygotowanych pod [...]]]></description>
			<content:encoded><![CDATA[<p>Całkiem niedawno wpadł mi w ręce podręcznik do Pythona. Książka wyglądała na interesującą, więc długo nie zwlekając wziąłem się za czytanie, chwilę później już pisałem pierwsze <em>Hello-world</em>&#8216;y w dotąd zupełnie mi obcym języku. Z początku nie bardzo wiedziałem, którą wersje Pythona zainstalować &#8211; strona python.org oferuje multum możliwości, dostępne jest kilkanaście (kilkadziesiąt?) paczek, przygotowanych pod konkretne platformy i maszyny. Pokierowałem się podpowiedziami znalezionymi w internecie: 3.x to najnowsza odmiana tego języka, 2.x jest starszą wersją (ale wciąż rozwijaną do 2013r.). Aplikacje pisane pod 3.x mogą nie być w pełni kompatybilne z Pythonem serii 2.x (i odwrotnie), ponadto większość zewnętrznych bibliotek była pisana pod starszą wersją, dlatego też zdecydowałem się na &#8222;bezpieczne&#8221; 2.6.7.</p>
<p>Nagłówek artykułu sugeruje, że będę starał się dokonać porównania Javy i Pythona. Przecież to dwa kompletnie różne światy. Niemniej jednak postaram się w skrócie nakreślić czym cechuje się Python i opisać co poniektóre ciekawsze rozwiązania, z którymi spotkałem się podczas mojej krótkiej i burzliwej znajomości z tym językiem.</p>
<p><strong>Intro</strong></p>
<p>W odróżnieniu do Javy, Python jest językiem typowanym dynamicznie: zmiennych się nie deklaruje i tym samym nie określa się ich typu. Znaczy to mniej więcej tyle, że do tej samej zmiennej można przypisywać obiekty różnych klas bez potrzeby rzutowania, nie narażając się na odpowiednik javowego <em>ClassCastException</em>. Skoro już mowa o klasach &#8211; Python jest w pełni obiektowy, a więc typy proste (<span style="color: #e34adc">bool</span><span style="color: #808030">,</span> <span style="color: #e34adc">int</span><span style="color: #808030">,</span> <span style="color: #e34adc">float</span><span style="color: #808030">,</span> <span style="color: #e34adc">complex</span>) również są obiektami. Python jest językiem interpretowanym, nie wymagającym kompilacji (ten krok jest opcjonalny &#8211; interpreter może generować skompilowany kod do plików *.pyc). Fakt ten może spodobać się weteranom Javy &#8211; przecież nieraz budowanie złożonych projektów potrafiło zająć ładne parenaście minut. Jednak dynamiczne typowanie w połączeniu z brakiem konieczności kompilacji (który de facto często w pewnym stoponiu weryfikuje poprawność kodu) i nieuwagą programisty może przyczynić się do powstawania błędów. Ale to temat na osobną dyskusję.</p>
<p><strong>Liczby.</strong></p>
<p>Cechą, której nie miałem okazji specjalnie wykorzystać, a która bardzo pozytywnie mnie zaskoczyła, jest wbudowana obsługa liczb zespolonych. Dostępny mamy typ prosty <span style="color: #e34adc">complex</span>.</p>
<pre style="color: #000000;background: #ffffff"><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> 1j <span style="color: #808030">*</span> 1J
<span style="color: #808030">(</span><span style="color: #808030">-</span><span style="color: #008c00">1</span><span style="color: #808030">+</span>0j<span style="color: #808030">)</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> 1j <span style="color: #808030">*</span> <span style="color: #e34adc">complex</span><span style="color: #808030">(</span><span style="color: #008c00">0</span><span style="color: #808030">,</span><span style="color: #008c00">1</span><span style="color: #808030">)</span>
<span style="color: #808030">(</span><span style="color: #808030">-</span><span style="color: #008c00">1</span><span style="color: #808030">+</span>0j<span style="color: #808030">)</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> a<span style="color: #808030">=</span><span style="color: #008000">1.5</span><span style="color: #808030">+</span><span style="color: #008000">0.</span>5j
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> a<span style="color: #808030">.</span>real
<span style="color: #008000">1.5</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> a<span style="color: #808030">.</span>imag
<span style="color: #008000">0.5</span></pre>
</p>
<p>Kolejną ciekawostką jest fakt, że ograniczeniem długości liczby typu long jest w zasadzie tylko ilość dostępnej pamięci operacyjnej. Dostajemy zatem &#8222;out-of-the-box&#8221; możliwość wyrażania odległości międzygalaktycznych w milimetrach. Tylko co, jeśli będziemy chcieli przekazać obliczony wynik na inną maszynę?</p>
<p><strong>(), [], {}.</strong></p>
<p>Zdarza się, że potrzebujemy, aby metoda zwróciła więcej niż jeden obiekt. Rzecz jasna mowa tu nie o liście/tablicy, ale o obiektach różnych typów. Jednocześnie nie widzimy sensu tworzenia nowej klasy, która i tak byłaby wykorzystana tylko w tym jednym miejscu. Wtedy (na przykładzie Javy) zaczyna się kombinowanie: może przekazywać jeden obiekt przez parametr, w metodzie wypełniać go danymi, a drugą część informacji zwracać przez return statement?; może przejrzeć pakiet *utils w poszukiwaniu generycznej klasy Pair&lt;A,B&gt; lub Trio&lt;A,B,C&gt; i we wspomnianej metodzie zwracać właśnie obiekt takiej klasy? a może spróbować użyć mapę?</p>
<p>Zdaje się, że m.in. wówczas przydałyby się znane z Pythona <em>krotki</em> &#8211; niemodyfikowalne sekwencje referencji dostępnych niezależnie. Dostęp do poszczególnych elementów odbywa się przez podanie indeksu (numeracja od zera).</p>
<pre style="color: #000000;background: #ffffff"><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #e34adc">tuple</span> <span style="color: #808030">=</span> <span style="color: #008c00">12345</span><span style="color: #808030">,</span> <span style="color: #008c00">54321</span><span style="color: #808030">,</span> <span style="color: #0000e6">'hello!'</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #e34adc">tuple</span>
<span style="color: #808030">(</span><span style="color: #008c00">12345</span><span style="color: #808030">,</span> <span style="color: #008c00">54321</span><span style="color: #808030">,</span> <span style="color: #0000e6">'hello!'</span><span style="color: #808030">)</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #e34adc">tuple</span> <span style="color: #808030">=</span> <span style="color: #808030">(</span><span style="color: #008c00">12345</span><span style="color: #808030">,</span> <span style="color: #008c00">54321</span><span style="color: #808030">,</span> <span style="color: #0000e6">'hello!'</span><span style="color: #808030">)</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #e34adc">tuple</span>
<span style="color: #808030">(</span><span style="color: #008c00">12345</span><span style="color: #808030">,</span> <span style="color: #008c00">54321</span><span style="color: #808030">,</span> <span style="color: #0000e6">'hello!'</span><span style="color: #808030">)</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #e34adc">tuple</span><span style="color: #808030">[</span><span style="color: #008c00">0</span><span style="color: #808030">]</span>
<span style="color: #008c00">12345</span></pre>
</p>
<p>Idąc za ciosem &#8211; kolejnym typem danych jest lista, oznaczana przy pomocy nawiasów kwadratowych. Bardzo podobna do krotki, jednak daje możliwość modyfikacji swoich danych.</p>
<pre style="color: #000000;background: #ffffff"><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #e34adc">list</span> <span style="color: #808030">=</span> <span style="color: #808030">[</span><span style="color: #0000e6">'spam'</span><span style="color: #808030">,</span> <span style="color: #0000e6">'eggs'</span><span style="color: #808030">,</span> <span style="color: #008c00">100</span><span style="color: #808030">,</span> <span style="color: #008c00">1234</span><span style="color: #808030">]</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #e34adc">list</span>
<span style="color: #808030">[</span><span style="color: #0000e6">'spam'</span><span style="color: #808030">,</span> <span style="color: #0000e6">'eggs'</span><span style="color: #808030">,</span> <span style="color: #008c00">100</span><span style="color: #808030">,</span> <span style="color: #008c00">1234</span><span style="color: #808030">]</span></pre>
</p>
<p>Słowniki, które w Pythonie tworzy się przy użyciu nawiasów klamrowych, prezentują nieco inny sposób grupowania danych. Podczas gdy krotki i listy są numerowane na podstawie indeksów liczbowych, słowniki do indeksacji stosują nazwy &#8211; mogą to być litery, ciągi znaków lub symbole. Słowniki można porównać do java.util.Map, dane wkładamy podając klucz oraz odpowiadającą mu wartość, klucze muszą być unikatowe, jednak pod jednym kluczem wystąpić może wiele wartości.</p>
<pre style="color: #000000;background: #ffffff"><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> tel <span style="color: #808030">=</span> <span style="color: #800080">{</span><span style="color: #0000e6">'jack'</span><span style="color: #808030">:</span> <span style="color: #008c00">4098</span><span style="color: #808030">,</span> <span style="color: #0000e6">'sape'</span><span style="color: #808030">:</span> <span style="color: #008c00">4139</span><span style="color: #800080">}</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> tel<span style="color: #808030">[</span><span style="color: #0000e6">'guido'</span><span style="color: #808030">]</span> <span style="color: #808030">=</span> <span style="color: #008c00">4127</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> tel
<span style="color: #800080">{</span><span style="color: #0000e6">'sape'</span><span style="color: #808030">:</span> <span style="color: #008c00">4139</span><span style="color: #808030">,</span> <span style="color: #0000e6">'guido'</span><span style="color: #808030">:</span> <span style="color: #008c00">4127</span><span style="color: #808030">,</span> <span style="color: #0000e6">'jack'</span><span style="color: #808030">:</span> <span style="color: #008c00">4098</span><span style="color: #800080">}</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> tel<span style="color: #808030">[</span><span style="color: #0000e6">'jack'</span><span style="color: #808030">]</span>
<span style="color: #008c00">4098</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #800000;font-weight: bold">del</span> tel<span style="color: #808030">[</span><span style="color: #0000e6">'sape'</span><span style="color: #808030">]</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> tel<span style="color: #808030">[</span><span style="color: #0000e6">'irv'</span><span style="color: #808030">]</span> <span style="color: #808030">=</span> <span style="color: #008c00">4127</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> tel
<span style="color: #800080">{</span><span style="color: #0000e6">'guido'</span><span style="color: #808030">:</span> <span style="color: #008c00">4127</span><span style="color: #808030">,</span> <span style="color: #0000e6">'irv'</span><span style="color: #808030">:</span> <span style="color: #008c00">4127</span><span style="color: #808030">,</span> <span style="color: #0000e6">'jack'</span><span style="color: #808030">:</span> <span style="color: #008c00">4098</span><span style="color: #800080">}</span></pre>
</p>
<p>Ciekawym niuansem jest możliwość dostępu do elementów sekwencji podając ujemną wartość indeksu. W Javie chcąc pobrać ostatni element listy, potrzeba mniej więcej takiego kodu: list.get(list.size() &#8211; 1); podczas gdy w Pythonie wystarczy: list[-1]. Przechodząc kolejno elementy listy użylibyśmy indeksów od 0 do len(list)-1. Ten sam efekt można osiągnąć iterując od -len(list) do -1. Taka mała rzecz, a cieszy.</p>
<p>Istnieją również skróty na &#8222;krojenie&#8221; sekwencji. W Javie skorzystalibyśmy z metody List.subList(), która zwraca widok oryginalnej listy. Odpowiadająca temu instrukcja Pythona to zaledwie: list[a:b], gdzie a i b to indeks początkowy i końcowy nowej listy.</p>
<pre style="color: #000000;background: #ffffff">s <span style="color: #808030">=</span> <span style="color: #0000e6">"ABCDEF"</span>
s<span style="color: #808030">[</span><span style="color: #008c00">2</span><span style="color: #808030">:</span><span style="color: #008c00">5</span><span style="color: #808030">]</span>  <span style="color: #808030">-</span><span style="color: #808030">-</span><span style="color: #808030">&gt;</span> <span style="color: #0000e6">"CDE"</span>
s<span style="color: #808030">[</span><span style="color: #008c00">4</span><span style="color: #808030">:</span><span style="color: #808030">]</span>   <span style="color: #808030">-</span><span style="color: #808030">-</span><span style="color: #808030">&gt;</span> <span style="color: #0000e6">"EF"</span>
s<span style="color: #808030">[</span><span style="color: #808030">:</span><span style="color: #008c00">2</span><span style="color: #808030">]</span>   <span style="color: #808030">-</span><span style="color: #808030">-</span><span style="color: #808030">&gt;</span> <span style="color: #0000e6">"AB"</span>
s<span style="color: #808030">[</span><span style="color: #808030">:</span><span style="color: #808030">-</span><span style="color: #008c00">1</span><span style="color: #808030">]</span>  <span style="color: #808030">-</span><span style="color: #808030">-</span><span style="color: #808030">&gt;</span> <span style="color: #0000e6">"ABCDE"</span>
s<span style="color: #808030">[</span><span style="color: #808030">-</span><span style="color: #008c00">1</span><span style="color: #808030">:</span><span style="color: #808030">]</span>  <span style="color: #808030">-</span><span style="color: #808030">-</span><span style="color: #808030">&gt;</span> <span style="color: #0000e6">"F"</span>
s<span style="color: #808030">[</span><span style="color: #808030">:</span><span style="color: #808030">]</span>    <span style="color: #808030">-</span><span style="color: #808030">-</span><span style="color: #808030">&gt;</span> <span style="color: #0000e6">"ABCDEF"</span></pre>
</p>
<p>Kolejny interesujący feature to funkcja range(a, b, c), która zwraca listę liczb od a do b (z opcjonalnym krokiem c), i która często przydaje się przy definiowaniu pętli for..in. Funkcja xrange() spełnia taką samą rolę, jednak poleca się ją stosować przy dużych rozmiarach list: zamiast alokować zbędnie duży fragment pamięci tylko po to, aby trzymać w niej uporządkowane wartości &#8211; xrange() na potrzeby iteracji tworzy tzw. lazy-list, która generuje i udostępnia jedynie elementy potrzebne w danej chwili.</p>
<pre style="color: #000000;background: #ffffff"><span style="color: #696969"># liczenie silni ze 100:</span>
product <span style="color: #808030">=</span> <span style="color: #008c00">1</span><span style="color: #006600">L</span>
<span style="color: #800000;font-weight: bold">for</span> i <span style="color: #800000;font-weight: bold">in</span> <span style="color: #e34adc">xrange</span><span style="color: #808030">(</span><span style="color: #008c00">1</span><span style="color: #808030">,</span> <span style="color: #008c00">100</span><span style="color: #808030">)</span><span style="color: #808030">:</span>
    product <span style="color: #808030">=</span> product <span style="color: #808030">*</span> i</pre>
</p>
<p><strong>Pozostałe małe plusiki</strong></p>
<p>Bardzo istotnym elementem kodu Pythona są białe znaki, a konkretnie wcięcia. To one określają bloki kodu. Z jednej strony jest to plus &#8211; mniej pisania, mniej linii kodu. Jednak błędnie zaaplikowane wcięcia w kodzie (np. wynikające z popularnej techniki copy-paste) mogą spowodować ciężkie do wytropienia błędy.</p>
<p>Świetnym ułatwieniem, które przydałoby się w innych językach, jest możliwość szeregowania (chaining) operatorów porównań:</p>
<pre style="color: #000000;background: #ffffff"><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> x <span style="color: #808030">=</span> <span style="color: #008c00">5</span>
<span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #008c00">1</span> <span style="color: #808030">&lt;</span> x <span style="color: #808030">&lt;</span> <span style="color: #008c00">10</span>
<span style="color: #e34adc">True</span></pre>
</p>
<p>Porównania wartości String&#8217;ów w Pythonie to kwestia użycia operatorów == lub !=. Daje to sporo poziom przejrzystości kodu, w porównaniu do Javy, gdzie wykorzystalibyśmy String.equals(), compare() lub compareTo().</p>
<p>Podobnie jak w Scali, w Pythonie możliwe jest deklarowanie funkcji wewnątrz funkcji. Zamiast powielać ten sam fragment kodu, lepiej zdefiniować i wywołać nową funkcję. Taka fragmentacja szybko mogłaby doprowadzić do zmniejszenia czytelności interfejsu danej klasy (multum krótkich metod), toteż warto zastanowić się nad umieszczeniem nowej funkcji w ciele funkcji, w której będzie ona używana. Korzystać również możemy z funkcji lambda (któtkich funkcji anonimowych), znanych m.in. z C# i Scali.</p>
<p><strong>&#8222;Talk less, more action&#8221;</strong></p>
<p>Podaje się, że pisząc w Pythonie, można być 5-10 razy bardziej produktywnym niż w Javie. Trudno się temu dziwić, jeśli otwarcie i odczytanie pliku tekstowego w Pythonie sprowadza się do:</p>
<pre style="color: #000000;background: #ffffff"><span style="color: #e34adc">file</span> <span style="color: #808030">=</span> <span style="color: #e34adc">open</span><span style="color: #808030">(</span><span style="color: #0000e6">'plik'</span><span style="color: #808030">)</span>
<span style="color: #e34adc">file</span><span style="color: #808030">.</span>read<span style="color: #808030">(</span><span style="color: #808030">)</span></pre>
</p>
<p>Podczas gdy w Javie należałoby zadeklarować odpowiedni bufor, utworzyć strumień podając ścieżke pliku, prawdopodobnie czytać fragmentami w pętli, całość okraszając tłustą warstwą try {} catch().</p>
<p>Python pozwala na dużą swobodę. Jest językiem skryptowym, ale nie oznacza to, że nie można pisać w nim kodu zorientowanego obiektowo. Oferuje zaawansowaną modularność (wprowadza pojęcie modułu i pakietu), choć właściwie całą, nawet bardziej skomplikowaną aplikację można zawrzeć w jednym pliku *.py.</p>
<p>Python daje duże możliwości. Może być stosowany przy projektach z wielu dziedzin, jako język podstawowy, jak i uzupełniający. Zbudujemy w nim GUI (pyGTK), napiszemy testy jednostkowe (pyUnit), utworzymy zwięzły i treściwy skrypcik użytkowy, dostarczymy plugin do Firefox&#8217;a, tudzież rozszerzenie do Blender&#8217;a, połączymy się z relacyjną bazą danych, obsłużymy dokumenty XML (wbudowane parsery SAX i DOM, narzędzia walidacji, transformacji XML, dodatkowy pakiet PyXML), wreszcie w parudziesięciu liniach zmieścimy prostego klienta email, czy komunikator sieciowy, postawimy aplikację webową (framework Django), w międzyczasie korzystając z bibliotek pisanych w C lub C++.</p>
<p><strong>Ok. Gdzie jest haczyk</strong><strong>?</strong></p>
<p>Python może nie wydawać się stabilną platformą, jeśli w danym momencie korzysta się z elementów, które z czasem się zmieniają. Jeśli chce się budować większą aplikację, warto trzymać się jednej wersji języka. Niestety takie podejście też nie jest najlepsze, bo:</p>
<ul>
<li> Nowsze wersje bibliotek zazwyczaj powstają tylko dla najnowszych wersji Pythona</li>
<li> Pewne nowe elementy Pythona mogą spowodować subtelne zmiany w działaniu aplikacji, które nie dadzą się łatwo wykryć. To z pewnością nie sprzyja biznesowi.</li>
</ul>
<p>Weźmy konkretny przykład. W Pythonie 2.3.4 i wcześniejszym poniższy snippet powoduje wygenerowanie wyniku, którego oczekuje się po programie napisanym w C:</p>
<pre style="color: #000000;background: #ffffff"><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #800000;font-weight: bold">print</span> <span style="color: #0000e6">"%x"</span> <span style="color: #808030">%</span> <span style="color: #808030">-</span><span style="color: #008c00">2</span>
fffffffe</pre>
</p>
<p>Poczynając od wersji 2.4 widzimy z goła odmienny wynik:</p>
<pre style="color: #000000;background: #ffffff"><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span><span style="color: #808030">&gt;</span> <span style="color: #800000;font-weight: bold">print</span> <span style="color: #0000e6">"%x"</span> <span style="color: #808030">%</span> <span style="color: #808030">-</span><span style="color: #008c00">2</span>
<span style="color: #808030">-</span><span style="color: #008c00">2</span></pre>
</p>
<p>Przedstawiona zmiana może wydawać się błaha, ale tak nie jest. W nowszej wersji Pythona zmianie uległ sposób traktowania liczb całkowitych bez znaku. Ponieważ z liczb całkowitych korzysta się nawet w najmniejszym skrypcie, tego rodzaju zmiana może nieść kolosalne konsekwencje.</p>
<p>Innymi słowy &#8211; Python jest na tyle młodym językiem, że jego twórcy na razie nie przejmują się kwestiami zgodności i stabilności (przynajmniej nie tak bardzo jak w Javie, w której cykle życia oprogramowania obejmują niejednokrotnie 10 lat).</p>
<p>Python to nie tylko maszyna wirtualna, API i składnia &#8211; to także zbiór bibliotek otaczających podstawowe funkcje systemu operacyjnego. Z założenia skrypty pythonowe mają być przenośne pomiędzy systemami operacyjnymi i hardware&#8217;m. Często ochrona przed różnicami pomiędzy systemami jest iluzoryczna, zwłaszcza w kwestii obsługi protokołów sieciowych i wielowątkowości. Np. interfejs gniazd sieciowych, stosowany w wielu programach, zgłasza inne wyjątki pod Windows, a inne pod *nix. Więc albo wyłapuje się wszystkie wyjątki, albo stosuje się osobny kod dla tych przypadków.</p>
<p>Z mojego, subiektywnego punktu widzenia mechanizm dołączania dodatkowych zewnętrznych bibliotek do instancji Pythona jest niekiedy mocno przesadzony. Nie wszystkie biblioteki wymagają instalacji &#8211; niektóre zwyczajnie wrzucamy do katalogu PythonXX\Lib\site-packages i po wykonaniu odpowiedniej instrukcji importu od razu są widoczne z poziomu interpretera. Inne biblioteki dostarczają cały instalator, który teoretycznie powinien wszystkim się zająć.<br />
Ku przestrodze: Instalacja Pythona 2.6.7 pod 64bitowym Windows7 nie powinna stwarzać problemów. Jednak potem doinstalowanie dodatkowych modułów może okazać się już nie takie proste &#8211; biblioteka szuka w rejestrze informacji o ścieżkce instalacji wymaganej wersji Pythona &#8211; i nic nie znajduje. Wtedy niezwykle irytujący staje się fakt, że byle biblioteka (której kod pewnie mieści się na paru ekranach), z wielce wyszukanym instalatorem, jest nie do zainstalowania, choćbyśmy ściągali coraz to inne wersje i samego Pythona i rozszerzeń. Jakby tego było mało &#8211; deinstalacja pod Win7 trwa ~8minut, i zostawia po sobie multum śmieci, m.in. w katalogach systemowych.</p>
<p>Dużym minusem jest brak możliwości debuggowania wątków (oczywiście można próbować to &#8222;obejść&#8221; przy pomocy logger&#8217;a, lub pisząc dokładne testy jednostkowe).</p>
<p><strong>Outro</strong></p>
<p>Python jest narzędziem zorientowanym na maksymalną zwięzłość, prostotę i wysoki stopień abstrakcji. Dzięki temu pozwala na szybkie i efektywne tworzenie aplikacji. Pozwala skupić się na samej funkcjonalności programu, odkładając kwestie niskopoziomowe na dalsze tło. Byłby świetnym wyborem, kiedy przyjdzie potrzeba napisania na szybko prostego skryptu, czy niewielkiej aplikacji w ramach uczelnianego projektu. Zdaje się, że nie jest to jeszcze język na tyle dojrzały, ustabilizowany i konsekwentny, aby na jego podstawie pisać rozbudowane aplikacje biznesowe o długim cyklu życia. Chyba, że jako wyjątkowo wysoko-poziomowy język uzupełniający, stanowiący niewielką część całości aplikacji.</p>
<p><strong>Polecam</strong></p>
<p><a title="http://stackoverflow.com/questions/101268/hidden-features-of-python" href="http://stackoverflow.com/questions/101268/hidden-features-of-python" target="_blank">http://stackoverflow.com/questions/101268/hidden-features-of-python</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/python-widziany-okiem-javianina/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Kiedy i dlaczego tworzyć oprogramowanie pod klucz i dlaczego framework Symfony2 pasuje tu jak ulał?</title>
		<link>http://xlab.pl/kiedy-i-dlaczego-tworzyc-oprogramowanie-pod-klucz-i-dlaczego-framework-symfony2-pasuje-tu-jak-ulal/</link>
		<comments>http://xlab.pl/kiedy-i-dlaczego-tworzyc-oprogramowanie-pod-klucz-i-dlaczego-framework-symfony2-pasuje-tu-jak-ulal/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 07:38:03 +0000</pubDate>
		<dc:creator>Wojtek Sznapka</dc:creator>
				<category><![CDATA[Programowanie PHP]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[oprogramowanie dedykowane]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1843</guid>
		<description><![CDATA[Gotowe rozwiązania Open Source Na rynku istnieje mnóstwo rozwiązań Open Source, rozwiązujące różne klasy zagadnień. Mowa tu o produktach e-commerce (Magento, Presta Shop), CMS (Drupal, Joomla, WordPress), systemach klasy CRM, ERP, czy DMS, a także „community builders”, czyli np. fora internetowe (PHP BB). W zdecydowanej większości powyższych przypadków nie potrzeba wiedzy programistycznej aby wdrożyć i [...]]]></description>
			<content:encoded><![CDATA[<h2>Gotowe rozwiązania Open Source</h2>
<p>Na rynku istnieje mnóstwo rozwiązań Open Source, rozwiązujące różne klasy zagadnień. Mowa tu o produktach e-commerce (Magento, Presta Shop), CMS (Drupal, Joomla, WordPress), systemach klasy CRM, ERP, czy DMS, a także „community builders”, czyli np. fora internetowe (PHP BB). W zdecydowanej większości powyższych przypadków nie potrzeba wiedzy programistycznej aby wdrożyć i rozwijać serwisy. Mają one obszerne zbiory rozszerzeń i wtyczek (plugins), które pozwalają dostosowywać systemy do potrzeb. Takie podejście pozwala na znaczne zmniejszenie kosztów wdrożenia aplikacji.</p>
<p>Pomimo tych zalet, często jest tak, że systemy te pasują do prostych modeli biznesowych, które w życiu codziennym występują nad wyraz rzadko. W starciu z rzeczywistością, wdrażanie takich systemów, a przede wszystkim utrzymanie i reakcje na rozwój rynku mają przełożenie na zasadę Pareto, która mówi o tym, że 80% funkcjonalności jesteśmy w stanie osiągnąć w 20% czasu, a 20% krytycznych funkcji systemu konsumuje 80% budżetu.</p>
<p>Głównymi problemami z jakimi spotykają się wdrożenia oparte o gotowe rozwiązania to przede wszystkim komplikacja logiki biznesowej systemu, której nie da się odwzorować na możliwości produktu. Często dochodzi do paradoksalnych sytuacji, w których model biznesowy trzeba dopasowywać do systemu, co nigdy nie powinno mieć miejsca. Inną kwestia jest rozwój aplikacji i zwiększenie ruchu, które powoduje, że dobrze działające oprogramowanie dla małej liczby użytkowników staje się bezużyteczne przy wielkim obciążeniu. Poza tym istnieje potencjalne ryzyko związane z atakami hakerskimi, gdyż kod jest otwarty i dostępny dla potencjalnych włamywaczy. Aby dostrzec skalę problemu, wystarczy przejrzeć serwisy z dostępnymi exploitami. Ostatnią kwestią, która przychodzi w tym momencie na myśl, jest to, że czasem społeczność rozwijająca dany produkt, w pewnym etapie może zaprzestać dalszych prac. Powodów może być kilka, raz jest to skłócenie zespołu, innym razem przejście na nową technologię, lub do innego projektu, pozostawiając dotychczasowych użytkowników samych sobie.</p>
<h2>Zalety tworzenia oprogramowania dedykowanego</h2>
<p>Wszystkie problemy opisane powyżej rozwiązuje oprogramowanie dedykowane, a nawet można się pokusić o stwierdzenie, że wnosi tutaj wiele wartości dodanych. Przede wszystkim klient dostaje dokładnie to czego potrzebuje i za co płaci. Oczywiście trzeba mieć na względzie, że nie każdy klient jest osobą techniczną i nie koniecznie musi mieć doświadczenie z systemami informatycznymi, więc doradztwo technologiczne jest tutaj nieocenioną wartością. Firma programistyczna na etapie przygotowania oferty doradza klientowi najlepsze rozwiązania, proponuje pewne opcje, tworząc przy tym najlepszą możliwą ofertę, budując relację i zaufanie z zamawiającym. Dzięki temu klient odzwierciedla swój model biznesowy w tworzonym systemie, nastawiając się na zysk z inwestycji w przyszłości. Poza tym oprogramowanie jest gotowe na rozwój, co jest bardzo ważnym czynnikiem, gwarantującym skuteczność przedsięwzięcia i reakcję na sygnały spływające od użytkowników lub na trendy rynkowe. Ważnym czynnikiem  jest tutaj również samopoczucie programistów, którzy nie klikają  w panelach administracyjnych Drupala czy Magento, ale programują i rozwiązują problemy, realizując się przy tym zawodowo.</p>
<h2>Nie wynajdujemy koła od nowa, czyli o frameworkach słów kilka</h2>
<p>Framework to z definicji zestaw uniwersalnych narzędzi na bazie których tworzy się aplikacje. Nie wyobrażalne jest, aby w tych czasach tworzyć systemy informatyczne bez wykorzystania takiego narzędzia. Aby lepiej zobrazować temat, możemy porównać do płyty podwoziowej samochodu. Daje nam ona wszelkie potrzebne mechanizmy, czyli ramę całego auta, łożyska, układ wydechowy, wiązki elektryczne. Na takiej ramie możemy stworzyć wiele rodzajów samochodów, np. pickup, miejski hatchback, średniej klasy sedan, lub ekskluzywny, drogi wóz. Podobnie jest z frameworkiem – zapewnia mechanizmy potrzebne w większości systemów. Mowa przede wszystkim o kontrolerze aplikacji, reagującym na żądania użytkownika, warstwie widoku, prezentującą dane w formie graficzne, warstwie dostępu do bazy danych, mechanizmie bezpieczeństwa, pozwalającą na autoryzowanie użytkowników i ograniczanie dostępu do poszczególnych części serwisu. To tylko niektóre z rozwiązań, nowoczesne frameworki dostarczają wiele więcej. Inną kwestią jest standaryzacja kodu tworzonego przy ich użyciu. Jest o wiele łatwiej nowej osobie wejść w projekt, jeśli framework narzuca standardy kodowania i rozwiązania umieszczane są w odpowiedniej strukturze kodu. Pozwala to na szybsze wdrażanie się nowych członków zespołu, a co za tym idzie na przyspieszenie całego rozwoju.</p>
<p>Jest jeszcze jedna ważna kwestia, która decyduje o sukcesie danego frameworka – liczba gotowych rozwiązań w postaci wtyczek lub komponentów. Jest to sytuacja analogiczna do gotowych rozwiązań Open Source, z tym, że tutaj łatwo rozszerzyć dany komponent oraz dostosować go do wymagań systemu. Mamy też zapewnione wsparcie społeczności w kwestii rozwiązywania problemów, tworzenia nowych funkcjonalności czy aktualizacji i wydawania poprawek.</p>
<h2>Dlaczego Symfony2 pasuje tutaj jak ulał?</h2>
<p>Symfony2 kontynuuje dobrą passę swojego poprzednika, który istnieje już 6 lat. Programiści wyciągnęli naukę z poprzedniej wersji, podpatrzyli rozwiązania z innych platform (Java, Ruby On Rails, Python i Django, czy Zend Framework) i przepisali całość od podstaw. Dzięki temu powstał najlepszy aktualnie framework PHP, który wygrywa przede wszystkim bardzo dobrą strukturą niezależnych modułów, które można rozwijać oddzielnie, a nawet wykorzystywać w innych projektach. Autorzy przewidzieli strukturę projektu tworząc tzw. Bundle, które są modułami, gotowymi do użycia w innych projektach (nawet wnętrze frameworka się z nich składa). W tym momencie warto wspomnieć o Bundlach dostarczanych przez programistów i firmy zewnętrzne (jest ich już prawie 600). Całość systemu jest oparta o nowoczesny kontener wstrzykiwania zależności (Dependency Injection Container), przez co podmiana kluczowych części systemu może być zrobiona w mgnieniu oka (to rozwiązanie bardzo szeroko stosuje się w Java EE oraz innych dojrzałych rozwiązaniach). Warto też zauważyć, że autorzy duży nacisk kładą na wydajność i szybkość działania, co jest zauważalne na pierwszy rzut oka, bez wnikliwych badań obciążeniowych.</p>
<p>O powadze sytuacji świadczy też fakt, że Symfony2 zostało w całości przeniesione do gita i jego kod jest utrzymywany w serwisie Github.com.  Dzięki temu każdy może go sklonować kod źródłowy, pracować na nim lokalnie wprowadzając poprawki czy tworząc nowe funkcjonalności, a później jednym kliknięciem wysłać prośbę o włączenie swoich zmian do głównego repozytorium. To powoduje, że na dzień dzisiejszy Symfony2 jest najczęściej rozgałęzianym  i najchętniej oglądanym repozytorium PHP na Githubie, a liczba osób, które miały swój wkład w rozwój przekracza 250. Poza tym za frameworkiem stoi francuska firma Sensio Labs, wraz z założycielem i głównym programistą Fabienem Potencierem. Ten fakt zapewnia stabilność rozwoju, wysoką jakość dokumentacji oraz dostępność szkoleń i materiałów. Firma ta zorganizowała nawet zbiórkę pieniędzy wśród społeczności i zleciła audyt bezpieczeństwa organizacji zajmującej się tego typu działaniami .</p>
<p>Reasumując, trzeba przyznać, że Symfony2 zrewolucjonizowało świat frameworków PHP, a można się nawet pokusić o stwierdzenie, że programiści innych języków (Python, Ruby, Groovy) też z szacunkiem patrzą na to rozwiązanie. Symfony2 idealnie nadaje się do rozwoju aplikacji dedykowanych i na pewno można go polecić do większości projektów.</p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/kiedy-i-dlaczego-tworzyc-oprogramowanie-pod-klucz-i-dlaczego-framework-symfony2-pasuje-tu-jak-ulal/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>RESTful Symfony2</title>
		<link>http://xlab.pl/restful-symfony2/</link>
		<comments>http://xlab.pl/restful-symfony2/#comments</comments>
		<pubDate>Mon, 01 Aug 2011 21:25:34 +0000</pubDate>
		<dc:creator>Wojtek Sznapka</dc:creator>
				<category><![CDATA[Programowanie PHP]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[symfony2]]></category>
		<category><![CDATA[webservice]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1840</guid>
		<description><![CDATA[Jakiś czas temu na cotygodniowym evencie &#8222;Piątek z XSolve&#8221; przedstawiłem prezentację pt. &#8222;RESTful Symfony2&#8243;, opisującą jak w łatwy sposób przy użyciu frameworka Symfony2 i rozszerzenia RestBundle tworzyć API REST. RestBundle jest rozwijane przez grupę programistów Friends Of Symfony, którzy w większości tworzą również rdzeń frameworka. Zachęcam do zapoznania się z prezentacją i wypróbowania możliwości zarówno [...]]]></description>
			<content:encoded><![CDATA[<p>Jakiś czas temu na cotygodniowym evencie &#8222;Piątek z XSolve&#8221; przedstawiłem prezentację pt. &#8222;RESTful Symfony2&#8243;, opisującą jak w łatwy sposób przy użyciu frameworka Symfony2 i rozszerzenia RestBundle tworzyć API REST. RestBundle jest rozwijane przez grupę programistów Friends Of Symfony, którzy w większości tworzą również rdzeń frameworka. Zachęcam do zapoznania się z prezentacją i wypróbowania możliwości zarówno Symfony2 jak i FOSRestBundle.<span id="more-1840"></span></p>
<div class="prezi-player">
<style type="text/css" media="screen">.prezi-player { width: 650px; } .prezi-player-links { text-align: center; }</style>
<p><object id="prezi_wh4xxmz1uiar" name="prezi_wh4xxmz1uiar" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="650" height="500"><param name="movie" value="http://prezi.com/bin/preziloader.swf"/><param name="allowfullscreen" value="true"/><param name="allowscriptaccess" value="always"/><param name="bgcolor" value="#ffffff"/><param name="flashvars" value="prezi_id=wh4xxmz1uiar&amp;lock_to_path=0&amp;color=ffffff&amp;autoplay=no&amp;autohide_ctrls=0"/><embed id="preziEmbed_wh4xxmz1uiar" name="preziEmbed_wh4xxmz1uiar" src="http://prezi.com/bin/preziloader.swf" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="650" height="500" bgcolor="#ffffff" flashvars="prezi_id=wh4xxmz1uiar&amp;lock_to_path=0&amp;color=ffffff&amp;autoplay=no&amp;autohide_ctrls=0"></embed></object>
<div class="prezi-player-links">
<p><a title="</p>
<p>                            W prezentacji opiszę jak w łatwy sposób szybko tworzyć usługi SOA komunikujace się RESTem w Symfony2.</p>
<p>                        " href="http://prezi.com/wh4xxmz1uiar/restful-symfony2/">RESTful Symfony2</a> on <a href="http://prezi.com">Prezi</a></p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/restful-symfony2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>XSolve Poland Symfony2 Launch Party</title>
		<link>http://xlab.pl/xsolve-poland-symfony2-launch-party/</link>
		<comments>http://xlab.pl/xsolve-poland-symfony2-launch-party/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 13:18:07 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Ogólne]]></category>
		<category><![CDATA[Programowanie PHP]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[premiera php]]></category>
		<category><![CDATA[RC6]]></category>
		<category><![CDATA[symfony2]]></category>
		<category><![CDATA[symfony2 premiera]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1824</guid>
		<description><![CDATA[W czwartek 28.07 odbędzie się oficjalna premiera Symfony2, następcy jednego z najpopularniejszych frameworków PHP, którego stworzenie zajęło grupie 225 osób z całego świata ponad półtora roku. Nowoczesny framework posiada kilkadzieisiąt nowych rozszerzeń oraz przepisany w całości rdzeń, a programiści śledzący jego rozwój doskonały powód do świętowania. W wielu miastach na całym świecie odbywają się imprezy związane [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;"><strong>W czwartek 28.07 odbędzie się oficjalna premiera Symfony2, następcy jednego z najpopularniejszych frameworków PHP, którego stworzenie zajęło grupie 225 osób z całego świata ponad półtora roku. Nowoczesny framework posiada kilkadzieisiąt nowych rozszerzeń oraz przepisany w całości rdzeń, a programiści śledzący jego rozwój doskonały powód do świętowania.</strong></p>
<p style="text-align: justify;">W wielu miastach na całym świecie odbywają się imprezy związane z premierą Symfony2. Także w Polsce programiści i osoby zainteresowane rozwojem tego frameworka będą mogły spotkać się i porozmawiać o jego możliwościach i zastosowaniach. W Gliwicach w siedzibie firm XSolve (branża software development) oraz Chilid (agencja New Marketing) w czwartek (28.07) odbędzie się XSolve Poland Symfony2 Launch Party! Impreza ma charakter otwarty i skierowana jest głównie do programistów pracujących we frameworku Symfony2 oraz osób działających w branży IT. Impreza organizowana jest przy promocyjnym wsparciu Wydawnictwa Helion, które zapewniło wartościowe nagrody dla gości, którzy wezmą udział w zaplanowanych konkursach.</p>
<p style="text-align: justify;">Spotkanie rozpocznie się o godzinie 17.00, w trakcie jego trwania odbędzie się prezentacja Symfony2, będzie również możliwość wymiany doświadczeń z programistami XSolve, którzy na co dzień korzystają z tego frameworka.</p>
<p style="text-align: justify;"><a href="http://www.facebook.com/event.php?eid=124217561004636" target="_blank">Polub wydarzenie na Facebooku!</a></p>
<p style="text-align: center;"><a href="http://xlab.pl/wp-content/uploads/2011/07/plakat_biel1.jpg"><img class="aligncenter size-full wp-image-1828" title="Symfony XSolve" src="http://xlab.pl/wp-content/uploads/2011/07/plakat_biel1.jpg" alt="symfony2, symfony, php, programowanie, framework symfony, framework" width="357" height="505" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/xsolve-poland-symfony2-launch-party/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>XSolve na konferencji Confitura 2011</title>
		<link>http://xlab.pl/xsolve-na-konferencji-confitura-2011/</link>
		<comments>http://xlab.pl/xsolve-na-konferencji-confitura-2011/#comments</comments>
		<pubDate>Mon, 13 Jun 2011 22:23:18 +0000</pubDate>
		<dc:creator>Wojtek Sznapka</dc:creator>
				<category><![CDATA[Programowanie Java]]></category>
		<category><![CDATA[confitura]]></category>
		<category><![CDATA[domain-driven design]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[konferencja]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1819</guid>
		<description><![CDATA[W minioną sobotę sześcioosobowa delegacja firmy  XSolve wzięła udział w konferencji Confitura 2011. Impreza organizowana przez grupę Warszawa JUG była poświęcona głównie technologii Java, ale nie zabrakło też nowinek z okolic Javy, czyli Scali, NoSQL, cloud computingu czy różnych tematów architektonicznych. Jednogłośnie uznaliśmy, że najlepszym wykładem był Domain-Driven Design Sławomira Sobótki, który w bardzo przystępny [...]]]></description>
			<content:encoded><![CDATA[<p>W minioną sobotę sześcioosobowa delegacja firmy  XSolve wzięła udział w konferencji <a href="http://confitura.pl">Confitura 2011</a>. Impreza organizowana przez grupę Warszawa JUG była poświęcona głównie technologii Java, ale nie zabrakło też nowinek z okolic Javy, czyli Scali, NoSQL, cloud computingu czy różnych tematów architektonicznych.<span id="more-1819"></span></p>
<p>Jednogłośnie uznaliśmy, że najlepszym wykładem był Domain-Driven Design Sławomira Sobótki, który w bardzo przystępny sposób pokazał tą technikę projektowania i modelowania systemów. DDD ma zastosowanie szczególnie tam, gdzie model domenowy jest bardzo złożony, a czas życia systemu liczy się w latach.</p>
<p>Ciekawa była również prezentacja Bartka Majsaka &#8222;Jak wycisnąć maksimum z testów&#8221;. TDD nie jest nam obce, ale podejścia jakie pokazał Bartek bardzo nam przypadły do gusty. W szczególności mam tu na myśli testy behawioralne oraz nagrywanie wykonania testów techniką screen-capture, co pozwala nam błyskawicznie przejrzeć testy funkcjonalne, które nie zakończyły się sukcesem.</p>
<p>Dwa wykłady były poświęcone tylko i wyłącznie Scali, którą nazywa się czasem następcą Javy. W szczególności pasowały one Pawłowi, który jest zapalonym miłośnikiem tej technologii i firmowy ekspertem w tej dziedzinie. Szczególnie zaciekawiło nas usytyuowanie Scali w klasie rozwiązań Enterprise, które prezentował Paweł Dolega.</p>
<p>Oczywiście nie ominęliśmy też prelekcji o architekturze modelu dla rozwiązań NoSQL. Prowadzący spotkał się z niemałymi sprzeciwami z widowni, dzięki czemu prezentacja nabrała dynamiki i zmusiła Jarosława do usilnego bronienia swoich poglądów :-)</p>
<p>Podsumowując, konferencję oceniamy pozytywnie. Nie ma zarzutów co do organizacji, która była na prawdę na wysokim poziomie, aczkolwiek mieliśmy wrażenie, że 45 minutowe prezentacje rzadko komu wystarczały, żeby przeprowadzić pełny wykład. Większość prelekcji była dobrze przygotowana i przeprowadzona, aczkolwiek zdarzały się też takie, które wymagają większego wysiłku w przyszłości :-) Generalnie Confiturę uznajemy za udaną i z chęcią wybierzemy się również w przyszłym roku.</p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/xsolve-na-konferencji-confitura-2011/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>.NET i memory leak?! czyli dzień z życia programisty</title>
		<link>http://xlab.pl/net-i-memory-leak-czyli-dzien-z-zycia-programisty/</link>
		<comments>http://xlab.pl/net-i-memory-leak-czyli-dzien-z-zycia-programisty/#comments</comments>
		<pubDate>Fri, 01 Apr 2011 10:53:37 +0000</pubDate>
		<dc:creator>Jarek Kożdoń</dc:creator>
				<category><![CDATA[Programowanie .NET]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[Memory leak]]></category>
		<category><![CDATA[Profiler]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[XAML]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1796</guid>
		<description><![CDATA[Dzisiaj historia z życia wzięta – czyli ponad dzień pracy programisty. Akcja będzie wartka, a potencjalnemu czytelnikowi zalecam wczytanie do pamięci RAM wewnątrz głów dll&#8217;ek z zasobami o WPF&#8217;ie. Zaczęło się niewinnie, przyszło zgłoszenie od testerów, że aplikacja zajmuje strasznie dużo pamięci, a przy wykonywaniu pewnej operacji ta zajętość jeszcze rośnie i wielce nazywać to [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #000000">Dzisiaj historia z życia wzięta – czyli ponad dzień pracy programisty. Akcja będzie wartka, a potencjalnemu czytelnikowi zalecam wczytanie do pamięci RAM wewnątrz głów dll&#8217;ek z zasobami o WPF&#8217;ie.</span></p>
<p><span style="color: #000000">Zaczęło się niewinnie, przyszło zgłoszenie od testerów, że aplikacja zajmuje strasznie dużo pamięci, a przy wykonywaniu pewnej operacji ta zajętość jeszcze rośnie i wielce nazywać to chcieli memory leakiem. Jako programista raczej nie dowierzałem, przecież w dot-necie tak być nie może, zgodnie z teorią pamięć sama się zwalnia, Pan Garbage Collector robi wszystko za nas&#8230; pomijając fakt że programista generalnie nie wierzy testerom, którzy zawsze szukają dziury w całym&#8230;</span></p>
<p><span style="color: #000000">ot&#8230; teoretycznie&#8230;</span></p>
<p><strong><span style="color: #000000">Godzina 1</span></strong></p>
<p><span style="color: #000000">kawa i te sprawy&#8230; partyjka piłkarzyków, przecież zadanie na pewno zostanie odbite!</span></p>
<p><strong><span style="color: #000000">Godzina 2</span></strong></p>
<p><span style="color: #000000">Sprawdzam – i już widzę, że jednak coś jest na rzeczy. Coś się nie zwalnia. Dziwne&#8230;</span></p>
<p><strong><span style="color: #000000">Godzina 3</span></strong></p>
<p><span style="color: #000000">No tak – testerzy jak to w ich zwyczaju coś znaleźli, ale sami nie wiedzieli co. Nie trzeba nawet wykonywać zgłoszonej akcji&#8230; wystarczy wejść do okienka i wyjść z niego. I tak kilka razy i task manager poda nam jakieś fantastyczne, zawrotne sumy pożeranej przez naszą aplikację pamięci.</span></p>
<p><strong><span style="color: #000000">Godzina 4</span></strong></p>
<p><span style="color: #000000">Kod przeanalizowany, wszystko co trzeba zdaje się być zwalniane. Wszystko gra, a jednak&#8230; jednak nie&#8230; Powoli pojawiają się jednak promyki nadziei na znalezienie przyczyny.</span></p>
<p><strong><span style="color: #000000">Godzina 5</span></strong></p>
<p><span style="color: #000000">Nadzieja rośnie, podejrzany jest namierzony – udało się zablokować przeciek. Ale coś jednak tutaj nie pasuje, coś jest nie-tak. Bug niby zwalczony, ale wewnątrz płonie ogień buntu, że przecież to nie była faktyczna przyczyna. Trzeba sięgnąć po cięższą artylerię. Trzeba skombinować jakiegoś profilera z opcją analizy pamięci. Na pierwszy ogień idzie <strong>ANTS Memory Profiler</strong> firmy <strong>Red Gate</strong> („tej od .<strong>NET Reflectora</strong>”). Piłkarzyki, kawa&#8230; w końcu musi się pobrać i zainstalować (tak trochę tej kawy dzisiaj&#8230; to piątek, zmęczenie tygodnia się kumuluje, a rano wstałem o 5:15&#8230; pobiegać&#8230;)</span></p>
<p><strong><span style="color: #000000">Godzina 6</span></strong></p>
<p><span style="color: #000000">Profiler odpalony, bardzo pozytywne zaskoczenie, intuicyjność pierwsza klasa, bez czytania tutoriali, bez instrukcji w ciągu kilku minut znajduję – prawdziwą przyczynę błędu. Otóż okienko WPF zostaje w pamięci, a jest trzymane przez&#8230; przez jego własną kontrolkę! Przecież to niemożliwe&#8230; przecież „<strong>GC</strong>” wykrywa i cykliczne referencje i w ogóle te wszystkie szmery bajery&#8230;</span></p>
<p><span style="color: #000000">Mija jeszcze kilka chwil zanim ogarnę cały temat&#8230;</span></p>
<p><span style="color: #000000">Sprawdzam co to za kontrolka, Google, dokumentacja MSDN i robi mi się smutno, dopisuję 1 (słownie jedną) linię kodu i „fixuję buga w JIRA&#8217;ze”.</span></p>
<p><span style="color: #000000">Po przydługim wstępie wytłumaczenie na przykładzie, dla uproszczenia malutka aplikacja WPF – 2 formatki i jedna klasa oczywiście:</span></p>
<h3><span style="color: #000000">Okienko główne z buttonem i akcją otwierającą nowe okienko:</span></h3>
<p><span style="color: #0000ff"><span style="font-size: small">&lt;</span></span><span style="color: #a31515"><span style="font-size: small">Window</span></span><span style="color: #ff0000"><span style="font-size: small"> x</span></span><span style="color: #0000ff"><span style="font-size: small">:</span></span><span style="color: #ff0000"><span style="font-size: small">Class</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;MemoryLeaking.Window1&#8243;<br />
</span></span><span style="color: #ff0000"><span style="font-size: small">xmlns</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;<br />
</span></span><span style="color: #ff0000"><span style="font-size: small">xmlns</span></span><span style="color: #0000ff"><span style="font-size: small">:</span></span><span style="color: #ff0000"><span style="font-size: small">x</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;http://schemas.microsoft.com/winfx/2006/xaml&#8221;<br />
</span></span><span style="color: #ff0000"><span style="font-size: small">Title</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;Window1&#8243;</span></span><span style="color: #ff0000"><span style="font-size: small"> Height</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;170&#8243;</span></span><span style="color: #ff0000"><span style="font-size: small"> Width</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;306&#8243;&gt;<br />
</span></span><span style="color: #0000ff"><span style="font-size: small">&lt;</span></span><span style="color: #a31515"><span style="font-size: small">Grid</span></span><span style="color: #0000ff"><span style="font-size: small">&gt;<br />
</span></span><span style="color: #0000ff"><span style="font-size: small">&lt;</span></span><span style="color: #a31515"><span style="font-size: small">Button</span></span><span style="color: #ff0000"><span style="font-size: small"> Margin</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;50,50,50,50&#8243;</span></span><span style="color: #ff0000"><span style="font-size: small"> Click</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;Button_Click&#8221;&gt;</span></span><span style="color: #a31515"><span style="font-size: small">Take the RAM!</span></span><span style="color: #0000ff"><span style="font-size: small">&lt;/</span></span><span style="color: #a31515"><span style="font-size: small">Button</span></span><span style="color: #0000ff"><span style="font-size: small">&gt;<br />
</span></span><span style="color: #0000ff"><span style="font-size: small">&lt;/</span></span><span style="color: #a31515"><span style="font-size: small">Grid</span></span><span style="color: #0000ff"><span style="font-size: small">&gt;<br />
</span></span><span style="color: #0000ff"><span style="font-size: small">&lt;/</span></span><span style="color: #a31515"><span style="font-size: small">Window</span></span><span style="color: #0000ff"><span style="font-size: small">&gt;</span></span></p>
<p><span style="color: #0000ff"><span style="font-size: small">namespace</span></span><span style="color: #000000"><span style="font-size: small"> <span style="color: #000000">MemoryLeaking</span><br />
</span></span><span style="font-size: small">{<br />
</span><span style="color: #808080"><span style="font-size: small">///</span></span><span style="color: #008000"><span style="font-size: small"> </span></span><span style="color: #808080"><span style="font-size: small">&lt;summary&gt;<br />
</span></span><span style="color: #808080"><span style="font-size: small">///</span></span><span style="color: #008000"><span style="font-size: small"> Interaction logic for Window1.xaml<br />
</span></span><span style="color: #808080"><span style="font-size: small">///</span></span><span style="color: #008000"><span style="font-size: small"> </span></span><span style="color: #808080"><span style="font-size: small">&lt;/summary&gt;<br />
</span></span><span style="color: #0000ff"><span style="font-size: small">public</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #0000ff"><span style="font-size: small">partial</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #0000ff"><span style="font-size: small">class</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #2b91af"><span style="font-size: small">Window1</span></span><span style="color: #000000"><span style="font-size: small"> : </span></span><span style="color: #2b91af"><span style="font-size: small">Window<br />
</span></span><span style="font-size: small">{<br />
</span><span style="color: #0000ff"><span style="font-size: small">public</span></span><span style="color: #000000"><span style="font-size: small"> <span style="color: #000000">Window1()<br />
</span></span></span><span style="color: #000000"><span style="font-size: small">{<br />
</span><span style="font-size: small">InitializeComponent();<br />
</span></span><span style="font-size: small"><span style="color: #000000">}<br />
</span> </span><span style="color: #0000ff"><span style="font-size: small"><br />
private</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #0000ff"><span style="font-size: small">void</span></span><span style="color: #000000"><span style="font-size: small"> <span style="color: #000000">Button_Click</span>(</span></span><span style="color: #0000ff"><span style="font-size: small">object</span></span><span style="color: #000000"><span style="font-size: small"> sender, </span></span><span style="color: #2b91af"><span style="font-size: small">RoutedEventArgs</span></span><span style="color: #000000"><span style="font-size: small"> e)<br />
</span></span><span style="font-size: small">{<br />
</span><span style="color: #0000ff"><span style="font-size: small">new</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #2b91af"><span style="font-size: small">MemoryTakingWindow</span></span><span style="color: #000000"><span style="font-size: small">().ShowDialog();<br />
</span></span><span style="color: #2b91af"><span style="font-size: small">GC</span></span><span style="color: #000000"><span style="font-size: small">.Collect();<br />
</span></span><span style="color: #000000"><span style="font-size: small">}<br />
</span><span style="font-size: small">}<br />
</span><span style="font-size: small">}</span></span></p>
<h3><span style="color: #000000">Klasa „zjadająca RAM” (banalnie prosta – lista stringów, do każdego przypisujemy GUID):</span></h3>
<p><span style="color: #0000ff"><span style="font-size: small">namespace</span></span><span style="color: #000000"><span style="font-size: small"> MemoryLeaking<br />
</span></span><span style="font-size: small">{<br />
</span><span style="color: #0000ff"><span style="font-size: small">class</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #2b91af"><span style="font-size: small">MemoryTakingClass<br />
</span></span><span style="font-size: small">{<br />
</span><span style="color: #0000ff"><span style="font-size: small">private</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #2b91af"><span style="font-size: small">List</span></span><span style="color: #000000"><span style="font-size: small">&lt;</span></span><span style="color: #0000ff"><span style="font-size: small">string</span></span><span style="color: #000000"><span style="font-size: small">&gt; MemoryTaker;<br />
</span></span><span style="font-size: small"><br />
</span><span style="color: #0000ff"><span style="font-size: small">public</span></span><span style="color: #000000"><span style="font-size: small"> MemoryTakingClass()<br />
</span></span><span style="font-size: small">{<br />
</span><span style="color: #000000"><span style="font-size: small">MemoryTaker = </span></span><span style="color: #0000ff"><span style="font-size: small">new</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #2b91af"><span style="font-size: small">List</span></span><span style="color: #000000"><span style="font-size: small">&lt;</span></span><span style="color: #0000ff"><span style="font-size: small">string</span></span><span style="color: #000000"><span style="font-size: small">&gt;(100000);<br />
</span></span><span style="color: #0000ff"><span style="font-size: small"><br />
for</span></span><span style="color: #000000"><span style="font-size: small"> (</span></span><span style="color: #0000ff"><span style="font-size: small">int</span></span><span style="color: #000000"><span style="font-size: small"> i = 0; i &lt; 100000; i++)<br />
</span></span><span style="font-size: small"><span style="color: #000000">{</span><br />
</span><span style="color: #000000"><span style="font-size: small">MemoryTaker.Add(</span></span><span style="color: #2b91af"><span style="font-size: small">Guid</span></span><span style="color: #000000"><span style="font-size: small">.NewGuid().ToString());<br />
</span></span><span style="color: #000000"><span style="font-size: small">}<br />
</span><span style="font-size: small">}<br />
</span><span style="font-size: small">}<br />
</span><span style="font-size: small">}</span></span></p>
<h3><span style="color: #000000">Okienko „zjadające RAM”:</span></h3>
<p><span style="color: #0000ff"><span style="font-size: small">&lt;</span></span><span style="color: #a31515"><span style="font-size: small">Window</span></span><span style="color: #ff0000"><span style="font-size: small"> x</span></span><span style="color: #0000ff"><span style="font-size: small">:</span></span><span style="color: #ff0000"><span style="font-size: small">Class</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;MemoryLeaking.MemoryTakingWindow&#8221;<br />
</span></span><span style="color: #ff0000"><span style="font-size: small">xmlns</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;<br />
</span></span><span style="color: #ff0000"><span style="font-size: small">xmlns</span></span><span style="color: #0000ff"><span style="font-size: small">:</span></span><span style="color: #ff0000"><span style="font-size: small">x</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;http://schemas.microsoft.com/winfx/2006/xaml&#8221;<br />
</span></span><span style="color: #ff0000"><span style="font-size: small">xmlns</span></span><span style="color: #0000ff"><span style="font-size: small">:</span></span><span style="color: #ff0000"><span style="font-size: small">winForms</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms&#8221;<br />
</span></span><span style="color: #ff0000"><span style="font-size: small">Title</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;MemoryTakingWindow&#8221;</span></span><span style="color: #ff0000"><span style="font-size: small"> Height</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;134&#8243;</span></span><span style="color: #ff0000"><span style="font-size: small"> Width</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;306&#8243;&gt;<br />
</span></span><span style="color: #0000ff"><span style="font-size: small">&lt;</span></span><span style="color: #a31515"><span style="font-size: small">Grid</span></span><span style="color: #0000ff"><span style="font-size: small">&gt;<br />
</span></span><span style="color: #0000ff"><span style="font-size: small">&lt;</span></span><span style="color: #a31515"><span style="font-size: small">WindowsFormsHost</span></span><span style="color: #ff0000"><span style="font-size: small"> Name</span></span><span style="color: #0000ff"><span style="font-size: small">=&#8221;host&#8221;&gt;&lt;/</span></span><span style="color: #a31515"><span style="font-size: small">WindowsFormsHost</span></span><span style="color: #0000ff"><span style="font-size: small">&gt;<br />
</span></span><span style="color: #0000ff"><span style="font-size: small">&lt;/</span></span><span style="color: #a31515"><span style="font-size: small">Grid</span></span><span style="color: #0000ff"><span style="font-size: small">&gt;<br />
</span></span><span style="color: #0000ff"><span style="font-size: small">&lt;/</span></span><span style="color: #a31515"><span style="font-size: small">Window</span></span><span style="color: #0000ff"><span style="font-size: small">&gt;<br />
</span></span><span style="font-size: small"><span style="color: #0000ff"><br />
namespace</span> MemoryLeaking<br />
</span><span style="font-size: small">{<br />
</span><span style="color: #808080"><span style="font-size: small">///</span></span><span style="color: #008000"><span style="font-size: small"> </span></span><span style="color: #808080"><span style="font-size: small">&lt;summary&gt;<br />
</span></span><span style="color: #808080"><span style="font-size: small">///</span></span><span style="color: #008000"><span style="font-size: small"> Interaction logic for MemoryTakingWindow.xaml<br />
</span></span><span style="color: #808080"><span style="font-size: small">///</span></span><span style="color: #008000"><span style="font-size: small"> </span></span><span style="color: #808080"><span style="font-size: small">&lt;/summary&gt;<br />
</span></span><span style="color: #0000ff"><span style="font-size: small">public</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #0000ff"><span style="font-size: small">partial</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #0000ff"><span style="font-size: small">class</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #2b91af"><span style="font-size: small">MemoryTakingWindow</span></span><span style="color: #000000"><span style="font-size: small"> : </span></span><span style="color: #2b91af"><span style="font-size: small">Window<br />
</span></span><span style="font-size: small">{<br />
</span><span style="color: #0000ff"><span style="font-size: small">public</span></span><span style="color: #000000"><span style="font-size: small"> MemoryTakingWindow()<br />
</span></span><span style="font-size: small">{<span style="color: #000000"><br />
</span></span><span style="font-size: small"><span style="color: #000000">InitializeComponent();</span></span></p>
<p><span style="color: #0000ff"><span style="font-size: small">this</span></span><span style="color: #000000"><span style="font-size: small">.DataContext = </span></span><span style="color: #0000ff"><span style="font-size: small">new</span></span><span style="color: #000000"><span style="font-size: small"> </span></span><span style="color: #2b91af"><span style="font-size: small">MemoryTakingClass</span></span><span style="color: #000000"><span style="font-size: small">();<br />
</span></span><span style="color: #000000"><span style="font-size: small">}<br />
</span><span style="font-size: small">}<br />
</span><span style="font-size: small">}</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Wszystkich estetów wyczulonych na <strong>GC.Collect()</strong> proszę o wybaczenie. Użycie tego wywołania w naszym przykładzie ma bardzo głęboki sens – chodzi o to, by mieć pewność, że w pamięci zajmowanej przez proces będą zajęte wyłącznie bajty rzeczywiście zajęte. Zresztą czasem takie wywołanie <strong>ma </strong>głębszy sens, chociaż oczywiście lepiej go unikać i projektować aplikację tak, by nie było ono potrzebne. To jednak temat na osobne dyskusje.</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Dla wyjaśnienia – oprócz przekopiowania powyższego kodu do własnej aplikacji należy jeszcze dodać do projektu referencję do biblioteki <strong>WindowsFormsIntegration</strong> (z niej pochodzi ta dziwna kontrolka <strong>&lt;WindowsFormsHost&gt;</strong>. Kontrolka służy do hostowania kontrolek pochodzących z tradycyjnych “winformsów” w kontrolkach / oknach <strong>WPF</strong>.</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">I teraz – do dzieła. Najpierw wykres zużycia pamięci dla takiej aplikacji, po kilku wywołaniach okna <em>MemoryTakingWindow</em>:</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><a href="http://xlab.pl/wp-content/uploads/2011/04/memory_leak_11.png"><img class="aligncenter size-full wp-image-1800" src="http://xlab.pl/wp-content/uploads/2011/04/memory_leak_11.png" alt="" width="378" height="158" /></a><br />
</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Gdybyśmy byli budowniczymi moglibyśmy się cieszyć z (prawie) równych schodów, jednak jako programiści wpadamy właśnie w konsternację&#8230; przecież to niemożliwe, żeby takie cyrki działy w aplikacji <strong>.NET</strong>!</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Dokładnie to samo czułem. Pierwsza myśl skierowała mnie na <em>DataContext </em>(tutaj oczywiście uproszczony), gdyż w rzeczywistej aplikacji klasa do niego podpinana zabierała najwięcej pamięci i przechowywała olbrzymie ilości danych. Dokonałem małej modyfikacji w celu weryfikacji podejrzeń – mianowicie do klasy DataContext dodałem finalizer (u nas byłby to <em>~MemoryTakingClass(){ }</em>) i postawiłem tam breakpointa. Breakpoint po kilku minutach miał wciąż tyle trafień, co nasz reprezentacja w ostatnim meczu z Litwą (dla mniej zorientowanych – <strong>0</strong>).</span></span></p>
<p lang="zxx"><span style="font-size: small"><span style="color: #000000">Pierwsza myśl była banalnie prosta, skoro tam gdzieś jakieś zależności się trzymają, to przecież wystarczy odpiąć DataContext od kontrolki! Czyli dodać taki kod:</span></span></p>
<p><span style="font-size: small"><span style="color: #000000"> Closed += ((sender, e) =&gt;<br />
</span></span><span style="font-size: small"><span style="color: #000000">{<br />
</span> </span><span style="color: #0000ff"><span style="font-size: small">this</span></span><span style="color: #000000"><span style="font-size: small">.DataContext = </span></span><span style="color: #0000ff"><span style="font-size: small">null</span></span><span style="color: #000000"><span style="font-size: small">;<br />
</span></span><span style="font-size: small"><span style="color: #000000">});</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">na przykład gdzieś w konstruktorze naszego okienka MemoryTakingWindow. Postęp jest natychmiastowy – po powtórzeniu doświadczenia otrzymujemy dużo ładniejszy wynik w postaci ząbków:</span></span></span></p>
<p lang="zxx"><a href="http://xlab.pl/wp-content/uploads/2011/04/memory_leak_2.png"><img class="aligncenter size-full wp-image-1799" src="http://xlab.pl/wp-content/uploads/2011/04/memory_leak_2.png" alt="" width="385" height="162" /></a></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Pięknieje także liczba trafień w breakpointa – staje się dokładnie równa liczbie wywołań okna.</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Na tym etapie można by zamknąć zadanie i przejść dalej. Jednak bardziej dociekliwym jednostkom jest wciąż mało i wciąż coś nie gra. Dlaczego przecież wcześniej obiekt klasy <em>MemoryTakingClass </em>nie był zwalniany? Dlaczego ciągle coś go trzymało, fakt uwolnienia go po odpięciu od DataContext jest podejrzany – oznacza przecież, że&#8230; coś ciągle trzyma okienko! Tylko co i dlaczego, no i czy na pewno.</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Tutaj właśnie sięgnąłem po grubą altyrerię w postaci <strong>ANTS Memory Profilera</strong>. Po uruchomieniu aplikacji w Profilerze wykonujemy “doświadczenie” (otwarcie kilkukrotne okienka) i używamy funkcji “<strong>Take memory snapshot</strong>”, po czym w szukamy naszych klas na liście:</span></span></p>
<p lang="zxx"><a href="http://xlab.pl/wp-content/uploads/2011/04/memory_leak_3.png"><img class="aligncenter size-full wp-image-1801" src="http://xlab.pl/wp-content/uploads/2011/04/memory_leak_3.png" alt="" width="854" height="285" /></a></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Tutaj wybieramy naszego “podejrzanego” i wykorzystujemy opcję “<strong>Instance list</strong>”, która zwraca nam listę wszystkich instancji klasy istniejących w momencie stworzenia snapshota.</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><a href="http://xlab.pl/wp-content/uploads/2011/04/memory_leak_41.png"><img class="aligncenter size-full wp-image-1816" src="http://xlab.pl/wp-content/uploads/2011/04/memory_leak_41.png" alt="" width="900" height="244" /></a><br />
</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">I cóż to?! W pamięci zalega nam 5 obiektów okna! Wiemy już gdzie leży przyczyna całej tej udręki – a odpinanie DataContext nie było fixem, a tylko ograniczeniem uciążliwości błędu &#8211; pozbywamy się z pamięci najcięższych obiektów, ale niestety nie wszystkich. Pozostaje ostatni krok – odpowiedź na pytanie &#8211; co powstrzymuje nasze okno przed zwolnieniem? Musimy prześledzić wszelkie referencje do niego. Gdyby przyszło nam w tym momencie analizować kod&#8230;</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Całe szczęście możemy wykorzystać ostatnią “prezentowaną” dziś opcję <strong>ANTS Profilera </strong>– “<strong>Instance Retention Graph”</strong>. Jest to graf przedstawiający łańcuchy obiektów wstrzymujących <strong>Garbage Collectora</strong> przed “skolekcjonowaniem” naszych obiektów. Analizując ten graf wypatrujemy wszystkich niepewnych połączeń, w naszym przypadku wygląda to tak:</span></span></p>
<p lang="zxx"><a href="http://xlab.pl/wp-content/uploads/2011/04/memory_leak_5.png"><img class="aligncenter size-full wp-image-1803" src="http://xlab.pl/wp-content/uploads/2011/04/memory_leak_5.png" alt="" width="446" height="372" /></a></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Już pierwszy stopień od okna pokazuje kontrolkę <strong>WindowsFormsHost</strong>, co rodzi pytanie – dlaczego kontrolka będąca “dzieckiem” naszego okna miałaby niby blokować jego sprzątnięcie?</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Patrzymy “stopień wyżej” na klasę “<strong>WinFormsAdapter</strong>”, której pole <strong>_host</strong> zawiera referencję do naszego hosta – klasa ta nam zapewne za wiele nie mówi (co nie dziwi, gdyż jest to wewnętrzna klasa w <strong>WindowsFormsIntegration</strong>).</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Stopień wyżej widzimy klasę <strong>ProcessInputEventHandler</strong>, po nazwie i polu (<strong>_target</strong>) sądzić można, że metoda klasy <strong>WinFormsAdapter </strong>obsługuje zdarzenie <strong>PostProcessInput </strong>pochodzące z klasy <strong>InputManager</strong>.<br />
Gdyby bardziej zgłębić kalsę <strong>InputManagera </strong>– okazuje się, ze ma ona statyczne pole <strong>Current </strong>i do niego właśnie podpina się <strong>WindowsFormsHost</strong> za posrednictwem klasy <strong>WinFormsAdapter</strong>, z tego powodu referencja do kontrolki jest trzymana “na zawsze”, a co za tym idzie blokuje całe nasze okno. Co gorsza okno blokowało obiekt podpięty do <strong>DataContext</strong>, a obiekt ten mały zdecydowanie nie był!</span></span></p>
<p lang="zxx">
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Gdyby za każdym razem zanim użyje się kontrolki przestudiować MSDN można by zauważyć, że klasa dziedziczy po <strong>HwndHost</strong>, który jak wszyscy wiemy implementuje interfejs <strong>IDisposable</strong>&#8230; zaraz nie wszyscy? i wcale mnie to nie dziwi&#8230; w każdym razie &#8211;  jeżeli nawet pośrednio nasza kontrolka dziedziczy po <strong>IDisposable</strong>, to  po skończeniu pracy z naszą kontrolką wystarczy wywołać metodę <strong>Dispose()</strong> i wszystko będzie działać jak należy.</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small">Zmieniamy zatem naszą obsługę zdarzenia Closed na następującą:</span></span></p>
<p lang="zxx"><span style="color: #000000"> <span style="font-size: small">Closed += ((sender, e) =&gt;<br />
</span></span><span style="font-size: small">{<br />
</span><span style="color: #0000ff"><span style="font-size: small">this</span></span><span style="color: #000000"><span style="font-size: small">.<span style="color: #000000">host.Dispose();<br />
</span></span></span><span style="font-size: small"><span style="color: #000000">});</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">i wszystko gra – wykres zajmowanej pamięci właściwie się nie zmieni w porównaniu do poprzedniego (niepełnego) fixa, gdyż nasze okienko samo w sobie pamięci za wiele nie pochłania (brak zauważalnych efektów), ale już wynik działania profilera – owszem. Na liście klas nie znajdziemy już pozycji <em>MemoryTakingWindow </em>(pod warunkiem, że okienko nie jest otwarte podczas pobierania snapshota, oczywiście).</span></span></span></p>
<p lang="zxx"><span style="color: #000000"><br />
</span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">Kilka wniosków na koniec:<br />
- Panowie z <strong>Red Gate </strong>mają głowy na karku. Wiedzą co programiści lubią – ich narzędzia są świetnie wykonane, bardzo funkcjonalne, a zarazem intuicyjne i estetyczne. W celu znalezienia mojego błędu nie potrzebowałem korzystać z żadnej dokumentacji, czy instrukcji. Wszystko wydawało się super-naturalne!</span></span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">- kontrolka <strong>WindowsFormsHost</strong> lubi zrobić psikusa. Należy pamiętać, że przy zamykaniu okna należy wywołać metodę <strong>Dispose</strong> (wg. informacji znalezionych &#8222;na Google&#8217;u&#8221; bywa tak, że trzeba ją najpierw jeszcze ręcznie usunąć z nadrzędnego grida, czy innego kontenera, jednak nie ręczę za prawdziwość tej informacji, tylko przestrzegam przed ewentualnością). Nie jest to wiedza “oczywista” i raczej wymaga przekazania informacji przez kogoś, bądź też kilku godzin męki – jak w moim przypadku.</span></span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">- WPF jest “fajny” i daje sporo możliwości, ale czyha tu na programistę wiele przykrych niespodzianek, które mogą napsuć krwi. Nie jest to jedyny tego przykład</span></span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">- teoretycznie winą programisty są konsekwencje nie zwolnienia zasobów i nie wywołania metody <strong>Dispose</strong> w klasie implementującej interfejs<strong> IDisposable</strong>.</span></span></span></p>
<p lang="zxx"><span style="color: #000000"><br />
</span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">I&#8230; kilka usprawiedliwień:</span></span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">- kontrolka <strong>WindowsFormsHost</strong>, jak to przystało na kontrolkę <strong>WPF</strong> dodawana jest w <strong>XAML</strong>&#8216;u – a z tego poziomu raczej ciężko stwierdzić, że akurat <strong>TA</strong> kontrolka rozwija jakiś tam interfejs. Metod również nie zobaczymy w intelisensie &#8211; nawet przypadkiem&#8230;</span></span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">- oczywiście wypadało zajrzeć na dokumentację kontrolki przed jej użyciem – szczególnie takiej &#8222;wyjątkowej&#8221; – ale jak to już było wyżej zaznaczone, <strong>WindowsFormsHost</strong> nie implementuje <strong>IDisposable</strong> bezpośrednio, a poprzez klasę bazową, więc i w dokumentacji na pierwszy rzut oka nie widzimy nic nakierowującego nas.</span></span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">- podpinanie się pod zdarzenia statycznych pól jest generalnie mechanizmem &#8222;trochę dziwnym&#8221; i ryzykownym i dość często odradzanym. Jeśli o mnie chodzi – mam wrażenie, że kod pod <strong>WindowsFormsHost </strong>mógłby być napisany troszkę lepiej &#8211; w celu zniwelowania tego ryzyka.</span></span></span></p>
<p lang="zxx"><span style="font-size: small"><span style="color: #000000">- kontrolki implementujące interfejs <strong>IDisposable</strong> to rzadkość i raczej niewielu programistów spodziewa się takiego psikusa.</span></span></p>
<p lang="zxx"><span style="font-size: small"><span style="color: #000000">- Czytelnikowi wydać się może dziwne &#8211; przecież w przykładzie na pierwszy rzut oka widać, że to <strong>WidnowsFormsHost</strong> coś tu miesza, jednak w naszej prawdziwej aplikacji &#8211; jak to w życiu rzeczywistym &#8211; kontrolka nie rzucała się w oczy&#8230; była dodana do formatki pośrednio (stanowiła element innej kontrolki dodanej do okienka), ponadto stanowiła jedną z kilkudziesięciu kontrolek, a przy tym zdecydowanie nie istotna, pokazywała się tylko na kilka chwil i miała rozmiar kilkunastu px&#8230;)</span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">- to nie ja dodałem kontrolkę do tamtego formularza ;)</span></span></span></p>
<p lang="zxx"><span style="color: #000000"><span style="font-size: small"><span style="color: #000000">- nadmierne pseudo-poczucie humoru we wpisie jest implikacją pory oraz dnia, w którym powstawał. Czyli &#8222;jakiś weekendowy wieczór&#8221; ;)</span></span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/net-i-memory-leak-czyli-dzien-z-zycia-programisty/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Dynamiczna konfiguracja środowiska LAMP dla lokalnej maszyny</title>
		<link>http://xlab.pl/dynamiczna-konfiguracja-srodowiska-lamp-dla-lokalnej-maszyny/</link>
		<comments>http://xlab.pl/dynamiczna-konfiguracja-srodowiska-lamp-dla-lokalnej-maszyny/#comments</comments>
		<pubDate>Wed, 23 Mar 2011 15:52:24 +0000</pubDate>
		<dc:creator>Wojtek Sznapka</dc:creator>
				<category><![CDATA[Programowanie PHP]]></category>
		<category><![CDATA[dnsmasq]]></category>
		<category><![CDATA[lamp]]></category>
		<category><![CDATA[mod vhost alias]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[vhost]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1790</guid>
		<description><![CDATA[Jeśli kiedykolwiek rozwijałeś aplikacje w PHP na swoim lokalnym komputerze, prawdopodobnie używałeś konfiguracji Apache opartej o vhosty. Kilkoma trikami możesz zmienić swojego linuksa w serwer developerski, bez konieczności konfigurowania vhosta dla każdej aplikacji z osobna. Przy minimalnym wysiłku konfiguracyjnym, potrzebowałeś do tego trzech kroków: pobrania repozytorium na dysk stworzenie konfiguracji vhost z jakąś nazwą serwera [...]]]></description>
			<content:encoded><![CDATA[<p>Jeśli kiedykolwiek rozwijałeś aplikacje w PHP na swoim lokalnym komputerze, prawdopodobnie używałeś konfiguracji <strong>Apache</strong> opartej o vhosty. Kilkoma trikami możesz zmienić swojego linuksa w serwer developerski, bez konieczności konfigurowania <strong>vhost</strong>a dla każdej aplikacji z osobna. Przy minimalnym wysiłku konfiguracyjnym, potrzebowałeś do tego trzech kroków:</p>
<ol>
<li>pobrania repozytorium na dysk</li>
<li>stworzenie konfiguracji <strong>vhost</strong> z jakąś nazwą serwera</li>
<li>stworzenie wpisu w <strong>/etc/hosts</strong> który będzie odzwierciedlał nazwę serwera użytego w <strong>vhoście</strong> na 127.0.0.1</li>
</ol>
<p>Jestem pewny, że powyższa ścieżka jest używana przez wielu programistów. Możemy pominąć dwa ostatnie kroki, ograniczając przygotowanie środowiska do umieszczenia kodu źródłowego w specjalnym folderze na dysku. Aby to osiągnąć potrzebujemy moduł Apache&#8217;a <strong>mod_vhost_alias</strong> oraz prosty serwer DNS, który będzie rozwiązywał lokalne domeny dla nas.<br />
Instalacja<strong> mod_vhost_alias </strong>jest dość prosta. Moduł jest prawdopodbnie dołączony do twojej instalacji Apache, pozostaje go tylko uruchomić następującą komendą:</p>
<pre>sudo a2enmod vhost_alias</pre>
<p>Dzięki <strong>mod vhost alias</strong> możemy dynamicznie wskazywać <strong>Document Root </strong>bazując na nazwie serwera. Wystarczy umieścić następującą konfigurację w pliku <strong>/etc/apache2/sites-enabled/000-default</strong></p>
<p><script src="https://gist.github.com/881441.js"> </script></p>
<p>Teraz wszystkie odwołania będą wskazywały na nasz /var/www/FIRST_PART_OF_DOMAIN/web, ponieważ użyliśmy modyfikatora %1. Możesz wprowadzić własną konwencję używając innych modyfikatorów w dyrektywie  <strong>VirtualDocumentRoot</strong> (<a href="http://httpd.apache.org/docs/2.2/mod/mod_vhost_alias.html">patrz dokumentacja</a>). Powyższa konfiguracja jest bardzo minimalistyczna, powinieneś dodać do niej jeszcze logowanie itp.</p>
<p>Ostatnią rzeczą, o jaką należy się zatroszczyć jest dynamiczne rozwiązywanie nazw domen. Najprostszym sposobem jest dodawanie nazwy serwera do pliku<strong> /etc/hosts</strong>, ale to wymaga dodawania wpisu dla każdego hosta. Na przykład wpis w <strong>/etc/hosts</strong>:</p>
<pre> 127.0.0.1 myapp.local.dev</pre>
<p>uruchomi aplikację zlokalizowaną w  /var/www/myapp/ (wskaże na katalog web/, według konwencji symfony). Jeśli chcesz to zautomatyzować, zainstaluj <strong>dnsmasq</strong>, prosty serwer DNS</p>
<pre>sudo apt-get install dnsmasq</pre>
<p>Następnie wyedytuj <strong>/etc/dnsmasq.conf</strong> file (może być położony gdzie indziej, tutaj na przykładzie Ubuntu):</p>
<pre>listen-address=127.0.0.1
address=/.local.dev/127.0.0.1</pre>
<p>Ostatnią rzeczą jest aktualizacja pliku <strong>/etc/resolv.conf</strong> przez dodanie adresu naszego DNSa na początek:</p>
<pre>nameserver 127.0.0.1</pre>
<p>Następnie restartujemy <strong>dnsmasq</strong> i <strong>Apache2</strong>:</p>
<pre>sudo /etc/init.d/apache2 restart
sudo /etc/init.d/dnsmasq restart</pre>
<p>Od teraz możesz się cieszyć nową konfiguracją środowiska LAMP. Każdy nowy projekt potrzebuje być tylko umieszczony w katalogu  /var/www/PROJECT_NAME i będzie od razu dostępny z poziomu przeglądarki pod adresem  PROJECT_NAME.local.dev</p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/dynamiczna-konfiguracja-srodowiska-lamp-dla-lokalnej-maszyny/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

