Archive for Thoughts

Kod ci wszystko wytłumaczy

2011-10-27 22:12

(…) są dwa style pisania – pierwszy to: “popatrzcie jaki ja jestem mądry” – a drugi to: “popatrzcie jakie to proste”.

Jerzy Grębosz, Symfonia C++

Autor tego stwierdzenia miał na myśli przede wszystkim pisanie technicznej prozy, a więc wszelkiego rodzaju artykułów, książek, kursów i tutoriali (i blogów? ;]). Po namyśle stwierdzam jednak, że równie dobrze nadaje się ono i do poezji – czyli kodu. Podobnie bowiem przedstawia się kwestia wyższości drugiego stylu nad pierwszym, w większości przypadków.

“Większość” nie oznacza aczkolwiek “wszystkich”. Czasami górę biorą na przykład kwestie wydajnościowe, które niekiedy uzasadniają wyprodukowanie kodu wyglądającego jak przemyślnie zaszyfrowane zaklęcie. Klasycznym przykładem jest procedura szybkiego obliczania 1/\sqrt{x}, wyciągnięta wprost ze źródeł Quake‘a III:

  1. float InvSqrt (float x){
  2.     float xhalf = 0.5f*x;
  3.     int i = *(int*)&x;
  4.     i = 0x5f3759df - (i>>1);
  5.     x = *(float*)&i;
  6.     x = x*(1.5f - xhalf*x*x);
  7.     return x;
  8. }

Funkcja ta (której autorstwo niesłusznie przypisuje się czasem Johnowi Carmackowi) doskonale pokazuje, jak ważna jest czytelność i zrozumiałość kodu. Robi to w najlepszy możliwy sposób, tj. nie posiadając żadnej z tych dwóch cech :) W zamian oferuje znacznie ważniejszą w swoim zastosowaniu jakość – czyli wydajność.
Obliczanie odwrotności pierwiastka kwadratowego to jedna z najczęściej używanych operacji w grafice 3D – zawiera ją np. każda normalizacja wektora. Sensowne jest więc jak największe zoptymalizowanie tej funkcji. Będzie ona przecież wywoływana setki czy tysiące razy podczas renderowania pojedynczej klatki.

W sumie daje to kilkadziesiąt tysięcy wywołań na sekundę, a to dość unikatowa perspektywa jeśli chodzi o wartościowanie szybkości, czytelności, elastyczności – i tak dalej. I właśnie dlatego wspominam o niej jako o oczywistym wyjątku. Parafrazując popularną ostatnio proporcję: w 99% przypadków podobny kompromis nie będzie musiał dotyczyć nawet 1% kodu :)

O wiele bardziej typową sytuacją jest bowiem zdecydowana wyższość klarowności, czystości i zrozumiałości. To jest właśnie ów drugi styl: “zobaczcie jakie to proste”. Bierze on pod uwagę oczywisty w gruncie rzeczy fakt, iż głównym odbiorcą kodu jest człowiek, a nie komputer. Jeśli przyszły czytelnik potrafi z łatwością zrozumieć intencje autora – bo są one wyrażone przejrzyście i jednoznacznie – to niemal równie łatwo przyjdzie mu modyfikacja, rozszerzanie i poprawianie programu. Nie wspominając już nawet o tym, że program, który daje się łatwo “wytłumaczyć” samym kodem z definicji nie może być zanadto skomplikowany. Syntaktyczna prostota przekłada się więc na semantyczną, która z kolei dobrze koreluje z innymi pożądanymi właściwościami – jak choćby niezawodnością.

Czwarty dodatek do WoW-a

2011-10-23 16:53

