Monthly archive for March, 2008

Konferencja się zbliża…

2008-03-31 21:37
Mapka poglądowa IGK

1 – Akademia Podlaska
2 – PKP
3 – PKS
4 – Droga z Warszawy

…i to wielkimi krokami. Mam oczywiście na myśli doroczną konferencję IGK, której piąta już edycja rozpocznie się w Siedlcach już w ten piątek. Wpadł mi właśnie w ręce skrócony informator, który zawiera wiele ciekawych informacji. Są oczywiście podstawowe wiadomości logistyczne związane z tym, jak na miejsce konferencji w ogóle trafić. Te są jednak potrzebne głównie tym, którzy wybierają się tam pierwszy raz; takim wyjadaczom jak ja, stawiającym się na (prawie) każdej edycji, nie są już w ogóle potrzebne :-)
Znacznie bardziej interesujące są tematy referatów, które będzie można usłyszeć na miejscu. Tym razem cztery z nich (czyli więcej niż połowa wszystkich!) będą wygłoszone przez osoby związane z Warsztatem, co mieści się około zwyczajowej średniej. Rarytasem będzie pewnie wykład poprowadzony przez jednego z twórców Wiedźmina, a dokładniej przez głównego projektanta rozgrywki, który opowie o produkcji i projektowaniu gier.

Zatem będzie ciekawie. Już nie mogę się doczekać :)

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

Nagłówki i przestrzenie nazw

2008-03-30 16:11

Niestety, przestrzenie nazw w C++ nie mają takiego wdzięku jak pakiety w Javie czy assemblies w .NET. Zwłaszcza w połączeniu z plikami nagłówkowymi potrafią one sprawić nieco problemów. Jeśli bowiem nie będziemy uważali, to możemy dość łatwo zniwelować korzyści, jakie płyną z ich używania.

Ale po kolei. Jeśli mamy do czynienia z modułem kodu (plikiem .cpp), to możemy bez żadnych skrupułów umieszczać w nim deklaracje using lub using namespace. Jeśli tylko nie prowadzi to do niejednoznaczności, wszystko jest w porządku, bowiem zasięg tych deklaracji ogranicza się tylko i wyłącznie do tego jednego pliku.
Gorzej jest niestety z plikami nagłówkowymi. Ponieważ włączane są one tu i ówdzie przy pomocy dyrektywy #include, nie można tak po prostu wpisywać w nich deklaracji using namespace. Zostałyby one bowiem rozpropagowane do wszystkich plików, które dany nagłówek włączają, efektywnie niwelując wszelkie korzyści zamknięcia fragmentów kodu w przestrzeń nazw. Bo co to za namespace, który wszyscy “rozpakowują” i przenoszą jego zawartość do przestrzeni globalnej?…

Dlatego nie ma rady: w plikach nagłówkowych można używać wyłącznie nazw kwalifikowanych – poprzedzonych wszystkimi nazwami przestrzeni, jak np. XC::Base::GC::BlockInfo. W przeciwnym wypadku na pewno zaśmiecimy sobie którąś z przestrzeni (najczęściej globalną) identyfikatorami, które do niej nie należą – co będzie widoczne w systemach podpowiadania takich jak IntelliSense.

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

Trzy funkcje semaforów

2008-03-28 18:10

Podobno programowanie równoległe jest trudne: fakt, że kilka czynności może być wykonywanych “jednocześnie”, wprowadzać ma duże zamieszanie i komplikować życie. Nie zgadzam się! Nawet jeśli procesy lub wątki działają w tym samym czasie, to jeszcze nie jest powód do zmartwień. Prawdziwe problemy zaczynają się przecież dopiero wtedy, gdy trzeba ich działanie zsynchronizować :-)
A do tego przydają się na przykład semafory. Przy ich pomocy których można zresztą zrealizować większość popularnych mechanizmów blokowanej synchronizacji, jak choćby sekcje krytyczne. Jednak cała sztuka polega zawsze na tym, żeby użyć ich w sposób odpowiedni do danego zastosowania i nie nabawić się przy tym zagłodzenia, zakleszczenia (deadlock) lub innych “równoległych” błędów.

