Monthly archive for May, 2011

Mobilne Taphoo

2011-05-29 19:56


QR-Code z linkiem do Marketu

Dzisiejszy okrągły, 512-ty post to doskonała okazja, żeby pochwalić się nową produkcją… No, może nie do końca nową, ale z pewnością wartą zauważenia :) Chodzi o Taphoo – czyli moją całkiem udaną grę sprzed kilku lat – w wersji na platformę mobilną Android. Styl grafiki został przy okazji trochę zmieniony, a sterowanie jest oczywiście dostosowane do (znacząco innego) interfejsu urządzeń. Z opinii wczesnych testerów wynika na szczęście, że po tym przeniesieniu na mniejsze (ale za to dotykowe i przenośne) ekrany gra wciąż prezentuje się przynajmniej tak samo dobrze ;)

Jeśli więc mamy szczęście posiadać telefon, tablet, netbook, lodówkę lub suszarkę z Androidem, to zachęcam do przyjrzenia się tej produkcji (*). Zwłaszcza że jest ona – podobnie jak wersja pod Windows – całkowicie freeware :)

Taphoo w Android Markecie

(*) W przypadku suszarek i lodówek mogą wystąpić problemy z wyświetlaniem grafiki i sterowaniem.

Tags: ,
Author: Xion, posted under Games » 11 comments

Wielki atraktor Wikipedii

2011-05-25 23:29

Za sprawą najnowszego komiksu z xkcd – a właściwie tekstu, który pojawia się po najechaniu myszką na obrazek – w Internecie robi karierę mem na temat rzekomej “zbieżności” artykułów Wikipedii do hasła ‘filozofia’. Zbieżność ta była zdefiniowana przez kolejne kliknięcia w pierwszy (z paroma wyjątkami) link w każdym artykule i kolejne powtarzanie tego procesu. W końcu powinniśmy trafić na wspomniany tekst o filozofii.
Zabawną cechą tego memu jest fakt, iż stosuje się do niego swego rodzaju zasada nieoznaczoności: samym swoim istnieniem (i popularnością) oddziałuje on na zjawisko, które zdaje się opisywać. W końcu mówimy tutaj o serwisie, którego zawartość edytują tysiące użytkowników, a dzięki całej tej plotce ich uwaga jest tym bardziej skupiona na tekstach leżących na ścieżce do tej nieszczęsnej ‘filozofii’… jeśli takowa faktycznie istnieje.

A czy istnieje? No właśnie :) Traktując to jako swego rodzaju pouczającą zabawę, postanowiłem zbadać sprawę i wysmażyłem odpowiedni program, który potrafi automatycznie wykonywać procedurę opisaną na początku, tj. kolejno przechodzić przez teksty w Wikipedii i “klikać” w pierwsze linki z ich treści. Szybko zorientowałem się wtedy, że twierdzenie o zbieżności do Philosophy jest tylko wycinkiem większej, bardziej interesującej całości.
Okazało się bowiem, że Wikipedia ma coś w rodzaju uniwersalnego atraktora, którego ‘filozofia’ jest częścią. Ma on postać cyklu zmieniającego się w czasie (z powodu edycji, oczywiście) i obejmuje interesujący zestaw pojęć, które semantycznie są połączone zależnością rekurencyjną. Obserwując kształt owego cyklu w dłuższym przedziale czasowym, można by zapewne wyodrębnić terminy zupełnie podstawowe, które są w nim obecne stale lub wypadają tylko na krótką chwilę. Kto wie, może w ten sposób udało by się dokonać jakiegoś fundamentalnego odkrycia z dziedziny filozofii, na przykład odpowiedzieć na pytanie o życie, Wszechświat i całą resztę? ;-)