Nie mam już wiele wspólnego ze światkiem World of Warcraft, ale akurat wieści o nowych dodatkach potrafią jeszcze wzbudzić we mnie zainteresowanie. Tak jest też z ogłoszonym (przed)wczoraj – zależnie od strefy czasowej – dodatkiem numer cztery, noszącym nazwę Mists of Pandaria.
Z pozoru nie zaskakuje on niczym nadzwyczajnym, jako że pod względem rozszerzeń WoW stał się już podobny do The Sims: ta sama idea z nowymi dekoracjami. Mamy więc tutaj wyższy limit poziomu postaci (90), nowy kontynent (Pandaria), nową rasę i klasę, świeżą dostawę instancji i raidów – i tak dalej. Krótko mówiąc: standard. W takiej sytuacji naturalnie jest poszukiwanie rozwiązań, które nie wpadają tak łatwo w dobrze znane szuflady i pozwalają domyślać się, w jakim kierunku gra będzie dalej podążać.
A według mnie jest on dość oczywisty. Otóż Blizzard chce dokonać czegoś, co jest “niemożliwe”, a zarazem absolutnie konieczne, biorąc pod uwagę obecne trendy w komputerowej rozrywce. Wyzwanie jest koncepcyjnie aż nazbyt proste, ale jego realizacja – jeśli w ogóle możliwa – wymaga balansowania na bardzo, bardzo cienkiej linie.

Co należy zrobić? Bagatela: połączyć Diablo z FarmVille – w przenośni, rzecz jasna.

Tags:
Author: Xion, posted under Games, Thoughts » 4 comments

class Fish extends Animal?…

2011-09-22 22:24

Pisałem już wcześniej o tym, że ostatnimi czasy programowanie obiektowe nie ma zbyt dobrej prasy i swego rodzaju modą stało się jego krytykowanie. Nie jest to oczywiście trend zupełnie pozbawiony podstaw. Z jednej bowiem strony dla pewnych problemów lepsze wydają się inne paradygmaty: np. dla modelu żądanie-odpowiedź (typowego dla aplikacji webowych) najwyraźniej całkiem dobrze sprawdza się programowanie funkcyjne. Z kolei zastosowania wymagające dużej wydajności (np. programowanie grafiki 3D czasu rzeczywistego) mogą istotnie nie tolerować narzutu związanego z polimorfizmem funkcji wirtualnych – albo przynajmniej tak się wydaje tym, którzy się nimi zajmują.

Sądzę jednak, że spory udział ma tu też pewien powszechny (niestety) zwyczaj krytykowania rzeczy, których nie do końca rozumiemy. Szerokie kręgi zatacza bowiem pewien specyficzny sposób opacznego interpretowania idei OOP-u. Jego źródła upatruję w wielu (może nawet większości) kursach, książkach, tutorialach, artykułach i wszelkiego rodzaju materiałach instruktażowych dla początkujących adeptów programowania. Sam dodałem swój niechlubny wkład do tego stanu rzeczy, do czego się tu otwarcie przyznaję. No cóż, nikt mnie ostrzegł – ani wtedy (czyli jakieś 6 lat temu), ani nawet teraz.
A ostrzeżenie jest absolutnie niezbędne. Także dlatego, że co najmniej raz słyszałem, jak owo mylne pojęcie na temat OOP-u stało się poważnym argumentem w rzeczowej poza tym dyskusji na temat jego zalet i (głównie) wad. Nawet ważniejszym powodem jest jednak to, iż niewłaściwa interpretacja założeń programowania obiektowego może prowadzić do źle zaprojektowanych systemów, które trudno się potem konserwuje i rozbudowuje.

O jakiego więc rodzaju konfuzji tu mówimy?

Nie mów mi, co jest naturalne

2011-08-17 23:03

Powszechny stereotyp sugeruje, że programiści uwielbiają spierać się co do zalet i wad używanych przez siebie rozwiązań: języków, frameworków, bibliotek czy nawet narzędzi takich jak edytory. Zapewne jest w tym spore ziarno prawdy. Nie ma oczywiście nic złego w rzeczowej dyskusji, w której używane są racjonalne i mające podstawy argumenty. Z tym jednak nie zawsze jest tak różowo.

Jednym z często używanych, ogólnych i pasujących niemal wszędzie “argumentów” jest wspominanie o naturalności danego rozwiązania – lub o jej braku. Mam osobiście duży problem z określeniem zarysów jakichkolwiek użytecznych granic dla tego pojęcia. Nawet więcej: jest ono na tyle niedookreślone, że z niemal równym powodzeniem można by mu przypisać dwa dokładnie przeciwstawne znaczenia. Oba byłyby wprawdzie ścisłe i pozwalały jednoznacznie powiedzieć, czy coś faktycznie jest naturalne czy nie. Problem w tym, że dla wszystkich rozważanych rzeczy odpowiedź byłaby taka sama – a to już jest bezużyteczne. Predykat, który zwraca zawsze true lub zawsze false nie niesie ze sobą żadnej informacji.

