Posts from 2010

Czas do końca projektu

2010-11-28 15:04

Oszacowanie czasu potrzebnego do wykonania danego projektu to odwieczny problem inżynierii oprogramowania. Być może w ostatnich latach coś się w tym względzie zmieniło, ale jeśli nie, to wciąż pozostaje aktualna sugestia, że najskuteczniejszym sposobem jest po prostu… zapytanie kogoś kompetentnego :) Najwyraźniej wypracowanie jakichś ścisłych i skutecznych metod oceny nakładu pracy i czasu przy tworzeniu oprogramowania jest wciąż poza naszym zasięgiem i trzeba się uciekać do metod typu \pi * drzwi – z naciskiem na drzwi.
Sam mam kilka teorii na temat tego, czemu tak jest. Jedną z nich jest postulat, że do różnego rodzaju projektów należy stosować różne modele przewidujące czas ich trwania. Owych rodzajów jest zaś dokładnie trzy i są to bardzo proste kategorie. Wyróżniam mianowicie projekty zbyt proste, odpowiednie i zbyt trudne. Określenia te odnoszą się – jak można się domyślić – do stopnia trudności danego projektu dla zespołu, który go wykonuje. Nie należy jednak traktować ich zbyt dosłownie ;)

I tak przez projekt zbyt prosty rozumiem taki, którego główne wyzwanie (czyli główna funkcjonalność) jest w gruncie rzeczy łatwe do zrozumienia i zaprojektowania, a co za tym idzie także do zakodowania. Spotykając się z takim zadaniem, możemy bez dużego wysiłku wypracować dla niego rozwiązanie, które wystarczy “tylko” zaimplementować.
Paradoksalnie jednak tutaj mogą zacząć się schody. Kiedy główny problem jest już za nami, i to bardzo szybko, motywacja do kontynuowania prac spada. Mimo że zwykle pozostaje jeszcze sporo do zrobienia, nie są to już czynności wymagające dużego wysiłku intelektualnego, więc często mogą być po prostu nudne. Tempo sukcesywnie więc spada w miarę zbliżania się do końca.

Dokładnie odwrotnie jest z kolei w przypadku projektów zbyt trudnych. Gdy główny problem jest tak skomplikowany, że przez długi czas nie wiadomo, jak właściwie się do niego zabrać, postęp prac jest nikły. W pewnym momencie jednak (miejmy nadzieje) przychodzi olśnienie – albo raczej seria mniejszym “eurek” – i od tego momentu wszystko nabiera bardzo dużego przyspieszenia. I nawet po rozwiązaniu głównego problemu nie musi ono wcale zwalnia, lub inaczej: nawet jeśli zwalnia, to efekt ten nie jest łatwo zauważalny w skali czasowej całego przedsięwzięcia.

Trzecia kategoria leży natomiast pośrodku między dwiema powyższymi. Projekt jest odpowiedni, jeśli przez cały czas trwania prezentuje mniej więcej podobny poziom trudności dla zespołu, który go wykonuje. Oznacza to, że jego główny problem daje się rozwiązać systematycznie i sekwencyjnie, nie zaś prawie automatycznie (w przypadku projektów zbyt łatwych) lub tylko za pomocą nagłego odkrycia (jak w przypadku projektów zbyt trudnych).

Tym trzem kategoriom projektów możemy przypisać krzywe określające poziom zaawansowania prac w zależności od czasu. Nietrudno jest zauważyć, że dla przedsięwzięć zbyt łatwych będzie to funkcja logarytmiczna, dla zbyt trudnych – wykładnicza, zaś dla odpowiednich będzie ona zbliżona do linii prostej:

Jeśli umiemy rozpoznać, do której z tych trzech kategorii należy nasz projekt, to niewykluczone, że możemy spróbować uniknąć niektórych pomyłek przy szacowaniu czasu pozostałego do końca projektu. Dla projektów zbyt łatwych można na przykład łatwiej niż zwykle ulec złudzeniu planowania i nie docenić czasu pozostałego do końca prac, kierując się tym, iż na początku “idzie jak z płatka”. Dla zbyt trudnych można natomiast błędnie ekstrapolować początkowe trudności w przyszłość i wnioskować, że projekt będzie trwał całe lata (podczas gdy może trwać miesiące lub… dekady, w zależności od tego, kiedy nastąpi “olśnienie”).

Najważniejszym wnioskiem – jeśli moje przemyślenia są prawdziwe – jest jednak korzyść, jaką daje zapewnienie, by projekt był odpowiedni. Wówczas szansa na wiarygodne oszacowanie pozostałego czasu jest znacznie zwiększona, bo mówimy wtedy o ekstrapolacji funkcji w przybliżeniu liniowej. Żeby jednak móc korzystać z tej pożytecznej cechy, musimy postarać się o odpowiednie dobranie zespołu do zadania… lub odwrotnie :)

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

le srana be la lojban. be’o poi mi na nelci

2010-11-13 21:45

…czyli co mi się w lojbanie nie podoba.

Moje poprzednie notki o lojbanie mogły pozostawić wrażenie, iż przedstawiam go bardzo jednostronnie, celowo pomijając jego wady. Nawet jeśli tak nie było, to siłą rzeczy nie mogłem dotąd poświęcić wystarczająco dużo miejsca różnego rodzaju niedoskonałościom, od których język ten – jak każdy wytwór człowieka – nie jest wolny. A jest ich pewna ilość warta uwagi i nie mam tu wcale na myśli postękiwań z gatunku “przecież to w ogóle jest totalnie bez sensu” :P Mam raczej na myśli uprawnioną krytykę, wskazującą na rozbieżności między założeniami a realizacją. Do tego zaś pożytecznie byłoby wpierw te założenia przypomnieć.
Zgodnie z tym co można przeczytać na oficjalnej stronie lojban.org, język lojban:

  1. został zaprojektowany tak, by być kulturowo neutralny
  2. ma jednoznaczną gramatyką opartą na zasadach logiki
  3. ma fonetyczną ortografię, pozwalającą jednoznacznie zdekodować ciąg dźwięków jako słowo
  4. w porównaniu do naturalnych języków jest prosty i łatwy do nauki
  5. posiada 1300 słów źródłowych, które można łączyć tworząc miliony słów pochodnych
  6. jest regularny i jego zasady nie mają wyjątków

Powyższa lista nie jest nawet kompletna (usunąłem z niej punkty w oczywisty sposób niemal sprawdzalne, jak choćby potencjalne zastosowania języka), a i tak wydaje się niezwykle ambitnym zestawieniem feature‘ów. Czy ma ona odpowiednie pokrycie w rzeczywistości? Zobaczmy więc.

Tags: ,
Author: Xion, posted under Culture » 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
 


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