Nieco mniej ambitnym wyzwaniem jest zbadanie, jak daleko od atraktora znajdują się pewne hasła. Innymi słowy, ile kliknięć dzieli nas od wpadnięcia w cykl zapętlających się pojęć, jeśli zaczynamy od danego artykułu? Jeśli zastanowimy się nad tym chwilę, to można dojść do wniosku, że odpowiedź byłaby miarą odwrotności “stopnia abstrakcji” danego pojęcia. Skoro bowiem w atraktorze znajdują się terminy bardzo ogólne, oddalanie się od niego powinno nas przybliżać do konkretów. Czy tak jest w rzeczywistości?…
Wygląda na to, że faktycznie coś w tym jest. Poniżej przedstawiam tendencyjne wyniki sprawdzenia pewnej liczby bynajmniej wcale nie losowo wybranych haseł. i obliczenia odległości każdej z nich od Czarnej Dziury Abstrakcji:

blog 14 Internet 7 programming 8
compiler 6 Turing machine 5 Angry Birds 18
Sun 4 velociraptor 2 Boeing 747 22
South Park 28 Darth Vader 8 Julius Caesar 34

Nie jestem wprawdzie do końca pewien, co oznacza to, że Angry Birds są niemal dwa razy bardziej abstrakcyjne od Juliusza Cezara, ale na pewno musi to coś znaczyć ;]

Tags: , , ,
Author: Xion, posted under Culture, Internet, Programming » 3 comments

Czytelne wywołania funkcji

2011-05-23 21:22

Ktokolwiek, kto programował dłużej w Windows API zna bardzo dobrze klasyczną sekwencję instrukcji, składającą się na zarejestrowanie nowej klasy okna i jego utworzenie. Jej częścią jest między innymi wywołanie funkcji CreateWindow lub CreateWindowEx, które przyjmują odpowiednio 11 lub 12 parametrów. Mimo że nie są one rekordzistkami pod tym względem (bije je chociażby CreateFont z 14 argumentami), to i tak mogą się “poszczycić” dużym potencjałem w zaciemniania kodu i czynienia go trudnym w zrozumieniu lub modyfikacji.
Niestety, takie lub nieco mniej drastyczne przypadki można spotkać w wielu językach, platformach i technologiach. Odchodzą one daleko od rozsądnego zalecenia, aby liczba parametrów funkcji nie przekraczała dwóch lub trzech, z ewentualnym uwzględnieniem this/self/Me. Jak sobie z nimi radzić, aby wynikowy kod zawierający tak rozrośnięte wywołania był jeszcze w jakikolwiek sposób czytelny?…

Otóż należy postarać się, aby każdy z wielu argumentów był identyfikowalny czymś więcej niż tylko pozycją w ciągu oddzielonym przecinkami. Dobrze tutaj sprawdza się feature niektórych języków programowania zwany argumentami słownikowymi. Umożliwia on “przypisywanie” w wywołaniu wartości parametrów do ich nazw. Pozwala to na zmianę ich kolejności, ale przede wszystkim dodaje czytelną etykietę dla każdego argumentu. Przykład takiego słownikowego wywołania w Pythonie widać poniżej:

  1. # posortowanie listy łańcuchów od najdłuższego
  2. sorted(strings, key = len, reverse = True)

Teoretycznie podobny efekt można osiągnąć także w językach nieposiadających wspomnianej opcji. Podejrzewam zresztą, że sposób ten jest pierwszym, jaki większości przyszedł do głowy. Chodzi tu o zwyczajne opatrzenie każdego argumentu odpowiednim komentarzem. Wiele przykładów tak właśnie traktuje argumenty wspomnianej funkcji CreateWindow(Ex):

  1. hWindow = CreateWindowEx(NULL,                   // rozszerzony styl
  2.                           windowClass.c_str(), // klasa okna
  3.                           "My Window",       // tekst na p. tytułu
  4.                           WS_OVERLAPPEDWINDOW,   // styl okna
  5.                           20,         // współrzędna X
  6.                           20,         // współrzędna Y
  7.                           600,         // szerokość
  8.                           500,         // wysokość
  9.                           NULL,                  // okno nadrzędne
  10.                           NULL,                  // menu
  11.                           hInstance,             // instancja aplikacji
  12.                           NULL);                 // dodatkowe dane