Semafor (kolejowy)Istnieją oczywiście tzw. schematy synchronizacji, lecz ich przydatność jest mniej więcej kilkukrotnie mniejsza niż chociażby wzorców projektowych dla programowania obiektowego. Zauważyłem jednak, że sytuacje, w których używa się semaforów (lub podobnych obiektów) można zakwalifikować do jednej z trzech grup, z których każda następna jest ugólnieniem poprzedniej:

  • Prostym i częstym przypadkiem jest wykorzystanie semafora do ochrony jakiegoś zasobu. Wówczas każdy proces (lub wątek – na tym poziomie nie ma to znaczenia) musi sprawdzić semafor przed dostępem do tego zasobu – czyli np. przed zapisem do współdzielonej pamięci.
    1. Wait (S);   // czekamy na semaforze
    2. /* praca z zasobem */
    3. Release (S);   // zwalniamy semafor

    W ten sposób tworzy się oczywiście sekcja krytyczna, bo tylko jeden proces uzyska do naszego zasobu dostęp. Wygodne jest tutaj myślenie o semaforze jako obiekcie ochraniającym zasób, a nie fragment kodu. Oczywiście na samym początku taki semafor jest zwykle opuszczony.

  • Niekiedy semafor służy do oczekiwania na spełnienie jakiegoś warunku. Weźmy na przykład serwer sieciowy, który na jednym wątku nasłuchuje połączeń (operacja blokująca), a w kolejnym wykonuje już jakieś czynności przygotowawcze dla nowego klienta. Gdy ów klient faktycznie się połączy, ten drugi wątek powinien się zająć jego obsługą, a pierwszy nadal nasłuchiwać nowych połączeń.
    Skąd ten drugi wątek we, że jest już nowy klient? Ano “wisi” on na (początkowo podniesionym) semaforze. Wątek nasłuchujący podniesie go wtedy, gdy połączenie z klientem zostanie nawiązane. Semafor sluży więc do sprawdzania pewnego warunku: czy klient jest już połączony.
  • W najbardziej ogólnej wersji semaforem kontrolujemy dostęp do różnych “miejsc” w kodzie. Każde takie miejsce można sobie wyobrazić jako pokój. Semafory będą wtedy drzwiami, stopień ich uchylenia – wartością licznika, zaś procesy będą osobami, które próbują się przez rzeczone drzwi przeciskać celem przejścia z jednego miejsca do drugiego. Wtedy wystarczy “tylko” ustalić warunki zamykania i odmykania drzwi – i już :) Rzecz w tym, że konstrukcja całego układu tych pomieszczeń nie jest w ogólności rzeczą prostą.

Bo programowanie równoległe – którego synchronizacja jest nieodłączną częścią – to jednak ciężki kawałek chleba ;]

Tags:
Author: Xion, posted under Programming » Comments Off on Trzy funkcje semaforów

Wiosenne porządki #2 – Ujednolicanie interfejsu

2008-03-26 21:45

Jedną z bardziej denerwujących cech bibliotek, z jakimi można się zetknąć, jest ich wewnętrzna niespójność pod względem interfejsu. Dotyczy to na przykład drobnych kruczków związanych z postacią wywołań funkcji i metod. Znanym przedstawicielem tego gatunku “kwiatków” są chociażby standardowe funkcje C(++) od zapisu do plików – fprintf i fputs:

  1. int fprintf (FILE* stream, const char* format, ...);
  2. int fputs (const char* str, FILE* stream);

Obie działają podobnie (z dokładnością do formatowania w fprintf), lecz różnią się irytującym szczegółem: miejscem parametru określającego plik (typ FILE*), do którego zapisujemy. Nietrudno się tu pomylić i to niekoniecznie wtedy, gdy korzystamy z obu funkcji w tym samym kodzie.

