Archive for Programming

JSON, czyli co dobrego dał światu JavaScript

2010-11-24 22:04

O języku JavaScript mogę powiedzieć mnóstwo złych rzeczy. Począwszy od tego, że powszechność stosowania anonimowych funkcji jako callbacków powoduje, że stężenie zagnieżdżonych nawiasów w kodzie osiąga często poziomy lispowe. Skończyć zaś mogę na koszmarnym wsparciu dla “normalnej” obiektowości, znającej chociażby pojęcie klasy i obiektu, który nie jest po prostu przypadkową kolekcją jakichś tam atrybutów.

Lecz co ciekawe, to właśnie takie traktowanie obiektów leży u źródła bardzo pożytecznego wynalazku wywodzącego się z okolic JavaScriptu – czyli formatu JSON (JavaScript Object Notation). Ponieważ w JS wszystko jest swego rodzaju hierarchicznym słownikiem, obiekt możemy zdefiniować podając po prostu listę nazw i definicji (wartości) jego składników:

  1. var foo = {
  2.     "first": "value",
  3.     "second": "another value",
  4.     "compound": { "hello": "world" },
  5.     "integer": 42
  6. }

A ponieważ JavaScript jest językiem interpretowanym, możliwe jest wykonanie kodu podanego jako tekst (funkcją eval). Stąd możliwość użycia składni samego kodu JS – a dokładniej jej podzbioru zaprezentowanego wyżej – jako formatu serializacji obiektów, a więc w praktyce do przechowywania dowolnych danych. I tym właśnie jest JSON.

Wśród zalet tego formatu, obok natywnej obsługi przez jeden z popularnych języków programowania, na pewno da się łatwo zauważyć prostotę połączoną ze sporymi możliwościami. JSON to co najmniej “hierarchiczna wersja INI” z kilkoma dodatkami, takimi jak obsługa tablic czy kluczy będących dowolnymi ciągami znaków. Format nie jest zaś ani tak rozwlekły jak XML, ani tak ścisły w swej składni jak YAML. Jest więc łatwy do czytania i pisania dla człowieka oraz nie daje dużego narzutu przy przesyłaniu przez sieć. Stąd zresztą bierze się jego popularność do takich zastosowań jak zdalne wywoływanie funkcji (RPC) jako alternatywa dla przyciężkiego, XML-owego standardu SOAP. Korzysta z niego chociażby jeden z wariantów API Facebooka.

Jak wygląda obsługa JSON-a w językach programowania poza JavaScriptem? Otóż całkiem dobrze, co też opisuję dokładniej poniżej. I tak:

  • Zwykła Java oferuje pakiet org.json, w którym potrzebne klasy (jak JSONObject i JSONArray) są dostępne do użycia.
  • W Pythonie mamy pakiet o nazwie simplejson (niektóre starsze wersje 2.x) lub po prostu json. Użycie JSON-a jest w tym języku bardzo proste ze względu na podobny do JavaScriptu model obiektowości.
  • Platforma .NET nie ma (o ile mi wiadomo) wbudowanych narzędzi do obsługi formatu JSON, ale istnieją oczywiście do tego zewnętrzne biblioteki takie jak JSONSharp czy CsJson.
    Update: Okazuje się, że serializator do formatu JSON jednak istnieje (od wersji 3.5) i stanowi go klasa JavaScriptSerializer.

Pełniejsza lista jest dostępna na oficjalnej stronie JSON-a i obejmuje chyba każdy choć trochę szerzej używany język. Niezależnie więc od tego, do czego zechcemy tego formatu użyć i na jakiej platformie pracujemy, powinniśmy być w stanie całkiem łatwo to zrobić.

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

Małe kruczki

2010-11-22 8:31