Ale rzeczywisty kod to nie przykład z tutoriala, a nadmiar kolorowych komentarzy niekoniecznie musi dobrze wpływać na przejrzystość całej instrukcji. W dodatku wciąż jesteśmy skazani na domyślną kolejność parametrów, a wszelkie rozbieżności między argumentami a ich opisem (bardzo mylące!) nie są wykrywane przez kompilator…

Co można zatem zrobić? Odpowiedź jest prosta: należy napisać kod, który sam się dokumentuje ;-) A rozwijając tę myśl do czegoś bardziej konkretnego: powinniśmy zauważyć, że absolutnie każdy język posiada możliwość opisywania nie tylko parametrów funkcji, ale ogóle jakichkolwiek wyrażeń. Nazywa się to… dokładnie tak – deklaracją zmiennych:

  1. const char* windowTitle = "My Window";
  2. POINT pos = { 20, 20 };
  3. SIZE size = { 600, 500 };
  4. DWORD style = WS_OVERLAPPEDWINDOW;
  5. hWindow = CreateWindowEx(NULL, windowClass.c_str(), windowTitle,
  6.        style, pos.x, pos.y, size.cx, size.cy,
  7.        NULL, NULL, hInstance, NULL);

Przy takim rozwiązaniu niepotrzebne są już żadne dodatkowe wyjaśnienia, bo wszystko widać tu doskonale. Wywołanie stało się czytelne, bo każdy z parametrów jest po prostu swoją nazwą lub nieistotnym NULL-em. Warto też zauważyć, że w typowym kodzie wiele z tych nazw byłoby już zdefiniowanych wcześniej, bo np. byłyby argumentami funkcji otaczającej to wszystko. Ilość dodatkowych deklaracji niekoniecznie musiałaby więc być zbliżona do długości listy parametrów wywołania.

Powyżej widać zatem, że nawet z wyjątkowo rozrośniętymi funkcjami można sobie całkiem nieźle poradzić. Nie traktujmy tego jednak jako zachęty do wydłużania list argumentów naszych własnych funkcji. Zdecydowanie lepiej jest użyć struktury (jak to robi się np. przy tworzeniu urządzenia DirevtX) czy nawet wzorca Builder bez jego abstrakcyjnej części.

Tags: , , ,
Author: Xion, posted under Programming » 6 comments

Drugi problem, czyli API do wyrażeń regularnych

2011-05-19 22:54

Napotykając problem, niektórzy ludzie myślą: “Użyję wyrażeń regularnych!”
W rezultacie mają dwa problemy.

Jamie Zawinski @ alt.religion.emacs

Ten słynny cytat jest, według mnie, lekkim niedoszacowaniem. Decydując się na skorzystanie z wyrażeń regularnych, z miejsca dostajemy bowiem dwa problemy z nimi samymi :) Pierwszych z nich jest sama składnia, która dla nieprzyzwyczajonego oka jest cokolwiek nietrywialna. To głównie ona jest wskazywana jako główna trudność w sprawnym i efektywnym używaniu regexów.
Dzisiaj jednak chciałem zwrócić uwagę na ten drugi, rzadziej zauważany problem. Otóż samo wyrażenie to nie wszystko, trzeba je jeszcze odpowiednio użyć w naszym kodzie. I tutaj mogą zacząć się schody, bo w różnych językach programowania sprawa ta wygląda często odmiennie. Na szczęście jest da się tu też wskazać podobieństwa i spróbować dokonać uogólnienia.