Podobna niejednolitość jest na szczęście w miarę łatwa do wykrycia i usunięcia – oczywiście pod warunkiem, że mówimy tutaj o bibliotece, której nie wykorzystuje jeszcze nikt postronny. Oprócz niespójnych prototypów funkcji powinniśmy jeszcze zwrócić uwagę na:

  • Nazwy metod wykonujących podobne czynności. Dotyczy to na przykład metod dostępowych, służących symulowaniu właściwości. Powinny one być zgodne z jednym szablonem nazewnictwa, np. Get/SetSomething, IsEnabled, itd. Podobnie metody z nazwami zawierającymi czasowniki “znaczące”, takie jak load, create, read, write powinny przede wszystkim robić to, co owe czasowniki wyrażają.
  • Sensownie dobrane przeciążenia funkcji i parametry domyślne. Wypadałoby bowiem, aby w typowych sytuacjach możliwe było użycie krótszych wywołań z mniejszą ilością parametrów niż wtedy, gdy musimy zrobić coś specjalnego i bardziej skomplikowanego. Zazwyczaj osiągnięcie tego nie jest trudne i sprowadza się do nadania jakimś parametrom rozsądnych wartości domyślnych (przy ich ewentualnym przestawieniu) lub dopisaniu prostych wersji przeciążonych dla danej funkcji.
  • Nazwy parametrów w deklaracjach i definicjach funkcji. W C(++) nie musimy ich pisać w deklaracjach, ale jest to bardzo wskazane, gdyż ułatwia korzystanie z plików nagłówkowych jako swego rodzaju “spisu treści”. Jednak z drugiej strony musimy wtedy dbać, żeby w obu miejscach były one ze sobą zgodne. W przeciwnym razie możemy bowiem napotkać bardzo przykre błędy, jeśli zmienimy kolejność argumentów funkcji tego samego typu.

Nanoszenie podobnych poprawek jest oczywiście dość skomplikowaną operacją, ale wciąż nie ingeruje ona ani w projekt biblioteki, ani – z grubsza – w sposób, w jaki końcowy programista ma jej używać. Mimo to podejrzewam, że w przypadku mojego siln… tj. kodu będzie to dosyć czasochłonne. Całkiem często zmieniałem bowiem swoje upodobania odnośnie kwestii, które wymieniłem powyżej (i których lista nie jest też pewnie kompletna).
Ale cóż, wiosna dopiero się zaczyna, więc czasu – przynajmniej teoretycznie – jest dużo ;-)


Author: Xion, posted under Programming » 2 comments

Magazyn o Warsztacie

2008-03-25 17:03

Okładka pierwszego numeru WMagk_b wcielił w życie bardzo ciekawy pomysł, polegający na wydawaniu co jakiś czas magazynu opisującego wydarzenia dziejące się na Warsztacie. Chodzi tu na przykład o postępy w amatorskich projektach, które są z tym community związane, interesujące screeny, ciekawostki z forum i inne warte odnotowania fakty. W o wiele skromniejszej formie coś takiego już występowało w postaci tzw. Community News, ale ostatecznie niezbyt się to przyjęło.

Miejmy nadzieję, że z WMagiem – bo tak w skrócie się to wydawnictwo nazywa – będzie inaczej. Pierwszy numer nie grzeszy może zachwycającą szatą graficzną, ale i tak warto mu się przyjrzeć. Do czego zachęcam, prezentując poniższe linki:

Tags: ,
Author: Xion, posted under Internet » Comments Off on Magazyn o Warsztacie

Wielkanocne jaja

2008-03-23 20:19

Wprawdzie Google ostatecznie rozstrzyga rywalizację między Gwiazdką a Wielkanocą na korzyść tej pierwszej, ale to zwyczaj z okolic święta wiosennego użyczył nazwy dla pewnej zabawnej praktyki programistycznej. Chodzi o easter eggs, czyli ukryte napisy, ekrany, a czasem całe pod-aplikacje, obecne w programie acz niedostępne niewtajemniczonym użytkownikom. Mimo tego, wiele spośród tych ‘jaj’ stało się wyjątkowo znanych.

Pinball w Wordzie 97Dotyczy to naturalnie tych aplikacji, które są szeroko znane – czyli na przykład tych wyprodukowanych przez znaną i (nie)lubianą firmę z Redmond. Różne wersje pakietu Office zawierają przykładowo przynajmniej kilka różnych gier, począwszy od prostego flippera (Word 97) przez symulator lotu aż po… grę FPP (we wczesnej wersji Excela). W Windows poniżej wersji XP można było też wykorzystać ciekawostkę ukrytą w jednym z wygaszaczy ekranu, który mógł wyświetlać kolejno nazwy znanych wulkanów na świecie.
Okno About programu mIRCSpora ilość easter eggs jest zawarta w okienkach About programów – co jest całkiem zrozumiałe, zważywszy że prawie nikt tam nie zagląda :) Do bardziej znanych należy chyba odgłos wydawany po kliknięciu w nos na fotografii twórcy programu mIRC.