Jak więc wyglądają te dwie przeciwstawne postacie?… Z jednej strony trudno zareagować inaczej niż śmiechem na wszelkie próby doszukiwania się pierwotnej Natury w takich zjawiskach jak języki programowania. Życzę powodzenia każdemu, kto próbowałby znaleźć paralele między alternatywą w rodzaju “pętla for czy funkcja map” a decyzjami, jakie musieli podejmować nasi przodkowie na afrykańskiej sawannie jakieś 200 tysięcy lat temu. Tak pojmowana naturalność wyklucza oczywiście wszystkie te rzeczy, o które tak przyjemnie jest się spierać. Pocieszmy się przynajmniej tym, że porażka w używaniu któregoś z nich nie oznacza skończenia jako posiłek dla lwa.
Z drugiej strony jednak nie widać powodu, dla którego dowolne wytwory człowieka nie miałyby być uważane za w pełni naturalnie, jeśli nie odmawiamy tego miana mrowiskom, gniazdom ptakom czy pajęczynom. To znów tworzy nam dobrze określony, jednoznaczny predykat… który jednak zawsze zwraca true, co redukuje jego przydatność do zera.

To wszystko jest oczywiście podejrzane. Jeśli pojęcie ‘naturalny’ nie służy do przekazania nawet jednego bitu użytecznej informacji, to nie powinno być w ogóle używane. Ale jest; to sugeruje, że jego cel jest inny. Może być nim na przykład ukrycie braku rzeczywistego argumentu i próba przemycenia subiektywnego punktu widzenia pod przykrywką obiektywnie brzmiącej etykiety. Słówko ‘naturalny’ brzmi bowiem lepiej niż nawet ‘intuicyjny’. Wydaje się być znacznie precyzyjniejsze (intuicje są przecież mgliste) i sprawia wrażenie odwoływania do pozornie uniwersalnych kryteriów (w przeciwieństwie do subiektywnych intuicji).
Zwykle jednak to tylko złudzenie, ukrywające brak dobrego uzasadnienia dla swoich twierdzeń. Zatem nie mów mi, co jest naturalne. Magiczne zaklęcia nie zastąpią braku rzetelnych argumentów.

Wąskie szyjki od butelek

2011-07-21 21:51

Kilka dni temu zajmowałem się optymalizacją szybkości aplikacji, która działa na platformie Google App Engine. Żeby dobrze podejść do tego zadania, zacząłem oczywiście od poszerzenia swojej wiedzy na temat zagadnienia, co obejmowało chociażby obejrzenie odpowiedniej prezentacji z zeszłorocznego Google I/O. Przedstawiono tam odpowiednie narzędzie służące do profilowania (Appstats), czyli niezbędnego etapu przygotowawczego (o czym mam nadzieję wszyscy pamiętają ;]). Dodatkowo dowiedziałem się też o najważniejszych źródłach opóźnień w tego rodzaju aplikacjach – i to okazało się dość zaskakujące.

Ogólny wniosek, jaki zdołałem stamtąd wyciągnąć, dotyczy właśnie prawidłowego wykrywania wąskich gardeł (zwanych bottlenecks – tytułowe szyjki od butelek). W przypadku wspomnianej aplikacji okazało się na przykład, że nawet stosunkowo skomplikowana logika (przetwarzanie sporych porcji danych w JSON-ie, renderowanie długich szablonów HTML, itd.) napisana całkowicie w wysokiego poziomu języku interpretowanym (Python) relatywnie zajmuje dosłownie chwilę. Nieporównywalnie dłuższy czas związany jest z dowolnym wywołaniem API platformy, bo każde z nich wymaga sieciowej wycieczki do osobnego serwera, który może je obsłużyć. To zaś sprawia, że wszelkie próby optymalizacji samych algorytmów (nawet potworków rzędu O(n^3) czy O(n^4)) nie mają sensu, jeśli nie wiąże się to ze zmniejszeniem ilości wspomnianych wywołań, czyli np. dostępu do magazynu danych.