Podstawowym elementem interfejsu programistycznego do wyrażeń regularnych jest zwykle obiekt wzorca (pattern), czyli samego wyrażenia. Zawiera on jego postać skompilowaną, którym jest mniej lub bardziej skomplikowana (w zależności od składni) konstrukcja przypominająca automat stanów. Zbudowanie tej wewnętrznej reprezentacji jest konieczne, aby przeprowadzić jakąkolwiek operację (np. wyszukiwania czy dopasowania). Jeśli więc planujemy skorzystać z jednego wyrażenia w celu przetworzenia większej liczby tekstów, dobrze jest posługiwać się gotowym, skompilowanym obiektem.
Ten ogólny opis dobrze przenosi się na rzeczywiste języki programowania, w których możemy znaleźć takie klasy jak:

Tekstową postać wyrażeń regularnych podajemy zwykle do konstruktorów wyżej wymienionych klas, względnie używamy jakichś statycznych lub globalnych funkcji z odpowiednich pakietów. Przy okazji warto też wspomnieć o problemie escape‘owania znaków specjalnych w wyrażeniach, który w mocno niepożądany sposób interferuje z analogicznym mechanizmem w samych językach programowania. Ponieważ w obu przypadkach używa się do tego znaku backslash (\), w wyrażeniach wpisywanych do kodu należy go podwoić:

  1. boost::regex exp("\\w+"); // kompiluje wyrażenie \w+

W C# i Pythonie można tego uniknąć, stosując mechanizm surowych napisów (raw strings). Programiści C++ i Javy nie mają niestety tego szczęścia ;)

Gdy mamy już obiekt skompilowanego wyrażenia, możemy użyć go do jakichś pożytecznych celów. Jeśli są one proste – jak choćby sprawdzenie, czy jakiś ciąg ma formę określoną regeksem – to możemy zazwyczaj obejść się jednym prostym wywołaniem:

  1. IPV4_REGEX = re.compile(r"^([12]?\d{1,2}\.){3}[12]?\d{1,2}$")
  2. def is_ipv4_addr(text):
  3.     return bool(IPV4_REGEX.match(text))

Bardziej skomplikowane jest wyszukiwanie wszystkich dopasowań wyrażenia w danym tekście, zwłaszcza jeśli przy okazji chcemy dobrać się do fragmentów znalezionych podciągów. Tutaj zaczynają objawiać się pewne różnice między poszczególnymi językami, ale ogólny schemat pozostaje ten sam. Opiera się on na skonstruowaniu odpowiedniej pętli przelatującej po kolejnych dopasowaniach i operowaniu na obiekcie, który takie dopasowanie (match) reprezentuje:

Obiekt dopasowania udostępnia zazwyczaj kilka przydatnych metod i właściwości, jak choćby zakres indeksów znalezionego ciągu. Są też tam fragmenty, które “wpadły” w podgrupy strukturalne (subsequences, subgroups, capture groups, itp.), na które nasze wyrażenie było podzielone. Chodzi tu o jego części ujęte w nawiasy okrągłe; to, jakie konkretne znaki zostały dopasowane do każdego z nich zostaje bowiem zapamiętane w obiekcie match.
Między innymi dzięki temu faktowi możliwe jest określanie bardzo ogólnych wzorców do wyszukania w tekście, a następnie przeglądanie tego, co udało nam się znaleźć i podejmowanie decyzji na podstawie jakichś znaczących elementów dopasowania. W ten sposób możemy przetwarzać teksty o stopniu skomplikowania znacznie przekraczającym to, co w teorii daje się opisać wyrażeniami regularnymi. Żeby nie pozostać gołosłownym, zaprezentuję na przykład prosty sposób na konwersję tekstu zawierającego często spotykane na forach znaczniki BBCode (takie jak [url] czy [img]) na jego odpowiednik HTML-owy, gotowy do wyświetlenia.

  1. import re
  2.  
  3. # wyrażenie dopasowujące tagi BBCode, np. [b]foo[/b]
  4. BBTAG_RE = re.compile(r"\[\s*(\w+)\s*\](.*)\[/\s*\1\s*\]")
  5.  
  6. # funkcja zamieniająca pojedynczy tag BBCode na HTML
  7. SIMPLE_BBTAGS = { 'b': 'strong', 'i': 'em', 'u': 'u' }
  8. def _bbtag_to_html(match):
  9.     tag = match.group(1).lower()
  10.     content = match.group(2)
  11.      
  12.     if tag in SIMPLE_BBTAGS.keys():
  13.         html_tag = SIMPLE_BBTAGS[tag]
  14.         return "<%s>%s</%s>" % (html_tag, content, html_tag)
  15.     if tag == 'url':
  16.         return '<a href="%s">%s</a>' % (content, content)
  17.     if tag == 'img':
  18.         return '<img src="%s" alt="">' % content
  19.      
  20.     return ""
  21.  
  22. # właściwa funkcja
  23. def bbcode_to_html(text):
  24.     return BBTAG_RE.sub(_bbtag_to_html, text)

