<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-973718928927935206</id><updated>2012-02-01T10:56:01.214+01:00</updated><category term='proces'/><category term='lean'/><category term='szukam pracy'/><category term='najlepsze praktyki'/><category term='myślenie systemowe'/><category term='współpraca z klientem'/><category term='java'/><category term='refaktoryzacja'/><category term='jug'/><category term='zarządzanie projektami'/><category term='metodyki'/><category term='refaktoring'/><category term='wzorce'/><category term='efektywność'/><category term='asertywność'/><category term='klasa'/><category term='współpraca'/><category term='behaviour-driven development'/><category term='strategie doskonałości'/><category term='programowanie'/><category term='organizacja pracy'/><category term='społeczność'/><category term='praca'/><category term='czysty kod'/><category term='komunikacja'/><category term='scrum'/><category term='rozwiązywanie problemów'/><category term='agile'/><category term='wzorce implementacyjne'/><category term='uczenie się'/><category term='clean code'/><category term='styl kodowania'/><category term='software craftsmanship'/><category term='umiejętności miękkie'/><category term='tdd'/><category term='DDD'/><category term='test-driven development'/><category term='biznes'/><category term='bdd'/><category term='projekty'/><title type='text'>Radość tworzenia oprogramowania</title><subtitle type='html'>O Javie, projektowaniu i programowaniu obiektowym, architekturze, testowaniu, zarządzaniu wymaganiami, zespołach programistycznych - współdziałaniu i zarządzaniu. O tym co trudno uchwytne, a często decydujące - o aspektach miękkich funkcjonowania programistów (i nie tylko).
A przede wszystkim - o pasji :-)</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/16721570127754631476</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>42</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-5420487595643972003</id><published>2012-02-01T10:54:00.001+01:00</published><updated>2012-02-01T10:56:01.225+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='myślenie systemowe'/><category scheme='http://www.blogger.com/atom/ns#' term='zarządzanie projektami'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='proces'/><category scheme='http://www.blogger.com/atom/ns#' term='efektywność'/><title type='text'>Właściwość złożonych systemów</title><content type='html'>Dzisiaj rano jadąc samochodem do pracy natknąłem się na dużo dłuższy korek niż zwykle. "No tak, przy takim mrozie pewnie wszyscy jadą szczególnie ostrożnie" - pomyślałem i powoli się turlałem Trasą Łazienkowską. Po kilkunastu minutach, w pewnym momencie zauważyłem z daleka, że na jezdni w przeciwnym kierunku był wypadek i policja oraz pogotowie robiły, co swoje. Na moim pasie nic się szczególnego nie działo. Niby nic, a jednak... Kierowcy najzwyczajniej w świecie zwalniali, żeby zobaczyć co się dzieje na drugim pasie. Nikt się nie zatrzymywał, tylko patrzyli, co się dzieje. I z tego powodu fragment, który zazwyczaj przemierzałem w 5 minut, zajął mi tym razem 20 minut. Po przejechaniu tego punktu ruch znacząco przyspieszył i przebiegał normalnie.&lt;br /&gt;&lt;br /&gt;Dlaczego o tym piszę? Od razu dostrzegłem analogię do projektów programistycznych :) Przedsięwzięcia programistyczne - ludzie, architektura, procesy - to złożony system. Często niewielkie zmiany, pozornie nieistotne elementy mają ogromny, kaskadowy wpływ na to co się dzieje w projektach.&lt;br /&gt;&lt;br /&gt;Być może o jeden punkt decyzyjny za dużo, za mało, brak lub nadmiar dokumentacji, brak asertywności lub przyzwolenia o mówieniu o błędach, brak ścisłej współpracy lub zbyt swobodna współpraca bez ustalonych reguł mogą znacząco zmniejszać efektywność całego procesu. Warto o tym pamiętać!&lt;br /&gt;&lt;br /&gt;W przypadku ruchu drogowego sytuacja jest nieco prostsza, bo łatwiej ją zmierzyć - jest to prędkość i czas przejazdu na tej samej trasie. Nie mamy tego luksusu w projektach, gdzie zazwyczaj to, co jest realizowane nie jest tak powtarzalne. Jednak możemy przybliżać się do oszacowania i porównywania. Szacując zadania oraz dodając relatywną miarę złożoności zadań (funkcjonalności).&lt;br /&gt;Mniej formalną metodą są punkty (points, story points), które są jednostką względną, służącą raczej do porównania złożoności różnych funkcjonalności, niż do dokładnej analizy złożoności (która jest niezwykle pracochłonna, a i tak pozostanie tylko prognozą). Bardziej formalną metodą (gdzie dużo precyzyjniej należy argumentować podane szacowania) mogą być kilkuczynnikowe metody szacowania i pomiar zadań za pomocą punktów funkcyjnych.&lt;br /&gt;&lt;br /&gt;Wtedy możemy obserwować czy nasza prędkość się zmienia, jak wprowadzane zmiany mają na nią wpływ.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-5420487595643972003?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/5420487595643972003/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=5420487595643972003' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/5420487595643972003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/5420487595643972003'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2012/02/wasciwosc-zozonych-systemow.html' title='Właściwość złożonych systemów'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-3002222662544523311</id><published>2011-12-09T10:13:00.000+01:00</published><updated>2011-12-09T10:13:20.171+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='najlepsze praktyki'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><category scheme='http://www.blogger.com/atom/ns#' term='metodyki'/><title type='text'>Dlaczego Agile nie zadziała</title><content type='html'>Wprowadzenie metody z rodziny Agile nie jest w ogóle łatwe. Problemem zazwyczaj jest to, że menedżment powierzchownie dowiadując się o co chodzi, odbiera nową metodę jako obietnicę - od teraz w magiczny sposób wszystko zacznie lepiej działać. Nieważne, że mamy kiepskich ludzi i hołdujemy zasadzie "każdego specjalistę można zastąpić przez skończoną liczbę studentów". Nieważne, że kompletnie nie dba się o zarządzanie wiedzą i umiejętności w zespole, bo nigdy nie ma na to czasu. Nieważne, że osoby realizujące projekty są przerzucane między projektami - bo przecież chodzi o interdyscyplinarność i każdy się powinien we wszystkim orientować. Nieważne, że terminy ustala się apriori, z do końca niejasnych przyczyn lub zakłada się, że to jedyny sposób, żeby przekonać klienta, że jesteśmy profesjonalni, a w terminie się "jakoś zmieścimy". Nieważne, że nie znajdujemy czasu na to, aby utrzymywać architekturę i kod, bo przecież nie ma czasu na tego typu zbędne czynności. &lt;br /&gt;Nieważne, bo przecież Agile obiecuje, że teraz będzie już tylko pięknie. Dokleimy etykietkę to tego co robimy teraz - niech się to nazywa np. "Scrum", zrobimy trochę więcej chaosu, bo przecież chodzi o zarządzanie chaosem - zatem każdy robi co chce i jak chce, przestajemy cokolwiek dokumentować. Przecież stosujemy Agile, wszystko się samozorganizuje.&lt;br /&gt;&lt;br /&gt;I dlatego najczęściej Agile nie działa, bo ludzie, którzy po omacku go stosują lub menedżment, który wstępnie akceptuje korzyści z danego podejścia, stosują bardzo uproszczone myślenie - "Ok. Robimy Scrum. Ale tak naprawdę 8 z 10 elementów nam nie pasuje, więc wybierzemy sobie, to co pasuje (dwa elementy), a resztę będziemy robić tak jak do tej pory (czytaj wyżej). &lt;br /&gt;I tak wszystko będzie tak jak było, albo gorzej.&lt;br /&gt;&lt;br /&gt;ZATEM UWAGA: W takim przypadku nie należny, nawet nie WOLNO zacząć stosować Agile. Agile to zmiana, ogromna zmiana, to nie etykietka, która rozwiąże wszystkie problemy (w tym przypadku prawdopodobnie lepiej się sprawdzi butelka alkoholu).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-3002222662544523311?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/3002222662544523311/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=3002222662544523311' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/3002222662544523311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/3002222662544523311'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/12/dlaczego-agile-nie-zadziaa.html' title='Dlaczego Agile nie zadziała'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-7413864408392059542</id><published>2011-11-26T17:07:00.001+01:00</published><updated>2011-11-26T17:07:50.676+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='uczenie się'/><category scheme='http://www.blogger.com/atom/ns#' term='strategie doskonałości'/><category scheme='http://www.blogger.com/atom/ns#' term='efektywność'/><title type='text'>Efektywne poznawanie tematu</title><content type='html'>Tym razem temat nieco wychodzący poza projekty informatyczne. Ostatnio dużo robię tzw. pracy researchowej, gdzie muszę na bazie dużej ilości źródeł wiedzy zbudować spójny ekstrakt praktycznych informacji. Po dłuższej pracy w tym temacie napiszę o kilku wskazówkach, które miałem okazję wielokrotnie wykorzystywać.&lt;br /&gt;&lt;br /&gt;Jeśli chcesz zbudować wiedzę na pewien temat np. continuous integration, technologia X.&lt;br /&gt;&lt;b&gt;Cel: chcesz naprawdę dobrze zrozumieć temat.&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Założenie: Nie znasz nikogo, kto mógłby Cie naprowadzić na dobrą drogę ;-)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt; &lt;/b&gt;&lt;br /&gt;1. Przeprowadź spike'a* (maks. kilka godzin) odnośnie źródeł informacji - &lt;b&gt;gdzie co możesz znaleźć i jaki jest poziom materiałów&lt;/b&gt; (wiarygodność i szczegółowość): &lt;br /&gt;a) &lt;b&gt;sprecyzuj pytania, na które chciałbyś znaleźć odpowiedzi&lt;/b&gt;;&lt;br /&gt;b) w pierwszej kolejności wybieraj książki - jeśli są dobre, znajdziesz tam wiarygodne i uporządkowane informacje;&lt;br /&gt;c) w drugiej kolejności wybieraj materiały akademickie (prace doktorskie, prace z konferencji) - zaletą jest wiarygodność, czasem jednak są nieuporządkowane, czasami (jeśli autor jest kiepski) jest to zwykłe bicie piany;&lt;br /&gt;c) blogi i artykuły wiarygodnych osób w branży (rozpoznawalnych i uznanych);&lt;br /&gt;d) unikaj w miarę możliwości forów, blogów i luźnych informacji, których źródeł (osób) nie kojarzysz - dużo się naczytasz, niewiele dowiesz.&lt;br /&gt;2. Kiedy już określisz listę wiarygodnych źródeł - &lt;b&gt;określ minimum, które jest Ci potrzebne&lt;/b&gt;.&lt;br /&gt;3. Jeśli zaczynasz czytać tekst (i dotyczy on Twojego minimum), &lt;b&gt;czytaj go bardzo dokładnie&lt;/b&gt;, nie idź do przodu, jeśli nie rozumiesz, tego co przeczytałeś.&lt;br /&gt;4. Wielokrotnie się przekonałem, że &lt;b&gt;lepiej dowiedzieć się mniej, ale mieć wiedzę jak brzytwa&lt;/b&gt;, niż przeczytać "o wszystkim" po łebkach.&lt;br /&gt;5. &lt;b&gt;Rób notatki!&lt;/b&gt; To jedna z najważniejszych składowych! Wiele osób czyta dużo, ale nie robi notatek. Notatki zmuszają Cię do dokładniejszego zrozumienia tego co czytasz. Żeby zrobić notatkę (zazwyczaj) musisz coś zrozumieć. Niech notatka będzie parafrazą (czyli Twoim własnym sformułowaniem), nie cytatem.&lt;br /&gt;&lt;br /&gt;*Spike - ograniczony czasowo, krótki okres na zbadanie tematu (maks. 2 dni), który jest Ci obcy lub mało znany.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-7413864408392059542?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/7413864408392059542/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=7413864408392059542' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/7413864408392059542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/7413864408392059542'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/11/efektywne-uczenie-sie.html' title='Efektywne poznawanie tematu'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-4056499384945397731</id><published>2011-10-13T18:02:00.000+02:00</published><updated>2011-10-13T18:02:46.927+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><title type='text'>Trzeba zrobić miejsce...</title><content type='html'>Z tomiku ... &lt;i&gt;Poezja dla zaangażowanych w projekty&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Trzeba zrobić miejsce&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Nigdy nie ma dobrego czasu na pierwsze dziecko,&lt;br /&gt;Nigdy nie ma dobrego czasu na drugie dziecko,&lt;br /&gt;Nigdy nie ma dobrego czasu na budowanie domu,&lt;br /&gt;Nigdy nie ma dobrego czasu na remont,&lt;br /&gt;Nigdy nie ma dobrego czasu na ślub,&lt;br /&gt;Nigdy nie ma dobrego czasu, żeby wprowadzić refaktoryzację,&lt;br /&gt;I nigdy nie ma dobrego czasu, żeby zacząć pisać testy jednostkowe,&lt;br /&gt;W każdym z tych przypadków, trzeba po prostu podjąć decyzję,&lt;br /&gt;Zacząć to robić, a czas i środki się znajdą,&lt;br /&gt;Bo będą musiały...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-4056499384945397731?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/4056499384945397731/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=4056499384945397731' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/4056499384945397731'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/4056499384945397731'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/10/trzeba-zrobic-miejsce.html' title='Trzeba zrobić miejsce...'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-3270827390845037857</id><published>2011-10-10T15:25:00.000+02:00</published><updated>2011-10-10T15:25:46.563+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='współpraca z klientem'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='lean'/><title type='text'>Klienci chcą być zwinni...</title><content type='html'>Jedno z ostatnich spotkań, gdzie ustalam (MS) sposób współpracy z klientem (szczegóły celowo nieco zmodyfikowane lub usuniętę, jednak bazujące na rzeczywistym przypadku). Klient (K) mówi:&lt;br /&gt;K: To bardzo poważne przedsięwzięcie i zapowiadają się poważne koszty, prawdę mówiąc nasz sponsor ma spore wątpliwości, co to tej sumy. Nie będzie w stanie jej wydać. Projekt jest dość innowacyjny i nie wiadomo, jak odpowie rynek...&lt;br /&gt;MS: To nawet dobrze się składa, ponieważ możemy zaproponować inny sposób współpracy. Cały system to rzeczywiście spora inwestycja i dość ryzykowna, gdyż produkt zwyczajnie może się nie przyjąć. Przyjrzyjmy się co jest esencją systemu... być może to będzie część, która nam podpowie co dalej zrobić.&lt;br /&gt;(kilkadziesiąt minut wspólnej analizy i dyskusji)&lt;br /&gt;MS: Świetnie! Zatem XYZ to jest to, co przyciągnie klientów, wszystko inne jest wtórne. To nazywamy corem biznesowym tego systemu. Zatem zróbmy tak: zakontraktujmy tę pierwszą część, co do pozostałych części przedstawiliśmy zgrubne szacunki, po tych pracach okaże się, na ile są trafne. Ale co najważniejsze po wdrożeniu core przekonamy się, jak rynek reaguje i czy reaguje, zbierzemy informację zwrotną. Wtedy podejmiemy dalsze decyzje.&lt;br /&gt;K: Ok. To wygląda całkiem obiecująco. Zaryzykujemy tylko 1/4 całej początkowej sumy. Ciekawa sprawa, muszę o tym porozmawiać ze sponsorem.&lt;br /&gt;(... klient zarażony, a konkurencja bez szans, bo ofertująca w tradycyjnym modelu - a tymczasem koncept klienta się zmienił :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-3270827390845037857?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/3270827390845037857/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=3270827390845037857' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/3270827390845037857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/3270827390845037857'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/10/klienci-chca-byc-zwinni.html' title='Klienci chcą być zwinni...'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-2199342268962509626</id><published>2011-09-25T00:35:00.001+02:00</published><updated>2011-09-25T00:39:05.793+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='komunikacja'/><category scheme='http://www.blogger.com/atom/ns#' term='asertywność'/><category scheme='http://www.blogger.com/atom/ns#' term='umiejętności miękkie'/><title type='text'>Czas na szkolenie z asertywności!</title><content type='html'>Tak się składa, że w poprzednim poście pisałem o asertywności w kontekście zarządzania czasem, natomiast analizując różne przypadki, z którymi miałem do czynienia, mogę z dużym przekonaniem stwierdzić, że brak asertywności (wliczam w to odpowiedni sposób komunikacji) jest przyczyną (źródłem) dużej części innych problemów w projekcie.&lt;br /&gt;Weźmy za przykład presję. Zazwyczaj presja idzie z tak zwanej góry. Górą może być klient lub jakiś istotny dyrektor lub prezes (jakby mógł być jakiś nieistotny!). Presja ta jest zazwyczaj przenoszona na kolejne poziomy w dół aż dochodzi do zespołu projektowego (w typowym uogólnionym przypadku: klient/dyrektor=&amp;gt;kierownik projektu=&amp;gt;zespół projektowy).&lt;br /&gt;I teraz uwaga powiem coś co może się niektórym nie spodobać, ale&lt;br /&gt;&lt;br /&gt;TA PRESJA JEST POTRZEBNA!&lt;br /&gt;&lt;br /&gt;Tak. Nie ma co psioczyć, że ktoś każe zrobić pracę w krótszym terminie. Z ekonomicznego punktu widzenia jest to bardzo rozsądne. Zresztą zgodnie z &lt;a href="http://pl.wikipedia.org/wiki/Prawo_Parkinsona"&gt;prawem Parkinsona&lt;/a&gt; , którego doświadczyłem wielokrotnie osobiście zarówno jako wykonawca jak i odbiorca czy obserwator, krótkie terminy są wskazane.&lt;br /&gt;Nierozsądne jest poddawanie się tej presji. Jeśli masz przekonanie, że dany termin jest nierealny, powiedz to (asertywnie). Przygotuj się dobrze, przygotuj argumenty (pamiętaj o uwzględnieniu perspektywy swojego rozmówcy, a nie tylko Twojej) i przedyskutuj dlaczego to jest nierealne.&lt;br /&gt;Bardzo często się przekonują, że kierownicy (czy inne osoby decyzyjne) są bardzo skłonni zaakceptować inne szacowanie, jeśli tylko jest ono dobrze uzasadnione. Choć również są i tacy, którzy nie są skłonni (ale nie oszukujmy się - jest ich może z 5%, więc jeśli myślisz, że to na pewno dotyczy Ciebie, to jest duże prawdopodobieństwo, że się mylisz!)&lt;br /&gt;&lt;br /&gt;Jeśli więc zastanawiasz się, z czego się przeszkolić, to Twój typ powinien zmierzać w stronę asertywności ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-2199342268962509626?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/2199342268962509626/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=2199342268962509626' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2199342268962509626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2199342268962509626'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/09/czas-na-szkolenie-z-asertywnosci.html' title='Czas na szkolenie z asertywności!'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-6316594151031230959</id><published>2011-09-23T00:24:00.000+02:00</published><updated>2011-09-23T00:24:04.975+02:00</updated><title type='text'>Klucz do zarządzania czasem</title><content type='html'>Jest kilka tematów, które cały czas pojawiają się w mojej głowie i wraz z kolejnymi odkryciami przechodzę do kolejnego poziomu jego zrozumienia. Tak jest z "zarządzaniem czasem".&lt;br /&gt;Moje obecne doświadczenie jest takie, że możesz doświadczyć owego "zarządzania czasem" na kilku poziomach głębokości:&lt;br /&gt;&lt;br /&gt;1) Znajomość technik - tutaj masz do dyspozycji GTD, czy też tzw. klasyczne zarządzanie czasem. Po prostu technicznie jesteś w stanie zapanować nad tym co robisz, być może używasz jakiegoś narzędzia, jakiejś metody, potrafisz porozdzielać i poukładać swoją zadania w kalendarzu lub na liście TODO.&lt;br /&gt;&lt;br /&gt;2) Świadomy wybór rzeczy ważnych i rezygnowanie z "szumu zadaniowego" czyli spraw mało istotnych - większość osób robi to co mają do zrobienia, tak jak leci, często robią to z przyzwyczajenia, bezrefleksyjnie. Nawet jeśli świetnie opanowałeś techniki, to niewiele Ci to pomoże. (więcej: http://msieraczkiewicz.blogspot.com/2010/08/hiperoptymalizator-czasu.html)&lt;br /&gt;&lt;br /&gt;3) &lt;b&gt;Kluczem do zarządzania czasem jest asertywność i komunikacja - to trzeci (najwyższy) w mojej typologii poziom. Nigdy nie pozbędziesz się wrażenia, ze masz zbyt mało czasu, jeśli nie jesteś odpowiednio asertywny - wobec szefa, znajomych, rodziny, siebie (sic!) i nie potrafisz tego odpowiednio zakomunikować, nie będąc ani agresywnym ani uległym. Tak to lakoniczne stwierdzenie. Ale niech to będzie koan, dla tych bardziej zainteresowanych :)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Czy będzie czwarty poziom? Niewykluczone ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-6316594151031230959?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/6316594151031230959/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=6316594151031230959' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6316594151031230959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6316594151031230959'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/09/klucz-do-zarzadzania-czasem.html' title='Klucz do zarządzania czasem'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-1292360637942238386</id><published>2011-08-04T12:17:00.001+02:00</published><updated>2011-08-04T15:45:59.236+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='efektywność'/><title type='text'>Dotrzymywanie terminów za wszelką cenę to błąd!</title><content type='html'>Terminy są potrzebne. Nie ważne czy pracujesz w Scrumie (Agile) czy w metodyce wodospadopodobnej - jedno jest pewne - bez terminów brak mobilizacji. Mówi o tym tzw. prawo Parkinsona (nie wiem czy ma on coś wspólnego z chorobą wieku starczego).&lt;br /&gt;&lt;br /&gt;Problem pojawia się w sytuacji, kiedy widać, że nie uda się dotrzymać terminu. Klasyczny sposób postępowania polega na brutalnym dotrzymaniu terminu za wszelką cenę! I to jest błąd!&lt;br /&gt;&lt;br /&gt;Dlaczego? Zadaj sobie trud i poświęć kilka minut, że znaleźć ciemne strony dotrzymywania terminów za wszelką cenę ...&lt;br /&gt;&lt;br /&gt;(Czas na znalezienie...Ci co nie lubią myśleć sami, mogą przejść natychmiast to następnego punktu ;-))&lt;br /&gt;&lt;br /&gt;Oczywiście roztrząsane dookoła konsekwencje to:&lt;br /&gt;- nadgodziny (szkodliwe dla psychiki i niewydajne - można się spierać),&lt;br /&gt;- dług techniczny.&lt;br /&gt;&lt;br /&gt;Jednak konsekwencje są straszniejsze:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Zespoły, które dotrzymują terminów za wszelką cenę nie uczą się!&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Tzn. uczą się tego, że można pozwolić sobie na kiepskie praktyki, nieefektywny sposób pracy, brak asertywności, jeśli w okolicy terminu ponagina się czas pracy oraz przymknie (a w zasadzie zamknie) się oczy na jakość.&lt;br /&gt;Od dziś będę nazywać to Stress-Driven Development :-)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dotrzymywanie terminów utrwala złe praktyki realizowania projektów.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Oczywiście naiwnym byłoby twierdzić, że niedotrzymywanie terminu jest rozwiązaniem. Nie jest! Bo samo w sobie nic nie da! Potrzeba jeszcze narzędzi wyciągania wniosków i wprowadzania ich w życie.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Kiedy musisz stwierdzić, że nie zdążysz na umówiony termin: będziesz musiał o tym teamleada jeśli jesteś programistą, jeśli jesteś teamleadem - kierownika projektu, jeśli kierownikiem - klienta i/lub kierownika/dyrektora wyższego szczebla, jauććć to może boleć. Dlatego najczęściej tego nie robisz, wolisz być nieasertywny lub nagiąć swój czas lub swoje zasady, aby dotrzymać terminu. Ot cały mechanizm.&lt;br /&gt;Jak zaboli (choć istnieją również mniej bolesne/bezbolesne metody) wtedy będziesz miał okazję rzeczywiście się czegoś nauczyć. Wtedy będziesz mógł się rzeczywiście rozwijać, wtedy będziesz miał motywację, aby zmienić proces, zamiast utrwalać jego nieefektywność.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-1292360637942238386?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/1292360637942238386/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=1292360637942238386' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/1292360637942238386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/1292360637942238386'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/08/dotrzymywanie-terminow-za-wszelka-cene.html' title='Dotrzymywanie terminów za wszelką cenę to błąd!'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-8622473881023769962</id><published>2011-07-12T01:22:00.000+02:00</published><updated>2011-07-12T01:22:47.056+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clean code'/><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='czysty kod'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoryzacja'/><title type='text'>O nazewnictwie słów kilka – metody (in progress)</title><content type='html'>(Uwaga! Artykuł w trakcie rozwoju!)&lt;br /&gt;Może temat wydaje się banalny i wyświechtany, bo któż nie wie, że trzeba tworzyć jednoznaczne, czytelne nazwy. Natomiast ciągle jest obszar bardzo zaniedbany. Ciągle zespoły są dalekie od zrozumienia, że to właśnie od nazewnictwa zależy najwięcej. Żadna refaktoryzacja nie ma takiej mocy, jak zmiana nazwy. To przede wszystkim nazwy, jeśli stosowane odpowiednio, tworzą tzw. samodokumentujący się kod, kreują jednoznaczny język w źródłach systemu, który tworzysz.&lt;br /&gt;Temat opisany wprawdzie w Clean Code, ale nie tak konkretnie jak ja to widzę, nieco po wierzchu i z innej perspektywy.&lt;br /&gt;&lt;br /&gt;Dzisiaj kilka słów o anatomii metody (funkcji). Każda metoda ma tzw. sygnaturę czyli nazwę, parametry oraz zwracany typ, kluczowe składowe z punktu widzenia refaktoryzacji, gdyż na czytelność składają się wszystkie trzy elementy – nie tylko nazwa.&lt;br /&gt;Ponadto można powiedzieć, że są dwa rodzaje metod:&lt;br /&gt;• zwracające wynik;&lt;br /&gt;• niezwracające wynik.&lt;br /&gt;Metody zwracające wynik&lt;br /&gt;(Uwaga! Poniższe zasady nie dotyczą tzw. interfejsów typu fluent)&lt;br /&gt;&lt;pre class="brush:java; gutter: false;"&gt;&amp;nbsp;&lt;br /&gt;double computeSomeResult(int parameter1, double parameter2, int parameter3 …)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;• nazwa metody zawsze konkretnie i jednoznacznie musi określać, czym dana metoda się zajmuje i musi z niej wynikać, co będzie jej wynikiem;&lt;br /&gt;• sygnaturę metody twórz zawsze w kontekście klasy, w której się znajduje (nie powtarzaj nazwy klasy w nazwie metody);&lt;br /&gt;• tym samym metody zwracające informacje o błędach powstałych podczas jej wykonania są antywzorcem (choć oczywiście jest śladowa liczba przypadków, kiedy taka strategia może być uzasadniona – zazwyczaj gdy pracujemy z kodem odziedziczonym); tej chorobie ulega wiele frameworków;&lt;br /&gt;• wysoce karalne jest traktowanie parametrów wejściowych jako sposób na zwracanie wyniku, co najczęściej dzieje się w przypadku opisanym w punkcie powyżej;&lt;br /&gt;• parametry metody współtworzą znaczenie z nazwą – muszą ją uzupełniać i być z nią zgodne.&lt;br /&gt;Przykłady i komentarze&lt;br /&gt;1)&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java; gutter: false;"&gt;&amp;nbsp;&lt;br /&gt;List&amp;lt;Content&amp;gt; retrieveChildren(Content parentContent)  &lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ok! Nazwa sugeruje, że będą wyszukiwane dzieci parametru i taki też jest zwrócony typ.&lt;br /&gt;Bardziej fluentowe wersje (TBD wyjaśnić co to):&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java; gutter: false;"&gt;&amp;nbsp;&lt;br /&gt;List&amp;lt;Content&amp;gt; retrieveChildrenOf(Content parentContent)  &lt;br /&gt;List&amp;lt;Content&amp;gt; childrenOf(Content parentContent)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Lub jeśli byłoby to adekwatne do kontekstu, metoda &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;childrenOf &lt;/span&gt;mogłaby być składową klasy &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Content&lt;/span&gt; i wtedy jej sygnatura wyglądałaby:&lt;br /&gt;&lt;pre class="brush:java; gutter: false;"&gt;&amp;nbsp;&lt;br /&gt;class Content {&lt;br /&gt;   List&amp;lt;Content&amp;gt; retrieveChildren() // ..&lt;br /&gt;   // lub bardziej fluentowo&lt;br /&gt;   List&amp;lt;Content&amp;gt; children() // ..&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;2)&lt;br /&gt;&lt;pre class="brush:java; gutter: false;"&gt;&amp;nbsp;&lt;br /&gt;interface ContentProcessorResolver {&lt;br /&gt;   //…&lt;br /&gt;   /* @return zwraca listę treści dostosowaną do danego resolwera */&lt;br /&gt;   public List&amp;lt;? extends Content&amp;gt; resolve(Content content);&lt;br /&gt;   //…&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Zła nazwa – sugerowałaby (w kontekście interfejsu, w którym się znajduje), że wynikiem będzie obiekt klasy &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ContentProcessor&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;TBC…&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-8622473881023769962?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/8622473881023769962/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=8622473881023769962' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/8622473881023769962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/8622473881023769962'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/07/o-nazewnictwie-sow-kilka-metody-in.html' title='O nazewnictwie słów kilka – metody (in progress)'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-2795133690200638785</id><published>2011-07-06T13:36:00.000+02:00</published><updated>2011-07-06T13:36:01.030+02:00</updated><title type='text'>Przypadek przekroczenia zakresu - Proste wprowadzenie do BDD cz. 4</title><content type='html'>I na deser z JBehave, Behaviour-Driven Developement oraz kalkulatorem (jeee) ostatnia część.&lt;br /&gt;&lt;br /&gt;&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/qIUaOnUfJqc?hd=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-2795133690200638785?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/2795133690200638785/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=2795133690200638785' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2795133690200638785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2795133690200638785'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/07/przypadek-przekroczenia-zakresu-proste.html' title='Przypadek przekroczenia zakresu - Proste wprowadzenie do BDD cz. 4'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/qIUaOnUfJqc/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-6258064860817757420</id><published>2011-07-05T09:29:00.000+02:00</published><updated>2011-07-05T09:29:30.715+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='behaviour-driven development'/><category scheme='http://www.blogger.com/atom/ns#' term='test-driven development'/><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='bdd'/><title type='text'>Implementacja - Proste wprowadzenie do BDD cz. 3</title><content type='html'>JBehave, Behaviour-Driven Development (BDD) ciąg dalszy, tym razem już implementujemy... i kilka ciekawych ficzerów narzędzia... &lt;br /&gt;&lt;br /&gt;Have fun!&lt;br /&gt;&lt;br /&gt;&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/OMM_lyUfX3E?hd=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-6258064860817757420?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/6258064860817757420/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=6258064860817757420' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6258064860817757420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6258064860817757420'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/07/implementacja-proste-wprowadzenie-do.html' title='Implementacja - Proste wprowadzenie do BDD cz. 3'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/OMM_lyUfX3E/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-1960766142040115119</id><published>2011-07-04T11:36:00.001+02:00</published><updated>2011-07-04T11:37:47.270+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='behaviour-driven development'/><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='bdd'/><title type='text'>Pierwsza historyjka - Proste wprowadzenie do BDD cz. 2</title><content type='html'>Odpalamy mózg... Odpalamy JBehave i jedziemy...&lt;br /&gt;&lt;br /&gt;&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/SGfaFbAr4TA?hl=pl&amp;fs=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-1960766142040115119?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/1960766142040115119/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=1960766142040115119' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/1960766142040115119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/1960766142040115119'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/07/pierwsza-historyjka-proste-wprowadzenie.html' title='Pierwsza historyjka - Proste wprowadzenie do BDD cz. 2'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/SGfaFbAr4TA/default.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-7915914789216892257</id><published>2011-06-29T09:34:00.000+02:00</published><updated>2011-06-29T09:34:29.579+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='behaviour-driven development'/><category scheme='http://www.blogger.com/atom/ns#' term='test-driven development'/><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='bdd'/><title type='text'>Proste wprowadzenie do BDD cz. 1</title><content type='html'>Dzisiaj premiera screencasta, a w zasadzie pierwsze koty za płoty - eksperymentalne próby z blogowaniem wideo i taką formą dzielenia się spostrzeżeniami.&lt;br /&gt;&lt;br /&gt;Na pierwszy ogień idzie Behaviour-Driven Development i JBehave. Narzędzie pozwalające bardzo poukładać sobie w głowie, jaką ścieżką przejść od wymagań do implementacji. W rolach głównych występują :) User Stories, Testy akceptacyjne, Test-Driven Development i JBehave. Razem będzie 5 filmów, teraz pierwsze dwa!&lt;br /&gt;&lt;br /&gt;Oglądaj koniecznie w rozdzielczości 720p i na pełnym ekranie&lt;br /&gt;&lt;br /&gt;&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/z_0l-OnAU78?hd=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/u1ILpMkJin4?hd=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-7915914789216892257?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/7915914789216892257/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=7915914789216892257' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/7915914789216892257'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/7915914789216892257'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/06/proste-wprowadzenie-do-bdd-cz-1.html' title='Proste wprowadzenie do BDD cz. 1'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/z_0l-OnAU78/default.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-1978244617887216724</id><published>2011-06-29T01:28:00.000+02:00</published><updated>2011-06-29T01:28:47.816+02:00</updated><title type='text'>Naturalny porządek refaktoryzacji pod lupą cz. 5 Ewolucja architektury</title><content type='html'>&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:TrackMoves/&gt;   &lt;w:TrackFormatting/&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:PunctuationKerning/&gt;   &lt;w:ValidateAgainstSchemas/&gt;   &lt;w:SaveIfXMLInvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:IgnoreMixedContent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:AlwaysShowPlaceholderText&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:DoNotPromoteQF/&gt;   &lt;w:LidThemeOther&gt;PL&lt;/w:LidThemeOther&gt;   &lt;w:LidThemeAsian&gt;X-NONE&lt;/w:LidThemeAsian&gt;   &lt;w:LidThemeComplexScript&gt;X-NONE&lt;/w:LidThemeComplexScript&gt;   &lt;w:Compatibility&gt;    &lt;w:BreakWrappedTables/&gt;    &lt;w:SnapToGridInCell/&gt;    &lt;w:WrapTextWithPunct/&gt;    &lt;w:UseAsianBreakRules/&gt;    &lt;w:DontGrowAutofit/&gt;    &lt;w:SplitPgBreakAndParaMark/&gt;    &lt;w:EnableOpenTypeKerning/&gt;    &lt;w:DontFlipMirrorIndents/&gt;    &lt;w:OverrideTableStyleHps/&gt;    &lt;w:UseFELayout/&gt;   &lt;/w:Compatibility&gt;   &lt;w:DoNotOptimizeForBrowser/&gt;   &lt;m:mathPr&gt;    &lt;m:mathFont m:val="Cambria Math"/&gt;    &lt;m:brkBin m:val="before"/&gt;    &lt;m:brkBinSub m:val="&amp;#45;-"/&gt;    &lt;m:smallFrac m:val="off"/&gt;    &lt;m:dispDef/&gt;    &lt;m:lMargin m:val="0"/&gt;    &lt;m:rMargin m:val="0"/&gt;    &lt;m:defJc m:val="centerGroup"/&gt;    &lt;m:wrapIndent m:val="1440"/&gt;    &lt;m:intLim m:val="subSup"/&gt;    &lt;m:naryLim m:val="undOvr"/&gt;   &lt;/m:mathPr&gt;&lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"  DefSemiHidden="true" DefQFormat="false" DefPriority="99"  LatentStyleCount="267"&gt;   &lt;w:LsdException Locked="false" Priority="0" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Normal"/&gt;   &lt;w:LsdException Locked="false" Priority="9" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="heading 1"/&gt;   &lt;w:LsdException Locked="false" Priority="0" QFormat="true" Name="heading 2"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/&gt;   &lt;w:LsdException Locked="false" Priority="0" QFormat="true" Name="heading 8"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 1"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 2"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 3"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 4"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 5"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 6"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 7"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 8"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 9"/&gt;   &lt;w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/&gt;   &lt;w:LsdException Locked="false" Priority="10" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Title"/&gt;   &lt;w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/&gt;   &lt;w:LsdException Locked="false" Priority="11" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/&gt;   &lt;w:LsdException Locked="false" Priority="22" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Strong"/&gt;   &lt;w:LsdException Locked="false" Priority="20" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="59" SemiHidden="false"   UnhideWhenUsed="false" Name="Table Grid"/&gt;   &lt;w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/&gt;   &lt;w:LsdException Locked="false" Priority="1" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/&gt;   &lt;w:LsdException Locked="false" Priority="34" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/&gt;   &lt;w:LsdException Locked="false" Priority="29" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Quote"/&gt;   &lt;w:LsdException Locked="false" Priority="30" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="19" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="21" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="31" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/&gt;   &lt;w:LsdException Locked="false" Priority="32" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/&gt;   &lt;w:LsdException Locked="false" Priority="33" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Book Title"/&gt;   &lt;w:LsdException Locked="false" Priority="37" Name="Bibliography"/&gt;   &lt;w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt; /* Style Definitions */ table.MsoNormalTable {mso-style-name:Standardowy; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:none; text-autospace:ideograph-other; font-size:12.0pt; font-family:"Times New Roman","serif"; mso-bidi-font-family:Tahoma; mso-font-kerning:1.5pt;}&lt;/style&gt; &lt;![endif]--&gt;  &lt;br /&gt;&lt;div class="Textbody"&gt;Dalszym krokiem, na dużo wyższym poziomie abstrakcji i wymagającym dogłębnego zrozumienia systemu. Na bazie pojawiających się wzorców, rozwijających się obiektów dziedzinowych po pewnym czasie dostrzegamy konieczność modyfikacji architektury. Z pomocą mogą nam przyjść wzorce architektoniczne lub wprowadzenie innych mechanizmów architektonicznych. Na tego typu przekształcenia może się składać m. in.:&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; text-indent: -18.0pt;"&gt;&lt;span style="font-family: StarSymbol; font-size: 9.0pt; line-height: 150%; mso-bidi-font-family: StarSymbol; mso-fareast-font-family: StarSymbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;●&lt;span style="font: 7.0pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;wprowadzanie warstw;&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; text-indent: -18.0pt;"&gt;&lt;span style="font-family: StarSymbol; font-size: 9.0pt; line-height: 150%; mso-bidi-font-family: StarSymbol; mso-fareast-font-family: StarSymbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;●&lt;span style="font: 7.0pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;wprowadzenie lub zmiana O/RM;&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; text-indent: -18.0pt;"&gt;&lt;span style="font-family: StarSymbol; font-size: 9.0pt; line-height: 150%; mso-bidi-font-family: StarSymbol; mso-fareast-font-family: StarSymbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;●&lt;span style="font: 7.0pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;zmiana organizacji logiki biznesowej;&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; text-indent: -18.0pt;"&gt;&lt;span style="font-family: StarSymbol; font-size: 9.0pt; line-height: 150%; mso-bidi-font-family: StarSymbol; mso-fareast-font-family: StarSymbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;●&lt;span style="font: 7.0pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;wprowadzenie lub zmiana szkieletu aplikacji.&lt;/div&gt;&lt;div class="Textbody"&gt;Często w systemach przyjmuje się, że stworzona raz architektura będzie doskonale spełniać swoje zadanie przez cały cykl życia produktu. Tymczasem zmienność wymagań oraz trudność stworzenia optymalnej architektury od samego początku powoduje, że założenia architektoniczne należy cały czas monitorować oraz wprowadzać ewolucyjne zmiany, tak aby powstające rozwiązania były proste. Sztywna, nie zmieniana architektura najczęściej prowadzi do powstawania rozwiązań trudnych w zrozumieniu, naszpikowanych obejściami.&lt;/div&gt;&lt;h2 style="margin-left: 0cm; mso-list: l1 level2 lfo1; text-indent: 0cm;"&gt;&lt;span style="mso-bidi-font-family: Arial; mso-fareast-font-family: Arial;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font: 7.0pt &amp;quot;Times New Roman&amp;quot;;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Verdana&amp;quot;,&amp;quot;sans-serif&amp;quot;;"&gt;Ciągła refaktoryzacja&lt;/span&gt;&lt;/h2&gt;&lt;div class="Textbody"&gt;Przedstawiony proces przedstawia koncepcję ciągłej refaktoryzacji, w której jest ona częścią prac projektowych na każdym poziomie – architektury, projektu, kodu. Nie jest wydzieloną fazą, samodzielną częścią – jest częścią integralną prac. Chcę zaznaczyć, że powyższy proces (mimo, że tak został przedstawiony) nie jest całkowicie liniowy. Często realizując jeden z późniejszych kroków należy wielokrotnie wracać do kroków wcześniejszych. Przedstawiona strategia przedstawia bardziej kierunek działań niż sztywny algorytm.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-1978244617887216724?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/1978244617887216724/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=1978244617887216724' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/1978244617887216724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/1978244617887216724'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/06/naturalny-porzadek-refaktoryzacji-pod_5301.html' title='Naturalny porządek refaktoryzacji pod lupą cz. 5 Ewolucja architektury'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-6351810493446662686</id><published>2011-06-29T01:24:00.001+02:00</published><updated>2011-06-29T01:26:58.298+02:00</updated><title type='text'>Naturalny porządek refaktoryzacji pod lupą cz. 4 Refaktoryzacja do wzorców</title><content type='html'>Stosując dotychczasowe kroki zaczynamy mieć coraz bardziej kształtne rozwiązanie, jednak głównie to co otrzymujemy to metody pogrupowane w klasy. Nadszedł czas na zastosowanie zasad obiektowych (np. zebranych w SOLID). Analizujemy kod pod kątem powtarzalności, potrzeby elastyczności, zapachów kodu i wprowadzamy wzorce projektowe. Często tam gdzie mamy wiele metod o zbliżonym schemacie będzie można zastosować &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Template Method&lt;/span&gt; lub &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Strategy&lt;/span&gt;. Tam gdzie tworzymy złożone struktury, tam stosujemy wzorzec &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Builder&lt;/span&gt;. Tam gdzie mamy do czynienia z nieskomplikowaną maszyną stanową wprowadzamy &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;State&lt;/span&gt;. Tam gdzie potrzebujemy polimorficznego tworzenia obiektów używamy&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; Abstract Factory&lt;/span&gt; lub jej zdegenerowanej postaci &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Simple Factory&lt;/span&gt;.&lt;br /&gt;Jeśli przyjrzymy się  klasie &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;TextObfuscatorMethods&lt;/span&gt; z przykładu, możemy zauważyć, że większość metod przyjmuje jako parametr przetwarzany tekst. Jest to sygnał, że te metody powinny być w klasie, która ma pole zawierające przetwarzany tekst. W zasadzie możemy odwrócić sytuację i w klasie &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;TextObfuscatorMethods &lt;/span&gt;umieścić pole typu przetwarzany tekst, wtedy metody staną się praktycznie bezparametrowe. Tym samym klasa nabiera charakteru wzorca &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Builder&lt;/span&gt;.&lt;br /&gt;Inną opcją, pod warunkiem, że chcielibyśmy uzyskać możliwość dowolnego składania przekształceń zaciemniających tekst (stosować je wybiórczo, w dowolnej kolejności, o czym chcielibyśmy decydować w czasie wykonania), wtedy można by zastosować wzorzec &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Decorator&lt;/span&gt;.&lt;br /&gt;Wersja z Budowniczym wyglądałaby jak poniżej.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;public class TextObfuscator&lt;br /&gt;{&lt;br /&gt;    private ObfuscatedTextBuilder builder = null;&lt;br /&gt;    // ...&lt;br /&gt;    public string Obfuscate(string text)&lt;br /&gt;    {&lt;br /&gt;        builder.NewText(text);&lt;br /&gt;&lt;br /&gt;        builder.ChangeWordsOrderRandomly();&lt;br /&gt;        builder.AddMeaninglessWordsRandomly();&lt;br /&gt;        builder.RemoveSeparators();&lt;br /&gt;        builder.AddSeparatorsRandomly();&lt;br /&gt;        builder.RemoveSpaces();&lt;br /&gt;        builder.ReplacePolishCharactersWithNonPolish();&lt;br /&gt;        builder.ReplaceUpperAndLowercase();&lt;br /&gt;&lt;br /&gt;        return builder.ToString();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;public class ObfuscatedTextBuilder&lt;br /&gt;{&lt;br /&gt;    // ...&lt;br /&gt;    private List&lt;textpart&gt; textParts = new List&lt;textpart&gt;();&lt;br /&gt;    public virtual void NewText(string text)&lt;br /&gt;    {&lt;br /&gt;        this.textParts = ParseTextForWordsAndNonWords(text);&lt;br /&gt;    }&lt;br /&gt;    // ...&lt;br /&gt;    public virtual void RemoveSpaces()&lt;br /&gt;    {&lt;br /&gt;        for (int i = 0; i &amp;lt; textParts.Count; i++)&lt;br /&gt;        {&lt;br /&gt;            RemoveSpacesFromTextPart(textParts, i);&lt;br /&gt;            RemoveTextPartIfEmpty(textParts, i);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public virtual void AddMeaninglessWordsRandomly()&lt;br /&gt;    {&lt;br /&gt;        for (int i = 0; i &amp;lt; textParts.Count; i++)&lt;br /&gt;        {&lt;br /&gt;            if (ShouldAddMeaninglessWords())&lt;br /&gt;            {&lt;br /&gt;                textParts.Insert(i, TextPart.SpaceSeparator); i++;&lt;br /&gt;                textParts.Insert(i, new TextPart(DrawMeaninglessWord(), TextPartType.WORD)); i++;&lt;br /&gt;                textParts.Insert(i, TextPart.SpaceSeparator);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    // ...&lt;br /&gt;}&lt;br /&gt;&lt;/textpart&gt;&lt;/textpart&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-6351810493446662686?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/6351810493446662686/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=6351810493446662686' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6351810493446662686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6351810493446662686'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/06/naturalny-porzadek-refaktoryzacji-pod_29.html' title='Naturalny porządek refaktoryzacji pod lupą cz. 4 Refaktoryzacja do wzorców'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-3835137477108070168</id><published>2011-06-11T01:55:00.017+02:00</published><updated>2011-06-29T01:20:40.639+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='czysty kod'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoryzacja'/><title type='text'>Naturalny porządek refaktoryzacji pod lupą cz. 3 Extract Method</title><content type='html'>&lt;div class="Textbody"&gt;W następnym kroku przyglądamy się odpowiedzialnościom poszczególnych klas oraz metodom, pod kątem dopasowania do odpowiedzialności klasy. Najlepiej przeanalizuj wszystkie metody oraz pogrupuj je pod kątem wykonywania podobnych operacji. Szukamy dla nich miejsca w innych klasach lub w nowej klasie. Pamiętaj: jeśli w danej klasie istnieje znacząca metoda prywatna (dłuższa niż 3-4 wiersze), to metoda ta powinna znaleźć się w innej klasie.&lt;/div&gt;&lt;div class="Textbody"&gt;W naszym przykładzie metody głównie skupiają wokół pojedynczych operacji mających na celu zaciemnianie tekstu oraz zapewniającym wykonanie operacji z pewnym prawdopobieństwem. Możemy wyodrębnić odpowiadające tym operacjom klasy TextObfuscatorMethods oraz Probability.&lt;/div&gt;&lt;div class="Textbody"&gt;Kod po tej zmianie mógłby wyglądać tak:&lt;/div&gt;&lt;pre class="brush: csharp;"&gt;public class TextObfuscator&lt;br /&gt;{&lt;br /&gt;    // ...&lt;br /&gt;    public string Obfuscate(string text)&lt;br /&gt;    {&lt;br /&gt;        List&amp;lt;TextPart&amp;gt; parts = methods.ParseTextForWordsAndNonWords(text);&lt;br /&gt;        methods.ChangeWordsOrderRandomly(parts);&lt;br /&gt;        methods.AddMeaninglessWordsRandomly(parts);&lt;br /&gt;        methods.RemoveSeparators(parts);&lt;br /&gt;        methods.AddSeparatorsRandomly(parts);&lt;br /&gt;        methods.RemoveSpaces(parts);&lt;br /&gt;        // ...&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class TextObfuscatorMethods&lt;br /&gt;{&lt;br /&gt;    // ...&lt;br /&gt;    public virtual void RemoveSpaces(List&amp;lt;TextPart&amp;gt; parts)&lt;br /&gt;    {&lt;br /&gt;        for (int i = 0; i &amp;lt; parts.Count; i++)&lt;br /&gt;        {&lt;br /&gt;            RemoveSpacesFromTextPart(parts, i);&lt;br /&gt;            RemoveTextPartIfEmpty(parts, i);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static void RemoveSpacesFromTextPart(List&amp;lt;TextPart&amp;gt; parts, int i)&lt;br /&gt;    {&lt;br /&gt;        parts[i] = parts[i].ReplaceContents(" ", "");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public virtual void RemoveSeparators(List&amp;lt;TextPart&amp;gt; parts)&lt;br /&gt;    {&lt;br /&gt;        for(int i = 0; i &amp;lt; parts.Count; i++)&lt;br /&gt;        {&lt;br /&gt;            RemoveSeparatorsFromTextPart(parts, i);&lt;br /&gt;            RemoveTextPartIfEmpty(parts, i);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public virtual void AddSeparatorsRandomly(List&amp;lt;TextPart&amp;gt; parts)&lt;br /&gt;    {&lt;br /&gt;        for (int i = 0; i &amp;lt; parts.Count; i++)&lt;br /&gt;        {&lt;br /&gt;            if (ShouldAddSeparator())&lt;br /&gt;            {&lt;br /&gt;                parts.Insert(i, TextPart.NewSeparator(DrawSeparator())); i++;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private bool ShouldAddSeparator()&lt;br /&gt;    {&lt;br /&gt;        return probability.ShouldBeDone(ADDING_SEPARATOR_PROBABILITY);&lt;br /&gt;    }&lt;br /&gt;    // ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Probability&lt;br /&gt;{&lt;br /&gt;    private Random random = new Random();&lt;br /&gt;&lt;br /&gt;    public bool ShouldBeDone(double probability)&lt;br /&gt;    {&lt;br /&gt;        if (probability &amp;lt; 0.0 || probability &amp;gt; 1.0)&lt;br /&gt;        {&lt;br /&gt;            throw new ProbabilityException("Probability should be in range [0.0, 0.1]");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return random.NextDouble() &amp;lt; probability;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-3835137477108070168?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/3835137477108070168/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=3835137477108070168' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/3835137477108070168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/3835137477108070168'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/06/naturalny-porzadek-refaktoryzacji-pod_11.html' title='Naturalny porządek refaktoryzacji pod lupą cz. 3 Extract Method'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-1999470495758604913</id><published>2011-06-07T11:02:00.001+02:00</published><updated>2011-06-07T11:04:35.584+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='szukam pracy'/><category scheme='http://www.blogger.com/atom/ns#' term='praca'/><title type='text'>Czy myślałeś kiedyś o karierze trenera/konsultanta?</title><content type='html'>Jako że nasza działalność (BNS IT &lt;a href="http://www.bnsit.pl/"&gt;http://www.bnsit.pl&lt;/a&gt;) nabiera coraz większego rozmachu, pojawia się miejsce dla osób, które są chętne, aby pracować z innymi w celu dzielenia się wiedzą i doświadczeniem oraz chcą wspierać zespoły w zwiększaniu efektywności pracy.&lt;br /&gt;Zatem jeśli masz doświadczenie praktyczne w pracy na projektami programistycznymi, jesteś kompetentny w PRZYNAJMNIEJ W JEDNYM z następujących obszarów:&lt;br /&gt;- wzorce projektowe&lt;br /&gt;- dobre praktyki pracy z kodem (refaktoryzacja,                       czysty kod, obiektowość (SOLID, GRASP,                       interfejsy))&lt;br /&gt;- test-driven development&lt;br /&gt;- domain-driven design&lt;br /&gt;- scrum (agile)&lt;br /&gt;- komunikacja w zespole (w kontekście projektów                       programistycznych),&lt;br /&gt;- zarządzanie czasem dla programistów,&lt;br /&gt;- zarządzanie projektami,&lt;br /&gt;- zarządzanie wymaganiami, analiza.&lt;br /&gt;&lt;br /&gt;Ważna jest wiedza i doświadczenie projektowe, co do warsztatu trenera, jesteśmy w stanie odpowiednio do tego przygotować.&lt;br /&gt;&lt;br /&gt;Jesteśmy głównie zainteresowani stałą współpracą. Aczkolwiek ewentualnie opcja współpracy od czasu do czasu też wchodzi w grę.&lt;br /&gt;&lt;br /&gt;Pisz śmiało: m [kroppka] sieraczkiewicz [mauppa] bnsit [kropkka] pl&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-1999470495758604913?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/1999470495758604913/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=1999470495758604913' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/1999470495758604913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/1999470495758604913'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/06/czy-myslaes-kiedys-o-karierze.html' title='Czy myślałeś kiedyś o karierze trenera/konsultanta?'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-4209338734954438620</id><published>2011-06-07T10:43:00.004+02:00</published><updated>2011-06-28T10:35:00.030+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='czysty kod'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoring'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoryzacja'/><title type='text'>Naturalny porządek refaktoryzacji pod lupą cz. 2 Compose Method</title><content type='html'>&lt;h2&gt;Compose Method&lt;/h2&gt;&lt;div class="Standard"&gt;Analiza metod takich jak przedstawiona w części 1. najczęściej prowadzi nas do zrozumienia, jakie są główne punkty algorytmu zawartego w metodzie. I to jest właśnie kolejny krok – postaraj się podzielić dużą metodę na mniejsze kroki wyodrębniając je do osobnym metod (refaktoryzacja Extract Method). Tym samym pierwotna metoda będzie się składać z sekwencji wywołań metod składowych. Przy odpowiedniej konwencji nazewniczej uzyskamy kod, który czyta się jak książkę.&lt;/div&gt;Przy okazji warto co nieco posprzątać – głównie wprowadzić zmiany w mało intuicyjnych nazwach. Przykład znajdziesz poniżej.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;public class TextObfuscator&lt;br /&gt;{&lt;br /&gt;    // ...&lt;br /&gt;    public string Obfuscate(string text)&lt;br /&gt;    {&lt;br /&gt;        String result = ChangeWordsOrderRandomly(text);&lt;br /&gt;        result = AddMeaninglessWordsRandomly(result);&lt;br /&gt;        result = RemoveSeparators(result);&lt;br /&gt;        result = AddSeparatorsRandomly(result);&lt;br /&gt;        result = ReplacePolishCharactersWithNonPolishCharacters(result);&lt;br /&gt;        result = ReplaceUpperAndLowerCharactersRandomly(result);&lt;br /&gt;        result = RemoveSpaces(result);&lt;br /&gt;        return result;&lt;br /&gt;    }&lt;br /&gt;    public String RemoveSpaces(String text)&lt;br /&gt;    {&lt;br /&gt;        return text.Replace(" ", "");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String RemoveSeparators(String text)&lt;br /&gt;    {&lt;br /&gt;        return Regex.Replace(text, SEPARATORS_REGEX, "", RegexOptions.CultureInvariant);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public String ReplacePolishCharactersWithNonPolishCharacters(String text)&lt;br /&gt;    {&lt;br /&gt;        return text&lt;br /&gt;                .Replace("ą", "a")&lt;br /&gt;                .Replace("ł", "l")&lt;br /&gt;                .Replace("ę", "e")&lt;br /&gt;                .Replace("ń", "n")&lt;br /&gt;                .Replace("ż", "z")&lt;br /&gt;                .Replace("ź", "z")&lt;br /&gt;                .Replace("ó", "o")&lt;br /&gt;                .Replace("ś", "s")&lt;br /&gt;                .Replace("ć", "c")&lt;br /&gt;                .Replace("Ą", "A")&lt;br /&gt;                .Replace("Ł", "L")&lt;br /&gt;                .Replace("Ę", "E")&lt;br /&gt;                .Replace("Ń", "N")&lt;br /&gt;                .Replace("Ż", "Z")&lt;br /&gt;                .Replace("Ź", "Z")&lt;br /&gt;                .Replace("Ó", "O")&lt;br /&gt;                .Replace("Ś", "S");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String ReplaceUpperAndLowerCharactersRandomly(String text)&lt;br /&gt;    {&lt;br /&gt;        String result = "";&lt;br /&gt;        char[] textArray = text.ToCharArray();&lt;br /&gt;&lt;br /&gt;        foreach (char currentCharacter in textArray)&lt;br /&gt;        {&lt;br /&gt;            if (ShouldBeUpperAndLowerReplaced())&lt;br /&gt;            {&lt;br /&gt;                result += ReplaceLowerAndUpper(currentCharacter);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                result += currentCharacter;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return result;&lt;br /&gt;    }&lt;br /&gt;    // ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-4209338734954438620?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/4209338734954438620/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=4209338734954438620' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/4209338734954438620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/4209338734954438620'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/06/naturalny-porzadek-refaktoryzacji-pod.html' title='Naturalny porządek refaktoryzacji pod lupą cz. 2 Compose Method'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-6190429369934952251</id><published>2011-05-27T00:26:00.003+02:00</published><updated>2011-06-28T10:35:17.070+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='czysty kod'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoring'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoryzacja'/><title type='text'>Naturalny porządek refaktoryzacji pod lupą cz. 1</title><content type='html'>(Rozwinięcie tego wpisu powinno pojawić się w najbliższym SDJ http://sdjournal.pl/)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="Textbody"&gt;Refaktoryzacja to odwieczny (to chyba nie najlepsze słowo jak na krótki czas funkcjonowania dyscypliny inżynierii oprogramowania ;-)) problem - bo wszyscy wiedzą, że powinno się to robić, a nikt nie ma na to czasu.&amp;nbsp;&lt;/div&gt;&lt;div class="Textbody"&gt;Jak już zaczniesz refaktoryzować, najczęściej nie wystarczy &lt;b&gt;po prostu refaktoryzać&lt;/b&gt;, bo łatwo wpaść w szał refaktoryzacji, który polega na refaktoryzowaniu wszystkiego i za wszelką cenę. Przedstawię poniżej strategię refaktoryzacji, która w sposób systemowy pozwala podejść do tego często niewdzięcznego zadania, jednocześnie przyczyniając się do ewolucyjnego rozwoju projektu i architektury. Podpowiada też, jak się zabrać za kod odziedziczony i zacząć go refaktoryzować. Oto magiczne punkty:&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; text-indent: -18.0pt;"&gt;1.&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Zacznij od prostego rozwiązania, zgodnie zasadą &lt;i style="mso-bidi-font-style: normal;"&gt;Keep it simple stupid&lt;/i&gt;. Nie myśl zbyt dużo o wzorcach, o wprowadzaniu wszelkiej możliwej elastyczności.&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; text-indent: -18.0pt;"&gt;2.&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Z dużych metod zaczynaj wyodrębniać mniejsze składowe metody (refaktoryzacja &lt;i&gt;Extract Method&lt;/i&gt;). Dąż do realizacji wzorca &lt;i&gt;Compose Method &lt;/i&gt;– niech Twoja główna metoda składa się z serii wywołań mniejszych metod.&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; text-indent: -18.0pt;"&gt;3.&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Kiedy Twoje klasy będą składały się z dużej ilości małych metod, zacznij analizować odpowiedzialność klasy. Przesuń metody, które realizują inne odpowiedzialności do bardziej odpowiednich dla nich klas.&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; text-indent: -18.0pt;"&gt;4.&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Z czasem zaczynasz dostrzegać, że w Twoich rozwiązaniach potrzeba elastyczności – zacznij wprowadzać wzorce projektowe, tam gdzie potrzeba.&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; text-indent: -18.0pt;"&gt;5.&lt;span style="font: 7pt &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Raz na jakiś czas (raz na kilka miesięcy przy większych projektach), analizuj to, co dzieje się z Twoim projektem. Architektura wymaga regularnego odświeżania i wprowadzania zmian, aby przystawała do pojawiających się wymagań.&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36pt; text-indent: -18pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36pt; text-indent: -18pt;"&gt;Idea rysunkowa została zawarta we wpisie &lt;a href="http://msieraczkiewicz.blogspot.com/2011/02/naturalny-porzadek-refaktoryzacji-idea.html"&gt;http://msieraczkiewicz.blogspot.com/2011/02/naturalny-porzadek-refaktoryzacji-idea.html&lt;/a&gt;&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36pt; text-indent: -18pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="Textbody" style="margin-left: 36pt; text-indent: -18pt;"&gt;&lt;/div&gt;&lt;div class="Textbody"&gt;Załóżmy, że mamy napisaną klasę udostępniającą metodą służącą do zaciemniania tekstu, będącego parametrem metody. Przykładowy kod znajdziesz na poniżej.&lt;/div&gt;&lt;pre class="brush: csharp;"&gt;public class TextManager&lt;br /&gt;{&lt;br /&gt;    private TextManagerHelper _hlp = null;&lt;br /&gt;    // ...&lt;br /&gt;    public TextManager(TextManagerHelper _helper)&lt;br /&gt;    {&lt;br /&gt;        this._hlp = _helper;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private Random rnd = new Random();&lt;br /&gt;&lt;br /&gt;    public string Convert(string text)&lt;br /&gt;    {&lt;br /&gt;        String result = "";&lt;br /&gt;        List&amp;lt;TextPart&amp;gt; prts = _hlp.Convert(text);&lt;br /&gt;&lt;br /&gt;        for (int i = 0; i &amp;lt; prts.Count; i++)&lt;br /&gt;        {&lt;br /&gt;            if (prts[i].Type.Equals(TextPartType.WORD) &amp;amp;&amp;amp; rnd.NextDouble() &amp;lt; 0.2)&lt;br /&gt;            {&lt;br /&gt;                if (i + 2 &amp;lt; prts.Count)&lt;br /&gt;                {&lt;br /&gt;                    TextPart t = prts[i];&lt;br /&gt;                    prts[i] = prts[i + 2];&lt;br /&gt;                    prts[i + 2] = t;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        for(int i1 = 0; i1 &amp;lt; prts.Count; i1++)&lt;br /&gt;        {&lt;br /&gt;            if (rnd.NextDouble() &amp;lt; 0.2)&lt;br /&gt;            {&lt;br /&gt;                prts.Insert(i1, new TextPart(" ", TextPartType.NONWORD)); i1++;&lt;br /&gt;                String[] wds = new String[] { "i", "a", "aczkolwiek", "poniekąd" };&lt;br /&gt;                int ind = rnd.Next(wds.Length);&lt;br /&gt;                prts.Insert(i1, new TextPart(wds[ind], TextPartType.WORD)); i1++;&lt;br /&gt;                prts.Insert(i1, new TextPart(" ", TextPartType.NONWORD));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        String result2 = "";&lt;br /&gt;&lt;br /&gt;        foreach (TextPart part in prts)&lt;br /&gt;        {&lt;br /&gt;            result2 += part.Contents;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        result = result2;&lt;br /&gt;        result = Regex.Replace(result, @"[\?!-\.,:;'\(\)]", "", RegexOptions.CultureInvariant);&lt;br /&gt;&lt;br /&gt;        String result1 = "";&lt;br /&gt;&lt;br /&gt;        for ( int i2 = 0; i2 &amp;lt; result.Split(' ').Length - 1; i2++)&lt;br /&gt;        {&lt;br /&gt;            if (rnd.NextDouble() &amp;lt; 0.5)&lt;br /&gt;            {&lt;br /&gt;                char [] chs = new char[] { '.', ',', '!' };&lt;br /&gt;                int j = rnd.Next(chs.Length);&lt;br /&gt;                result1 += result.Split(' ')[i2] + chs[j];&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                result1 += result.Split(' ')[i2] + " ";&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        result1 += result.Split(' ')[result.Split(' ').Length - 1];&lt;br /&gt;        result = result1;&lt;br /&gt;&lt;br /&gt;        result = result&lt;br /&gt;            .Replace("ą", "a")&lt;br /&gt;            .Replace("ł", "l")&lt;br /&gt;            .Replace("ę", "e")&lt;br /&gt;            .Replace("ń", "n")&lt;br /&gt;            .Replace("ż", "z")&lt;br /&gt;            .Replace("ź", "z")&lt;br /&gt;            .Replace("ó", "o")&lt;br /&gt;            .Replace("ś", "s")&lt;br /&gt;            .Replace("ć", "c")&lt;br /&gt;            .Replace("Ą", "A")&lt;br /&gt;            .Replace("Ł", "L")&lt;br /&gt;            .Replace("Ę", "E")&lt;br /&gt;            .Replace("Ń", "N")&lt;br /&gt;            .Replace("Ż", "Z")&lt;br /&gt;            .Replace("Ź", "Z")&lt;br /&gt;            .Replace("Ó", "O")&lt;br /&gt;            .Replace("Ś", "S");&lt;br /&gt;&lt;br /&gt;        String result3 = "";&lt;br /&gt;        char[] tArray = result.ToCharArray();&lt;br /&gt;&lt;br /&gt;        foreach (char ch in tArray) {&lt;br /&gt;            if (rnd.NextDouble() &amp;lt; 0.3)&lt;br /&gt;            {&lt;br /&gt;                char? newCh = null;&lt;br /&gt;                if (Char.IsLower(ch))&lt;br /&gt;                {&lt;br /&gt;                    newCh = Char.ToUpper(ch);&lt;br /&gt;                } else&lt;br /&gt;                {&lt;br /&gt;                    newCh = Char.ToLower(ch);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                result3 += newCh;&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                result3 += ch;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        result = result3.Replace(" ", "");&lt;br /&gt;&lt;br /&gt;        return result;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;C. D. N.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-6190429369934952251?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/6190429369934952251/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=6190429369934952251' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6190429369934952251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6190429369934952251'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/05/naturalny-porzadek-refaktoryzacji-pod.html' title='Naturalny porządek refaktoryzacji pod lupą cz. 1'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-5556856784945481637</id><published>2011-04-19T12:44:00.000+02:00</published><updated>2011-04-19T12:44:06.994+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='czysty kod'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoryzacja'/><title type='text'>Czysty kod</title><content type='html'>Toczą się filozoficzne dyskusje, czy czysty kod ma znaczenie i czy inwestować czas w jego czytanie.&lt;br /&gt;Nie będę się włączał w tę dyskusję bezpośrednio. Mały przykład:&lt;br /&gt;&lt;br /&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;o:OfficeDocumentSettings&gt;   &lt;o:TargetScreenSize&gt;800x600&lt;/o:TargetScreenSize&gt;  &lt;/o:OfficeDocumentSettings&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:TrackMoves/&gt;   &lt;w:TrackFormatting/&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:PunctuationKerning/&gt;   &lt;w:ValidateAgainstSchemas/&gt;   &lt;w:SaveIfXMLInvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:IgnoreMixedContent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:AlwaysShowPlaceholderText&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:DoNotPromoteQF/&gt;   &lt;w:LidThemeOther&gt;PL&lt;/w:LidThemeOther&gt;   &lt;w:LidThemeAsian&gt;X-NONE&lt;/w:LidThemeAsian&gt;   &lt;w:LidThemeComplexScript&gt;X-NONE&lt;/w:LidThemeComplexScript&gt;   &lt;w:Compatibility&gt;    &lt;w:BreakWrappedTables/&gt;    &lt;w:SnapToGridInCell/&gt;    &lt;w:WrapTextWithPunct/&gt;    &lt;w:UseAsianBreakRules/&gt;    &lt;w:DontGrowAutofit/&gt;    &lt;w:SplitPgBreakAndParaMark/&gt;    &lt;w:EnableOpenTypeKerning/&gt;    &lt;w:DontFlipMirrorIndents/&gt;    &lt;w:OverrideTableStyleHps/&gt;   &lt;/w:Compatibility&gt;   &lt;w:BrowserLevel&gt;MicrosoftInternetExplorer4&lt;/w:BrowserLevel&gt;   &lt;m:mathPr&gt;    &lt;m:mathFont m:val="Cambria Math"/&gt;    &lt;m:brkBin m:val="before"/&gt;    &lt;m:brkBinSub m:val="&amp;#45;-"/&gt;    &lt;m:smallFrac m:val="off"/&gt;    &lt;m:dispDef/&gt;    &lt;m:lMargin m:val="0"/&gt;    &lt;m:rMargin m:val="0"/&gt;    &lt;m:defJc m:val="centerGroup"/&gt;    &lt;m:wrapIndent m:val="1440"/&gt;    &lt;m:intLim m:val="subSup"/&gt;    &lt;m:naryLim m:val="undOvr"/&gt;   &lt;/m:mathPr&gt;&lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"  DefSemiHidden="true" DefQFormat="false" DefPriority="99"  LatentStyleCount="267"&gt;   &lt;w:LsdException Locked="false" Priority="0" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Normal"/&gt;   &lt;w:LsdException Locked="false" Priority="9" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="heading 1"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 1"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 2"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 3"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 4"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 5"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 6"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 7"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 8"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 9"/&gt;   &lt;w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/&gt;   &lt;w:LsdException Locked="false" Priority="10" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Title"/&gt;   &lt;w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/&gt;   &lt;w:LsdException Locked="false" Priority="11" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/&gt;   &lt;w:LsdException Locked="false" Priority="22" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Strong"/&gt;   &lt;w:LsdException Locked="false" Priority="20" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="59" SemiHidden="false"   UnhideWhenUsed="false" Name="Table Grid"/&gt;   &lt;w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/&gt;   &lt;w:LsdException Locked="false" Priority="1" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/&gt;   &lt;w:LsdException Locked="false" Priority="34" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/&gt;   &lt;w:LsdException Locked="false" Priority="29" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Quote"/&gt;   &lt;w:LsdException Locked="false" Priority="30" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="19" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="21" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="31" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/&gt;   &lt;w:LsdException Locked="false" Priority="32" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/&gt;   &lt;w:LsdException Locked="false" Priority="33" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Book Title"/&gt;   &lt;w:LsdException Locked="false" Priority="37" Name="Bibliography"/&gt;   &lt;w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt; /* Style Definitions */ table.MsoNormalTable {mso-style-name:Standardowy; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Calibri","sans-serif"; mso-bidi-font-family:"Times New Roman";}&lt;/style&gt; &lt;![endif]--&gt;  &lt;br /&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;prawo!Drugie!LEHMAna..oPiSujezJAWiskO!ZNanE.w,dziedZiNachi,wiEluI!!FIzyKi!zwieKszaNieNiEuPOrzAdKOwAnia!.W,.ENtropII. ,aCzkolwIEK! PONIekAD.!mIAre..uplYwU pONieKAd..czasuAczkOLWiek,&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;wpROWadZAnIe.dozMian!A,!aczkolWIeK !aNazywaNyCH,opROgrAmOWaniA ,iczesto !i!!prOgreSywnyMizwyKLE.poniEkAd,!PIeRWotna.StrUkturEnarusza.a.!PRoGramU.kUMulaCja,Zmian a.TEN,I !prOcEs!,,i.Tylko,liCzba,nasiLA, ,AcZkoLwiek,powiaZaniIntErakCjI poniEkAD!!roZnymi!ponIekad!,I!pomieDzYModuLamiw,sYStemiEZWiEkSZasie!.a, co! ,a,utruDniAzRoZUmienIe!!A,!acZKolwiek!I!..go,takzE!jEgO..modYfikacje..dalsze,&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;a,.jeST!,I.pOniEsieNie..aLternAtyWa,i.dodatKowyCh,WtrakciE!,nAKlaDOw,PielEgnaCjI..POswiecOnycHaczkOlwiek! ,na a,czynNosCi. ,a!ANTYREGREsYWnE!upRasZczaNie,StruKTuRy!i!LepszE.wprowadzaNyChwKOmPoNowANieI,.Zmian. ,iw,IsTNIejACE.i, rOwnoWaga.a,.OPrOgrAMOwanIe!pomIedZy,CzynnoscIami.,A,,ProGRESYwnyMI,RegresywNymI.od!.zaLeZYilOscI!.i, I.,RodZaju!infoRmaCji! a,plynacEJzwrOtnEj,srodoWiska!aCzkOlwieKZe,Inaczej!aczkOlwiEK!.,sa..pOnIEkad AobSLUGiwANE,zAdanIaZwiazaNe.Z,!.aczKOlWiEk!napraWa.blEdow!.a.!a!z,.inaczej. aCzkOLWIek!rozsZerzeniamI,funKcjOnalnyMi.&lt;/div&gt;&amp;nbsp;Tak najczęściej wygląda nasz kod! A fe...! &lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"&gt;Źródło: Wykład Bartosza Waltera o refaktoryzacji &lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-5556856784945481637?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/5556856784945481637/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=5556856784945481637' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/5556856784945481637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/5556856784945481637'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/04/czysty-kod.html' title='Czysty kod'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-5758678462740924755</id><published>2011-04-19T10:46:00.001+02:00</published><updated>2011-04-19T12:45:01.343+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DDD'/><category scheme='http://www.blogger.com/atom/ns#' term='efektywność'/><title type='text'>Zasada 20/80 Reloaded</title><content type='html'>Taki krótki wpis przyszedł mi do głowy.&lt;br /&gt;Wiele osób zna i być może stosuje zasadę 20/80 (cały Agile na tym stoi!), która w uogólniona brzmi mniej więcej tak: "20% procent naszych działań generuje 80% efektów". Innymi słowy - "mniej więcej 20% tego co robimy, ma sens". Mocne, prawda? Proste? &lt;br /&gt;Cholernie trudne! Bo jesteśmy przyzwyczajani i przyzwyczajeni do zapełniania czasu - żeby mieć poczucie, że cały czas robimy coś.&lt;br /&gt;Ale nie o tym chciałem pisać. Chciałem zwrócić uwagę na fakt, że wiele osób (nie chcę używać słowa "większość", choć bym się nie pomylił zbyt wiele) niepoprawnie interpretuje to stwierdzenie.&lt;br /&gt;&lt;br /&gt;Nie oznacza ono, że jak mamy 80% to już dalej nie warto poświęcać energii na dalszą pracę (projekt, release, funkcjonalność, zadanie, whatever)... ba! wtedy to już jest za późno! Właśnie zmarnowaliśmy ogromną ilość naszego cennego czasu. Bo co z tego, ze jest już 80% jeśli jest to zwykły shit, zadaniowa czy też funkcjonalna wata cukrowa!&lt;br /&gt;Powyższa zasada oznacza: znajdź 20% tego czym warto się zajmować i jak to znajdziesz, to włóż w to 200% energii i zaangażowania. Resztę można olać, najlepiej renegocjując wykonanie "owej reszty".&lt;br /&gt;Biznesowo: zamiast robić wielki system ze 100 ficzerami, lepiej zadać sobie pytanie, co naprawdę będzie użyteczne i co będzie używane i zrobić właśnie te 20 ficzerów.&lt;br /&gt;&lt;br /&gt;P.S.&lt;br /&gt;W DDD nazywamy to Core Domain! Zawsze bądź świadomy co jest Twoim corem! :) Zawsze zadawaj sobie pytanie, co jest Core w systemie, module, który robisz czy nawet funkcjonalności, którą realizujesz.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-5758678462740924755?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/5758678462740924755/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=5758678462740924755' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/5758678462740924755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/5758678462740924755'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/04/zasada-2080-reloaded.html' title='Zasada 20/80 Reloaded'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-6644490848948131352</id><published>2011-02-25T01:28:00.005+01:00</published><updated>2011-06-28T10:39:24.523+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='czysty kod'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoring'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoryzacja'/><title type='text'>Jaka nazwa dla tej metody?</title><content type='html'>&lt;pre class="brush: java;"&gt;public class OptionsAwareObject {  &lt;br /&gt;    private Options options;  &lt;br /&gt;      &lt;br /&gt;    public void updateOptions(String fontName, int fontSize) {  &lt;br /&gt;       options.setFontName(fontName);  &lt;br /&gt;       options.setFontSize(fontSize);  &lt;br /&gt;    }  &lt;br /&gt; }  &lt;br /&gt;   &lt;br /&gt; class Options {  &lt;br /&gt;   &lt;br /&gt;    private int foregroundColor;  &lt;br /&gt;      &lt;br /&gt;    private int backgroundColor;  &lt;br /&gt;      &lt;br /&gt;    private String fontName;  &lt;br /&gt;      &lt;br /&gt;    private int fontSize;&amp;nbsp;&lt;br /&gt;    // ...&lt;br /&gt;}  &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Czy updateOptions to dobra nazwa dla tej metody? Oczywiście, że nie! updateOptions jest ogólną nazwą, która sugerowałaby całościową aktualizacji opcji. Tymczasem my aktualizujemy tylko informacje nt. czcionki. Odpowiedzialnością metody jest zatem zmiana opcji związanych z czcionką. Lepszą nazwą byłaby:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;public void updateFontOptions(String fontName, int fontSize) {  //...&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-6644490848948131352?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/6644490848948131352/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=6644490848948131352' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6644490848948131352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6644490848948131352'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/02/jaka-nazwa-dla-tej-metody.html' title='Jaka nazwa dla tej metody?'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-6425045410916393284</id><published>2011-02-25T01:08:00.001+01:00</published><updated>2011-02-25T07:53:13.306+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software craftsmanship'/><title type='text'>Antylitania do programistów</title><content type='html'>Nienawidzę Was za to że: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;skupiacie się nad tym jakie ficzery ma Wasze IDE zamiast skupiać się na tym, jakich ficzerów potrzebuje Wasz klient/użytkownik,&lt;/li&gt;&lt;li&gt;klepanie w klawiaturę nazywacie myśleniem,&lt;/li&gt;&lt;li&gt;hektolitry czasu wyrzucacie w błoto testując manualnie swój kod,&lt;/li&gt;&lt;li&gt;więcej czasu spędzacie na walkę z frejmłorkami niż na dostarczaniu wartości dla końcowych użytkowników,&lt;/li&gt;&lt;li&gt; kodujecie wiele godzin nie zadając sobie pytania "co ja tak naprawdę robię",&lt;/li&gt;&lt;li&gt;naiwnie wierzycie, że technologie i narzędzia rozwiążą wasze problemy,&lt;/li&gt;&lt;li&gt;naiwnie wierzycie, że dobry algorytm jest ważniejszy od dobrego zrozumienia wymagań,&lt;/li&gt;&lt;li&gt;naiwnie wierzycie, że Wasza intuicja wystarczy w tworzeniu dobrego kodu,&lt;/li&gt;&lt;li&gt; naiwnie wierzycie, że jesteście w stanie ogarnąć złożoność kawałka systemu z którym pracujecie,&lt;/li&gt;&lt;li&gt;zgadzacie się na nierealne terminy,&lt;/li&gt;&lt;li&gt;że piszecie kiepski kod, znajdując na to wiele racjonalizacji (bo nie ma czasu),&lt;/li&gt;&lt;li&gt;w głowach tworzycie fragmenty kodu mimo że jeszcze dobrze nie wiecie co trzeba zrobić,&lt;/li&gt;&lt;li&gt;domyślacie się co trzeba zrobić, zamiast doprecyzować,&lt;/li&gt;&lt;li&gt;bezmyślnie podążacie za technologią, której używacie,&lt;/li&gt;&lt;li&gt;nie rozumiecie narzędzi i technologii, których używacie,&lt;/li&gt;&lt;li&gt;zamykacie się w swoim kawałku kodu, zrywając kontakt ze światem,&lt;/li&gt;&lt;li&gt;sądzicie, że to wszystko wina kierowników lub klienta i nie jesteście w stanie z tym nic zrobić.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;... mimo że kocham bo sam jestem programistą.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-6425045410916393284?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/6425045410916393284/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=6425045410916393284' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6425045410916393284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6425045410916393284'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/02/antylitania-do-programistow.html' title='Antylitania do programistów'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-432951635674339439</id><published>2011-02-19T16:55:00.002+01:00</published><updated>2011-02-19T17:00:58.857+01:00</updated><title type='text'>Call for ... code samples</title><content type='html'>Chętnie przedstawiłbym ideę naturalnego porządku refaktoryzacji na przykładowym kodzie. Niestety (co jest oczywiste rzecz jasna) nie mogę użyć kodu produkcyjnego klientów, a nie mam czasu przygotowywać do tego celu przykładu. Ale być może ktoś miałby chciałby na ten cel przeznaczyć swój kawałek kodu, projektu, który nie ma zbyt dużych (w zasadzie żadnych) obostrzeń co do publicznej publikacji.&lt;br /&gt;Główne założenie to musi być w kodzie co refaktoryzować ;-)&lt;br /&gt;&lt;br /&gt;W razie zainteresowania proszę o kontakt m [kropka] sieraczkiewicz [AT] bns [kropka] it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-432951635674339439?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/432951635674339439/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=432951635674339439' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/432951635674339439'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/432951635674339439'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/02/call-for-code-samples.html' title='Call for ... code samples'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-6167469983888234269</id><published>2011-02-15T20:45:00.001+01:00</published><updated>2011-02-15T20:48:43.182+01:00</updated><title type='text'>Naturalny porządek refaktoryzacji - idea rysunkowa</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-xviF_nzEEcI/TVrYekd1BmI/AAAAAAAAAAM/QsSa1AC-7D8/s1600/NOR.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 226px; height: 320px;" src="http://4.bp.blogspot.com/-xviF_nzEEcI/TVrYekd1BmI/AAAAAAAAAAM/QsSa1AC-7D8/s320/NOR.png" alt="" id="BLOGGER_PHOTO_ID_5574005508520871522" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-6167469983888234269?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/6167469983888234269/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=6167469983888234269' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6167469983888234269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6167469983888234269'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/02/naturalny-porzadek-refaktoryzacji-idea.html' title='Naturalny porządek refaktoryzacji - idea rysunkowa'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-xviF_nzEEcI/TVrYekd1BmI/AAAAAAAAAAM/QsSa1AC-7D8/s72-c/NOR.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-7888800519092022616</id><published>2011-02-15T00:17:00.006+01:00</published><updated>2011-02-15T00:46:12.695+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zarządzanie projektami'/><category scheme='http://www.blogger.com/atom/ns#' term='projekty'/><title type='text'>Młody kierowniku/team liderze! Opamiętaj się!</title><content type='html'>Chyba nie napisze nic nowego... ale to tylko fakt, że historia lubi się powtarzać... bezustannie (&lt;span style="font-style: italic;"&gt;vide: Marsz ku klęsce&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;Otóż&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Często powtarzanym, tragicznym w skutkach, nieprofesjonalnym działaniem drogi kierowniku/team liderze jest zobowiązywanie się do mało realnych terminów&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Naiwnie proste, można by rzec oczywiste, a jednak powtarza się. Dobrze o tym wiem, bo sam popełniałem nieraz ten błąd. Dlaczego zobowiązujemy się do mało realnych terminów:&lt;br /&gt;a) bo jest presja kogoś z zewnątrz (klienta, menedżera, dyrektora),&lt;br /&gt;b) bo wytwarzam presję wewnętrzną (chcę pokazać, że jesteśmy naprawdę dobrzy),&lt;br /&gt;c) bo kompletnie nie mam pojęcia (albo mam pojęcie ale tylko trochę), co rzeczywiście trzeba zrobić w projekcie,&lt;br /&gt;d) ??? - proszę o podpowiedzi :)&lt;br /&gt;&lt;br /&gt;Co do pierwszych dwóch podpunktów rozwiązanie jest (wydaje się) proste - potrzeba asertywności i zwykłej szczerości wobec siebie i wobec przełożonych, tudzież klienta. Ta trudność, szczególnie jeśli się zaczyna (lub ma się niewielkie doświadczenie), wymaga często wyjście poza strefę komfortu - powiedzieć, że się nie da (w tym czasie).&lt;br /&gt;I oczywiście można napotkać opór/sprzeciw, ale też najczęściej można pokazać swój profesjonalizm, który w tym przypadku zdefiniowałbym jako "Nie zobowiązuje się do niekonkretnych czy nierealnych terminów".&lt;br /&gt;Często słyszę pytanie: "A jak zrealizować projekt, w którym już wiadomo, że jest za mało czasu, że za mało ludzi, że niejasne wymagania. Jakie są najlepsze praktyki". Odpowiedź jest prosta "Nie zgadzaj się na to, a raczej - negocjuj". Pokaż dlaczego termin jest nierealny. Podziel pracę i oszacuj. Pokaż ryzyka. Nie zgadzaj się na obniżenie jakości ("Jakoś damy radę - zrobimy bez testów, bez definiowania kryteriów akceptacyjnych, byle działało").&lt;br /&gt;Ustalony termin to nie jest koniec świata i najczęściej można go negocjować, tylko uzbrój się w argumenty, które Ciebie przekonują.&lt;br /&gt;Sam jestem szefem. Nieraz zdarzało mi się chlapnąć jakiś termin, bez większego przemyślenia. Moi pracownicy często się do niego przywiązują - czasami nikomu nie przychodzi do głowy, żeby negocjować przesunięcie terminu. Czasami wystarczy krótka dyskusja i sprawa załatwiona. W tym świecie niemal wszystko jest negocjowalne! Ale często wymaga to odwagi! :) Sprawdźcie - jedną z głównych wartości związanych z Agile'em jest Odwaga. Wiecie dlaczego? :)&lt;br /&gt;&lt;br /&gt;Co do trzeciego podpunktu - zacznij używać jakiejś metodyki :) Skorzystaj z pomocy doświadczonego mentora.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-7888800519092022616?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/7888800519092022616/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=7888800519092022616' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/7888800519092022616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/7888800519092022616'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/02/mody-kierownikuteam-liderze-opamietaj.html' title='Młody kierowniku/team liderze! Opamiętaj się!'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-5837866987381067443</id><published>2011-02-09T23:16:00.009+01:00</published><updated>2011-02-10T01:12:32.903+01:00</updated><title type='text'>Kilka nowych koncepcji - Mantra architektoniczna, Design Retrospective, Współdzielony kontekst, Naturalny porządek refaktoryzacji</title><content type='html'>Ostatnio wyewoluowało mi się w głowie kilka nazwanych koncepcji, a w zasadzie może po prostu je dobrze zrozumiałem :) Kilka notatek poniżej, które traktuje jako alpha draft ;-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Mantra architektoniczna&lt;/span&gt;&lt;span style="font-weight: bold;"&gt; (ang. architectonic mantra)&lt;/span&gt;&lt;br /&gt;To co dzieje się praktycznie w każdym projekcie to dryfowanie architektury, tak że po kilku (nastu) miesiącach trwania projektu mało kto w zespole jest w stanie dobrze określić, jakie operacje powinny być wykonywane np. przez kontroller (lub managedbean lub whatever), jakie przez obiekty dziedzinowe, jakie przez fasady, usługi. Z czasem mieszane są odpowiedzialności tychże klas i coraz trudniej z rozwojem systemu. Jedyną opcją w tym przypadku jest tzw. mantra architektoniczna, która jest wariacją nt. techniki zdartej płyty znanej z psychologii komunikacji. Polega ona na tym, że należy w prace zespołu włączyć ciągłe przypominanie jakie mamy w architekturze główne bloki i jakie są też ich odpowiedzialności. W tym przypadku również sugeruję zespołom, aby wprowadziły regularne spotkania (raz/mc, raz/sprint), które nazywam &lt;span style="font-weight: bold;"&gt;Design Retrospective&lt;/span&gt; podczas których zespół:&lt;br /&gt;a) przypomina mantrę architektoniczną;&lt;br /&gt;b) analizuje sytuacje, w których niejasne jest, gdzie powinny się znaleźć konkretne klasy, operacje, pola - na bazie tego co się działo ostatnio w projekcie&lt;br /&gt;c) zbiera przypadki zdryfowania architektury i tworzy "program naprawczy"&lt;br /&gt;d) podejmuje decyzję o świadomej restrukturyzacji architektury (to akurat rzadziej).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Współdzielony kontekst (ang. shared context)&lt;/span&gt;&lt;br /&gt;Nie, nie, nie... bynajmniej nie chodzi tu o żadne wzorce projektowe czy architektoniczne. A o komunikację... Jak to powiedział Kent Beck gdzieś kiedyś "Większość problemów w projektach wynika z tego, że ktoś komuś czegoś nie powiedział". Zwolennicy Agile'a źródło problemów widzą w tzw. relay race, czyli przekazywaniu pracy między ludźmi (pewnie to znacie m. in. w takiej metaforze &lt;span class="f"&gt;&lt;cite&gt;www.&lt;b&gt;projectcartoon&lt;/b&gt;.com/)&lt;/cite&gt;.&lt;br /&gt;Problem polega w tym, że w sytuacji przekazywania produktów (dokumentacji, kodu, wymagań itp.) pracy jednej osoby (grupy osób) innej, nie jest przekazywany kontekst informacji, który doprowadził do powstania tego produktu, często mylnie zakładając, że jest on nieistotny. Ja twierdzę, że jest kluczowy.&lt;br /&gt;Ostatnio uczestniczyłem w takiej sytuacji. Jedna z osób dokonała wstępnej analizy wymagań i stworzyła podstawowy model  systemu (model dziedzinowy). Mieliśmy przeanalizować ten model. Jednak nie posiadając kontekstu &lt;/span&gt;&lt;span class="f"&gt;(pewne przymyślenia, wnioski, informacje, mikrodecyzje)&lt;/span&gt;&lt;span class="f"&gt;, który powstał w głowie osoby, która go stworzyła dość trudno na głębszym poziomie niż tylko poprawność UMLowa, ocenić poprawność modelu. Taką sytuację nazywam brakiem współdzielonego kontekstu.&lt;br /&gt;Dopiero zaczęliśmy wspólnie analizować wymagania w projekcie (User stories) i wspólnie budować model od nowa. Doszliśmy do podobnego modelu (z kilkoma subtelnymi różnicami), jednak w czasie "wspólnej pracy" powstał współdzielony kontekst (czyli uspójnione przemyślenia i rozumienie tematu). Współdzielony kontekst umożliwia trafniejsze podejmowanie decyzji oraz efektywniejszą kontynuację prac. To dlatego w Agile'u tak duży nacisk kładzie się na ścisłą współpracę - aby budować współdzielony kontekst.&lt;br /&gt;I stąd jedna przestroga: Nie zarzucaj nikogo produktem swojej pracy, będącej efektem wielu godzin działań i/lub przemyśleń, oczekując, że go dobrze zrozumie. Przynajmniej pójdź i razem z nim go (ten produkt) przeanalizuj i wytłumacz jak do tego doszedłeś. A najlepiej wypracowuj to wspólnie :) Oszczędzisz wiele pracy sobie i tej osobie, a w szczególności unikniesz wielu zniekształceń komunikacyjnych (które to właśnie generują bardzo dużo dodatkowej, niepotrzebnej pracy).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Naturalny porządek refaktoryzacji (ang. natural order of refactoring) albo inaczej co to naprawdę znaczy ewolucyjny design lub architektura&lt;/span&gt;.&lt;br /&gt;Jest to temat na osobny artykuł, tutaj więc pokrótce.&lt;br /&gt;Od pewnego czasu krystalizuje mi się koncept systematyzacji procesu refaktoryzacji od najniższego poziomu abstrakcji do najwyższego - naturalny sposób na ewolucyjny rozwój designu (projektu systemu).&lt;br /&gt;Idea jest taka - zaczynasz od najprostszego rozwiązania, które następnie refaktoryzujesz (jeśli potrzeba) na różnych poziomach abstrakcji (w pewnym ustalonym porządku). Oto porządek przekształceń (rozpoczynamy od niskopoziomowych).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;0. Transformacje (triangulizacje) - jeśli używasz TDD (http://cleancoder.posterous.com/the-transformation-priority-premise)&lt;br /&gt;1. Refaktoryzacje typu &lt;/span&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;Compose method&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;  (http://www.industriallogic.com/xp/refactoring/composeMethod.html) (czyli seria refaktoryzacji typu Extract method)&lt;/span&gt;&lt;br /&gt;Czyli pierwszą implementację złożonej metody rozbijam na serię wywołań kilku metod składowych na tym samym poziomie abstrakcji. Z jednego bloku kodu powstaje kilka metod.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. Refaktoryzacje typu Extract class, Extract interface, Move method, Move field na podstawie analizy odpowiedzialności klasy.&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Z czasem wyodrębnionych metod w powyższym kroku jest coraz więcej, więc klasa zaczyna być zbyt duża i często przestaje spełniać regułę SRP (pojedynczej odpowiedzialności). Zatem zaczynasz myśleć o przeniesieniu tychże metod gdzieś indziej. Do innej klasy, do nowej klasy, być może temu będzie towarzyszyć wyodrębnienie się interfejsu, być może będzie trzeba poprzesuwać pola w klasie.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. Refaktoryzacje do wzorców projektowych (http://www.industriallogic.com/xp/refactoring/)&lt;/span&gt;&lt;br /&gt;W sytuacjach, kiedy musisz przygotować się na zmienność w projekcie (np. różne wersje algorytmów, przetwarzanie zdarzeń, adaptowanie struktur czy zachowania), wprowadzasz w projekcie wzorce projektowe.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. Refaktoryzacja do wzorców architektonicznych (podstawowy opis wzorców &lt;span style="font-weight: bold;"&gt;http://martinfowler.com/eaaCatalog/)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Z czasem jeśli obecna architektura nie radzi sobie ze zmieniającymi się wymaganiami systemu albo potrzeba innej koncepcji, to modyfikujemy założenia architektoniczne - a zatem również musi ulec zmianie Mantra architektoniczna. Może to być: dodatnie warstwy, usunięcie warstwy, zmiana architektury dziedziny (Domain Model, Active Record, Exposed Domain Model) itp.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;Heurystyka zwinnego modelowania systemu (czyli jak zacząć i mieć pewien zgrubny koncept)&lt;/span&gt;&lt;br /&gt;Jak dojść zwinnie do wstępnego modelu, który pozwoli ruszyć z implementacją, a jednocześnie pozwoli uniknąć podstawowych błędów związanych z nieprzemyślaną architekturą? Jak i kiedy zaplanować architekturę? Zrobić wstępny projekt w podejściu zwinnym?&lt;br /&gt;Oto propozycja zwinnej "drogi" :) Jest to miks praktyk Scrumowych/Agilowych, ICONIXa i naszych doświadczeń BNSowych.&lt;br /&gt;1. Zdefiniuj (jeśli jeszcze nie masz) User Stories/Epics.&lt;br /&gt;Zazwyczaj wystarczy pokrycie 80% systemu. Pamiętaj, żeby nie przesadzać ze szczegółami. Jeśli twój system ma UI - koniecznie korzystaj z draftów ekranów. Jeśli nie ma przydadzą się uproszczone diagramy określające interakcje systemu. Jakie diagramy? To już zależy od Twojej dziedziny :)&lt;br /&gt;&lt;/span&gt;&lt;span class="f"&gt;2. Przeanalizuj interakcje z systemami zewnętrznymi. Z nich też będą wynikać US. W efekcie usługi czy elementy modelu.&lt;br /&gt;&lt;/span&gt;&lt;span class="f"&gt;3. Określ priorytety i zgrubnie określ co wejdzie do Realeasu (wersji wdrożeniowej - czyli zazwyczaj efekt kilku miesięcy prac).&lt;br /&gt;Pamiętaj, najbardziej będą interesować Cię rzeczy o wyższych priorytetach. Te o niższych nie są warte zbyt dużej uwagi.&lt;br /&gt;&lt;/span&gt;&lt;span class="f"&gt;4. Analizując po kolei User Stories, buduj model dziedziny (docelowo diagram klas dziedzinowych).&lt;br /&gt;Skupiaj się przede wszystkim na nazwach klas i powiązaniach. Jest to najbardziej naturalny słownik dziedzinowy (bardziej definicja nazw).&lt;br /&gt;5. Analizując po kolei User Stories (US), wyodrębniaj usługi (operacje) systemu.&lt;br /&gt;Najlepiej, żeby były sformułowane w języku biznesowym. Na początku nie dziel ich specjalnie. Nawet wrzucaj do wspólnego worka. Dla ułatwienia możesz powiązać je z odpowiednimi US.&lt;br /&gt;6. Określ złożoność operacji.&lt;br /&gt;Określ, które operacje są bardziej złożone (wychodzą poza klasyczny CRUD). Będzie to podstawa do określenia kierunku architektury.&lt;br /&gt;7. Wybierz kierunek architektury (w oparciu o model dziedzinowy)&lt;br /&gt;(m. in. Domain Model, Anemic Domain Model, Active Record, Exposed Domain Model). Uwzględnij technologie, jeśli jest już wybrana lub ją wybierz.&lt;br /&gt;8. Z wyróżnionych usług wybierz te o największym poziomie złożoności i ryzyku w celu analizy.&lt;br /&gt;Zrób proste szkice klas, interakcji, które pozwolą przeanalizować złożoność. Wybieraj tylko te usługi do analizy, które przynależą do US o wysokich priorytetach lub też mogą znacząco wpłynąć na wykonalność projektu.&lt;br /&gt;9. Osadź architekturę w technologii. Spartycjonuj usługi.&lt;br /&gt;Rozrysuj bloki architektury i typowe klasy. Na bazie listy usług - podziel je grupując wg zbliżonych odpowiedzialności (spójnych dziedzinowo).&lt;br /&gt;10. Przeanalizuj 1-2 US (koncept implementacji), które pozwolą zweryfikować założenia koncepcji.&lt;br /&gt;Jeśli weryfikacja się nie powiedzie, wróć do 7 lub 8.&lt;br /&gt;11. Zaimplementuj wybrane 1-2 US, aby zweryfikować koncepcje.&lt;br /&gt;Może to wymagać wstępnego setupu projektu, środowiska. Może to być podstawa to tzw. Iteracji 0, Sprintu 0, &lt;/span&gt;Elaboration phase (?? nie jestem ekspertem RUPa).&lt;br /&gt;Jeśli weryfikacja się nie powiedzie lub koncept ma luki przejdź do 7 lub 8.&lt;br /&gt;&lt;span class="f"&gt;12. Zdefiniuj Mantrę architektoniczną.&lt;br /&gt;13. Realizuj inkrementacyjnie projekt (to dalej definiuje metodyka).&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="f"&gt;Powiązany OFFTOPIC:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Zapodam pewną mądra myśl, która może kogoś natchnie do myślenia:&lt;/span&gt;&lt;br /&gt; &lt;span style="font-style: italic;"&gt;"W architekturze nie chodzi o  rysunki, diagramy, powiązania z innymi systemami, ale o głębokie  zrozumienie dziedziny i kontekstu systemu, z którym pracujesz. Zapomnij o  UMLu, zapomnij o supernarzędziach wspierających Cię w projektowaniu,  włącz myślenie. Włóż najwięcej energii w zrozumienie dziedziny. Ta  wiedza już po nitce poprowadzi Cię do odpowiednich konstrukcji  projektowych". &lt;/span&gt;&lt;br /&gt; &lt;span style="font-style: italic;"&gt;Tak, tak, to niewiele mówi. Na razie mogę odesłać do koncepcji Domain Driven Design oraz Lean Architecture (vide: Google).&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-5837866987381067443?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/5837866987381067443/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=5837866987381067443' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/5837866987381067443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/5837866987381067443'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/02/kilka-nowych-koncepcji-mantra.html' title='Kilka nowych koncepcji - Mantra architektoniczna, Design Retrospective, Współdzielony kontekst, Naturalny porządek refaktoryzacji'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-7131597016177394089</id><published>2011-02-06T11:32:00.006+01:00</published><updated>2011-02-06T12:30:09.793+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='komunikacja'/><category scheme='http://www.blogger.com/atom/ns#' term='biznes'/><category scheme='http://www.blogger.com/atom/ns#' term='współpraca'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><category scheme='http://www.blogger.com/atom/ns#' term='rozwiązywanie problemów'/><title type='text'>Nie powinieneś biegać ze złamaną nogą!</title><content type='html'>Jasne? Oczywiste? Niby tak się wydaje a jednak cały czas biegamy ze złamaną nogą...&lt;br /&gt;&lt;br /&gt;Jedną z najczęściej oczekiwanych odpowiedzi, którą chcą usłyszeć osoby(w trakcie szkoleń lub projektów doradczych) - to odpowiedź na pytanie: "Jak mam sobie poradzić z pewnymi problemami w mojej sytuacji" (w moim projekcie, z moim klientem, menedżerem analitykiem whatever...). Jest to oczywiście naturalne pytanie, ale dużo ważniejsze jest pytanie: "Czy sytuacja, w której się znajduję jest zdrowa?". A najczęściej nie jest! &lt;br /&gt;W takiej sytuacji, pierwotne pytanie można porównać do pytania: "Jak mogę szybko i efektywnie biegać ze złamaną nogą?". Chętnie poznam odpowiedzi...&lt;br /&gt;&lt;br /&gt;Przykłady:&lt;br /&gt;* Nie mamy dobrego kontaktu z osobą, która definiuje wymagania (bo między nami a klientem jest jeszcze firma pośrednia i dostajemy informacje z drugiej ręki, często nie mamy możliwości bezpośrednio skontaktowania się z taką osobą/osobami).&lt;br /&gt;&lt;br /&gt;* Biznes/kierownicy projektu nie uwzględniają technicznych potrzeb podczas ustalania priorytetów (biznesowe priorytety są najważniejsze, ale techniczne nie mogą być ignorowane, gdyż spowoduję nadmierny wzrost kosztów implementacji).&lt;br /&gt;&lt;br /&gt;* Nie ma nikogo, kto jest jednoznacznie odpowiedzialny za wymagania, definiuje je i odpowiada za zmiany (ponosi odpowiedzialność za ich koszt). Zazwyczaj odpowiedzialność ta jest rozmyta i wymagania pochodzą z nieskoordynowanych źródeł.&lt;br /&gt;&lt;br /&gt;* Brak aktywnego udziału i wsparcia osób biznesowych podczas prac implementacyjnych (trudność w uzyskaniu konkretnych informacji wyjaśniających, jak to dokładnie ma działać).&lt;br /&gt;&lt;br /&gt;* Brak refaktoryzacji, bo to kosztuje (za dużo i nikt za to nie zapłaci), bo to nie ma sensu (komu się uda posprzątać ten cały syf?).&lt;br /&gt;&lt;br /&gt;* I wiele innych... chyba na każdy z tych tematów można poświęcić osobny artykuł.&lt;br /&gt;&lt;br /&gt;Jak w takich sytuacjach zastosować coś rozsądnego? Jak w takim przypadku na przykład zastosować Scrum? (bo w takich sytuacjach najczęściej słyszę tego typu pytanie). Przypomnij sobie podstawowe pytanie: "Jak biegać ze złamaną nogą?"&lt;br /&gt;&lt;br /&gt;Zanim zaczniesz dopasowywać się do zaistniałej sytuacji postaraj się wyeliminować z niej patologie! Zazwyczaj tego nie robimy bo:&lt;br /&gt;* jest to trudne,&lt;br /&gt;* często wymaga konfrontacji obecnej rzeczywistości,&lt;br /&gt;* może doprowadzić początkowo do konfliktów i oporu,&lt;br /&gt;* wymaga często dość sporych umiejętności komunikacyjnych (w tym negocjacyjnych),&lt;br /&gt;* często będzie musiało to doprowadzić do zburzenia istniejącego status quo - a tego boi się prawie każdy ...&lt;br /&gt;* zwyczajnie wymaga odwagi!&lt;br /&gt;&lt;br /&gt;Więc zazwyczaj uczymy się biegać ze złamaną nogą. Jeeeeeeeeeee.... I like it. Na poziomie lokalnym udaje się wszystko poukładać (jakoś można z tym żyć), na poziomie globalnym jest to bez sensu. A jednak, tak zazwyczaj to funkcjonuje... Ciekawe, nieprawdaż? Niczym w amoku... &lt;br /&gt;&lt;br /&gt;Zanim zaczniesz dopasowywać do obecnej sytuacji, krytycznie ją zweryfikuj! Jest pewna mądrość: "Automatyzacja nieprawidłowego procesu (czyli potencjalne jego przyspieszenie) zazwyczaj zwiększa jego nieefektywność". Jeśli sytuacja, w której się znajdujesz jest niezdrowa, czy można znaleźć w tej sytuacji najlepsze praktyki...? Jakie będą najlepsze praktyki biegania ze złamaną nogą? :) &lt;br /&gt;&lt;br /&gt;Co zatem robić? To długa odpowiedź, często zależąca od subtelnych niuansów danego kontekstu. Tutaj nawet nie podejmę próby jej sformułowania. Ten post ma sprowokować do myślenia! Jest spora szansa, że jak zaczniesz analizować sytuację (sam/z osobami współpracownikami) - znajdziecie odpowiedzi. Pod warunkiem, że nie będziecie szukać czarodziejskiej różdżki, która bezszelestnie, bezinwazyjnie, bezproblemowo wszystko załatwi. Jeszcze raz przypomnę - próba rozpoczęcia zmian w tym kierunku wymaga ODWAGI i z pewnością wykroczenie poza własną STREFĘ KOMFORTU.&lt;br /&gt;&lt;br /&gt;Mały hint. Jeśli w dużym przybliżeniu założymy taki łańcuch (pozwól, że pominę uzasadnienie tego pogrupowania, żeby nie wydłużać posta, może kiedyś będzie okazja...):&lt;br /&gt;&lt;br /&gt;programista/tester/grafik... =&gt; analityk/kierownik =&gt; menedżer/klient/kierownik po stronie klienta&lt;br /&gt;&lt;br /&gt;Największą moc sprawczą mają oczywiście ostatnie elementy łańcucha, ale też zazwyczaj im najtrudniej dostrzec patologie, albo też bardzo często są ich źródłem (jako osoby decyzyjne). Tej grupie najłatwiej będzie doprowadzić do potrzebnych zmian. &lt;br /&gt;Najtrudniej mają osoby z początku tego łańcucha (gdyż są najmniej decyzyjne, przez to inicjowane zmiany wymagają często najwięcej odwagi!). Dla nich jedną ze skuteczniejszych (choć często żmudnych i długotrwałych) technik jest technika zdartej płyty :) (czyli ciągłe wskazywanie patologii, pokazywanie ich konsekwencji i upierdliwe o tym przypominanie... niestrudzenie, bez przerwy). Jeśli przy tym uda się zbudować koalicję w naszym łańcuchu, tym większa szansa na zmiany. &lt;br /&gt;&lt;br /&gt;Jest jedna opcja - można poszukać pomocy z zewnątrz. Analiza, rekomendacje zewnętrznej niezależnej, obiektywnej osoby/firmy mogą skatalizować proces zmian.&lt;br /&gt;&lt;br /&gt;Pamiętaj! Złożenie złamanej nogi może boleć!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-7131597016177394089?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/7131597016177394089/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=7131597016177394089' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/7131597016177394089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/7131597016177394089'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2011/02/nie-powinienes-biegac-ze-zamana-noga.html' title='Nie powinieneś biegać ze złamaną nogą!'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-2727154070616129567</id><published>2010-08-10T17:10:00.002+02:00</published><updated>2010-08-10T17:17:17.063+02:00</updated><title type='text'>Hiperoptymalizator czasu</title><content type='html'>21 maja 2009 - ostatni wpis ... sporo piasku w klepsydrach upłynęło. Pojawienie się pewnej małej istotki w moim życiu wiele zmieniło, ale powoli :) wracam do świata żywych. Na dobry początek pierwszy po przerwie wpis.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;Wydaje się, że zarządzanie czasem to wyeksploatowany temat, gdzie niewiele można już dodać, gdyż wszystko zostało powiedziane lub napisane. O ile rzeczywiście trudno dodać coś nowego, to dużo ważniejsze jest pytanie – co można ująć, w myśl zasady „Twórz rozwiązania najprostsze jak to możliwe, ale nie prostsze”.&lt;br /&gt;&lt;br /&gt;Jedną z głównych przypadłości cywilizacyjnych jest ogromny wybór, mnogość opcji, konkurencja, dziesiątki źródeł informacji. Jaki mamy z tego efekt? Przeciążenie informacjami, przeciążenie wyborami, co powoduje, że wartość informacji zaczyna się zacierać:&lt;br /&gt;&lt;br /&gt;•    co warto czytać?&lt;br /&gt;•    co warto poznać?&lt;br /&gt;•    czego warto się nauczyć?&lt;br /&gt;•    czemu warto poświęcić choć tak dużo czasu jak jedna sekunda naszego życia?&lt;br /&gt;&lt;br /&gt;Kiedyś (dziesięć lat temu) w ciągu roku byłem w stanie dotrzeć do kilku płyt. Świetnie je znałem, teksty znałem na pamięć i miały dla mnie autentyczną wartość. Niedługo później stać było mnie na to, aby kupować kilkanaście płyt w miesiącu i jaki był efekt? Osiemdziesięciu procent z nich w ogóle nie przesłuchałem i chyba nie było żadnej takiej, z którą bym się zżył tak mocno, jak kiedyś.&lt;br /&gt;Jesteśmy bombardowani informacjami i zadaniami do wykonania, a odłamki niszczą nasze zasoby wolnego czasu. Dlatego właśnie głównym wyzwaniem nie jest wcale&lt;br /&gt;&lt;br /&gt;•    optymalizacja posiadanego czasu,&lt;br /&gt;•    większa kontrola nad zadaniami i ich przewidywalność,&lt;br /&gt;•    świadomość wykorzystywanego czasu,&lt;br /&gt;•    i inne atrybuty dobrze zarządzanego czasu,&lt;br /&gt;&lt;br /&gt;ale umiejętność znalezienia tego, co z tych wszystkich potencjalnych informacji i zadań jest naprawdę istotne. I powiem szczerzenie, że wielokrotnie słyszałem o zasadzie Pareto 80/20 (Czyli to że 20% naszych działań generuje 80% efektów), nawet – jak mi się wydawało – stosowałem ją w życiu. Ba! Nawet sam jej uczyłem, ale teraz widzę, że moje zrozumienie tej zasady nie było głębokie. Polegało na powierzchownym stosowaniu techniki do porządkowania zadań. Teraz jednak zaczyna docierać do mnie jej dużo głębszy sens. Zasada Pareto ma nauczyć nas sztuki wyboru poprzez umiejętną rezygnację. Zarządzanie czasem nie polega na idealnym upchaniu jak największej ilości zadań w jak najkrótszym czasie. Zarządzanie czasem powinno polegać na tym, aby robić rzeczy ważne!&lt;br /&gt;&lt;br /&gt;Niezły banał, nieprawdaż? Ale spójrzmy na to z innej strony. Jak często się zastanawiasz, czy to co zrobiłeś w ostatnim czasie (dniu, tygodniu, miesiącu) było istotne? Z czego mógłbyś &lt;span style="font-weight: bold;"&gt;zrezygnować&lt;/span&gt; i nic by się nie stało? Czego mógłbyś zrobić mniej? Czy to co zrobiłeś, musiałeś lub powinieneś robić właśnie Ty? Tak, to tutaj jest ukryty sekret traconego czasu. Od kilku tygodni przeprowadzam taką analizę i z ogromnym zadziwieniem stwierdzam, że 30-50% rzeczy, które wykonałem nie zasługiwały na ilość energii im poświęconej. Niektóre sprawy mogłem sobie zwyczajnie odpuścić, przełożyć na później, zamiast na 130% zrobić na 105% ;-), większość zadań mogłem zrobić dużo prościej, dużo mniej czasu spędzić na spotkaniach. Wyciąganie tego typu wniosków, to prawdziwe hiperuczenie się. Powiem Wam coś więcej, mimo tej świadomości – &lt;span style="font-weight: bold;"&gt;cały czas&lt;/span&gt; co tydzień, stwierdzam że 30-50% nie musiałem wykonywać w taki sposób. Ogromna wiedza i doświadczenie z obszaru zarządzania czasem, stosowanie technik organizowania zadań, planowania, używania kalendarza, przypominaczy nie wystarcza. Najważniejszą, a jednocześnie najtrudniejszą umiejętnością jest sztuka eliminacji. Żeby się jej nauczyć, należy sobie jednak zadać niebanalne pytanie: „Co jest dla mnie naprawdę ważne” … Ale to już inna historia …&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-2727154070616129567?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/2727154070616129567/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=2727154070616129567' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2727154070616129567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2727154070616129567'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2010/08/hiperoptymalizator-czasu.html' title='Hiperoptymalizator czasu'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-8602556364437280084</id><published>2009-05-21T23:39:00.000+02:00</published><updated>2009-05-21T23:40:15.223+02:00</updated><title type='text'>Działaj tak, jakbyś miał nieskończenie wiele czasu…</title><content type='html'>&lt;div class="content clear-block"&gt;      &lt;p&gt;Tik, tak, tik, tak ... Zegar tyka nieuchronnie, czas płynie, deadline blisko, a zadań nie ubywa. Im bardziej się spieszysz, im bardziej idziesz na skróty tym więcej problemów się pojawia. Tymczasem odpowiedź jest prosta: &lt;cite&gt;Działaj tak, jakbyś miał nieskończenie wiele czasu!&lt;cite&gt;&lt;/cite&gt;&lt;/cite&gt;&lt;/p&gt; &lt;p&gt;No dobra, nie jest wcale taka prosta, przynajmniej nie jest prosta w realizacji. Zazwyczaj kierownik, klient, project manager lub analityk, stoi Ci nad głową i bezlitośnie przypomina o zbliżającym się terminie. Z pewnością nie oczekują po Tobie, że zaczniesz pracować jakbyś miał nieskończenie wiele czasu. W końcu zapewne znają prawo Parkinsona, że &lt;cite&gt;praca zajmuje tyle, ile jest na nią przeznaczonego czasu&lt;/cite&gt;! I nie pozwolą Ci, abyś tego czasu miał zbyt dużo. Stąd taki nacisk na terminy, deadliney i zobowiązania. &lt;/p&gt; &lt;p&gt;Tymczasem programowanie to bardzo wrażliwa materia ... wiele zmiennych, dużo informacji, założona architektura, struktura projektu, wielość technologii i narzędzi, to wszystko nie sprzyja programiście, kiedy nie ma czasu. Parametrów jest bardzo wiele i łatwo o błędy, a pośpiech je mnoży. Kroki na skróty powodują więcej szkód niż pożytku, a paradoksalnie tymczasowe rozwiązania powstałe wskutek pośpiechu, stają się fundamentami produkcyjnego systemu.&lt;/p&gt; &lt;p&gt;Dlatego właśnie &lt;cite&gt;działaj tak, jakbyś miał nieskończenie wiele czasu!&lt;/cite&gt; W takich momentach &lt;b&gt;wmawiaj to sobie bez opamiętania i możesz mi wierzyć, że nie rozleniwisz się z tego powodu! Twój kierownik, klient, project manager lub analityk nie pozwolą Ci na to&lt;/b&gt;. Ważne jednak, żebyś zwolnił mentalnie, aby uchronić się przed autodestrukcją, zarwanymi nocami, zerwanymi kontaktami z rodziną czy znajomymi ... no może przesadzam! Ale czasami trzeba postraszyć ;-)&lt;/p&gt;    &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-8602556364437280084?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/8602556364437280084/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=8602556364437280084' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/8602556364437280084'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/8602556364437280084'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2009/05/dziaaj-tak-jakbys-mia-nieskonczenie.html' title='Działaj tak, jakbyś miał nieskończenie wiele czasu…'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-361227372326689913</id><published>2009-04-22T01:44:00.002+02:00</published><updated>2009-04-22T09:48:10.910+02:00</updated><title type='text'>Rozmowa z klientem</title><content type='html'>&lt;h2&gt;Pierwsza rozmowa z klientem&lt;/h2&gt;  &lt;p class="MsoNormal"&gt;Dzisiaj rozpoczyna się nowy projekt. Jak zawsze w takich przypadkach w zespole panuje nutka podniecenia i próby zgadywania, co będzie jego przedmiotem. Już są pewne informacje, ale to ciągle jeszcze nic pewnego.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Rozmowa z klientem zaczyna się. Po kilku minutach wstępnej rozmowy, przechodzimy do konkretów. (K - Klient, Z - Zespół).&lt;br /&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: &lt;span style=""&gt; &lt;/span&gt;Jak moglibyśmy zdefiniować wizję projektu? Taką główną, nadrzędną myśl, ideę, która będzie mu przyświecać. Czemu ma służyć? Jest to o tyle ważne, że ta wizja, którą teraz zdefiniujemy, będzie głównym wyznacznikiem celowości podejmowanych działań. I oczywiście definiuje cel samego projektu. Motywuje do działania. Pozwala stworzyć końcowy obraz.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Chciałbym stworzyć system internetowy, który pozwoli w inteligentny sposób wyszukiwać przepisy kucharskie.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: To ciekawy pomysł i świetnie zdefiniowana wizja. Czy możemy mu się bliżej przyjrzeć?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Oczywiście. Istnieje wiele stron z przepisami kucharskimi i to nawet bardzo dobrych stron. Jednak mają one kilka wad. Są dość statyczne – nie pozwalają na bardziej zaawansowane przeszukiwanie przepisów. Zazwyczaj nie ma możliwości wybrania przepisów na bazie własnych upodobań czy wyszukania ich na bazie posiadanych składników. Brakuje swoistej inteligencji, która uprościłaby życiu użytkownikom portalu.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Powoli zaczyna mi się to wszystko układać. Może spróbujemy wyodrębnić najważniejsze funkcje systemu?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Mam sporo pomysłów, ale nieduży budżet. Dlatego na początek chciałbym, aby była możliwość wyszukania przepisu, bazując na liście składników, które posiadam w danym momencie. Załóżmy, że jest środa wieczór, mam jajka, mąkę, bakłażan, mleko, trochę masła i chciałbym zrobić coś z tego do jedzenia. Nie mam pomysłu na to, co to może być. Więc otwieram portal do wyszukiwania przepisów, wpisuję składniki, które posiadam oraz ewentualnie preferencje np. rodzaj potrawy – zupa, ciasto, zakąska, rodzaj kuchni – polska, azjatycka, francuska, włoska … W efekcie dostaję kilka przepisów, które mogę zrealizować z posiadanymi składnikami. I to wszystko.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: A w jaki sposób użytkownik będzie wpisywał dane?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Wszystko musi być jak najprostsze z punktu widzenia użytkownika. Użytkownik powinien jak najmniej myśleć i podejmować wysiłku. Dlatego wyobrażam sobie, że będą dwa pola tekstowe – jedno do wpisywania składników, wiersz po wierszu, drugie do wpisania preferencji, to drugie będzie opcjonalne. Minimum wpisywania i konfiguracji. Oczywiście mogą być dodatkowe opcje, ale dostępne pod przyciskiem „Zaawansowane”. W domyślnej formie musi do być uproszczone do minimum. Pewnie przydawałaby się jakaś forma podpowiadania, żeby użytkownik nie musiał zbyt wiele pisać.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Interesujące. Jak w tym polu tekstowym będzie użytkownik wpisywał składniki? W jakim formacie. Może tutaj napisze pan przykład na kartce.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Na przykład tak:&lt;br /&gt;1/2 kg mąki&lt;br /&gt;pół kostki masła&lt;br /&gt;1/3 litr mleka&lt;br /&gt;5 jaj&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Muszę przyznać, że to spore wyzwanie. Będzie wymagać analizy tego typu zapisu. Czy nie możemy zrobić tego w inny sposób, np. przez odpowiednie pola wyboru?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Nie, zdecydowanie nie. Komu by się chciało to robić w taki sposób. Musi to być zrealizowane w taki sposób. Kiedy w przypadku wizji użyłem słowo inteligentny, to właśnie to miałem na myśli. Rozumiem, że będzie to dość pracochłonne.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Tak, bardzo pracochłonne. Ale jeśli jest to warunek konieczny, to oczywiście możemy to zrealizować w taki sposób. Przedstawimy później wstępne oszacowaniu złożoności problemu i zdecyduje Pan, czy chce realizować to w ten sposób.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Jeśli się zdecyduję, to tylko w ten sposób!&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Widzę zatem, że zapis składników może być dość dowolny – mogą to być takie jednostki jak kilogramy pisane w całości lub skrótowo, a nawet bardziej umowne jednostki jak pół kostki.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Tak, to też jest warunek konieczny.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;No cóż, zapowiada się niebanalny projekt - myślę. Robi się coraz bardziej skomplikowany. Ciekawe co jeszcze wymyśli nasz Klient.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Czy coś jeszcze może być wpisywane do tego pola? Może w jakiejś innej formie?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Wydaje mi się, że nie.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: A co zatem z drugim polem – Preferencje? Też powiedział Pan, że ma to być pole tekstowe.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Tak, zdecydowanie. Również tutaj chciałbym, aby była możliwość swobodnego wpisania swoich preferencji np. zupa, kuchnia azjatycka.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Czyli poszczególne elementy rozdzielane przecinkami?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Tak, mogą być przecinki albo nowy wiersz.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Jakiego typu preferencje przychodzą panu do głowy?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Rodzaj kuchni – region, typ potrawy – np. zupa, ciasto, może rodzaj diety, w której jest dozwolona, czas wykonania.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Czy coś jeszcze można wpisać w to pole?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Wydaje mi się, że nie.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Dobrze, zatem mamy dwa pola tekstowe – w jednym wpisujemy składniki, które mamy do dyspozycji, w drugim preferencje oraz przycisk wyszukiwania.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Dokładnie! Powinno się to odbywać tak jak w typowych wyszukiwarkach internetowych – minimalny, ale inteligentny interfejs.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Dobrze, zatem przypuśćmy, że użytkownik wpisuje dane oraz wciska przycisk szukaj. I co dalej się dzieje?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Następnie jest strona z wynikami! Zupełnie jak w klasycznej wyszukiwarce. Dobrze by było, gdyby lista wyników pokazywała się w dwóch formach: w postaci skróconej – tylko nazwa potrawy oraz informacje związane z preferencjami czyli rodzaj kuchni, rodzaj potrawy; w postaci rozszerzonej – to co w postaci skróconej i dodatkowo jeszcze lista składników. W jednym i drugim przypadku, nazwa potrawy to link, do strony, na której znajdują się szczegóły przepisu.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Jeszcze wrócę na chwilę do wspomnianych list – jak użytkownik będzie wybierał rodzaj listy?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Hmm… Domyślnie niech będzie wersja skrócona, ale na liście wyników będzie do dyspozycji przycisk do zmiany formy wyników. A… i jeszcze wyniki powinny być stronicowane tak jak w przeglądarce i uszeregowane od najlepszego do najsłabszego.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: A co będzie decydować o tym, że jeden przepis jest lepszy od drugiego?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: H… dobre pytanie. Może niech to będzie minimalne lub maksymalne zużycie produktów.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Czyli jaka część produktów zostanie zużyta?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Tak?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: A co będzie domyślną opcją?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: … Niech będzie minimalne zużycie. No i jakiś przycisk do zmiany tego sortowania.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Świetnie! A czy coś jeszcze ma być na tej stronie wyników?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Chyba nie..&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: A jeszcze wspomniał Pan o przycisku „Zaawansowane”…&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Tak, ale jeszcze nie mam pomysłu, co tam miało by być. No w zasadzie jeden. Otóż można by wprowadzić taki parametr, który określałby jakie elementy miałyby nie być brane pod uwagę. Na przykład sól i pieprz, woda czy inne tego typu rzeczy, które każdy ma, nie powinno się wpisywać. Dlatego ustawienia zaawansowane mogłyby określać, co jest, a co nie jest brane pod uwagę.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: A jak miałoby to wyglądać? Myślę, że byłaby to lista z odhaczeniami, gdzie można by zaznaczać, to co nie jest brane pod uwagę.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: A co to mogłoby być?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Na obecną chwilę, to co mi przychodzi do głowy to: woda, sól, pieprz, inne przyprawy. Ale ta lista może ulec rozszerzeniu.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;K: Czy coś jeszcze powinno się znaleźć w sekcji zaawansowane?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Z: Chyba nie…&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Potem podsumowaliśmy rozmowę oraz kluczowe informacje, które z niej wyniknęły. Jest zatem zarys wymagań. Teraz czas uporządkowanie tychże wymagań. &lt;/p&gt;  &lt;h2&gt;Kilka wskazówek związanych z rozmową z klientem&lt;/h2&gt;  &lt;p class="MsoNormal"&gt;Klientem może być każdy: kierownik, szef, wykładowca, kolega, reprezentant klienta. Początek projektu to przede wszystkim czas na określenie wizji – oświadczeniu czemu system ma służyć. Jest to nadrzędny cel projektu. Na nim będziemy bazować, określając z klientem, które działania mają sens.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Następnie staramy się zebrać kluczowe wymagania na ogólnym poziomie – jakie konkretne funkcje system ma realizować. Kiedy już je mamy, rozkładamy na czynniki pierwsze. Bardzo przydatne będą pytania:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Czy coś jeszcze powinno się tu znaleźć …&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Co jest ważne w następnej kolejności …&lt;/p&gt;  &lt;p class="MsoNormal"&gt;oraz pytania za pomocą, które przechodzimy od ogólnych stwierdzeń do stwierdzeń konkretnych:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Co konkretnie musi zajść/jak to ma działać/jak to ma być zorganizowane, aby wymaganie X zostało spełnione…&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Co musi być spełnione, aby można było stwierdzić, że dana funkcja została zrealizowana…&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Oczywiście powyższy scenariusz jest mocno uproszczony, ale daje pewien pogląd na przebieg tego typu rozmowy.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-361227372326689913?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/361227372326689913/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=361227372326689913' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/361227372326689913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/361227372326689913'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2009/04/rozmowa-z-klientem.html' title='Rozmowa z klientem'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-6791683435372948817</id><published>2009-01-23T13:09:00.003+01:00</published><updated>2009-01-23T13:19:35.066+01:00</updated><title type='text'>Jak odmienić sposób programowania używając refaktoryzacji</title><content type='html'>Z przyjemnością informuję, że BNS IT wydało swoją pierwszą książkę, mojego autorstwa.&lt;br /&gt;Nosi tytuł "Jak całkowicie odmienić sposób programowania używając REFAKTORYZACJI".&lt;br /&gt;&lt;br /&gt;Szczegóły na stronie &lt;span style="font-size:180%;"&gt;&lt;a href="http://www.mistrzprogramowania.pl/sklep?page=shop.product_details&amp;amp;flypage=garden_flypage.tpl&amp;amp;product_id=1&amp;amp;category_id=1"&gt;mistrzprogramowania.pl&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Możesz pobrać wersję bezpłatną (jest to ok. połowa książki i zawiera trochę reklam BNS IT).&lt;br /&gt;&lt;br /&gt;Poniżej zamieszczam krótki fragment - wstęp ...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Na płycie nagrobnej pewnego anglikańskiego biskupa (ok. 1100 r.)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;spoczywającego w krypcie Opactwa Westminsterskiego widnieją następujące słowa: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Kiedy byłem młody i wolny, a moja wyobraźnia nie znała granic, marzyłem o tym, by zmienić świat.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Gdy wzrosłem w latach i mądrości, zrozumiałem, że świata nie da się zmienić.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Więc przykróciłem nieco swe zamiary, i postanowiłem zmienić jedynie swój kraj.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Lecz i on także pozostał niezmienny.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Gdy dożyłem swego zmierzchu, w ostatnim, rozpaczliwym zrywie zdecydowałem zmienić choć swoją rodzinę, istoty mi najbliższe.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Lecz niestety! Na nic się to zdało!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Teraz zaś, gdy spoczywam na łożu śmierci, nagle zdałem sobie sprawę, że&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;jeślibym zmienił najpierw tylko samego siebie, to być może swym przykładem&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;zmieniłbym i swą rodzinę. Przy jej inspiracji i wsparciu byłbym w stanie ulepszyć swój kraj, i kto wie, może zmieniłbym wówczas cały świat.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Zacząć od siebie&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Rzeczywistość projektowa jest złożona.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Zazwyczaj brakuje czasu&lt;/li&gt;&lt;li&gt;Trzeba pracować na starym kodzie, który pozostawia wiele do życzenia&lt;/li&gt;&lt;li&gt;Koledzy z biurka obok nie kwapią się do tego, żeby zacząć lepiej pisać programy&lt;/li&gt;&lt;li&gt;Klienci nie widzą czego chcą&lt;/li&gt;&lt;li&gt;Szefowi zależy tylko i wyłącznie na najszybszym wykonywaniu zadań&lt;/li&gt;&lt;li&gt;Biblioteki są źle udokumentowane i zawierają błędy&lt;/li&gt;&lt;li&gt;Narzędzia nie działają do końca tak jak powinny&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Jest wiele przeszkód, które utrudniają tworzenie oprogramowania i niestety&lt;br /&gt;zawsze tak będzie. Chcielibyśmy, żeby &lt;span style="font-weight: bold;"&gt;wszystko dookoła nas się&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;zmieniło&lt;/span&gt;, żebyśmy mogli w końcu zacząć programować w przyzwoity sposób. Czy&lt;br /&gt;nie przypomina to trochę sytuacji biskupa z Opactwa Westminster?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Czego można się spodziewać?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Ta książka jest inna. Nie&lt;br /&gt;będzie tu kwiecistych wyjaśnień wszystkich możliwych refaktoryzacji, nie&lt;br /&gt;będzie przykładów wyrwanych z kontekstu. W zamian za to poznasz wiele rzeczy,&lt;br /&gt;o których nikt nawet nie wspomina w innych książkach --- dowiesz się, jak&lt;br /&gt;używać omawiane techniki w praktyce i jak zastosować je od zaraz. Poznasz&lt;br /&gt;te, które są najbardziej użyteczne. Jeśli podążysz za autorem, twój sposób programowania całkowicie się odmieni.&lt;br /&gt;&lt;br /&gt;Pierwsze trzy rozdziały stanowią wstęp do refaktoryzacji i absolutne minimum,&lt;br /&gt;które musisz wiedzieć na jej temat. Kolejne rozdziały, to już techniki mistrzów.&lt;br /&gt;&lt;br /&gt;Chcesz przeczytać więcej? &lt;span style="font-size:180%;"&gt;&lt;a href="http://www.mistrzprogramowania.pl/sklep?page=shop.product_details&amp;amp;flypage=garden_flypage.tpl&amp;amp;product_id=1&amp;amp;category_id=1"&gt;mistrzprogramowania.pl&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-6791683435372948817?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/6791683435372948817/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=6791683435372948817' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6791683435372948817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/6791683435372948817'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2009/01/jak-odmieni-sposb-programowania-uywajc.html' title='Jak odmienić sposób programowania używając refaktoryzacji'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-2533447485604049588</id><published>2008-11-05T21:20:00.003+01:00</published><updated>2008-11-05T21:23:53.115+01:00</updated><title type='text'>Weekendowe warsztaty Wzorce projektowe</title><content type='html'>Serdecznie zapraszamy na „Warsztaty weekendowe poświęcone wzorcom projektowym”.  Jest to oferta specjalna dla użytkowników portalu Goldenline.pl i czytelników mojego Bloga i Michała. Tej oferty nie znajdziesz na stronie BNS IT!&lt;br /&gt;&lt;br /&gt;Warsztaty umożliwiają nabycie praktycznych umiejętności tworzenia aplikacji z użyciem wzorców projektowych w języku Java. &lt;br /&gt;&lt;br /&gt;Zobacz program &lt;br /&gt;&lt;a href="http://www.bnsit.pl/files/Wzorce_projektowe_java_i_refaktoring.pdf"&gt;http://www.bnsit.pl/files/Wzorce_projektowe_java_i_refaktoring.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Czego potrzebujesz?&lt;br /&gt;• Notebook z kartą wi-fi&lt;br /&gt;• Zapału, chęci i otwartego umysłu&lt;br /&gt;&lt;br /&gt;Twoja inwestycja to jedyne: 800 zł.&lt;br /&gt;&lt;br /&gt;Nigdzie nie znajdziesz szkolenia  ani warsztatów w takiej cenie i jakości.&lt;br /&gt;&lt;br /&gt;Powiedz znajomym.&lt;br /&gt;&lt;br /&gt;Gdzie?&lt;br /&gt;Warszawa, 13-14.12.2008&lt;br /&gt;Wrocław, 13-14.12.2008&lt;br /&gt;Kraków, 13-14.12.2008&lt;br /&gt;&lt;br /&gt;Kontakt:&lt;br /&gt;m.sieraczkiewicz [[[[[ MAUPA  ]]]]]] bnsit.pl&lt;br /&gt;+48 500 189 752&lt;br /&gt;&lt;a href="http://www.bnsit.pl"&gt;http://www.bnsit.pl&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-2533447485604049588?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/2533447485604049588/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=2533447485604049588' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2533447485604049588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2533447485604049588'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2008/11/weekendowe-warsztaty-wzorce-projektowe.html' title='Weekendowe warsztaty Wzorce projektowe'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-2004206402852821595</id><published>2008-08-10T15:20:00.001+02:00</published><updated>2008-08-10T15:22:29.257+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce implementacyjne'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoring'/><title type='text'>2. Spotkanie ŁJUG - podsumowanie</title><content type='html'>&lt;p&gt;Wczoraj, tj. 09.08.2008 odbyło się kolejne, drugie już spotkanie Łódzkiego JUGa. Mimo wakacyjnego okresu, znalazło się wielu śmiałków, którzy odważyli się poświęcić część sobotniego popołudnia, aby przyjść na spotkanie, które dotyczyło tak wspaniałego języka jak Java.&lt;br /&gt;Temat był dość nietypowy, ponieważ Wzorce implementacyjne, nie są szerzej znanym terminem, a jak się okazuje, wielu z nas ma na co dzień do czynienia z tematami przez nie podejmowanymi. Zagadnienia te często zahaczają o zagadnienia podstawowe takie jak sposoby nazywania, wydzielania klas, tworzenia wyjątków itp.&lt;/p&gt; &lt;p&gt;To taka magia, którą prędzej czy później włada doświadczony programista. Lecz czasami można do tej magii zbliżyć się wcześniej.&lt;br /&gt;Poniżej zamieszczam prezentację z tego spotkania. Nie zastąpi ona oczywiście osobistej obecności, ale może pozwolić przybliżyć się do tematu i zachęcić do dalszej eksploracji.&lt;/p&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s1600-h/pdf_icon.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 50px; height: 50px;" src="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s200/pdf_icon.jpg" alt="" id="BLOGGER_PHOTO_ID_5212992521401406930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;a href="http://www.bnsit.pl/files/09.08.2008-Wzorce-implementacyjne.pdf"&gt;Tutaj możesz wersję PDF prezentacji&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-2004206402852821595?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/2004206402852821595/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=2004206402852821595' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2004206402852821595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2004206402852821595'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2008/08/2-spotkanie-jug-podsumowanie.html' title='2. Spotkanie ŁJUG - podsumowanie'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/17938886516274513852</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s72-c/pdf_icon.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-2798325778047962083</id><published>2008-07-17T23:08:00.003+02:00</published><updated>2008-07-17T23:32:43.947+02:00</updated><title type='text'>Łatwość dostępu ponad uporządkowaniem informacji</title><content type='html'>Ostatnio eksperymentuję z różnymi sposobami informacji, tak aby mieć mieć do nich zdalny dostęp z dowolnego miejsca. Podstawowym narzędziem, którego używam jest SVN, który świetnie się sprawdza w przypadku projektów informatycznych, o tyle w przechowywaniu dokumentów w moim przypadku sprawdza się kiepsko. Z dwóch powodów:&lt;br /&gt;* trzeba mieć klienta (alternatywą są interfejsy www, ale te z kolei mają IMHO kiepskie usability)&lt;br /&gt;* swoista złożoność podejścia sprawia, że takie rozwiązanie skutecznie odstrasza mnie od regularnego korzystania.&lt;br /&gt;&lt;br /&gt;Ostatnio sprawdzam w działaniu Notatnik Google, który stawia przede wszystkim na prostotę pracy z informacjami, szczególnie z takimi, które mają charakter szkiców, wolnych myśli, przemyśleń. No i jest zdalny.&lt;br /&gt;Logika działania aplikacji jest zgodna z innymi narzędziami Google i samej idei Web 2.0. Przede wszystkim prostota i usability. Mamy zatem bardzo proste narzędzie, które umożliwia:&lt;br /&gt;* tworzenia notatek (i nadawanie etykiet)&lt;br /&gt;* notowania stron www (forma zakładek z możliwością cytowania tekstu strony)&lt;br /&gt;* możliwość tworzenia sekcji w celu ewentualnego strukturyzowania notatek.&lt;br /&gt;Dzięki integracji z Firefoxem poprzez odpowiedni plugin dostajemy pod prawym przyciskiem możliwość zanotowania fragmentu czytanej strony.&lt;br /&gt;W zasadzie to wszystko (no dobra prawie wszystko). Najważniejsze jest jednak to, że nie jest potrzebna ogromna ilość opcji, które pozwolą zorganizować pracę z notatkami - prosta idea tagowania (wszechobecna w web 2.0) i możliwość cytowania fragmentów stron internetowych to praktycznie to, czego potrzeba w 85% przypadków (nie pytajcie skąd ta liczba ;-)).&lt;br /&gt;W ten sposób mam zdalne narzędzie, w dodatku rozproszone - dokumenty można współdzielić a nawet współedytować oraz notatki mają charakter luźno ustrukturyzowany. Jak dla mnie świetnie. Jest to ciekawa alternatywa dla innych form przechowywania danych. Oczywiście jak sama nazwa wskazuje - bardziej notatek niż formalnych dokumentów, ale wtedy już warto poświęcić nieco czasu na SVN czy jakieś inne formy przechowywania plików na zdalnym serwerze (hmmm... Google Docs!?).&lt;br /&gt;&lt;br /&gt;Przychodzi mi do głowy pewien wniosek, że w przypadku informacji, z którymi często pracujemy, które chcemy mieć pod ręką, ważniejsze staje się łatwość pracy z takimi dokumentami (patrz Google Notatnik) niż ich uporządkowanie (SVN czy serwery plików czy whatever).&lt;br /&gt;&lt;br /&gt;Z drugiej strony to kolejne narzędzie Google, od którego można się uzależnić, co zaczyna być coraz bardziej niebezpieczne. Jeszcze przyjdzie taki dzień, kiedy Google zmonopolizuje świat - no dobra już to prawie zrobiło. Z tym że ilość danych o nas przechowywana przez Google staje się coraz bardziej niebezpieczna.&lt;br /&gt;&lt;br /&gt;Jestem ciekaw waszych sposobów pracy ze zdalnymi dokumentami/plikami/notatkami, szczególnie takimi dokumentami, które wymagają częstej edycji, zaglądania do nich.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-2798325778047962083?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/2798325778047962083/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=2798325778047962083' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2798325778047962083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2798325778047962083'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2008/07/atwo-dostpu-ponad-uporzdkowaniem.html' title='Łatwość dostępu ponad uporządkowaniem informacji'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/16721570127754631476</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-8751072718868551887</id><published>2008-07-16T12:56:00.006+02:00</published><updated>2008-07-16T22:55:42.835+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='organizacja pracy'/><category scheme='http://www.blogger.com/atom/ns#' term='strategie doskonałości'/><category scheme='http://www.blogger.com/atom/ns#' term='efektywność'/><title type='text'>Strategie doskonałości. Najprostsze możliwe środowisko.</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s1600-h/pdf_icon.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 50px; height: 50px;" src="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s200/pdf_icon.jpg" alt="" id="BLOGGER_PHOTO_ID_5212992521401406930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;a href="http://www.bnsit.pl/files/wzorce_implementacyjne_1.pdf"&gt;Tutaj możesz pobrać pełną wersję PDF artykułu&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Kto nie uwielbia tych wspaniałych chwil, kiedy projekt nabiera kształtu, kolejne funkcjonalności pojawiają się jedna za drugą i nie możemy się nacieszyć wspaniałym programistycznym dziełem. Pielęgnujemy każdy fragment, aby nasze oprogramowanie było jeszcze wspanialsze.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Jest to również moment, kiedy projekt zaczyna stawać się coraz bardziej złożony. Jeśli na przykład pracujemy nad aplikacją internetową, to przychodzi taki moment, kiedy aplikacja obsługuje logowanie, transakcje, współpracę z bazą danych, wielojęzyczność, złożone reguły bezpieczeństwa. Istnieje również pewna logika przetwarzania zdarzeń użytkownika – najczęściej korzystamy z jakiegoś frameworka MVC. System rzeczywiście jest już całkiem złożony. Restart całej aplikacji zajmuje kilkanaście a czasem kilkadziesiąt sekund, a nawet kilka minut.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Każdy dzień pracy w takim środowisku powoduje, że się przyzwyczajamy do tej całej złożoności. Co więcej, orientujemy się w niej coraz lepiej, czujemy się jak ryba w wodzie, korzystając z dobrze już znanych niuansów. Osiadamy w przyzwyczajeniu.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Rozwijamy dalej aplikację - tworzymy nową funkcjonalność. Niech będzie to ekran z wykresami tworzonymi na podstawie danych przechowywanych w systemie. Jeszcze nigdy nie mieliśmy do czynienia z wykresami, a przynajmniej nie z tą biblioteką, z której mamy skorzystać. Zatem ucząc się umiejętności związanych z tworzeniem wykresu, zaczynamy osadzać nowe rozwiązanie w złożonym systemie. W międzyczasie musimy przetestować kilka wariantów i sprawdzić, jak dokładnie działa komponent, którego chcemy użyć po raz pierwszy.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Zatem eksperymentujemy z różnymi parametrami. Zanim dokonamy testów, musimy odpowiednio skonfigurować framework MVC, odpowiednio osadzić komponent wykresu na stronie lub panelu, być może dodać elementy związane z bezpieczeństwem i wielojęzycznością. A wszystko to pojawia się tylko po to, żeby nauczyć się jak wykorzystywać komponent.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;A przecież dopiero się uczymy...&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Dopiero eksperymentujemy!&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Nie jest nam potrzebny cały ten narzut.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Nagle jeden z parametrów nie do końca działa tak jak byśmy chcieli. W zasadzie nie wiemy o co chodzi. Jednocześnie cały system się nie uruchamia, bo na szybko oprogramowaliśmy controller (z MVC), więc przy okazji zmagamy się z jego błędami – problem z dostępem do danych.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;W końcu udało się. Wracamy do naszego komponentu, ale jeszcze musimy zrestartować aplikację. Trwa to dość długo. Zbyt długo.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Czy w ogóle to całe środowisko jest potrzebne do przetestowania komponentu? Narzut ogromny – należy stworzyć wszystkie elementy potrzebne do uruchomienia testowego fragmentu, które narzuca środowisko. Czas potrzebny na efektywne badanie kolejnych parametrów jest subiektywnie oceniając wydłużony o 10-50 % z powodu złożoności systemu, w którym proces się odbywa.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;A gdyby mieć pod ręką najprostsze możliwe środowisko aplikacji webowej (czasami dostarczane razem z bibliotekami jako blank application) i używać je do testowania nowych elementów lub prostych fragmentów funkcjonalności. Bez narzutu pozostałych elementów środowiska, takich jak bezpieczeństwo, wielojęzyczność, logowanie! Najprościej jak to tylko możliwe. Oczywiście, kiedy już uda się przeprowadzić próby na prostym środowisku, przenosimy rozwiązanie do złożonego systemu, w którym pracujemy.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Być może nie tworzysz aplikacji webowych, ale z pewnością znajdziesz analogie w obszarze, w którym się specjalizujesz. Ogólny schemat postępowania jest taki sam bez względu na technologię.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Być może wydaje się to bardzo oczywiste -bo jest oczywiste. Ale dlatego tak często o tym zapominamy i tak często tracimy niepotrzebnie czas i często szargamy swój system nerwowy analizując wyjątki z warstwy danych, mimo że w tym momencie zajmujemy się eksperymentowaniem z komponentem wykresu. Wiele razy byłem świadkiem (lub uczestnikiem) takiej sytuacji!&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Całość powyższych rozważań można sprowadzić do zasadniczej myśli:&lt;/p&gt;&lt;br /&gt;                    &lt;br /&gt;                &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid; page-break-before: auto;" align="center"&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 255, 255);"&gt;&lt;br /&gt;&lt;i&gt;Pracuj w możliwie najprostszym środowisku&lt;/i&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;        &lt;p style="margin-bottom: 0cm;"&gt;Bardzo łatwo ulec przekonaniu, które z pewnością w tym momentem przychodzi do głowy: „... ale w moim środowisku nie można nic uprościć! Nie można przenieść tego, co robię, w inne, prostsze środowisko...”. Mogę cię zapewnić Czytelniku, że prawie zawsze można środowisko uprościć. Główne pytanie, na które trzeba sobie odpowiedzieć, to czy rzeczywiście warto, ponieważ bywają sytuacje, w których stworzenie uproszczonego środowiska lub przygotowania środowiska, będzie mało opłacalne. Jednak w dużej części przypadków warto to robić, tym bardziej że wypracowane rozwiązanie często może zostać użyte podczas prac nad następnymi funkcjonalnościami. Zatem poniesiony wysiłek zaprocentuje jeszcze wielokrotnie.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Kilka praktycznych sposobów na upraszczanie środowiska opisałem poniżej. Jestem przekonany, mój Czytelniku, że będą stanowić inspiracje, dzięki którym będziesz pracował jeszcze efektywniej i ten wspaniały zawód programisty, stanie się jeszcze wspanialszy.&lt;/p&gt;&lt;br /&gt;            &lt;br /&gt;        &lt;h1 class="western"&gt;Twórz uproszczone konteksty pracy&lt;/h1&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;W zasadzie przedstawiony na wstępie przykład jest ucieleśnieniem tej zasady.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Kiedy chcesz sprawdzić nowy komponent, bibliotekę, zastanów się jak możesz najprościej ją przetestować i poznać jej właściwości. Zazwyczaj złożona aplikacja, nad którą właśnie pracujemy, jest ostatnim miejscem nadającym się do tego celu.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Jeśli nigdy dotąd nie używałeś wyrażeń regularnych, a teraz będą ci potrzebne, zanim zaczniesz z nimi pracę najzwyczajniej świecie stwórz klasę z metodą main (tu mam na myśli Javę, ale każdy w to miejsce może wstawić sposób, w jaki tworzy się słynne już HelloWorld – bez narzutów technologicznych). I tam przetestuj wszystkie interesujące cię przypadki. W miejsce wyrażeń regularnych można wstawić każdą dowolną inną funkcjonalność: obiekty funkcyjne z jakarta-commons, generowanie pdf-ów, kopiowanie danych, łączenie się z serwerem SMTP i wysyłanie maili, bibliotekę do współpracy z bazą danych, funkcje statystyczne. Można wymieniać bez liku.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Kiedy już pracujesz w złożonym środowisku, np. budujesz strony internetowe z użyciem frameworka MVC, i chcesz przetestować nowy komponent graficzny, zazwyczaj lepiej zrobić to w środowisku poza projektem, a nie w aplikacji, którą właśnie tworzysz.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Jeśli chcesz przetestować działanie pola tekstowego, na który jest nałożona maska pewnego wzorca, który określa format danych przyjmowanych przez to pole, zrób to na możliwie najprostszym przykładzie, poza aplikacją. Zyskasz sporo czasu. Jeśli zrobisz to jeden raz – drugi, trzeci i kolejne będą coraz łatwiejsze.&lt;/p&gt;&lt;br /&gt;            &lt;br /&gt;        &lt;h1 class="western"&gt;Testuj jednostkowo i hermetyzuj logikę&lt;/h1&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Jeśli kiedyś zastanawiałeś się, do czego mogą przydać ci się testy jednostkowe, to mogę cię zapewnić, że między innymi mogą posłużyć jako świetne narzędzie do upraszczania środowiska pracy. Po pierwsze są świetnym zamiennikiem dla metody main – dają większe możliwości tworzenia bardziej złożonych przypadków testowania. Dodatkowo dzięki użyciu &lt;i&gt;mock objects&lt;/i&gt; jesteśmy w stanie pracować z minimalnym podzbiorem logiki biznesowej.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Na przykład jeśli pracujemy nad metodą lub funkcją, która (1) przygotowuje treść maila i (2) go wysyła, nie musimy go fizycznie wysyłać. Podstawiamy &lt;i&gt;mock object&lt;/i&gt; (bardzo uproszczoną implementację do celów testowych) i nie musimy czekać za każdym razem, żeby mail został wysłany. Oczywiście samo wysyłanie wiadomości też można przetestować. Ale można zrobić to osobno, a ewentualnie na końcu, kiedy oba mechanizmy (1) i (2) działają, przetestować je razem. Zgodnie z zasadą&lt;/p&gt;&lt;br /&gt;                    &lt;br /&gt;                &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid; page-break-before: auto;" align="center"&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 255, 255);"&gt;&lt;br /&gt;&lt;i&gt;W danej chwili testuj, zmieniaj lub pracuj nad jedną rzeczą&lt;/i&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;        &lt;p style="margin-bottom: 0cm;"&gt;(ta zasada nie ogranicza się do programowania!)&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Chciałbym zaznaczyć jedną rzecz. Stosowanie powyższych zasad nie uuchroni cię przed błędami, ale pozwoli ci zmniejszyć ilość sytuacji, w których błędy się będą pojawiać. Wyobraź sobie, że dzięki nawykowi upraszczania środowiska oszczędzisz godzinę dziennie (a możesz z pewnością więcej), w ciągu tygodnia oszczędzasz 5 godzin, w ciągu miesiąca 20 godzin. W ciągu roku ... ?&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Powróćmy jednak do testów. Żeby w pełni używać testów jednostkowych musimy nauczyć się pewnej cennej umiejętności, którą nazywam tutaj hermetyzacją logiki. Tworząc oprogramowanie musimy tworzyć je modułowo, tak aby poszczególne części były jak najmniej między sobą zależne (ang. &lt;i&gt;coupling&lt;/i&gt; ), tak aby można było ich używać niezależnie. W przypadku systemów obiektowych istnieje cała filozofia projektowania obiektowego, której celem jest osiągnięcie stanu, w którym poszczególne części systemu są od siebie jak najmniej zależne.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Jednak zarówno w przypadku systemów obiektowych jak i nieobiektowych można zastosować ogólniejszą &lt;i&gt;zasadę odpowiedzialności&lt;/i&gt; , tzn. tak tworzyć system, aby wszystkie jego części miały jednoznacznie określoną odpowiedzialność, bez względu czy to będzie metoda, klasa, pakiet, procedura, funkcja czy formularz interfejsu użytkownika. Część taka będzie zamykać w sobie dobrze zdefiniowaną funkcjonalność, bez zbędnych powiązań z zewnętrznymi elementami.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Jeśli zatem kodujesz logikę aplikacji w interfejsie użytkownika, jesteś daleki od realizacji tej zasady. W ten sposób wyraźnie wiążesz ze sobą interfejs użytkownika i logikę, nie jesteś w stanie jej w prosty sposób rozdzielić i pracować nad nimi osobno. Jeśli tworzysz interfejs użytkownika, umieszczaj w tej części kod, który dotyczy tylko i wyłącznie interfejsu użytkownika – czyli budowania jego wyglądu, ustawiania pól i ich odczytywania. W interfejsie użytkownika nie powinniśmy tworzyć złożonych algorytmów przetwarzania danych (no chyba, że dotyczą wyświetlania elementów na ekranie), do tego celu używamy niezależnych funkcji, metod, klas.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Z pomocą w tym przypadku przychodzą między innymi wzorzec MVC oraz model architektury wielowarstwowej. Zawsze jednak można się posłużyć &lt;i&gt;zdroworozsądkowym&lt;/i&gt; stosowaniem zasady odpowiedzialności, której konsekwencją są wymienione w poprzednim zdaniu koncepcje.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Chciałbym jeszcze raz podkreślić słowo „zdroworozsądkowym” – nie zawsze MVC czy inne koncepcje tego typu są do zastosowania w każdej sytuacji. Istnieje być może 3 % sytuacji, kiedy warto zakodować logikę w interfejsie użytkownika. Ale to jest jest tylko 3%. No może 5%, albo 10%. Ale cały czas jest to odstępstwo od reguły!&lt;/p&gt;&lt;br /&gt;            &lt;br /&gt;        &lt;h1 class="western"&gt;W danej chwili testuj, zmieniaj lub pracuj nad jedną rzecz&lt;/h1&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Powyższa reguła, choć już wspomniana wcześniej, jest tak istotna, że zasługuje na osobny punkt. Być może znacie odpowiedź na pytanie: „Jak zjeść słonia”. „Po kawałku”. Dokładnie ta reguła powinna towarzyszyć nam bezkompromisowo w codziennej pracy. A często nie towarzyszy. Możecie mi wierzyć, że często. Co więcej, również i mnie się zdarza czasami błądzić i jej nie stosować.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Zabierając się do realizacji większego zadania (takiego przynajmniej na 3-4 godziny), warto poświęcić kilka chwil na to, żeby zaplanować swoje działania. Zaplanować po to, by naszym słoniem, jak duży by on nie był, się nie zadławić.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Pamiętam bardzo dobrze moje doświadczenia programistyczne, kiedy podejmując się jakiegoś zadania, tworzyłem kilka godzin pełne rozwiązanie i wtedy uruchamiałem je... po raz pierwszy. No cóż, nigdy nie działało w tym momencie, bo w zasadzie nie miało prawa. Następne kilka godzin spędzałem na debugowaniu i poprawianiu kodu. Myślałem, że uda mi się zjeść całego słonia, od razu.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Zatem co warto zrobić na początku realizacji zadania? Mały plan. Tak aby ustalić przybliżony sposób tworzenia rozwiązania fragment po fragmencie. Załóżmy, że mam napisać sieć neuronową. (Jeśli nie wiesz zbyt dobrze co to takiego, nie przejmuj się, nie ma to dużego znaczenia w dalszych rozważaniach.) Nie tworzę gotowego rozwiązania. Krok po kroku zaczynam implementować najprostsze rzeczy. Na początek być może warto zaimplementować funkcję symulującą działanie neuronu. Być może później stworzyć klasę neuronu. Przetestować jego metody. Następnie być może implementować sieć. Następnie regułę propagacji wstecznej. To tylko przykładowa kolejność. &lt;i&gt;Ważne, żeby w danym&lt;br /&gt;            momencie rozwijać, zmieniać jedną rzecz na raz&lt;/i&gt; . Kiedy ona zacznie działać i będzie przetestowana, brać się za następną. Oczywiście całość warto przemyśleć już na samym początku (przynajmniej na pewnym poziomie ogólności), ale implementować kawałek po kawałku, krok po kroku. Takie mikroiteracje. Ciekawą formą osiągnięcia opisanego wyżej efektu jest Test-Driven Development (aczkolwiek, nie jest to z pewnością jedyny sposób – na pewno warty uwagi).&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Wiele razy widziałem sytuację, kiedy należało na przykład zaimplementować w aplikacji internetowej generowania raportu na podstawie danych przechowywanych w systemie i danych z bieżącego formularza. Programista jednocześnie rozwijał akcję (klasa obsługującej zdarzenie z interfejsu użytkownika), zmieniał interfejs użytkownika i pracował nad generowaniem raportu do pliku pdf (testując przy okazji jak generować pliki pdf). Wyobraźcie sobie, jak wiele szczegółów należy ogarniać umysłem, aby zapanować nad tym wszystkim. W takiej sytuacji zazwyczaj wszystkie elementy interferują ze sobą, a że są nie w pełni skończone, więc trudno znaleźć przyczynę popełnianych błędów.&lt;/p&gt;&lt;br /&gt;            &lt;br /&gt;        &lt;h1 class="western"&gt;Szukanie przyczyn błędów&lt;/h1&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Powyżej opisane sposoby mogą znacząco zmniejszyć ilość popełnianych błędów, ale bądźmy szczerzy – przyjdzie taki moment, kiedy przydarzy się sytuacja, w której nasz system lub jego fragment nie działa proprawnie. Jeśli stosujesz zasadę &lt;i&gt;W danej chwili testuj, zmieniaj lub pracuj nad jedną&lt;br /&gt;            rzeczą&lt;/i&gt; , to zadanie znalezienia przyczyny błędu masz znacząco ułatwione. Ponieważ dokonujesz niewielkich kroków rozwijając kod i łatwo możesz określić zmiany, które doprowadziły do wystąpienia błędu. Ta reguła działa, kiedy kroki są wystarczająco małe. Jeśli przez ostatnią godzinę dokonałeś mniej więcej kilkunastu zmian w plikach konfiguracyjnych, kodzie i w HTML-u, to znaleźć przyczynę będzie trudniej. Jeśli natomiast najpierw dokonałeś zmiany w pierwszym pliku konfiguracyjnych i całość zadziałała, później zmiany w drugim pliku konfiguracyjnym i całość zadziałała, następnie dokonałeś zmian w kodzie i tu pojawił się błąd – to wszystko jasne.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Oczywiście w życiu nie jest tak różowo i zdarzają się sytuacje, kiedy błędy pojawiają sie po pewnym czasie (na przykład kilka dni po zmianach albo nawet po kilku miesiącach). Otóż w takich sytuacjach proponowana zasada brzmi następująco:&lt;/p&gt;&lt;br /&gt;                    &lt;br /&gt;                &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid; page-break-before: auto;" align="center"&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 255, 255);"&gt;&lt;br /&gt;&lt;i&gt;Uprość dany fragment rozwiązania, tak aby zaczął działać, a następnie dodawaj kolejne elementy, aż do momentu wystąpienia błędu.&lt;/i&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;        &lt;p style="margin-bottom: 0cm;"&gt;Wtedy sytuacja będzie już jasna.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Załóżmy, że występuje taka sytuacja:&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Aplikacja oparta o MVC – zdarzenie polega na tym, żeby pobrać odpowiednie dane i wygenerować plik pdf. Istnieje komponent, w jakiś sposób zainicjalizowany, który realizuje to zadanie:&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;1.pobiera dane ze źródła danych&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;2.na ich podstawie generuje obiekt potrzebny do wygenerowania pliku pdf&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;3.tworzony jest plik pdf&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;4.plik pdf wysyłany jest na ekran&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Jak upraszczamy? Przykład postępowania (oczywiście szczegóły działania będą zależne od poszczególnego przypadku). Najpierw upewnijmy się, że komponent, którego używamy, jest poprawnie zainicjalizowany. Można na przykład podstawić za niego inny komponent (np. bardzo uproszczoną implementację komponentu) lub zainicjować go ręcznie, jeśli domyślnie jest tworzony na podstawie pliku konfiguracyjnego. Jeśli konfiguracja komponentu nie była przyczyną błędu, możemy zamiast pobierać dane ze źródła danych spreparować wyniki (badamy czy błąd zwiazany jest z wynikami pochodzącymi ze źródła danych). Następnie możemy sami wygenerować sztuczny obiekt do tworzenia pliku pdf (lub go w ogóle nie tworzyć). Zamiast tworzyć pdf (strumień binarny) można pokusić się o proste dane znakowe (strumień znakowy) i w ten sposób wykluczyć ewentualne błędy tworzenia pliku pdf i pokazywania go na ekranie. Jeśli na którymś etapie odkryjemy, że pojawia się błąd, analizujemy dany etap, stosując powyższy algorytm ograniczając go do tego etapu.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;W procesie wyszukiwania błędów niezwykle przydatne są pliki logów czy systemy debugujące (choć te przy złożonych systemach, są bardzo czasochłonne). Są to jednak tylko narządzia i mogą co najwyżej wesprzeć powyżej opisany proces. Całość pracy intelektualnej musimy wykonać sami.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Oczywiście przebieg postępowania będzie inny dla innej technologii czy innej sytuacji. Jesteś ekspertem w swojej dziedzinie, więc najlepiej będziesz wiedział jak tę strategie dostosować do środowiska, w którym działasz.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Skoro jesteśmy przy wyszukiwanie błędów, to przy okazji jeszcze jedna wskazówka:&lt;/p&gt;&lt;br /&gt;                    &lt;br /&gt;                &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid; page-break-before: auto;" align="center"&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 255, 255);"&gt;&lt;br /&gt;&lt;i&gt;Przyczyny błędów są najczęściej ukryte tam, gdzie dalibyśmy sobie głowę uciąć, że ich tam nie ma. Najprostsza i jedna z częstszych przyczyn błędów to literówka.&lt;/i&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;        &lt;br /&gt;            &lt;br /&gt;        &lt;h1 class="western"&gt;Podsumowanie&lt;/h1&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Powyższe przykłady miały nieco wyraźniej nakreślić regułę upraszczania środowiska, w którym rozwiązuje się dany problem czy zadanie. Ponieważ opisane powyżej aspekty dotyczą sfery naszych nawyków i przekonań, z pewnością Czytelniku kilkakrotnie mogłeś czuć wewnętrzny opór przed zaakceptowaniem ich treści lub stwierdzić, że w twoim przypadku nie ma to zastosowania. Jest to całkiem naturalny proces, ponieważ przedstawiane powyżej tezy przynależą do świata nauk humanistycznych, a szczególniej społecznych i psychologicznych. Nie są to pewniki. Tezy te potwierdzają się w większości przypadków, ale nie muszą we wszystkich. Ale jak to się mówi... wyjątki potwierdzają regułę.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Dokładniejsze przyjrzenie się swoim nawykom i eksperymenty związane z proponowanymi strategiami na pewno mogą stanowić dobrą zabawę, czego ci Czytelniku życzę. I oczywiście zwiększania efektywności oraz wzbogacania przyjemności z tworzenia oprogramowania.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-8751072718868551887?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/8751072718868551887/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=8751072718868551887' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/8751072718868551887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/8751072718868551887'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2008/07/strategie-doskonaoci-najprostsze-moliwe.html' title='Strategie doskonałości. Najprostsze możliwe środowisko.'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/16721570127754631476</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s72-c/pdf_icon.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-8448683600201763164</id><published>2008-07-08T01:05:00.004+02:00</published><updated>2008-07-08T01:15:57.912+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wzorce'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='styl kodowania'/><category scheme='http://www.blogger.com/atom/ns#' term='klasa'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce implementacyjne'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoring'/><title type='text'>Wzorce implementacyjne cz. 1</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s1600-h/pdf_icon.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 50px; height: 50px;" src="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s200/pdf_icon.jpg" alt="" id="BLOGGER_PHOTO_ID_5212992521401406930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;a href="http://www.bnsit.pl/files/wzorce_implementacyjne_1.pdf"&gt;Tutaj możesz pobrać pełną wersję PDF artykułu&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Tworząc oprogramowanie tworzymy wiele tysięcy wierszy kodu. Część tego kodu jest naszym kreatywnym wysiłkiem w tworzeniu Nowego, a część to powtarzalne elementy, które pojawiają się na każdym kroku. Jako programiści nie lubimy powtarzać wiele razy tych samych czynności, a jednak to robimy, gdyż nie jesteśmy w stanie tego uniknąć. W takiej sytuacji warto nabyć pewnych nawyków, które pozwolą nam jednoznacznie i świadomie podejmować decyzje, doprowadzą do czytelnego i jasnego w przesłankach kodu. &lt;p style="margin-bottom: 0cm;"&gt; &lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;Przytoczę za Kentem Beckiem zestaw praw, który dotyczy ogromnej części pisanego oprogramowania:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;kod oprogramowania częściej jest  czytany niż pisany (sic!),&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;w programowaniu nie istnieje  stwierdzenie „zrobione” (sic!) - kod ulega bezustannemu  rozwojowi,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;sercem oprogramowania  (niskopoziomowym) jest odpowiednie zarządzanie przepływem  instrukcji oraz zarządzanie jej stanem (zmiennymi),&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;osoba czytająca kod musi być w  stanie łatwo zrozumieć ideę, koncept zawarty w kodzie oraz łatwo  dotrzeć do szczegółów implementacyjnych (kod  powinien umożliwiać płynne przejście od ogólnej wizji do  szczegółów i od szczegółów do wizji).&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm;"&gt;Wspomniane wcześniej nawyki, które możemy inaczej nazwać wzorcami implementacyjnymi, są w dużym stopniu subiektywną decyzją, choć prawdopodobnie większość z nich jest używana i akceptowana przez profesjonalnych programistów. Warto zatem podkreślić trzy podstawowe wartości, które stoją za przedstawianymi w tym i kolejnych artykułach wzorcami:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;komunikacja (komunikatywność),&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;prostota,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;elastyczność.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt;   &lt;h1 class="western"&gt;Koszt oprogramowania&lt;/h1&gt; &lt;p&gt;Każdy programista, który brał udział w większym projekcie, wie że wytworzenie oprogramowania to tylko wierzchołek góry lodowej. System stworzony w wersji 1.0 to nie koniec podróży:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p&gt;z czasem rozwija się – ulega zmianom,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;należy naprawiać znalezione błędy.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Koszt całkowity jest więc dużo większy niż tylko oprogramowanie zasadniczych funkcjonalności. Co więcej, z przeprowadzonych badań statystycznych wynika, że koszt utrzymania systemu jest dużo większy niż jego wytworzenia (w średniej relacji 30%/70%).&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_T1QNPL_O_VY/SHKh6to17kI/AAAAAAAAAVM/9WuO752ja8E/s1600-h/koszt_calkowity.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_T1QNPL_O_VY/SHKh6to17kI/AAAAAAAAAVM/9WuO752ja8E/s200/koszt_calkowity.png" alt="" id="BLOGGER_PHOTO_ID_5220412948131212866" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;A co to takiego ten magiczny „koszt utrzymania”? Koszt zrozumienia, zmiany, przetestowania i wdrożenia. Ile razy zaglądaliśmy do własnego kodu (nie mówiąc już o czyimś kodzie), który został stworzony pół roku wcześniej i stwierdzaliśmy, że nie wiemy o co chodzi! Stosowanie wzorców – niskopoziomowych wzorców implementacyjnych, dotyczących strategii tworzenia kodu źródłowego, upraszcza nam życie – wiemy czego spodziewać się w kodzie i wiemy, że łatwo będziemy go mogli przeczytać.&lt;/p&gt; &lt;p&gt;Zatem o co chodzi? Co to za wzorce? Chciałbym przedstawić kilka a może kilkanaście strategii, które ułatwią podejmowanie decyzji podczas tworzenia oprogramowania. Dla uwiarygodnienia przedstawianych propozycji, podpierał się będę kodem źródłowym projektów:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p&gt;Spring Framework,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Hibernate,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Struts2,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;kod źródłowy JDK6.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Oczywiście nie sposób zawrzeć tychże strategii w jednym artykule, dlatego niniejszym rozpoczynam szereg artykułów poświęconych wzorcom implementacyjnym. Do dzieła!&lt;/p&gt; &lt;h1 class="western"&gt;Klasa&lt;/h1&gt; &lt;p style="orphans: 2;"&gt; &lt;/p&gt;&lt;p style="orphans: 2;"&gt;Klasa jest tak podstawowym elementem programowania obiektowego, że równie trudno określić oczywiste zasady, jakimi należy posługiwać się definiując i nazywając klasy. Istnieje wiele technik, które ułatwiają wyodrębnianie klas podczas analizy, takie jak karty CRC (&lt;a href="http://en.wikipedia.org/wiki/Class-Responsibility-Collaboration_card"&gt;http://en.wikipedia.org/wiki/Class-Responsibility-Collaboration_card&lt;/a&gt;) czy diagram klas analitycznych (Robustness Diagram) (&lt;a href="http://www.agilemodeling.com/artifacts/robustnessDiagram.htm"&gt;http://www.agilemodeling.com/artifacts/robustnessDiagram.htm&lt;/a&gt;). Jednak ciągle to do nas jako projektantów lub programistów należy decyzja, jak stworzyć nową klasę. Jest to największa sztuka związana z programowanie obiektowym.&lt;/p&gt; &lt;p&gt;Pokrótce można powiedzieć, że&lt;/p&gt; &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid; page-break-before: auto;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;każda klasa powinna mieć dobrze określoną odpowiedzialność&lt;/i&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Co oznacza dobrze? Klasa powinna być odpowiedzialna zazwyczaj za jedną rzecz w systemie.  &lt;/p&gt; &lt;p&gt;Na przykład klasa &lt;i&gt;Converter&lt;/i&gt; powinna dokonywać tylko i wyłącznie operacji konwersji i nie zajmować się niczym innym (np. zapisywaniem wyników konwersji do bazy danych). Po czym poznać, że klasa łamie tę zasadę? Główny objaw do duża ilość metod (choć to tylko objaw ilościowy), ostatecznie należy przeanalizować nazwy metod, a w zasadzie to, co takiego one robią. Jeśli metody nie są spójne ze sobą i wychodzą poza przeznaczenie klasy, to odpowiedzialnośc nie została dobrze określona.&lt;/p&gt; &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid; page-break-before: auto;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Nazwa klasy musi być z jednej strony zwięzła, a z drugiej strony oddająca w pełni przeznaczenie klasy.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Nadanie nazwy klasie to próba pogodzenia dwóch skrajnych sił – z jednej strony nazwa powinna być jak najkrótsza i jak najprosztsza (łatwiej ją zapamiętać, skojarzyć), a z drugiej strony musi precyzyjnie odzwierciedlać przeznaczenie klasy (co czasem wymaga dłuższych nazw).  Jedna z najważeniejszych funkcji nazwy klasy to komunikatywność. W praktyce nie warto od razu szukać idealnej nazwy, tylko na początku nadać taką, która nam przychodzi do głowy, a z czasem gdy odnajdziemy dużo lepszą, zmienić ją. W dobie zaawansowanych narzędzi refaktoryzacji, zmiana nazwy klasy nie powinna być zbyt wielkim problemem.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm;"&gt;Warto w praktyce dążyć w pierwszej kolejności do &lt;i&gt;nazw klas złożonych z jednego słowa&lt;/i&gt; (mam tu na myśli przede wszystkim klasy, które nie są dziedziczone z innych), gdyż łatwiej je zapamiętać. Ponadto nazwa klasy powinna być jak najbliższa świata klienta (słowem z jego dziedziny), jeśli klasa odzwierciedla element świata klienta.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Jest jeszcze jedna wskazówka, którą warto się kierować:  &lt;/p&gt; &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid; page-break-before: auto;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Im mniej klas w projekcie, tym lepiej&lt;/i&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Oczywiście kierunek jej oddziaływania jest przeciwny do kierunku oddziaływania reguły, która nakazuje wyodrębnianie jednoznacznej odpowiedzialności, gdyż ta z kolei powoduje większe rozdrobnienie klas. Tutaj jednak musimy działać zgodnie z maksymą wypowiedzianą przez Einsteina: &lt;i&gt;twórzmy rzeczy najprościej jak tak tylko możliwe, ale nie prościej.&lt;/i&gt;Te dwie siły trzeba w praktyce zrównoważyć. Z jednej strony tworzyć klasy od jasno określonej odpowiedzialności, z drugiej starać się ograniczać ilość powstających klas. Im więcej klas, tym więcej nazw do zapamiętania, miejsc do analizowania, debugowania, testowania itp. itd.&lt;/p&gt; &lt;p style="margin-bottom: 0cm; page-break-after: avoid;"&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm; page-break-after: avoid;"&gt;Podsumowując powyższe rozważania:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;klasa musi mieć dobrze określoną  odpowiedzialność (jednoznacznie) i wszystkie metody muszą być  spójne z tą odpowiedzialnością,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;nazwa klasy powinna być zwięzła,  ale z drugiej strony jednoznacznie wyrażająca odpowiedzialność  klasy,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;w pierwszej kolejności należy  szukać nazw złożonych z jednego słowa,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;im mniej klas w projekcie tym  lepiej.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-bottom: 0cm;"&gt;Dobrym case study są projekty open source. Jeśli nie znasz omawianej biblioteki, nie ma to większego znaczenia, gdyż zazwyczaj nie będziemy analizować funkcjonalności tychże, jakże wspaniałych narzędzi, a przyjrzymy się bliżej strukturze ich klas.&lt;/p&gt; &lt;p&gt;Na początek spójrzmy na klasę &lt;i&gt;org.hibernate.cfg.Configuration&lt;/i&gt; z projektu Hibernate 3. Nazwa &lt;i&gt;Configuration&lt;/i&gt; jest łatwa, jednoznaczna, wydaje się świetnie oddawać odpowiedzialność obiektu – jest to klasa skupiająca w sobie informacje związaną z konfiguracją Hibernate'a.&lt;br /&gt;Jak się bliżej przyjrzymy zawartości klasy, to zobaczymy m. in. takie  elementy:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;public class Configuration implements Serializable {&lt;br /&gt;&lt;br /&gt;  private static Logger log = LoggerFactory.getLogger( Configuration.class );&lt;br /&gt;&lt;br /&gt;  protected Map classes;&lt;br /&gt;  protected Map imports;&lt;br /&gt;  protected Map collections;&lt;br /&gt;.........&lt;br /&gt;  public Configuration addFile(File xmlFile) throws MappingException {&lt;br /&gt;.........&lt;br /&gt;  public Configuration addXML(String xml) throws MappingException {&lt;br /&gt;.........&lt;br /&gt;  protected void parseMappingElement(Element subelement, String name) {&lt;br /&gt;..........&lt;br /&gt;  private void parseSecurity(Element secNode) {&lt;br /&gt;..........&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%; page-break-after: avoid;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Georgia,serif;"&gt;&lt;span style="font-size:100%;"&gt;Oprócz metod do przechowywania i zarządzania konfiguracją, pojawiają się m. in. metody do parsowania pliku XML. Tutaj można poddać wątpliwość jednoznaczność odpowiedzialności tejże klasy, gdyż zaczyna być ona odpowiedzialna za parsowanie pliku XML. Choć można by szukać uzasadnienia tej decyzji w zasadzie &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;i&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Georgia,serif;"&gt;&lt;span style="font-size:100%;"&gt;im mniej klas, tym lepiej.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt; &lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%;"&gt; Inna klasa z tego samego projektu &lt;i&gt;org.hibernate.cfg.Mapping&lt;/i&gt;, budzi mniejsze wątpliwości – do tej klasy wydzielono wszelkie elementy związane z mapowaniem ORM (&lt;a href="http://en.wikipedia.org/wiki/Object-relational_mapping"&gt;http://en.wikipedia.org/wiki/Object-relational_mapping&lt;/a&gt;). Nazwa klasy jest prosta, jednoznaczna i ekspresyjna.&lt;/p&gt; &lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%;"&gt; Spójrzmy jeszcze na podwórko jdk6. Klasa &lt;i&gt;java.text.DateFormat&lt;/i&gt; ma bardzo ostro określoną odpowiedzialność – formatowanie dat w zależności od ustawień regionalnych (&lt;i&gt;Locale&lt;/i&gt;). Jednoznaczna i prosta nazwa (potrzebne były dwa słowa do tego celu).&lt;/p&gt; &lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%;"&gt; Takich przykładów znajdziemy tu bardzo dużo np.:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%;"&gt;  &lt;i&gt;java.util.regex.Matcher –&lt;/i&gt; nazwa jasno wyraża  odpowiedzialność – zbiór operacji związanych z  dopasowywaniem wyrażeń regularnych,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%;"&gt;  &lt;i&gt;java.net.Socket&lt;/i&gt; – nazwa jasno i jednoznacznie określa  przeznaczenie klasy – reprezentacja gniazda TCP oraz zbiór  operacji na tym gnieździe.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%;"&gt; Analizując kod źródłowy projektów Hibernate i jdk6 wyraźnie widać preferencje, którymi zaznaczają się w tych projektach:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%;"&gt;  w Hibernate często zdarza się łamanie zasad odpowiedzialności na  rzecz zmniejszenia ilości klas w projekcie (których i tak  jest dużo), co często jednak prowadzi do powstawania trudnych do  ogarnięcia klas (kilkanaście a nawet kilkadziesiąt metod),&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%;"&gt;  w jdk6 (i wcześniejszych również) tendencja jest zgoła  odwrotna, zdecydowanie nacisk kładzie się na ostrą, jednoznaczną  odpowiedzialność, kosztem wytwarzania dużej ilości klas – np.  żeby obsłużyć w pełni wyrażenie regularne potrzeba aż trzech  klas (!).&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%; page-break-after: avoid;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Georgia,serif;"&gt;&lt;span style="font-size:100%;"&gt;Polecam analizę kodów źródłowych tychże projektów oraz pozostałych (np. spring framework), gdyż jest to jeden z najlepszych praktycznych nauczycieli naprawdę dobrego stylu pisania oprogramowania.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Georgia,serif;"&gt;&lt;span style="font-size:100%;"&gt;Już samo podjęcie decyzji jaką stworzyć klasę (jaka odpowiedzialność, jakie metody, jaka nazwa), jest nielada wyzwaniem. Dlatego warto poświęcić wieczór, aby przeanalizować za i przeciw, tak aby trafnie podejmować tę jedną z częściej podejmowanych decyzji.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-right: 3cm; margin-bottom: 0.5cm; line-height: 150%;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Georgia,serif;"&gt;&lt;span style="font-size:100%;"&gt;Oczywiście to zaledwie początek i wierzchołek góry lodowej. Niebawem nieco rozważań na temat interfejsów.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-8448683600201763164?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/8448683600201763164/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=8448683600201763164' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/8448683600201763164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/8448683600201763164'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2008/07/wzorce-implementacyjne-cz-1.html' title='Wzorce implementacyjne cz. 1'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/16721570127754631476</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s72-c/pdf_icon.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-7824023648584535395</id><published>2008-06-19T22:13:00.000+02:00</published><updated>2008-06-19T22:27:17.450+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='styl kodowania'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoring'/><title type='text'>Porządki w kodzie czyli nie tylko o refaktoringu</title><content type='html'>Blogspot niestety rozczarowuje mnie pod kątem publikowania kodu źródłowego, co jest szczególnie ważne w przypadku tematów poruszających styl kodowania. Być może ktoś z was ma jakieś doświadczenia lub pomysły w tej kwestii. Ja używam narzędzia &lt;a href="http://formatmysourcecode.blogspot.com/2006/02/paste-your-text-here.html"&gt;http://formatmysourcecode.blogspot.com/2006/02/paste-your-text-here.html&lt;/a&gt;, ale mimo wszystko blogspot raz na jakiś czas deformatuje posta :/&lt;br /&gt;&lt;br /&gt;Poniżej zamieszczam cały artykuł poświęcony porządkom w kodzie - poprawnie sformatowany.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s1600-h/pdf_icon.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 50px; height: 50px;" src="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s200/pdf_icon.jpg" alt="" id="BLOGGER_PHOTO_ID_5212992521401406930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;a href="http://www.bnsit.pl/files/nie_tylko_refaktoring.pdf"&gt;Tutaj możesz pobrać pełną wersję PDF artykułu&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-7824023648584535395?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/7824023648584535395/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=7824023648584535395' title='Komentarze (5)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/7824023648584535395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/7824023648584535395'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2008/06/porzdki-w-kodzie-czyli-nie-tylko-o_5700.html' title='Porządki w kodzie czyli nie tylko o refaktoringu'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/16721570127754631476</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s72-c/pdf_icon.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-8868455556785834095</id><published>2008-06-19T19:42:00.000+02:00</published><updated>2008-06-19T22:08:09.298+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='styl kodowania'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoring'/><title type='text'>Porządki w kodzie czyli nie tylko o refaktoringu cz. 3</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s1600-h/pdf_icon.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 50px; height: 50px;" src="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s200/pdf_icon.jpg" alt="" id="BLOGGER_PHOTO_ID_5212992521401406930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;a href="http://www.bnsit.pl/files/nie_tylko_refaktoring_cz_3.pdf"&gt;Tutaj możesz pobrać wersję PDF artykułu&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 0, 0); font-weight: bold;"&gt;Ze względu na problemy z formatowaniem kodu w blogspot artykuł ten warto przeczytać w formie pliku PDF.&lt;/span&gt;&lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;Przyjrzyjmy się teraz metodzie boolMultipy oraz zmiennej lokalnej o nazwie sum. Zmienna ta jest deklarowana na samym początku metody, uzywana jest dużo później. Jest to nawyk, który pozostał jeszcze po językach proceduralnych (takich jak wczesne C przy PL/SQL), gdzie wymaga się zadeklarowania wszystkich zmiennych używanych w metodzie na samym początku. Na szczęście większość współczesnych języków programowania (w szczególności języków obiektów) nie ma tego ograniczenia. Zamiast tego podejścia sugeruję realizację zasady leniwej deklaracji zmiennych, którą można wyrazić za pomocą zdania&lt;/p&gt; &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid; page-break-before: auto;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Deklaruj zmienne najpóźniej jak to tylko możliwe&lt;/i&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Warto to robić z bardzo prostego powodu – łatwiej będzie czytać kod, jeśli w zasięgu wzroku będziemy mieli operacje wykonywane na danej zmiennej. Przy bardziej złożonych metodach umieszczenie deklaracji na samym początku, może spowodować, że analizując dalszą część metody nie będziemy w stanie zorientować się czy zmienna była do tej pory przetwarzana czy nie i co wpłynęło na jej wartość.&lt;/p&gt;  &lt;p style="margin-bottom: 0cm; page-break-after: avoid;"&gt;Załóżmy, że przewinęliśmy ekran tak, że widzimy następujący kod:&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;        for( int i = 0; i &amp;lt; len; i++ ) {&lt;br /&gt;&lt;br /&gt;if ( this.get(i) &amp;amp;&amp;amp; extendedBitSet.get(i) ) {&lt;br /&gt;  sum++;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return sum % 2 ;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-bottom: 0cm;"&gt;Rodzi się we mnie natychmiast pytanie – a co to za suma? Czy działo się z nią coś wcześniej? Czy może jej wartość została pobrana z zewnątrz?  &lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;W przypadku jednej zmiennej jeszcze to nie jest duży problem, ale wyobraźmy sobie sytuację, kiedy takich zmiennych jest pięć. Śledzenie logiki takiej metody będzie bardzo trudne.  &lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Bardzo prosta operacja przeniesienia deklaracji nieco niżej spowoduje, że kod będzie dużo bardziej czytelny:&lt;/p&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    public int boolMultiply( ExtendedBitSet extendedBitSet ) {&lt;br /&gt;&lt;br /&gt;int len = 0;&lt;br /&gt;&lt;br /&gt;if( this.fixedLength &amp;lt; extendedBitSet.fixedLength ) {&lt;br /&gt;len = this.fixedLength;&lt;br /&gt;} else {&lt;br /&gt;len = extendedBitSet.fixedLength;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int sum = 0;&lt;br /&gt;for( int i = 0; i &amp;lt; len; i++ ) {&lt;br /&gt;&lt;br /&gt;if ( this.get( i ) &amp;amp;&amp;amp; extendedBitSet.get( i ) ) {&lt;br /&gt;   sum++;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return sum % 2 ;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-bottom: 0cm;"&gt;Nieco bardziej złożona sytuacja jest w metodzie toByteArray. Jest ona niesamowicie trudna w analizie. Mi zajęło około 20 minut zrozumienie zasady jej działania. Teraz sobie wyobraźmy projekt złożony z tysiąca klas, z których każda zawiera tego typu metody. Zapanowanie nad takim kodem będzie graniczyło z cudem. Spójrzmy na kod tej metody:&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    public byte[] toByteArray() {&lt;br /&gt;int bytesNumber = 0;&lt;br /&gt;&lt;br /&gt;if ( fixedLength % 8 == 0 ) {&lt;br /&gt;bytesNumber = fixedLength / 8;&lt;br /&gt;} else {&lt;br /&gt;bytesNumber = fixedLength / 8 + 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;byte [] arr = new byte[ bytesNumber ];&lt;br /&gt;&lt;br /&gt;for( int j = bytesNumber - 1, k = 0; j &amp;gt;= 0 ; j--, k++ ) {&lt;br /&gt;&lt;br /&gt;for( int i = j * 8 ; i &amp;lt; ( j + 1 ) * 8; i++ ) {    &lt;br /&gt;&lt;br /&gt;    if ( i == fixedLength ) {&lt;br /&gt;        break;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if ( get( i ) ) {&lt;br /&gt;        arr[ k ] += (byte) Math.pow( 2, i % 8 );&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}    &lt;br /&gt;&lt;br /&gt;return arr;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-bottom: 0cm;"&gt;Metoda toByteArray zwraca bajtową reprezentacje ciągów bitowych – czyli ciąg bitowy o długości 14 bitów można zaprezentować za pomocą 2 bajtów, zaś ciąg bitowy o długości 23 bity można zaprezentować za pomocą 3 bajtów.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Algrotym można opisać w następujących krokach:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;określ liczbę bajtów,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;dla każdej ósemki bitów  (lub kilku bitów w przypadku niepełnych bajtów)  wykonaj następującą operację:&lt;/p&gt;  &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;sprawdź wartość każdego bitu&lt;/p&gt;   &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;jeśli bit ma wartość 1, dodaj   odpowiednią potęgę dwójki (wynikającą z pozycji bitu w   bajcie) do wyniku danego bajtu.&lt;/p&gt;  &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-bottom: 0cm;"&gt;Dlaczegóżby nie wyrazić tego algorytmu w formie programistycznej? Często o tym się zapomina. Jako programiści próbujemy w zwięzły sposób wyrazić nasze pomysły, co zazwyczaj prowadzi do bardzo nieczytelnych rozwiązań, których nie tylko inni ale i my sami nie jesteśmy w stanie zrozumieć w krótkim czasie. Ideałem jest dążenie do tego, aby jedno spojrzenie wystarczyło do odszyfrowania intencji twórcy. Nie potrzebujemy zagłębiać się w szczegóły realizacji algortmu, ważne byśmy wychwycili jego główną myśl. Spójrzmy na inną implementację metody toByteArray:&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    public byte[] toByteArray() {&lt;br /&gt;&lt;br /&gt;int bytesCount = computeBytesCount();&lt;br /&gt;&lt;br /&gt;byte [] byteArray = new byte[ bytesCount ];&lt;br /&gt;&lt;br /&gt;for ( int i = 0; i &amp;lt; bytesCount; ++i ) {&lt;br /&gt;&lt;br /&gt; int byteNumber = bytesCount - i - 1;&lt;br /&gt; byteArray[ byteNumber ] = computeByteValue( i );&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return byteArray;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-bottom: 0cm;"&gt;Najważniejsza zmiana, polega na bezpośrednim wyrażeniu algorytmu na ogólnym poziomie. Dzięki czemu jesteśmy w stanie w krótkim czasie zrozumieć intencję twórcy. Pomocnicza metoda computeBytesCount znajduje ilość bajtów nowej reprezentacji. W pętli dla każdego bajtu wykonywana jest operacja obliczania wartości bajtu i zapamiętywania wyniku. Czyż taki zapis nie jest dużo prostszy? Co z tego, że nie widać wszystkich elementów realizacji algorytmu. Bardziej dociekliwi zawsze mogą zajrzeć do metod computeBytesCount i computeByteValue.  &lt;/p&gt; &lt;p style="margin-bottom: 0cm; page-break-after: avoid;"&gt;Mogą one wyglądać następująco:&lt;/p&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;  private byte computeByteValue( int byteNumber ) {&lt;br /&gt;&lt;br /&gt;int firstBitPosition = byteNumber * 8;&lt;br /&gt;int lastBitPosition = ( byteNumber + 1 ) * 8 - 1;&lt;br /&gt;&lt;br /&gt;byte byteValue = 0;&lt;br /&gt;&lt;br /&gt;for ( int i = this.nextSetBit( firstBitPosition );&lt;br /&gt;  i &amp;gt;= firstBitPosition &amp;amp;&amp;amp;  i &amp;lt;= lastBitPosition;&lt;br /&gt;          i = this.nextSetBit( i + 1 ) ) {&lt;br /&gt;&lt;br /&gt;  int currentBitPosition = i - firstBitPosition;&lt;br /&gt;&lt;br /&gt;  if ( get( i ) == true ) {&lt;br /&gt;      byteValue += (byte) Math.pow( 2, currentBitPosition % 8 );&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return byteValue;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private int computeBytesCount() {&lt;br /&gt;int bytesCount = 0;&lt;br /&gt;&lt;br /&gt;if ( fixedLength % 8 == 0 ) {&lt;br /&gt;  bytesCount = fixedLength / 8;&lt;br /&gt;} else {&lt;br /&gt;  bytesCount = fixedLength / 8 + 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return bytesCount;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-bottom: 0cm;"&gt;Warto zauważyć, że kod realizujący zadanie zbytnio się nie uprościł, ale dużo łatwiej jest go teraz przeanalizować i zrozumieć. Teoria refaktoringu  nazywa tego typu działania wyłuskiwaniem metody (ang. extract method). Prawdę mówiąc tutaj poszliśmy nieco dalej, gdyż zmodyfikowaliśmy nieco implementację algorytmu, tak aby stała się bardziej czytelna. Zwróćmy uwagę na wiersze:&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;   int firstBitPosition = byteNumber * 8;&lt;br /&gt;&lt;br /&gt;int lastBitPosition = ( byteNumber + 1 ) * 8 - 1;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-bottom: 0cm; page-break-after: avoid;"&gt;Tak naprawdę są one wyodrębnieniem bardzo enigmatycznych wyrażeń z wiersza:&lt;/p&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    for( int i = j * 8 ; i &amp;lt; ( j + 1 ) * 8; i++ ) {&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Czyż intencja w takim przypadku nie staje się oczywista? Moje wieloletnie doświadczenia doprowadziły mnie do wniosku: &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid; page-break-before: auto;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Jawnie nazywaj złożone elementy kodu&lt;/i&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; page-break-after: avoid;"&gt;zamiast&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    j * 8&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;napisz&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    int firstBitPosition = byteNumber * 8;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Zasadę te rozszerzam do instrukcji warunkowych. Często w kodzie możemy spotkać wyrażenia, za którymi kryje się pewna logika. Warto bezpośrednio wyrazić naszą intencję. Czytelność niesamowicie wzrasta. &lt;p style="margin-bottom: 0cm; page-break-after: avoid;"&gt;Zamiast&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    if ( index &amp;gt;= 0 )&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;napisz&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    boolean isIndexInRange = ( index &amp;gt;= 0 );&lt;br /&gt;&lt;br /&gt;if ( isIndexInRange )&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-bottom: 0cm;"&gt;Kod zaczyna się czytać jak książkę! Przecież programowanie jest dla ludzi. Ułatwiajmy zatem sobie życie.&lt;/p&gt; &lt;p style="margin-bottom: 0cm; page-break-before: auto; page-break-after: avoid;"&gt; A oto najważniejsza zasada, będąca kwintesencją powyższych rozważań:&lt;/p&gt; &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid; page-break-before: auto;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Pisz kod w taki sposób, aby czytało się go jak powieść. Używaj jednoznacznych i jednocześnie prostych nazw. Realizowane operacje dziel na logiczne części i każdą implementuj w osobnych metodach.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Myślę, że jak na jeden raz, wystarczy. Wystarczy, żeby zaostrzyć apetyty i wzbudzić ochotę na więcej. Żeby oprowadzić nieco po ogrodzie refaktoringu i jego przyległościach. Zapewniam, że to niesamowite miejsce i daje niesamowicie wiele radości i satysfakcji.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Poniżej zamieszczam ostateczną wersję kodu, który przechodzi załączone testy (oczywiście ze zmianą uwzględniającą niestatyczność metod merge i boolMultiply).  &lt;/p&gt; &lt;p style="margin-bottom: 0cm; page-break-after: avoid;"&gt;Końcowa postać przykładowej klasy (warto ją porównać z postacią początkową):&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;public class ExtendedBitSet extends BitSet {&lt;br /&gt;&lt;br /&gt; private int fixedLength = 0;&lt;br /&gt;&lt;br /&gt; public ExtendedBitSet( int size, String str ) {&lt;br /&gt;     super( size );&lt;br /&gt;&lt;br /&gt;     fixedLength = size;&lt;br /&gt;     initializeBitSet( str );&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public ExtendedBitSet( String str ) {&lt;br /&gt;     this( str.length(), str );&lt;br /&gt;&lt;br /&gt;     initializeBitSet( str );&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private void initializeBitSet( String str ) {&lt;br /&gt;&lt;br /&gt;     int strLength = str.length();&lt;br /&gt;&lt;br /&gt;     for( int i = 0; i &amp;lt; strLength; ++i ) {&lt;br /&gt;&lt;br /&gt;         if ( str.charAt( strLength - 1 - i ) == '1' ) {&lt;br /&gt;             set( i );&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void merge( ExtendedBitSet extendedBitSet ) {&lt;br /&gt;&lt;br /&gt;     for ( int i = extendedBitSet.nextSetBit( 0 ); i &amp;gt;= 0;&lt;br /&gt;                     i = extendedBitSet.nextSetBit( i + 1 ) ) {&lt;br /&gt;&lt;br /&gt;         this.set( this.fixedLength + i );&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     this.fixedLength = this.fixedLength + extendedBitSet.fixedLength;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public int boolMultiply( ExtendedBitSet extendedBitSet ) {&lt;br /&gt;     int len = 0;&lt;br /&gt;&lt;br /&gt;     if( this.fixedLength &amp;lt; extendedBitSet.fixedLength ) {&lt;br /&gt;         len = this.fixedLength;&lt;br /&gt;     } else {&lt;br /&gt;         len = extendedBitSet.fixedLength;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     int sum = 0;&lt;br /&gt;&lt;br /&gt;     for( int i = 0; i &amp;lt; len; i++ ) {&lt;br /&gt;&lt;br /&gt;         if ( this.get( i ) &amp;amp;&amp;amp; extendedBitSet.get( i ) ) {&lt;br /&gt;             sum++;&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     return sum % 2 ;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public byte[] toByteArray() {&lt;br /&gt;&lt;br /&gt;     int bytesCount = computeBytesCount();&lt;br /&gt;     byte [] byteArray = new byte[ bytesCount ];&lt;br /&gt;  &lt;br /&gt;     for ( int i = 0; i &amp;lt; bytesCount; ++i ) {         &lt;br /&gt;&lt;br /&gt;         int byteNumber = bytesCount - i - 1;&lt;br /&gt;         byteArray[ byteNumber ] = computeByteValue( i );&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     return byteArray;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private byte computeByteValue( int byteNumber ) {&lt;br /&gt;     int firstBitPosition = byteNumber * 8;&lt;br /&gt;     int lastBitPosition = ( byteNumber + 1 ) * 8 - 1;&lt;br /&gt;&lt;br /&gt;     byte byteValue = 0;&lt;br /&gt;&lt;br /&gt;     for ( int i = this.nextSetBit( firstBitPosition );&lt;br /&gt;         i &amp;gt;= firstBitPosition &amp;amp;&amp;amp;  i &amp;lt;= lastBitPosition;&lt;br /&gt;                 i = this.nextSetBit( i + 1 ) ) {&lt;br /&gt;&lt;br /&gt;         int currentBitPosition = i – firstBitPosition;&lt;br /&gt;&lt;br /&gt;         if ( get( i ) == true ) {&lt;br /&gt;             byteValue += (byte) Math.pow( 2, currentBitPosition % 8 );&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     return byteValue;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; private int computeBytesCount() {&lt;br /&gt;&lt;br /&gt;     int bytesCount = 0;&lt;br /&gt;&lt;br /&gt;     if ( fixedLength % 8 == 0 ) {&lt;br /&gt;         bytesCount = fixedLength / 8;&lt;br /&gt;     } else {&lt;br /&gt;         bytesCount = fixedLength / 8 + 1;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     return bytesCount;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String convertToBitString( int size ) {&lt;br /&gt;&lt;br /&gt;     char [] resultArray = new char[ size ];&lt;br /&gt;&lt;br /&gt;     for ( int i = 0; i &amp;lt; size; ++i ) {&lt;br /&gt;         resultArray[ i ] = '0';&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     for ( int i = this.nextSetBit( 0 ); i &amp;gt;= 0; i = this.nextSetBit( i + 1 ) ) {&lt;br /&gt;         resultArray[ size - 1 - i ] = '1';&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     return new String( resultArray );&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String convertToBitString() {&lt;br /&gt;&lt;br /&gt;     return convertToBitString( this.fixedLength );&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Dodatek. Test przykładowej klasy.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;public class ExtendedBitSetTest extends TestCase {&lt;br /&gt;&lt;br /&gt;  public void testConstructorSizeAndString() throws Exception {&lt;br /&gt;&lt;br /&gt;      assertEquals( "{0, 2}", new ExtendedBitSet( 10, "101" ).toString() );&lt;br /&gt;      assertEquals( "0000000101", new ExtendedBitSet( 10, "101" ).convertToBitString() );&lt;br /&gt;      assertEquals( "0000001011", new ExtendedBitSet( 10, "1011" ).convertToBitString() );&lt;br /&gt;      assertEquals( "0010001011", new ExtendedBitSet( 10, "10001011" ).convertToBitString() );&lt;br /&gt;      assertEquals( "{0, 1, 3, 7}", new ExtendedBitSet( 10, "10001011" ).toString() );&lt;br /&gt;      assertEquals( "{0}", new ExtendedBitSet( 10, "001" ).toString() );&lt;br /&gt;      assertEquals( "0000000001", new ExtendedBitSet( 10, "001" ).convertToBitString() );&lt;br /&gt;      assertEquals( "00000000001", new ExtendedBitSet( 10, "001" ).convertToBitString( 11 ) );&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void testMerge() throws Exception {&lt;br /&gt;&lt;br /&gt;      ExtendedBitSet extendedBitSet1 = new ExtendedBitSet( 10, "1" );&lt;br /&gt;      ExtendedBitSet extendedBitSet2 = new ExtendedBitSet( 10, "1" );&lt;br /&gt;&lt;br /&gt;      assertEquals( "0000000001", extendedBitSet1.convertToBitString() );&lt;br /&gt;      assertEquals( "0000000001", extendedBitSet2.convertToBitString() );&lt;br /&gt;&lt;br /&gt;      ExtendedBitSet mergedBitSet = ExtendedBitSet.merge( extendedBitSet1, extendedBitSet2 );&lt;br /&gt;      String mergedString = mergedBitSet.convertToBitString();&lt;br /&gt;&lt;br /&gt;      assertEquals( "00000000010000000001", mergedString );&lt;br /&gt;      assertEquals( "{0, 10}", mergedBitSet.toString() );&lt;br /&gt;      assertTrue( mergedBitSet.get( 0 ) == true );&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void testBoolMultiple() throws Exception {&lt;br /&gt;&lt;br /&gt;      ExtendedBitSet extendedBitSet1 = new ExtendedBitSet( 3, "1" );&lt;br /&gt;      ExtendedBitSet extendedBitSet2 = new ExtendedBitSet( 10, "1" );&lt;br /&gt;&lt;br /&gt;      assertEquals( 1, ExtendedBitSet.boolMultiply( extendedBitSet1, extendedBitSet2 ) );&lt;br /&gt;&lt;br /&gt;      extendedBitSet1 = new ExtendedBitSet( 1000, "1" );&lt;br /&gt;      extendedBitSet2 = new ExtendedBitSet( 2, "1" );&lt;br /&gt;&lt;br /&gt;      assertEquals( 1, ExtendedBitSet.boolMultiply( extendedBitSet1, extendedBitSet2 ) );&lt;br /&gt;&lt;br /&gt;      extendedBitSet1 = new ExtendedBitSet( 10, "1" );&lt;br /&gt;      extendedBitSet2 = new ExtendedBitSet( 10, "1" );&lt;br /&gt;&lt;br /&gt;      assertEquals( 1, ExtendedBitSet.boolMultiply( extendedBitSet1, extendedBitSet2 ) );&lt;br /&gt;&lt;br /&gt;      extendedBitSet1 = new ExtendedBitSet( 10, "1" );&lt;br /&gt;      extendedBitSet2 = new ExtendedBitSet( 10, "10" );&lt;br /&gt;&lt;br /&gt;      assertEquals( 0, ExtendedBitSet.boolMultiply( extendedBitSet1, extendedBitSet2 ) );&lt;br /&gt;&lt;br /&gt;      extendedBitSet1 = new ExtendedBitSet( 10, "10" );&lt;br /&gt;      extendedBitSet2 = new ExtendedBitSet( 10, "10" );&lt;br /&gt;&lt;br /&gt;      assertEquals( 1, ExtendedBitSet.boolMultiply( extendedBitSet1, extendedBitSet2 ) );&lt;br /&gt;&lt;br /&gt;      extendedBitSet1 = new ExtendedBitSet( 10, "110" );&lt;br /&gt;      extendedBitSet2 = new ExtendedBitSet( 10, "110" );&lt;br /&gt;&lt;br /&gt;      assertEquals( 0, ExtendedBitSet.boolMultiply( extendedBitSet1, extendedBitSet2 ) );&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void testToByteArray() throws Exception {&lt;br /&gt;&lt;br /&gt;      ExtendedBitSet extendedBitSet = new ExtendedBitSet( "100000110" );&lt;br /&gt;      byte[] toByteArray = extendedBitSet.toByteArray();&lt;br /&gt;&lt;br /&gt;      assertEquals( 1, toByteArray[ 0 ] );&lt;br /&gt;      assertEquals( 6, toByteArray[ 1 ] );&lt;br /&gt;&lt;br /&gt;      extendedBitSet = new ExtendedBitSet( "10111111111" );&lt;br /&gt;&lt;br /&gt;      toByteArray = extendedBitSet.toByteArray();&lt;br /&gt;&lt;br /&gt;      assertEquals( 5, toByteArray[ 0 ] );&lt;br /&gt;      assertEquals( -1, toByteArray[ 1 ] );&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-8868455556785834095?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/8868455556785834095/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=8868455556785834095' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/8868455556785834095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/8868455556785834095'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2008/06/porzdki-w-kodzie-czyli-nie-tylko-o_19.html' title='Porządki w kodzie czyli nie tylko o refaktoringu cz. 3'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/16721570127754631476</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s72-c/pdf_icon.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-1490041321239662841</id><published>2008-06-18T00:40:00.000+02:00</published><updated>2008-06-19T19:35:54.880+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='styl kodowania'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoring'/><title type='text'>Porządki w kodzie czyli nie tylko o refaktoringu cz. 2</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s1600-h/pdf_icon.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 50px; height: 50px;" src="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s200/pdf_icon.jpg" alt="" id="BLOGGER_PHOTO_ID_5212992521401406930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;a href="http://www.bnsit.pl/files/nie_tylko_refaktoring_cz_2.pdf"&gt;Tutaj możesz pobrać wersję PDF artykułu&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 0, 0); font-weight: bold;"&gt;Ze względu na problemy z formatowaniem kodu w blogspot artykuł ten warto przeczytać w formie pliku PDF.&lt;/span&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm; font-style: normal;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;br /&gt;Zatem zrobiliśmy pierwszy krok w kierunku uporządkowania pierwotnego kodu.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Zróbmy zatem kolejny. Przyjrzyjmy się bliżej następującemu fragmentowi:&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;public class ExtendedBitSet extends BitSet {&lt;br /&gt;&lt;br /&gt; int length ;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Pole klasy length ma widoczność pakietową. Prawdopodobnie nie to było zamierzeniem autora. Być może zapomniał w sposób jawny napisać odpowiedni modyfikator dostępu. W każdym razie warto znać jedną z podstawowych konsekwencji tego rozwiązania: pole to będzie dostępne dla wszystkich klas w pakiecie, co ogranicza jego enkapsulacje informacji. Przypadek ten można uogólnić do stwierdzenia:&lt;/span&gt;  &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Nadawaj najbardziej restrykcyjny z możliwych modyfikatorów dostępu&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;W tym przypadku byłby to oczywiście modyfikator prywatny:&lt;/span&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    private int length;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;W przypadku gdy tworzona klasa będzie klasą bazową innych klas oraz będzie potrzeba udostępnienia tego pola, należy użyć modyfikatora dostępu protected:&lt;/span&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    protected int length;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Dobrą praktyką jest jednak wybieranie modyfikatora private, aż do momentu, gdy nie zaistnieje potrzeba użycia tego pola w klasie podrzędnej (czyli do momentu wyprowadzania nowych klas). Jest to analogia do typowej dla administratorów sieciowych strategii bezpieczeństwa: domyślnie blokuj.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Poza powyższymi uwagami, chciałbym zaproponować jeszcze jedno udoskonalenie. Jestem zwolennikiem jawnego inicjalizowania zmiennych, gdyż jest to bezpośrednie ujawnienie intencji autora. Jeśli tworzę pole obiektowe, to jawnie przypisuję mu wartość początkową na null, kiedy tworzę liczbę całkowitą inicjuję ją zerem. W ten sposób oszczędzam potencjalnemu czytelnikowi mojego kodu domyślania się, czy rzeczywiście chodziło mi o wartość domyślną, czy być może nie dokońca znając szczegóły języka, przyjąłem błędne założenie. W przypadku wyszukiwania przyczyn błędów może to mieć duże znaczenie.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Zatem podsumowując:&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;/p&gt;&lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Jawnie inicjuj pola i zmienne&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;W efekcie uzyskamy takie rozwiązanie:&lt;/span&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    private int length = 0;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;W powyżej przytoczonym wierszu ujawnił się jeszcze jeden nawyk związany ze sposobem programowania&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Jak najwięcej przestrzeni dla Twoich oczu &lt;/i&gt;&lt;/span&gt; &lt;/p&gt;   &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Wzrok lubi przestrzeń. Nie lubi zbitych zdań, ogromnych ilości wyrażeń na niewielkiej przestrzeni. Zróbcie prosty eksperyment. Weźcie niewielki fragment swojego kodu i dodajcie kilka spacji (pomiędzy operatorami, pomiędzy wierszami) i porównajcie, który zapis jest czytelniejszy.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; page-break-after: avoid;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Oto przykład:&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    public byte[] toByteArray() {&lt;br /&gt;    int bytesNumber ;&lt;br /&gt;    if(length % 8 == 0) bytesNumber = length / 8 ;&lt;br /&gt;    else bytesNumber = length / 8 + 1 ;&lt;br /&gt;    byte[] arr = new byte[bytesNumber] ;&lt;br /&gt;    for(int j = bytesNumber - 1, k = 0; j &amp;gt;= 0 ; j--, k++) {&lt;br /&gt;        for(int i = j * 8 ; i &amp;lt; (j + 1) * 8; i++){&lt;br /&gt;            if(i == length) break ;&lt;br /&gt;            if(get(i)) arr[k] += (byte)Math.pow(2, i % 8) ;&lt;br /&gt;        }&lt;br /&gt;    }                    &lt;br /&gt;    return arr ;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;oraz wersja przestrzenna:&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    public byte[] toByteArray() {&lt;br /&gt;&lt;br /&gt;     int bytesNumber = 0;&lt;br /&gt;&lt;br /&gt;     if ( length % 8 == 0 ) {&lt;br /&gt;         bytesNumber = length / 8;&lt;br /&gt;     } else {&lt;br /&gt;         bytesNumber = length / 8 + 1;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     byte [] arr = new byte[ bytesNumber ];&lt;br /&gt;&lt;br /&gt;     for( int j = bytesNumber - 1, k = 0; j &amp;gt;= 0 ; j--, k++ ) {&lt;br /&gt;&lt;br /&gt;         for( int i = j * 8 ; i &amp;lt; ( j + 1 ) * 8; i++ ) {&lt;br /&gt;&lt;br /&gt;             if ( i == length ) {&lt;br /&gt;                 break;&lt;br /&gt;             }&lt;br /&gt;&lt;br /&gt;             if ( get( i ) ) {&lt;br /&gt;                 arr[ k ] += (byte) Math.pow( 2, i % 8 );&lt;br /&gt;             }&lt;br /&gt;&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;     }             &lt;br /&gt;&lt;br /&gt;     return arr ;&lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Modyfikacja ta zajęła mi około dwóch minut. Jednak umiejętność tworzenia kodu zgodnego ze stylem kodowania, która jest moim nawykiem, umożliwia mi pisanie takiego kodu bez żadnego dodatkowego nakładu czasu. Za to jaka przyjemność z czytania!  A to dopiero początek. Kiedy mówimy o stylu kodowania przychodzi mi do głowy jeszcze jedna reguła:  &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Używaj konsekwentnie przyjętego standardu kodowania&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm;"&gt;Obecnie nie wyobrażam sobie tworzenia kodu, który nie podlega z góry ustalonym zasadom. Jeśli chodzi o pracę w zespole, jest to wręcz warunek konieczny pracy grupowej. A mamy ogromne wsparcie, gdyż istnieje wiele gotowych do wykorzystania standardów, np. &lt;i&gt;Code Conventions for the Java Programming Language&lt;/i&gt; (&lt;a href="http://java.sun.com/docs/codeconv/"&gt;http://java.sun.com/docs/codeconv/&lt;/a&gt;), oraz narzędzi, które pomogą go, szczególnie w początkowym okresie, sumiennie przestrzegać (&lt;i&gt;Checkstyle&lt;/i&gt; &lt;a href="http://checkstyle.sourceforge.net/"&gt;http://checkstyle.sourceforge.net/&lt;/a&gt;). &lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Poniżej znajduje się przykład omawianej klasy sformatowany wg standardu opartego na standardzie zaproponowanym przez Suna.&lt;br /&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;public class ExtendedBitSet extends BitSet {&lt;br /&gt;&lt;br /&gt;  private int length = 0;&lt;br /&gt;&lt;br /&gt;  public ExtendedBitSet( int size, String str ) {&lt;br /&gt;      super( size );&lt;br /&gt;&lt;br /&gt;      length = size;&lt;br /&gt;      int strLength = str.length();&lt;br /&gt;&lt;br /&gt;      for( int i = 0; i &amp;lt; strLength; ++i ) {          &lt;br /&gt;&lt;br /&gt;          if ( str.charAt( strLength - 1 - i ) == '1' ) {&lt;br /&gt;              set( i );&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public ExtendedBitSet( String str ) { &lt;br /&gt;      super( str.length() );&lt;br /&gt;&lt;br /&gt;      int strLength = str.length();&lt;br /&gt;      length = strLength;&lt;br /&gt;&lt;br /&gt;      for( int i = 0; i &amp;lt; strLength; ++i ) {&lt;br /&gt;&lt;br /&gt;          if( str.charAt( strLength - 1 - i ) == '1' ) {&lt;br /&gt;              set( i );&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void merge( ExtendedBitSet extendedBitSet ) { &lt;br /&gt;&lt;br /&gt;      for ( int i = extendedBitSet.nextSetBit( 0 ); i &amp;gt;= 0;&lt;br /&gt;                      i = extendedBitSet.nextSetBit( i + 1 ) ) {&lt;br /&gt;&lt;br /&gt;          this.set( this.length + i );&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      this.length = this.length + extendedBitSet.length;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public int boolMultiply( ExtendedBitSet extendedBitSet ) {&lt;br /&gt;&lt;br /&gt;      int sum = 0;&lt;br /&gt;      int len = 0;&lt;br /&gt;&lt;br /&gt;      if( this.length &amp;lt; extendedBitSet.length ) {&lt;br /&gt;          len = this.length;&lt;br /&gt;      } else {&lt;br /&gt;          len = extendedBitSet.length;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      for( int i = 0; i &amp;lt; len; i++ ) { &lt;br /&gt;&lt;br /&gt;          if ( this.get(i) &amp;amp;&amp;amp; extendedBitSet.get(i) ) {&lt;br /&gt;              sum++;&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      return sum % 2 ;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public byte[] toByteArray() {&lt;br /&gt;&lt;br /&gt;      int bytesNumber = 0;&lt;br /&gt;&lt;br /&gt;      if ( length % 8 == 0 ) {&lt;br /&gt;          bytesNumber = length / 8;&lt;br /&gt;      } else {&lt;br /&gt;          bytesNumber = length / 8 + 1;&lt;br /&gt;      }&lt;br /&gt;    &lt;br /&gt;      byte [] arr = new byte[ bytesNumber ];&lt;br /&gt;&lt;br /&gt;      for( int j = bytesNumber - 1, k = 0; j &amp;gt;= 0 ; j--, k++ ) {&lt;br /&gt;&lt;br /&gt;          for( int i = j * 8 ; i &amp;lt; ( j + 1 ) * 8; i++ ) {&lt;br /&gt;&lt;br /&gt;              if ( i == length ) {&lt;br /&gt;                  break;&lt;br /&gt;              }&lt;br /&gt;&lt;br /&gt;              if ( get( i ) ) {&lt;br /&gt;                  arr[ k ] += (byte) Math.pow( 2, i % 8 );&lt;br /&gt;              }&lt;br /&gt;&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;      }          &lt;br /&gt;&lt;br /&gt;      return arr ;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String convertToBitString( int size ) {&lt;br /&gt;&lt;br /&gt;      char [] resultArray = new char[ size ];&lt;br /&gt;&lt;br /&gt;      for ( int i = 0; i &amp;lt; size; ++i ) {&lt;br /&gt;          resultArray[ i ] = '0';&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      for ( int i = this.nextSetBit( 0 ); i &amp;gt;= 0; i = this.nextSetBit( i + 1 ) ) {&lt;br /&gt;          resultArray[ size - 1 - i ] = '1';&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      return new String( resultArray );&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String convertToBitString() {&lt;br /&gt;&lt;br /&gt;      return convertToBitString( this.length );&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Wróćmy do naszego pola length. Tak naprawdę posiada ono jeszcze jeden mankament – jego nazwa jest dokładnie taka sama jak nazwa metody z klasy bazowej. Jest to sytuacja niekorzystna z dwóch powodów:   &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;dwa różne byty nie powinny  mieć tej samej nazwy (metoda i pole), gdyż może to prowadzić do  pomyłek,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;nazwa zmiennej nie odzwierciedla  sensu właściwości. Pole to przechowuje wartość, która  określa ustaloną długość wektora bitowego. Dużo większy sens  miałaby na przykład nazwa fixedLength.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-bottom: 0cm;"&gt;Zmieńmy zatem nazwe pola length na fixedLength.  &lt;/p&gt; &lt;p style="margin-bottom: 0cm; page-break-after: avoid;"&gt;Podsumowując powyższe rozważania:&lt;/p&gt;    &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Nie używaj jednej nazwy do różnych celów&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;oraz&lt;/p&gt;&lt;br /&gt;&lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Nadawaj polom, metodom i klasom nazwy, które jednoznacznie odzwierciedlają ich znaczenie&lt;/i&gt;&lt;/span&gt;&lt;/p&gt; Analizując dalej przykład, spójrzmy na oba konstruktory, wyraźnie zauważymy pewną właściwość - jest tam mnóstwo powtarzającego się kodu. W ten sposób docieramy do zasady będącej esencją refaktoringu:&lt;br /&gt;&lt;p&gt;&lt;/p&gt; &lt;p style="border: 1px solid rgb(76, 76, 76); padding: 1cm 0.5cm; background: rgb(76, 76, 76) none repeat scroll 0% 50%; margin-top: 0.5cm; margin-bottom: 0.5cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; page-break-inside: avoid;" align="center"&gt; &lt;span style="color: rgb(255, 255, 255);"&gt;&lt;i&gt;Eliminuj wszelkie powtórzenia&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm;"&gt;Powtórzenie to zło, które towarzyszy programistom na każdym kroku. Kuszące kopiuj-wklej, zazwyczaj ostatecznie prowadzi do kilkunastominutowych lub co gorsza wielogodzinnych poszukiwań błędów, wynikających z rozsynchronizowania się podobnych fragmentów kodu. Powtórzenia na dłuższą metę są nie do utrzymania, stąd ich eliminowanie jest podstawowym celem wszelkich refaktoringów. Przykładowy kod możemy zmienić do następującej postaci:&lt;/p&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;    public ExtendedBitSet( int size, String str ) { &lt;br /&gt;       super( size );&lt;br /&gt;&lt;br /&gt;       fixedLength = size;&lt;br /&gt;       initializeBitSet( str );&lt;br /&gt;   }&lt;br /&gt;   public ExtendedBitSet( String str ) {&lt;br /&gt;       this( str.length(), str );  &lt;br /&gt;&lt;br /&gt;       initializeBitSet( str );&lt;br /&gt;   }&lt;br /&gt;  &lt;br /&gt;   private void initializeBitSet( String str ) {&lt;br /&gt;       int strLength = str.length();       &lt;br /&gt;&lt;br /&gt;       for( int i = 0; i &amp;lt; strLength; ++i ) {           &lt;br /&gt;&lt;br /&gt;           if ( str.charAt( strLength - 1 - i ) == '1' ) {&lt;br /&gt;               set( i );&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Kod nam się powoli porządkuje i wygląda coraz lepiej. Wprowadziliśmy zmiany związane z wyglądem (standard kodowania i przestrzeń), wyeliminowaliśmy kilka powtórzeń i niejednoznaczności. Oczywiście zawsze należy wyważyć stopień refaktorowania lub upiększania kodu, tak aby nie stać się ofiarą perfekcjonizmu. Warto wesprzeć się pomocą innych programistów, najlepiej takich, którzy sami posługują się pewnymi zasadami oraz posiadają duże doświadczenie, i poprosić o opinię. Z pewnością wiele można się będzie dowiedzieć na temat swojego programowania.&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-1490041321239662841?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/1490041321239662841/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=1490041321239662841' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/1490041321239662841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/1490041321239662841'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2008/06/porzdki-w-kodzie-czyli-nie-tylko-o_17.html' title='Porządki w kodzie czyli nie tylko o refaktoringu cz. 2'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/16721570127754631476</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s72-c/pdf_icon.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-4330005924195945946</id><published>2008-06-08T14:31:00.000+02:00</published><updated>2008-06-19T19:38:32.080+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='styl kodowania'/><category scheme='http://www.blogger.com/atom/ns#' term='refaktoring'/><title type='text'>Porządki w kodzie czyli nie tylko o refaktoringu        cz. 1</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s1600-h/pdf_icon.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 50px; height: 50px;" src="http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s200/pdf_icon.jpg" alt="" id="BLOGGER_PHOTO_ID_5212992521401406930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;a href="http://www.bnsit.pl/files/nie_tylko_refaktoring_cz_1.pdf"&gt;Tutaj możesz pobrać wersję PDF artykułu&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 0, 0); font-weight: bold;"&gt;Ze względu na problemy z formatowaniem kodu w blogspot artykuł ten warto przeczytać w formie pliku PDF.&lt;/span&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm; font-style: normal;"&gt;Początkowo moim zamysłem było stworzenie artykułu o refaktoringu. Jednak im bardziej zastanawiałem się nad tematem, tym bardziej utwierdzałem się w przekonaniu, iż nie będę pisał tylko i wyłącznie o refaktoringu. Chodzi o coś znacznie istotniejszego, o przelanie bardzo rozległej wiedzy, a w zasadzie doświadczenia związanego z tworzeniem kodu. Kodu, który nie tylko działa, nie tylko jest dobrze zaprojektowany, ale przede wszystkim doskonale się czyta. Kiedy osiągamy tę umiejętność, stajemu u progu profesjonalizmu. Programistycznego profesjonalizmu.  &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Zatem będzie to artykuł między innymi o refaktoringu, ale wzbogacony o zbiór przemyśleń, sugestii, czasami również wątpliwości, którą mają pobudzić Cię, Czytelniku, do refleksji, zweryfikowania swoich programistycznych poczynań. Wierzę, że spowodują cały proces zmian – wprowadzenia nowych, dobrych nawyków.&lt;/p&gt; &lt;h2 class="western"&gt;Przede wszystkim czytelność&lt;/h2&gt; &lt;p style="margin-bottom: 0cm;"&gt;Programowanie bardzo szybko ewoluuje. Pamiętam jeszcze dość dobrze czasy, kiedy rozpocząłem swoją przygodę z kodowaniem jakieś dziesięć lat temu. Programy pisało się wtedy całkiem inaczej. Ceniono pomysłowość, zwięzłość i enigmatyczność. Im kod był bardziej niezrozumiały, tym programista był lepszy.  &lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Jednak z czasem systemy informatyczne stawały się coraz bardziej skomplikowane, wymagały coraz większej wiedzy i co najważniejsze, stały się produktem pracy zespołowej. Obecnie pojedynczy programista nie jest w stanie zdziałać zbyt wiele. Być może stworzy rozbudowany program desktopowy, natomiast nie będzie w stanie w wystarczająco skończonym czasie stworzyć rozproszonego systemu, opartego o architekturę trójwarstwową, zapewniającego odpowiedni poziom bezpieczeństwa, umożliwiającego zarządzanie prawami dostępu do wybranych części aplikacji, realizującym wielojęzyczność itp. itd. Takie systemy tworzy obecnie kilkunastu lub kilkudziesięciu programistów, w zależności od wielkości projektu, przez kilka lub kilkanaście miesięcy. Programista przestał być nierozumianym przez nikogo indywidualistą, a stał się graczem zespołowym, nastawionym na współpracę.  &lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt; &lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;Co za tym idzie, sposób kodowania też musiał się zmienić. Wyłonił się podstawowy postulat dotyczący kodowania:&lt;/p&gt;  &lt;p style="margin-bottom: 0cm;"&gt;&lt;i&gt;&lt;b&gt;Przede wszystkim czytelność&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm;"&gt;Istnieją przynajmniej trzy podstawowe powody, które potwierdzają ważność tego stwierdzenia:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;wymagania się zmieniają,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;programowanie to umiejętność  zespołowa,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;projekty są zbyt duże, aby  pojedyncza osoba była w stanie ogarnąć całość.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt;  &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; Z tych właśnie powodu w ciągu ostatnich kilku lat bardzo mocno rozwijają się takie techniki jak refaktoring, pisanie testów oraz zwraca się ogromną uwagę na standard kodowania.&lt;/p&gt;  &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; To właśnie Czytelność będzie głównym bohaterem tego artykułu. Będzie on zawierać sugestie i przemyślenia, które ułatwią realizację powyższego postulatu. Niektóre wskazówki będą stanowić moją subiektywną opinię, inne będą wyrażać mądrość doświadczeń społeczności programistycznej. Oczywiście należy pamiętać o pewnej zasadzie: “Jedyną niezmienną zasadą jest to, że nie ma niezmienych zasad”. Uogólniając, należy stwierdzić, iż przedstawiane wnioski sprawdziły się w wielu sytuacjach, co nie znaczy, że są zasadne w 100% przypadkach. Dlatego należy uważnie się przyglądać pojawiającym się na co dzień problemom i odważnie stosować przytoczone wskazówki. Warto krytycznie spojrzeć na swoje nawyki lub ich brak i rozpocząć zmiany. Zatem do dzieła!&lt;/p&gt; &lt;h2 class="western"&gt;Poprzez przykład do celu&lt;/h2&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; Analiza kodu mniej doświadczonych programistów, często doprowadzała mnie do zaskakujących spostrzeżeń, umożliwiających znalezienie źródła problemów młodych (ale również i tych doświadczonych) adeptów sztuki programowania. Dlatego artykuł ten oparty będzie o przykład nie najlepiej napisanej klasy, która będzie analizowana i stopniowo udoskonalana.  &lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; Celem, postawionym przed autorami poniższego kodu, było zaimplementowanie klasy pochodnej klasy java.util.BitSet (wektora bitowego) wzbogaconej o:  &lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm; font-style: normal;"&gt;  możliwość konkatenacji,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm; font-style: normal;"&gt;  właściwość narzuconej długości wektora (pole length),&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm; font-style: normal;"&gt;  specyficznego mnożenia dwóch wektorów bitowych  polegającego na zwróceniu wartości 0, jeśli jedynki w obu  wektorach bitowych powtarzają się na parzystej ilości miejsc,  oraz wartości 1, jeśli jedynki pokrywają się na nieparzystej  ilości miejsc,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm; font-style: normal;"&gt;  operację zamiany wektora na ciąg znakowy (w określonym z góry  formacie),&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm; font-style: normal;"&gt;  operację zamiany wektora w ciąg bajtów.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; Pragnę zaznaczyć, iż treść przykładu nie ma tu większego znaczenia. Przytoczony kod służy tylko jako ilustracja często występujących niedoskonałości programistycznych. Ponadto, ponieważ nieodłączną częścią refaktoringu są testy, sprawdzające testowany kod, jako dodatek do artykułu została zamieszczona klasa testowa do analizowanej klasy.&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; Oto zaproponowana implementacja nowej wersji wektora bitowego:&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;import java.util.* ;&lt;br /&gt;public class ExtendedBitSet extends BitSet {&lt;br /&gt; int length ;&lt;br /&gt; public ExtendedBitSet(int size, String str) {&lt;br /&gt;     super(size) ;&lt;br /&gt;     length = size ;&lt;br /&gt;     int strLength = str.length();&lt;br /&gt;     for(int i = 0; i &amp;lt; strLength; ++i) {&lt;br /&gt;         if(str.charAt( strLength - 1 - i) == '1') set(i) ;&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt; public ExtendedBitSet(String str) {&lt;br /&gt;     this( str.length(), str );&lt;br /&gt;     int strLength = str.length();&lt;br /&gt;     for(int i = 0; i &amp;lt; strLength; ++i) {&lt;br /&gt;         if(str.charAt( strLength - 1 - i) == '1') set(i) ;&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt; public static ExtendedBitSet merge(ExtendedBitSet a, ExtendedBitSet b) {&lt;br /&gt;     StringBuffer str = new StringBuffer(a.convertToBitString() + b.convertToBitString()) ;&lt;br /&gt;     return new ExtendedBitSet(a.length + b.length, str.toString()) ;&lt;br /&gt; }&lt;br /&gt; public static int boolMultiply(ExtendedBitSet a, ExtendedBitSet b) {&lt;br /&gt;     int sum = 0 ;&lt;br /&gt;     int len ;&lt;br /&gt;     if(a.length &amp;lt; b.length) len = a.length ;&lt;br /&gt;     else len = b.length ;&lt;br /&gt;     for(int i = 0; i &amp;lt; len; i++) {&lt;br /&gt;         if (a.get(i) &amp;amp;&amp;amp; b.get(i)) sum++ ;&lt;br /&gt;     }&lt;br /&gt;     return sum % 2 ;&lt;br /&gt; }&lt;br /&gt; public byte[] toByteArray() {&lt;br /&gt;     int bytesNumber ;&lt;br /&gt;     if(length % 8 == 0) bytesNumber = length / 8 ;&lt;br /&gt;     else bytesNumber = length / 8 + 1 ;&lt;br /&gt;     byte[] arr = new byte[bytesNumber] ;&lt;br /&gt;     for(int j = bytesNumber - 1, k = 0; j &amp;gt;= 0 ; j--, k++) {&lt;br /&gt;         for(int i = j * 8 ; i &amp;lt; (j + 1) * 8; i++){&lt;br /&gt;             if(i == length) break ;&lt;br /&gt;&lt;br /&gt;             if(get(i)) arr[k] += (byte)Math.pow(2, i % 8) ;&lt;br /&gt;         }&lt;br /&gt;     }                     &lt;br /&gt;     return arr ;&lt;br /&gt; }&lt;br /&gt; public String convertToBitString( int size ) {&lt;br /&gt;     char [] resultArray = new char[ size ];&lt;br /&gt;     for ( int i = 0; i &amp;lt; size; ++i ) {&lt;br /&gt;         resultArray[ i ] = '0';&lt;br /&gt;     }&lt;br /&gt;     for ( int i = this.nextSetBit(0); i &amp;gt;= 0; i = this.nextSetBit(i + 1) ) {&lt;br /&gt;         resultArray[ size - 1 - i ] = '1';&lt;br /&gt;     }&lt;br /&gt;     return new String( resultArray );&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String convertToBitString() {&lt;br /&gt;     return convertToBitString( this.length );&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;W pierwszej kolejności spójrzmy na klasę całościowo. Jedna z pierwszych rzeczy, która rzuca się w oczy to fakt, że metody konkatenacji i mnożenia wektorów są statyczne. Jest to sprzeczne z bardzo ważną zasadą:&lt;/span&gt;  &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;Twórz spójne interfejsy i klasy&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Jeśli przyjrzymy się klasie bazowej BitSet, łatwo zauważymy, iż żadna publiczna metoda nie jest statyczna. Dostępne są m. in. niestatyczne metody or( Bitset ), xor( Bitset ), których celem jest modyfikacja obiektu na rzecz którego są one wywolywane (operacja na this), a nie udostępnienie metody zewnętrznej (statycznej), która tworzy nowy obiekt, będący efektem implementowanej operacji. Zatem obydwie metody (merge i boolMultiply) swoją postacią wprowadzają rozdźwięk w strukturze nowej klasy, prowadząc do niespójnego interfejsu klasy ExtendedBitSet. W tym przypadku utrzymanie spójności poprzez zamianę metod statycznych na metody niestatyczne, uprości używanie klasy ExtendedBitSet, gdyż będzie się z niej korzystać tak samo jak z klasy BitSet. &lt;/span&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Istnieje jeszcze jedna zasada, którą warto przytoczyć analizując metody merge i boolMultiply:&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;b&gt;Unikaj statycznych elementów w programowaniu&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Elementy statyczne to pozostałość po programowaniu proceduralnym, gdyż statyczność oznacza globalność. A przecież jedną z konsekwencji programowania obiektowego jest zamykanie implementowanych funkcjonalności w autonomicznych i możliwie jak najbardziej niezależnych obiektach. Dlatego elementów statyczne używaj tylko wtedy, kiedy nie ma innego wyjścia lub kiedy informacja lub operacja ma rzeczywiście charakter globalny. Zatem używaj pól statycznych jako stałych, szczególnie stałych globalnych, zaś metod statycznych używaj dla operacji globalnych. Przykładem użycia metod i pól statycznych jest wzorzec Singletonu, jednak „wzorcowość” tego wzorca bywa kwestionowana (&lt;a href="http://picocontainer.codehaus.org/Singleton"&gt;http://c2.com/cgi/wiki?SingletonsAreEvil&lt;/a&gt;). Ponadto należy pamiętać,  że metody statyczne nie są polimorficzne, co oznacza, że nie możemy dostarczyć ich alternatywnych implementacji oraz że nie możemy ich zastępować za pomocą mocków. Zatem ich użycie powoduje usztywnienie kodu oraz utrudnia testowanie.&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0cm; font-style: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;Zmieńmy zatem nieco przytoczony kod, zgodnie z pierwszymi dwoma regułami:&lt;/span&gt;&lt;/p&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;  public void merge( ExtendedBitSet extendedBitSet ) {&lt;br /&gt;     for ( int i = extendedBitSet.nextSetBit(0); i &amp;gt;= 0;&lt;br /&gt;             i = extendedBitSet.nextSetBit(i + 1) ) {&lt;br /&gt;         this.set( this.length + i );&lt;br /&gt;     }&lt;br /&gt;     this.length = this.length + extendedBitSet.length;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public int boolMultiply( ExtendedBitSet extendedBitSet ) {&lt;br /&gt;     int sum = 0 ;&lt;br /&gt;     int len ;&lt;br /&gt;     if(this.length &amp;lt; extendedBitSet.length) len = this.length ;&lt;br /&gt;     else len = extendedBitSet.length ;&lt;br /&gt;     for(int i = 0; i &amp;lt; len; i++) {&lt;br /&gt;         if (this.get(i) &amp;amp;&amp;amp; extendedBitSet.get(i)) sum++ ;&lt;br /&gt;     }&lt;br /&gt;     return sum % 2 ;&lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;To dopiero pierwsze wprawki, więcej już niebawem.&lt;br /&gt;c. d. n.&lt;p style="margin-bottom: 0cm; font-style: normal;"&gt;&lt;/p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-4330005924195945946?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/4330005924195945946/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=4330005924195945946' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/4330005924195945946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/4330005924195945946'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2008/06/porzdki-w-kodzie-czyli-nie-tylko-o_08.html' title='Porządki w kodzie czyli nie tylko o refaktoringu        cz. 1'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/16721570127754631476</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_T1QNPL_O_VY/SFhFFB7mFdI/AAAAAAAAAVE/GqRj7DbTt-g/s72-c/pdf_icon.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-973718928927935206.post-2868668329345999010</id><published>2008-06-07T19:44:00.000+02:00</published><updated>2008-06-07T19:53:58.917+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jug'/><category scheme='http://www.blogger.com/atom/ns#' term='społeczność'/><title type='text'>JUG Łódź</title><content type='html'>Sprawy potoczyły się bardzo szybko - pierwsze info na jdn.pl, lista dyskusyjna&lt;a class="moz-txt-link-freetext" href="http://groups.google.com/group/lodz-jug?hl=pl"&gt;&lt;span style="font-family:monospace;"&gt; &lt;/span&gt;http://groups.google.com/group/lodz-jug?hl=pl&lt;/a&gt;, niesamowita reakcja łódzkich fanów Javy, Javarsovia i tak po tygodniu w sobotę 07.06.2008 o godz. 16.00  odbyło się pierwsze spotkanie osób zainteresowanych rozwojem JUGu w Łodzi i chwała wszystkim za to. Trzymam kciuki i wierzę, że ta inicjatywa rozwinie się w prężnie współdziałającą grupę ludzi.&lt;br /&gt;Najważniejsze założenia na najbliższy czas, to trzy miesiące testów wewnętrznych - spotkań, które mają rozkręcić zainteresowanych po to, by później rozpocząć już działania na szerszą skalę.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/973718928927935206-2868668329345999010?l=msieraczkiewicz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://msieraczkiewicz.blogspot.com/feeds/2868668329345999010/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=973718928927935206&amp;postID=2868668329345999010' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2868668329345999010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/973718928927935206/posts/default/2868668329345999010'/><link rel='alternate' type='text/html' href='http://msieraczkiewicz.blogspot.com/2008/06/jug-d.html' title='JUG Łódź'/><author><name>Mariusz Sieraczkiewicz</name><uri>http://www.blogger.com/profile/16721570127754631476</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