Podobne pozornie zaskakujące wnioski można wyciągnąć, gdy przyjrzymy się wewnętrznej strukturze innych platform. Bardzo dobrym przykładem jest chociażby diagram opóźnień I/O w komputerach PC. Łatwo na nim zauważyć, w których miejscach należy jak najbardziej ograniczyć ruch danych, aby uzyskać odpowiedni wzrost wydajności. Przy takim spojrzeniu na aplikacje, podejście znane jako DOD (Data Oriented Design) nabiera też nieco więcej sensu ;-)

Tags: , , ,
Author: Xion, posted under Programming, Thoughts » 1 comment

Stosu przepełnienie

2011-07-16 18:44

Większość programistów zna (albo powinna znać) serwis Stack Overflow. Dla niezorientowanych wyjaśniam, że jest to specyficznego rodzaju forum dyskusyjne dla koderów, nastawione przede wszystkim na zadawanie pytań i udzielanie na nie odpowiedzi. Ze względu na swoje rozmiary mierzone liczbą zgromadzonej wiedzy, stanowi ono też doskonałe źródło szybkiej informacji w tych częstych przypadkach, gdy potrzebujemy prostego rozwiązania jakiegoś niezbyt skomplikowanego problemu.
Oprócz bycia nieocenioną pomocą w pracy programisty, SO jest też ciekawym przypadkiem sprawnie działającej społeczności, na straży której nie stoją całe zastępy moderatorów. Zamiast tego to sami użytkownicy – za pomocą sukcesywnie zdobywanych przywilejów, takich jak edycja czy tagowanie pytań – wcielają w życie zasady dyskusji. Podobno fachowo idea ta nazywa się crowdsourcingiem; możemy dołączyć to słówko do pokaźnej już liczby dziwnych pojęć spod znaku Web 2.0 :)

Centralnym mechanizmem, wokół którego kręci się światek Stack Overflow (oraz niezliczonych innych stron opartych na tym samym silniku) jest reputacja poszczególnych użytkowników. To zwykły numer, w swoim znaczeniu podejrzanie podobny do tzw. karmy, nad której obecnością na forum Warsztatu raz się nawet nieco rozpisałem. Reputacja jest zwiększana między innymi wtedy, gdy nasze pytania lub odpowiedzi zostaną poparte (upvote) przez innych użytkowników. To nam daje punkty, które w większej ilości przekładają się na przywileje quasi-moderatorskie. W sumie jest to więc klasyczny przykład sprzężenia zwrotnego dodatniego (positive feedback loop), występującego w świecie w najprzeróżniejszych formach – od giełdy po FarmVille.

Jak w każdym takim systemie, także i tutaj wszystkie trybiki nie zawsze jednak działają idealnie. Ponieważ reputacja w serwisie SO jest dobrem mającym wartość także poza nim, nie dziwi duża chęć do jej zwiększania, występująca u wielu użytkowników. Nie jest to wbrew pozorom nic trudnego – nawet mimo obecności licznych ekspertów z niemal każdej poddziedziny związanej z programowaniem, którzy weryfikują i oceniają udzielane odpowiedzi.
Jest tak z prostej przyczyny: w serwisie pojawia się całe mnóstwo pytań trywialnych, na które bez problemu odpowie każda średnio zaawansowana w danym temacie osoba. Ze względu na ilość użytkowników (ponad 700 tysięcy) fakt ten generuje dość komiczne sytuacje, gdy w przeciągu mniej niż minuty pojawiają się trzy albo cztery niemal dokładnie identyczne odpowiedzi. Zabawa czasami zamienia się więc raczej w konkurs szybkiego pisania na klawiaturze :)

Mimo tych wad muszę stwierdzić, że uczestnictwo w dyskusjach na SO jest w ogólnym rozrachunku bez wątpienia pożyteczne. Wymierną osobistą korzyścią jest oczywiście sama reputacja, przeliczalna rozmiar ego po bardzo korzystnym kursie ;] Ważniejsza jest aczkolwiek możliwość utrwalania i poszerzania swojej wiedzy w wybranych działkach koderskiej działalności.

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

Niekoniecznie należy słuchać ekspertów

2011-06-20 22:45