Najważniejsza jego część to wykonywane w funkcji _bbtag_to_html przetwarzanie obiektu typu re.MatchObject zawierającego dane o znalezionym, pojedynczym tagu. Pobieramy tam jego nazwę i zawartość, które zostały dopasowane jako odpowiednio: pierwsza i druga podgrupa wyrażenia. Samo przeglądanie tekstu w poszukiwaniu tagów i ich zastępowanie jest wykonywane wbudowaną funkcją re.RegexObject.sub, która ukrywa szczegóły wspomnianej wcześniej pętli.

Mam nadzieję, że powyższy przykład dowodzi, że możliwe jest zastosowanie wyrażeń regularnych bez znaczącego wzrostu liczby problemów do rozwiązania :) Jakkolwiek dziwnie to zabrzmi, korzystanie z regeksów może bowiem niekiedy przyczynić się do wzrostu czytelności wynikowego kodu, przynajmniej dla bardziej doświadczonych programistów. Jest tak ze względu na duże podobieństwa nie tylko między różnymi wariantami składni wyrażeń, ale też między bibliotekami do ich obsługi w różnych językach programowania, które to dzisiaj starałem się przedstawić.

Tags: , , , , ,
Author: Xion, posted under Programming » 2 comments

Indeksowanie w Pythonie

2011-05-15 16:34

Przeglądając jakiś rzeczywisty kod w języku Python można często natknąć się na nietypowe wykorzystanie operatora nawiasów kwadratowych. Tradycyjnie znaki te służą do indeksowania tablic, co w językach kompilowanych bezpośrednio do kodu maszynowego równa się prostej operacji na wskaźnikach:

  1. int tab[N];
  2. // ...
  3. assert( tab[i] == *(tab + i) );

Ponieważ jednak Python nie jest takim językiem, jego twórcy pozwolili sobie na to, by zawarte w nim kilogramy warstw abstrakcji oferowały dodatkową funkcjonalność również przy tak trywialnym zagadnieniu. W rezultacie indeksowanie tablic (a właściwie list, w tym i łańcuchów znaków) jest tu operacją, która często ukrywa w sobie znacznie bardziej skomplikowaną logikę niż to widać na pierwszy rzut oka.

Zacznijmy od tego, że w dopuszczalnymi indeksami są nie tylko dodatnie, ale i ujemne liczby całkowite. Oznaczają one dostęp do końcowych elementów tablicy: -1 do pierwszego od końca, -2 do drugiego, i tak dalej. Być może nie wydaje się logiczne to, że elementy tab[0] i tab[-1] są na przeciwnych krańcach listy podczas gdy ich indeksy różnią zaledwie o jeden. Uzasadnieniem jest tu odniesienie do indeksowania od końca w innych językach, czyli tab[tab.length() - i]. W Pythonie po prostu pomija się jawne zapisanie odwołania do długości tablicy.