Przeskakując między wieloma językami programowania, bibliotekami czy frameworkami po pewnym czasie można wyrobić sobie zdolności “uogólniające”, dzięki którym takie zmiany nie są specjalnie kłopotliwe. Jednak nawet jeśli potrafimy płynnie przechodzić od jednego języka do drugiego, to zawsze istnieje szansa, że zapomnimy przy okazji o jakimś szczególe, drobnej rzeczy specyficznej dla konkretnego narzędzia – tytułowym małym kruczku.
A przynajmniej mi się tak nierzadko zdarza. Dlatego tę notkę dedykuję pojedynczym, drobnym a “dziwnym” cechom poszczególnych języków programowania, o których często zdarza mi się zapominać. A są one następujące:

  • W C++ nie dodaje się stałych tekstowych. W dziesiątkach języków programowania (i nie tylko programowania) zapis w stylu "ala" + " ma " + "kota" jest najzupełniej oczywistą konkatenacją trzech napisów. Ale w C++ nie. Ponieważ stałe dosłowne, takie jak teksty w cudzysłowach, są – w przybliżeniu – typu const char*, ich łączenie operatorem + jest interpretowane jako dodawanie dwóch wskaźników. Serio.
    Wniosek: W C++ w takich sytuacjach plus jest zbędny i należy go pominąć "ala" " ma " "kota", o ile oczywiście nie łączymy obiektów klasy string.
  • W Javie łańcuchy znaków porównujemy… inaczej. Otóż Java jest bardzo obiektowa i w związku z tym nawet dla typu java.lang.String nie robi wyjątku i obsługuje go tak, jak każdą inną klasę. A to oznacza, że zwykły operator == działa dla napisów tak samo, jak dla innych obiektów (inaczej niż choćby w C#), tj. porównuje ich referencje w celu sprawdzenia, czy mamy do czynienia z tym samym obiektem. Tym samym, nie zaś takim samym, czyli równym co do wartości – a o to nam zwykle chodzi, gdy pracujemy z napisami.
    Wniosek: W Javie do porównywania napisów korzystamy z metody equals. To pewnie dlatego wciąż nie ma w niej switcha dla napisów ;-)
  • Słowniki w Pythonie domyślnie “iterują się” po kluczach. Żeby oszczędzić nadmiernie rozbudowanych wyjaśnień, rzucę poniższym kawałkiem kodu:
    1. for k, v in dictionary: print k, " => ", v

    który na pierwszy rzut oka wygląda na zupełnie poprawną iterację po zawartości słownika dictionary, w której zmienna k dostaje klucz, a v wartość. Jest on dowodem, że oczami należy rzucać zawsze przynajmniej dwa razy. W istocie bowiem k i v będą kolejno otrzymywały, uwaga, po dwa elementy klucza (potraktowanego jako para). Po prostu konwersja słownik → coś_po_czym_można_iterować daje w Pythonie kolekcję kluczy, a nie par klucz-wartość. Nie pytajcie, dlaczego.
    Wniosek: Albo iterujemy po kluczach i wartość uzyskujemy zwykłym indeksowaniem, albo korzystamy z metody items w celu uzyskania kolekcji par klucz-wartość.

  • W Javascripcie zmienne – nawet te użyte po raz pierwszy w funkcjach – są domyślnie globalne. Nawet nie śmiem dociekać, co jest uzasadnieniem dla tego faktu…
    Wniosek: Pierwsze przypisanie do nowej zmiennej wewnątrz funkcji należy opatrywać słowem kluczowym var.
Tags: , , , ,
Author: Xion, posted under Programming » 7 comments

Wątpliwości na właściwym poziomie

2010-11-16 19:36

Nikt nie lubi być w błędzie. Niestety, to niezbyt przyjemne uczucie jest częstym doświadczeniem dla programisty. Ciągle popełniamy błędy, będąc przekonanym o poprawności napisanego przez siebie kodu, i nieustannie musimy korygować swoje przekonania na ten temat. W pewnym sensie jest to podobne do pracy naukowców, zmuszonych do korygowania swoich teorii w obliczeniu dowodów eksperymentalnych.