Nieodłączną częścią realizacji projektu programistycznego jest wybór używanych technologii. Dotyczy to zarówno samego początku, jak i późniejszych etapów, gdy czasami trzeba zdecydować się np. na skorzystanie z jakiejś biblioteki X lub jej zamiennika Y. Takie dylematy mają i koderzy-amatorzy (co często uzewnętrzniają na przeróżnych forach ;]), i firmy tworzące oprogramowanie komercyjnie. Decyzję trzeba jednak w końcu podjąć; czy są jakieś uniwersalne kryteria, którymi można się kierować?
Inżynieria oprogramowania każe zwykle zdać się na poprzednie doświadczenia lub wiedzę ekspertów. Ta druga opcja jest często preferowana wobec braku podstaw (tj. wspomnianych doświadczeń) do skorzystania z pierwszej. Wydaje się to rozsądne. W końcu osoba, która bardzo dobrze zna dane rozwiązanie, powinna mieć też odpowiednie pojęcie o tym, czy aplikuje się ono do konkretnego problemu.

A jednak mam co do tego całkiem poważne wątpliwości. Potrafiłbym znaleźć kilka sensownych argumentów na to, że osoba biegła w stosowaniu danej technologii nie musi być wcale dobrym doradcą. W grę mogą bowiem wchodzić silne czynniki zaburzające solidność osądu eksperta. Przychodzą mi na myśl zwłaszcza dwa:

  • Osoba świetnie znająca jakieś rozwiązanie jest z pewnością taką, która zastosowała je w co najmniej kilku projektach. Kto wie, być może nawet zakończyły się one sukcesem ;) Niezależnie od ich wyniku, zdobyte przy okazji doświadczenie prawdopodobnie nauczyło naszego eksperta, jak powinien radzić sobie z przeróżnymi kruczkami, niejasnościami, niedoróbkami, brakami czy wręcz jawnymi bugami występującymi w danej platformie czy bibliotece. Jeśli wielokrotnie i z powodzeniem dawał sobie z nimi radę, jest wielce prawdopodobne, iż będzie (nawet nieświadomie) umniejszał ich znaczenie podczas “obiektywnej” oceny całego rozwiązania. Po prostu z perspektywy czasu nie będą się one wydawały aż tak dolegliwe, jakie mogą być w rzeczywistości dla osoby słabiej obeznanej z daną technologią.
  • Nasz ekspert od rozwiązania X na pewno poświęcił sporo czasu i mocy obliczeniowej swoich neuronów na dokładnie zapoznanie się z jego szczegółami. Wysiłek ten sprawił przy okazji, że w naturalny sposób zaczął on wyżej cenić X-a, ponieważ w ten sposób potwierdzał w swoich oczach słuszność decyzji, aby rozwijać swoją znajomość tego zagadnienia. Dzięki tej (znów: zwykle nieświadomej) praktyce, nasz ekspert zapobiegł powstaniu dysonansu poznawczego (cognitive dissonance) lub przynajmniej znacząco go zredukował. Efektem ubocznym tego zjawiska jest jednak zaburzone postrzeganie wartości X-a jako rozwiązania, związane głównie z tzw. błędem potwierdzania (confirmation bias) lub zaprzeczania (disconfirmation bias). Krótko mówiąc, nasz ekspert generalnie przywiązuje większą wagę do pozytywnych ocen X-a, a mniejszą do negatywnych. Niezbyt dobrze wróży to jego obiektywności.

Jak wynika z powyższych argumentów, wypowiedziane przez eksperta zdanie na temat przydatności jakiegoś rozwiązania niekoniecznie musi być obiektywne i wartościowe. Oczywiście nie twierdzę, że największe pole do popisu przy podejmowaniu decyzji powinni mieć wobec tego początkujący, bo to z kolei zakrawa na przegięcie w drugą stronę :) Sądzę jednak, że najbardziej kompetentnymi i obiektywnymi osobami byłyby takie, które wprawdzie stosowały dane rozwiązanie w praktyce, ale nie są w nim całkiem biegłe. A już zupełnie dobrze byłoby wówczas, jeśli mają one też pewne pojęcie o porównywalnych, alternatywnych rozwiązaniach.

 


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