Znacznie bardziej interesującym aspektem indeksowania jest użycie dwukropka (:). W zasadzie to zamienia on wówczas całą operację na “krojenie” (slice) tablicy, bo pozwala on na na wybór nie jednego elementu, a całego przedziału. Dokładniej mówiąc tab[i:j] oznacza fragment tablicy wyznaczony półotwartym zakresem indeksów [i; j). Kawałek ten zawiera więc tab[i], ale pomija tab[j]; jest to analogiczne chociażby do iteratorów begin() i end() w kontenerach STL.
To właśnie slicing jest tą nietypową operacją, która dla niewprawnego oka wygląda cokolwiek zagadkowo. Jest tak zwłaszcza wtedy, gdy wykorzystuje ona możliwość pominięcia jednego z krańców przedziału, który to jest wówczas “dociągany” do odpowiedniego krańca całej listy.

Łącząc wszystkie te zawiłości możemy już rozszyfrować większość często występujących przypadków użycia indeksowania w Pythonie:

  1. tab[1:] # tablica bez pierwszego elementu
  2. tab[:-1] # tablica bez ostatniego elementu
  3. tab[:n] # co najwyżej n początkowych elementów tablicy
  4. tab[-n:] # n > 0 końcowych elementów tablicy
  5.  
  6. # początkowy ciąg aż do wystąpienia znaku @
  7. username = email[:email.index('@')]
  8.  
  9. # końcowy ciąg począwszy od ostatniej kropki
  10. extension = filename[filename.rindex('.'):]

Dwa ostatnie przykłady pokazują też, że tego rodzaju operacje są bardzo przydatne podczas przetwarzania łańcuchów znaków, które to “przypadkiem” są również swego rodzaju tablicami.

Tags: , , ,
Author: Xion, posted under Programming » 6 comments

Google I/O Extended 2011 w Warszawie

2011-05-11 9:47

Wczoraj miałem okazję wziąć udział w imprezie Google I/O Extended 2011. W dużym skrócie polegała ona wspólnym oglądaniu (i późniejszej dyskusji) live streamu z konferencji Google I/O w San Fransisco, na której tytułowa firma prezentuje nowe rozwiązania technologiczne, mające pojawić się w powszechniejszym użyciu w najbliższych miesiącach. Nie będę specjalnie rozwodził się na temat treści tych prezentacji, bo można się do nich z łatwością dostać, czytając niusy z dowolnego serwisu technologicznego. Wspomnę tylko o ciekawostkach, które szczególnie zwróciły moją uwagę, a są to:

  • Usługa streamowania swojej własnej muzyki z “chrmury” na dowolne urządzenie (komputer, telefon, itp.), po uprzednim załadowaniu plików – czyli Google Music. Z jej najważniejszych cech należy wymienić przede wszystkim to, że jest dostępna wyłącznie w USA :P
  • Android Open Accessories i ADK – otwarta (przynajmniej w sensie androidowym) platforma programowo-sprzętowa, umożliwiająca tworzenie urządzeń, gadżetów i różnych innych akcesorii, które można następnie kontrolować za pomocą telefonów i tabletów z systemem Android (od 3,1 wzwyż). Otwiera to pole do automatyzacji wielu otaczających nas “interfejsów” technicznych, jak na przykład oświetlenie czy sprzęty kuchenne… w mniej lub bardziej odległej przyszłości ;)

Całość imprezy Google I/O Extended 2011 była organizowana przez Google Technology User Group (GTUG) i było to pierwsze poważne wydarzenie pod auspicjami tej grupy. Skorzystam w tym miejscu z okazji i pozwolę sobie na zachęcenie wszystkich mieszkających w jednym z trzech miast z GTUG-iem (Warszawa, Kraków, Poznań) do zainteresowania się działaniami grup i eventami, które będą przez nie organizowane. Zawsze można się czegoś ciekawego dowiedzieć, a może też wyjść z jakimiś fajnymi gadżetami ;-)

Tags: , , ,
Author: Xion, posted under Events, Thoughts » Comments Off on Google I/O Extended 2011 w Warszawie