Trzeba jednak zawsze wiedzieć, w co tak naprawdę powinniśmy wątpić, bazując na obserwacjach, doświadczeniu i przydatnej cesze umysłu znanej jako zdrowy rozsądek. To zwłaszcza ona mówi o jednej prostej regule odnoszącej się do poszukiwania źródeł błędów; mianowicie:

Im “dalej” on naszego własnego kodu szukamy przyczyn błędów, tym mniejsze jest prawdopodobieństwo, że je tam odnajdziemy.

Przez ‘odległość’ rozumiem tutaj – z grubsza – wysokość przekroju przez kolejne poziomy abstrakcji, na których oparta jest tworzona przez nas aplikacja. Może być ich niewiele albo bardzo dużo, ale jedno pozostaje prawdą: szansa na to, że powód niepożądanego zachowania programu leży gdzieś w niższych warstwach jest bardzo, bardzo, bardzo mała. Ponadto wraz z zagłębianiem się w owe warstwy niższe prawdopodobieństwo nie tylko spada, ale też spada niezwykle szybko. Mam podejrzenia, że gdyby ktoś pokusił się o opracowanie jakiegoś matematycznego modelu dla tego zjawiska (analizując ogromną ilość błędów i ich przyczyn z wielu rzeczywistych projektów o różnym charakterze), to okazałoby się, że spadek ten jest wykładniczy.

Z tego wynikają przynajmniej dwa proste wnioski. Po pierwsze: jeśli właśnie zastanawiasz się, czy twój kod nie spowodował objawienia się ukrytego błędu w kompilatorze, to… nie, nie spowodował ;P
Po drugie: błędy w niższych warstwach abstrakcji – jakkolwiek rzadkie – to jednak zdarzają się. i zawsze istnieje szansa, że akurat my będziemy mieli z tego powodu bardzo zły dzień. Lecz zanim odważymy się zejść w debugowaniu o krok w dół, powinniśmy być bardzo pewni, że wykluczyliśmy wszystkie możliwości odnoszące się do aktualnego poziomu – tym pewniejsi, im niżej chcemy zejść. A i na tak na 99% pominiemy coś, co wykraczało poza naszą przestrzeń hipotez, czym nie należy się jednak zbytnio przejmować. Błądzić bowiem, to rzecz bardzo koderska :)

Tags: , ,
Author: Xion, posted under Programming, Thoughts » 5 comments

Szanuj programistę swego…

2010-11-10 14:00

…możesz nie mieć wnet żadnego.

Natrafiłem wczoraj na artykuł opisujący prawdopodobne przyczyny porażki systemu operacyjnego Symbian. Dla niezorientowanych – których, jak przewiduję, może być całkiem sporo – wyjaśniam, że chodzi tutaj o system działający na bardziej zaawansowanych telefonach komórkowych, popularny jeszcze kilka lat temu. Wydaje się, że miał on przed sobą całkiem obiecującą przyszłość, biorąc pod uwagę to, że popularne obecnie usługi typu współdzielenie lokacji czy rzeczywistość rozszerzona (augmented reality) najwyraźniej działały na nim całe lata przed powstaniem chociażby iPhone’a. Coś więc musiało pójść bardzo nie tak, skoro obecnie rynek smartphone‘ów jest zdominowany przez wspomnianego iPhone’a oraz system Android. I stąd właśnie wynika ciekawa nauczka życiowa dla twórców tego rodzaju platform – i nie tylko.

W skrócie brzmi ona: “Dbaj o programistów, który mają tworzyć aplikacje oparte o twoje rozwiązanie”. Realizacja polega na dostarczeniu sensownego, kompletnego i dobrze udokumentowanego API oraz utrzymywania dobrego kontaktu ze społecznością twórców kodu. Symbian nie miał najwyraźniej żadnej z tych rzeczy, a brak pierwszej z nich mogę zresztą potwierdzić osobiście :) Generalnie wrogie (!) nastawienie decydentów do samego pomysłu tworzenia niezależnych aplikacji na tę platformę na pewno nie przysłużyło się w jej dłuższym okresie, co można właśnie teraz obserwować.