Jaja możemy jednak znaleźć nie tylko w programach użytkowych, ale także w grach. Kto nie zna słynnego “krowiego poziomu” (cow level) z Diablo II? Blizzard ma zresztą więcej takich kwiatków w zanadrzu – jak choćby zabawne dźwięki wydawane przez jednostki w obu znanych RTS-ach (WarCraft i StarCraft). W World of Warcraft ilość różnych smaczków liczy się co najmniej w tysiącach.

Niestety, przed easter eggs przyszłość rysuje się ponuro. Możliwość umieszczenia w kodzie programu nieudokumentowanego kodu jest bowiem potencjalnym zagrożeniem i może prowadzić do powstania tzw. bomb logicznych. To oczywiście zmartwienie koncernów, które mogą nie ufać swoim programistom. Amatorskich produkcji siłą rzeczy to nie dotyczy.
Tak więc umieszczajmy w swoich grach i aplikacjach jak najwięcej jajcarskich pomysłów, póki jeszcze możemy :) Wesołych świąt!

Tags:
Author: Xion, posted under Applications, Games » 2 comments

Wiosenne porządki #1 – Odprzedrostkowywanie klas

2008-03-22 18:21

Przez ostatnich kilkanaście tygodni nie zaglądałem właściwie do kodu swojego siln… tzn. biblioteki (;P). I chociaż entropia kodu, którym nikt się nie zajmuje, nie powinna w zasadzie rosnąć, od czasu do czasu przydadzą się większe lub mniejsze porządki. Zwłaszcza jeśli w międzyczasie zmieniły się nasze poglądy dotyczące tego, jak programować trzeba, a jak nie należy.

Mniej więcej coś takiego przytrafiło mi się jakiś czas temu. Dość długo byłem zwolennikiem tzw. notacji węgierskiej. Jest to pewna reguła odnosząca się do nazw wprowadzanych do kodu źródłowego – takich jak nazwy zmiennych, klas, funkcji, itd. – która postuluje, aby poprzedzać je pewnymi przedrostkami. Prefiksy te mają dostarczać pewnych informacji, mówiąc na przykład, czy mamy do czynienia z klasą, strukturą czy ze zmienną. W tym ostatnim przypadku dodatkowo rozróżniamy też zmienne lokalne od pól klas, a także wprowadzamy przedrostki identyfikujące ich typy. Produktem tych zasad mogą być ostatecznie nazwy typu CFoo::m_pstrVar.
Prawdopodobnie cała ta zabawa była przydatna wtedy, gdy nie dysponowało się zintegrowanymi środowiskami programistycznymi (IDE). Teraz nietrudno jest poznać typ zmiennej: wystarczy najechać kursorem na dowolną nazwę w kodzie, a w podpowiedzi dostaniemy jego deklarację. Proste i praktyczne.

Podejrzewam, że nadmierna sympatia do notacji węgierskiej wzięła się u mnie stąd, że stykałem się z nią dawno temu w kodach napisanych w C i C++, z których – nie ukrywajmy – niewiele wtedy rozumiałem :) Tym więc mogę usprawiedliwić fakt, że bezmyślnie przejąłem ten poroniony w gruncie rzeczy sposób nazewnictwa. Na szczęście nigdy nie jest za późno, aby nawrócić się na właściwą drogę, co też niniejszym czynię ;]
Wyrzucenie wszystkich prefiksów chociażby z nazw zmiennych byłoby sporym zadaniem, zwłaszcza że mówimy o kodzie liczącym przecież 30 tysięcy linii (co jest, przy okazji, bardzo dziwne, jeśli się weźmie pod uwagę jego mizerię funkcjonalną :)). Dlatego rozpoczynam skromnie: od poprawienia nazw wszystkich klas i struktur tak, aby nie były opatrzone żadnymi “ozdobnikami”. Nie ukrywam, że w ten sposób staram się upodobnić do konwencji stosowanej w .NET i JVM. Bo przecież dobre wzorce są po to, aby je naśladować…


Author: Xion, posted under Programming » 12 comments
 


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