Sprawcie sobie piłeczkę

2011-05-06 19:23

Wśród niezbędnych gadżetów programistycznych często wymieniany jest kubek kawy. Trzeba jednak przyznać, że zazwyczaj chodzi tutaj o jego zawartość: szybko wypijaną i pospiesznie uzupełnianą. Nie twierdzę oczywiście, że pusty kubek nosi jakiekolwiek znamiona przydatności podczas kodowania. Stanowi on jednak przykład na to, że na biurku programisty typowo znajdzie się zawsze coś więcej niż tylko klawiatura, myszka i ekran.


Mój egzemplarz pochodzi ze
spotkania HTML5 w Chrome Web Store

Może być tam chociażby mała, kauczukowa piłeczka. Model standardowy jest zwykle w jednolitym kolorze, ma średnicę około sześciu centymetrów i oznaczony jest mniej lub bardziej znajomym logo, wskazującym na jego pochodzenie. To oczywiście nie jest przypadek, ponieważ najprostszym sposobem na wejście w posiadanie tego wyrobu gumowego jest wzięcie udziału w spotkaniu, wykładzie, konferencji czy innego rodzaju evencie, gdzie takie fanty rozdawanego są darmo.

Po co jednak koder miałby trzymać pod ręką coś takiego? Otóż dlatego, że – jak zdołałem stwierdzić – piłeczka taka ma całe mnóstwo zastosowań bezpośrednio związanych z programowaniem. Mówiąc bardziej zrozumiałym językiem, jej funkcjonalność jest niezwykle bogata, gdyż obsługuje ona szeroki wachlarz różnych przypadków użycia. Oto niektóre z nich:

  • Piłeczkę można podrzucać. To pożyteczne zajęcie trenuje refleks i koordynację ruchową, a także pozwala w pożyteczny sposób zabić czas oczekiwania na ukończenie jakiejś dłuższej operacji. Krótko mówiąc, piłeczka jest narzędziem wspomagającym kompilację. Istnieje dowiedziona (przez amerykańskich naukowców) zależność między wielkością i stopniem skomplikowania projektów, nad którymi pracuje programista, a jego umiejętnościami żonglowania.
  • Piłeczkę można ściskać. Wspomaga to koncentrację i pozwala na łatwiejsze skupienie się podczas poszukiwania rozwiązań problemów, na jakie natrafiamy w trakcie kodowania. Nie bez znaczenia jest też fakt, że ćwiczenie to działa pozytywnie w profilaktyce RSI.
  • Piłeczką można rzucać o ścianę. Jest to rzecz jasna metoda wspomagająca debugowanie, której adekwatność jest skorelowana z czasem poświęconym na szukanie błędu. Oprócz absorbowania negatywnej energii piłeczka odbijająca się od ściany pozwala też na chwilowe oderwanie się od przeczesywania kodu w poszukiwaniu usterki, co z kolei często umożliwia uświadomienie sobie pomyłki, która legła u jej podstaw.
  • Piłeczka toczy się i spada z biurka. Ta jej cecha to idealny przykład pozornego buga, pod którym tak naprawdę kryje się użyteczny feature. Jeśli bowiem piłeczka spadnie nam z biurka i potoczy się w odległe miejsce, konieczne będzie doprowadzenie jej do porządku. Tego nie da się raczej zrobić zdalnie, więc będzie musieli wstać z krzesła i zrobić kilka kroków, a to zawsze jest pożądane.

Widzimy zatem, że kauczukowa piłeczka posiada niezaprzeczalne zalety i jest wybitnie użytecznym narzędziem programistycznym. Jeśli więc będziemy mieli okazję wejścia w jego posiadanie, zalecam skorzystanie z niej – zwłaszcza, że rzecz jest bardzo często rozprowadzana jako freeware :)

Tags: , ,
Author: Xion, posted under Programming » 9 comments
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.