Wynika z tego interesujący wniosek: sukces rynkowy rozwiązania takiego jak system operacyjny czy inna platforma programowo-sprzętowa jest ściśle związany z łatwością tworzenia rozwiązań pochodnych (takich jak np. aplikacje), które z nim współpracują. Nie wydaje się to wcale oczywiste, bo przecież z biznesowego punktu widzenia aplikacje można tworzyć na każdej platformie – to głównie kwestia kosztów zatrudnienia odpowiednio wykwalifikowanych programistów, które mogą być przeważone przez późniejsze korzyści. Najwyraźniej jednak nie jest to takie proste, bo istnieje tutaj jakaś nietrywialna zależność… Ciekawe, jaka? :)

W każdym razie można z tego wysnuć optymistyczny wniosek, iż tworzenie bibliotek, platform i API strawnych dla programisty leży w żywotnym finansowym interesie ich twórców. A w związku z tym możemy mieć nadzieję, że liczba tych pierwszych będzie się z czasem sukcesywnie zwiększać.

Tags: , ,
Author: Xion, posted under Programming, Thoughts » 12 comments

Pierwsze kroki w Pythonie

2010-11-06 13:33

Python to już od dłuższego czasu bardzo popularny język do wszelakich zastosowań. Oprócz pisania w nim samodzielnych programów lub aplikacji webowych, jest on też często używany jako język skryptowy rozszerzający możliwości programów, czego chyba najbardziej znanym przykładem jest Blender. Istnieje więc duża szansa, że niezależnie od dziedziny IT, którą się zajmujemy, prędzej czy później przyjdzie nam zetknąć się z tym językiem.
W takim przypadku często dobrze jest wybiec przed szereg i zapoznać się z Pythonem już teraz, co by nie obudzić się potem w wielkim zaskoczeniu ;-) Na szczęście doświadczenie pracy z tym językiem należy raczej do przyjemnych, co oczywiście nie zmienia faktu, że dobrze jest co nieco o nim wiedzieć.

Dlatego też postanowiłem napisać krótką instrukcję paru kroków, które powinny pomóc wszystkim zainteresowanym w rozpoczęciu przygody z Pythonem. Chodzi tu przede wszystkim o przygotowanie kompilatora interpretera, narzędzi pomocniczych oraz środowiska programistycznego. Nie jest to, na całe szczęście, bardzo trudne:

  1. Zaczynamy od zaopatrzenia w sam podstawowy pakiet Pythona, czyli w interpreter i pakiety biblioteki standardowej języka. Jeśli korzystamy z jakiejś użytkownikowo-przyjaznej dystrybucji Linuksa (np. Ubuntu), to pewnie będziemy już takie coś posiadali. W przeciwnym razie wybieramy się na stronę Python.org i wybieramy wersję dla swojej platformy. Jeżeli jest to Windows, to zalecam wybranie wersji 32-bitowej niezależnie od bitowości samego systemu – inaczej możemy mieć problemy ze współpracą z pomocniczymi narzędziami.
    Aktualnie w obiegu są dwie edycje Pythona: seria 2.x i 3.x. W dalszych krokach zakładam używanie serii 2.x głównie ze względu na większą przenośność jej i narzędziowych aplikacji.
  2. Niemal niezbędnym programem pomocniczym przy korzystaniu z Pythona jest easy_install, będący częścią pakietu setuptools. Pozwala on na łatwe instalowanie dodatkowych pakietów, trochę tak jak apt-get na debianowych Linuksach. Jest to bardzo wygodne i skutkuje np. tym, że aplikacje napisane w Pythonie potrafią same rozwiązać swoje zależności podczas instalacji i ściągnąć pakiety wymagane do swojego działania.
  3. Jeśli nie zostało to zrobione za nas, powinniśmy dodać katalog instalacyjny Pythona (zawierający plik wykonywalny interpretera) oraz podkatalog Scripts (zawierający program easy_install) do zmiennej środowiskowej PATH. Ułatwi to między innymi późniejszą konfigurację środowiska programistycznego.
  4. Opcjonalnie możemy zaopatrzyć się w DreamPieshell dla Pythona, który jest o wiele wygodniejszy i potężniejszy niż wbudowany IDLE, że o systemowej konsoli nie wspomnę. Korzystanie z shella jest dość częste; dzięki niemu możemy bezboleśnie sprawdzić działanie funkcji i konstrukcji językowych, używanych w naszych programach.
  5. Wreszcie, czas zaopatrzyć się w środowisko programistyczne, czyli IDE. Tu do wyboru mamy kilka możliwości, zależnie od używanej platformy i preferencji, o czym szczegółowo informuje nas oficjalne wiki. Jeśli przypadkiem używamy już któregoś z dwóch popularnych, uniwersalnych IDE – czyli Eclipse lub NetBeans – możemy użyć wtyczek rozszerzających je o możliwość współpracy z Pythonem (odpowiednio PyDev oraz NBPython). Alternatywą jest użycie samodzielnych IDE do Pythona takich jak PyScripter.

Co dalej? No cóż, to już zależy od tego, do czego chcemy Pythona używać. W celu znalezienie inspiracji możemy na przykład przeglądnąć posortowane tematycznie drzewko dostępnych pakietów i wybrać coś, co nas interesuje. Następnie możemy zainstalować nowe pakiety za pomocą programu easy_install, podając po prostu nazwę paczki, lub ściągnąć je w postaci archiwum i uruchomić skrypt setup.py z parametrem install.
A co zrobić w celu nauczenia się samego języka?… Jeżeli nie odpowiada nam studiowanie samej dokumentacji, możemy spróbować poszukać w sieci odpowiedniego tutorialu, takiego jak np. dostępna za darmo ksiażka Dive Into Python.

Tags: ,
Author: Xion, posted under Applications, Programming » 5 comments

Triki z PowerShellem #17 – Stan baterii

2010-11-02 18:27

Wykonywałem ostatnio skomplikowane akrobacje z bashem, plikiem /etc/rc.local, modułami kernela i innymi linuksowymi wynalazkami, aby uruchomić system spod znaku pingwina na swoim laptopie. Problem leżał w posiadaniu przezeń dwóch kart graficznych, działających w trybie hybrydowym, z których jedna (zintegrowana) działa zawsze, natomiast druga (zewnętrzna) budzi się na żądanie w celu obsłużenia bardziej skomplikowanych aplikacji graficznych i gier. Naturalnie Linux nie jest przygotowany do współpracy z tą technologią. więc o bezproblemowym działaniu X-owych okienek (poza trybem recovery) nie mogło być mowy.
Rozwiązaniem było całkowite wyłączenie zewnętrznej karty i to w niezbyt delikatny sposób, bo poprzez… pozbawienie jej zasilania za pomocą odpowiedniego polecenia modułu acpi. O tym, czy polecenie to faktycznie coś dało, mogłem się natomiast przekonać przy pomocy obserwacji szybkości rozładowywania się baterii, dostępnej w pliku /proc/acpi/battery/BAT1/state i wyglądającej mniej więcej tak:

  1. present:                 yes
  2. capacity state:          ok
  3. charging state:          discharging
  4. present rate:            13634 mW
  5. remaining capacity:      57720 mWh
  6. present voltage:         15947 mV

Tak to właśnie wygląda na systemie, który podobno “po prostu działa” ;-) Żarty żartami, ale powyższy raport nt. stanu zasilania jest zbiorem całkiem interesujących informacji, które byłyby pożyteczne także i w systemie Windows. Pomyślałem więc, czy i tam nie udało by się pozyskać podobnych danych. Odpowiedź – jak można się domyślić – jest oczywiście pozytywna.

Tags: , , , ,
Author: Xion, posted under Applications, Programming » Comments Off on Triki z PowerShellem #17 – Stan baterii

Rozproszone systemy kontroli wersji

2010-10-20 23:10

Z systemami kontroli wersji (w skrócie VCS) zetknął się każdy programista i dla niemal wszystkich jest to oczywiste narzędzie pracy. Dla wielu jednak wciąż jeszcze kojarzą się one z jednym, centralnym miejscem zawierającym zawierającym bazę kodu projektu (czyli repozytorium) oraz z licznymi kopiami roboczymi, nad którymi pracują programiści. Kiedy zaś chcą połączyć swoje zmiany, wówczas wykonują tylko operację znaną jako commit.

Tak jest w systemach typu CVS czy Subversion, ale obecnie sporą popularność zyskały też inne, działające na nieco innej zasadzie. Nazywają się one rozproszonymi (distributed version control system – DVCS) i zgodnie z tym określeniem ich główną cechą jest brak wydzielonego, centralnego repozytorium. Zamiast tego może być ich dowolna ilość, która w rzeczywistych projektach może łatwo urosnąć do setek, a nawet tysięcy. Najczęściej bowiem swoje własne repozytorium ma na przykład… każdy pracujący nad projektem programista.
Obłęd? Niezupełnie. Wszystko opiera się bowiem na operacji synchronizacji dwóch repozytoriów, którą nazywa się – w zależności od punktu widzenia – push lub pull. Push oznacza wprowadzenie poprawek z naszego repozytorium do innego, zaś pull oznacza ściągnięcie zmian z innego repozytorium do własnego. Jak nietrudno zauważyć, operacja ta jest symetryczna. I chociaż techniczne wszystkie repozytoria są równoważne, w praktyce jedno z nich jest zwykle bazą projektu, zawierającą jego “autorytatywną” wersję. Ponadto z każdym repozytorium można też pracować “normalnie”, tj. przy pomocy znanych i lubianych operacji commit i update.


Działanie rozproszonych systemów kontroli wersji

Po co taka zmiana? Przydaje się ona zwłaszcza w dwóch sytuacjach:

  • Dla projektów typu open source umożliwia względnie niezależne opracowywanie poprawek do projektów. W tym celu wystarczy sklonować główne repozytorium, a następnie w spokoju pracować nad uzyskanym kodem, korzystając z jego kopii. Chcąc następie uczynić zmiany obowiązującymi, możemy wykonać push – ale tylko wtedy, jeśli mamy do tego prawa. Jeśli nie, możliwe jest stworzenie łatki (patch), zawierającej nasze modyfikacje i przekazania jej osobie zarządzającej projektem. Ta zaś może – zapewne po przetestowaniu zmian na własnej kopii repozytorium – wprowadzić je wreszcie do bazy kodu. Podobny akceptowania poprawek występował w projektach open source już od dawna, ale dopiero rozproszone systemy kontroli wsparły go od strony technicznej.
  • Jeśli pracujemy wyłącznie lokalnie nad własnymi projektami, możemy stworzyć sobie takież repozytorium, które będzie przy tym jedynym. Nie synchronizujemy wtedy zmian z żadnym innym repozytorium, ale wciąż możemy korzystać ze standardowych funkcjonalności systemów kontroli wersji.

W średniej skali (takiej, jak przedstawiona na obrazku powyżej) systemy rozproszone sprawdzają się natomiast nieco gorzej – zwłaszcza, gdy częstotliwość zmian jest duża. Wówczas często zachodzi potrzeba łączenia (merge) różnych ścieżek tworzenia aplikacji.

Tym niemniej warto się zainteresować tego rodzaju systemami kontroli wersji, by przekonać się, że poza Subversion też coś istnieje :) Przykładami rozproszonych VCS-ów są np. Mercurcial i Git.

Tags: , , , ,
Author: Xion, posted under Applications, Programming » 3 comments
 


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