Nov 4 2009

Mysql i Snow Leopard

Po aktualizacji systemu do MacOS X 10.6 (Snow Leopard) zauważyłem, że nie startuje moja baza danych Mysql. Sprawdziłem ręcznie co jest nie tak:

cd /Library/StartupItems/MySQLCOM
sudo ./MySQLCOM start
Could not find MySQL startup script!


aha! Poszedłem więc do /usr/local i zrobiłem link symboliczny
sudo ln -s mysql* mysql
Po ponownej próbie uruchomienia bazy danych otrzymałem komunikat:
Starting MySQL database server
Czyli wszystko ok.


May 4 2009

Matura

Żwawy żuczek z żółtym brzuchem żwawo z życiem
żuł rzeżuchę. Wtem żółw, drobiąc nóżką,
bieży po żywności zapas świeży. Żuczku, żaczku,
żwawe dziecię, zmykaj chyżo, bo żółw zje cię.
Żuk już żagle chciał rozpostrzeć, gdy marudę żółwia
spostrzegł, co wysiłek czyniąc duży, żmudnie
grzebał się w kałuży. Zżarł rzeżuchę żuk niecnota,
a żółw grzebie się wśród błota.

Dziś matury – tradycyjnie rozpoczynają się od języka polskiego. Jak sobie przypomnę, że od mojej minęło już 13 lat…. ;) .

Wszystkim maturzystom, życzę połamania piór.


Apr 1 2009

Prima Aprilis w IntelliJ IDEA

Dzisiaj podczas pisania kodu w JSF, po użyciu często używanego skrótu podpowiadającego składnię zauważyłem coś dziwnego. Poza standardową listą atrybutów możliwych do użycia zobaczyłem na końcu listy napis: “Don’t be lazy, type it yourself”.

screen2Nieźle się uśmiałem. Zacząłem ostro klikać Ctrl+Space i poczytałem sobie więcej takich perełek, np.

“Just relax”

“Not so fast”

“Are you sure?”

“Don’t panic”

“And why did you do that?”

“Code completition might be insuitable for children under 7″

“Please type slower, I can’t keep up with you”

i wiele wiele innych :)


Mar 9 2009

Confused with Ranges

Fajną nowością w języku Groovy, w porównianiu do języka Java są Ranges. Jest to kolekcja ( a dokładnie wyjasniając implementuje interfejs java.util.List ), która definiuje zasięg kolekcji – początek i koniec. Oznacza się go oddzielajac dwoma kropkami pierwszy element od ostatniego, np. 1..3 zawiera kolekcję liczb od 1 do 3 (włącznie), a 1..<3 zawiera kolekcję liczb od 1 do 3 (nie wliczając 3). Problem jest właśnie ze zrozumieniem jak działa ten znak miejszości.

Mamy na przykład w kodzie tablicę:

 1 def a = ['a', 'b', 'c', 'd', 'e']

Elementy posiadają indeksy od 0 do 4, jednak w groovym dodatkowo posiadają indeksy od -5 do -1 .

   a  b  c  d  e
   0  1  2  3  4
  -5 -4 -3 -2 -1

Dodatkowe indexy służą m.in. do pobierania elementów tablicy od końca.

 1 assert a[0] == 'a'
 2 assert a[-5] == 'a'

Możemy pobierać elementy tablicy za pomocą Range:

 1 assert a[0..3] == ['a', 'b', 'c', 'd']

lub w odwrotnej kolejności:

 1 assert a[-1..-5] == ['e', 'd', 'c', 'b', 'a']

Teraz porównywanie ‘do’:

 1 assert a[0..<3] == ['a', 'b', 'c']

nie wlicza 3 do zasięgu, więc są wypisane elementy o indeksach 0, 1 i 2.
Jak to się ma przy indeksach ujemnych? Sprawdźmy:

 1 assert a[-5..<-3] == ['a', 'b']

zasięg bierze indeksy DO 3 więc zaczynając od pierwszego -5 na -4 kończy. Czyli wszystko tak jak powinno.

Teraz zagadka:

biorąc pod uwagę, że elementy tablicy posiadają indeksy tak jak wyżej podano:

   a  b  c  d  e
   0  1  2  3  4
  -5 -4 -3 -2 -1

Które elementy posiada subtablica a[0..<-3] ?

Logicznie rzecz biorąc index mniejszy od -3 = -4 . więc subtablica powinna zwierać elementy ‘a’ (index początkowy 0) i ‘b’ (indeks -4). Jednak wynik jest inny:

 1 assert a[0..<-3] == ['a', 'b', 'c', 'd']

Jak to interpretować? Otóż we wszystkich podanych wyżej (oprócz ostatniego) przykładach początek zasięgu był mniejszy od końca ( a < b ). W ostatnim, początek jest większy od końca ( 0 > -3). Groovy zatem interpretuje taki zasięg jako odwrotny i znak mniejszości faktycznie również odwraca i traktuje jako znak większości. Czyli w powyższym przykładzie podaje jako koniec zasięgu index większy od -3 czyli -2. Z tego powodu mamy taki wynik.

Tak samo będzie w przypadku:

 1 assert a[4..<1]  == ['e', 'd', 'c']

Feb 28 2009

dobry kod – na skróty

Każdy kiedyś uczył się pisać. Najpierw rysując szlaczki aby opanować kontrolę nad dłonią, potem literka za literką cały alfabet. Gdy już się nauczyliśmy – charakter pisma wyrabiał się wraz z ilością zapisanego tekstu. Jednak niektórzy starali stawiać równe, okrągłe literki, starali się robić równe odstępy między wyrazami. Tak długo, aż mieli ładny, czytelny charakter pisma. Ale nie wszyscy się starają – większość pisze tak jak leci.

Tak samo jest z programistami. Gdy nauczą się podstaw programowania – nabierają doświadczenia poprzez pisanie programów i…. to wszystko. Pisanie programów w stylu: „ważne, że działa” i doświadczenie jedynie poprzez własnoręcznie napisany kod. Ale nie każdy taki jest. Niektórzy chcą pisać dobry kod – starają się, uczą nowych rzeczy, analizują inne programy, aby zobaczyć jak piszą inni. Dążą do pisania kodu w jak najlepszym stylu.

Jak jednak wygląda dobry kod? Jak się go pisze? Czterowersem z rymem naprzemiennym?

Jak można ocenić, że kod jest dobry?

Przez tyle lat gdy na świecie są komputery narodziło się mnóstwo autorytetów z dziedziny programowania. Powstały też kanony, standardy i przede wszystkim dobre style programowania. Po tych wszystkich latach można także ocenić który kod jest dobrze napisany.

Przede wszystkim program powinien być bardziej przemyślany niż napisany. Czym więcej czasu poświęcimy na projektowanie i analizę, tym więcej czasu zaoszczędzimy na programowaniu.

Przed przystąpieniem do pracy na programem powinniśmy wiedzieć co, gdzie i jak powinno w programie funkcjonować. Które klasy powinny znaleźć się w programie, co powinny wykonywać i jak się nazywać, a także z którymi innymi klasami powinny być połączone.

Na samym początku powinniśmy zadać sobie pytanie CO ten program (lub pojedynczy moduł programu) powinien robić lub CZYM powinien być. Musimy się zastanowić jakie warunki program musi spełniać aby dobrze działał – czyli wykonywał to co powinien. Pamiętaj: niezależnie gdzie pracujesz, jakie oprogramowanie tworzysz oraz jakiego języka programowania używasz – jednego możesz być pewien: wymagania się zmieniają. Dobrze napisany program pozwoli nam na szybkie zmodyfikowanie i dostosowanie programu do nowych wymagań.

Powinniśmy napisać przypadki użycia. Są to napisane krok po kroku działania programu. Może to bardzo pomóc przy projektowaniu programu. Analizując później tak sporządzony przypadek użycia – możemy rzeczowniki w nim użyte uznać jako klasy a czasowniki jako metody.

Nazwy klas powinny jednoznacznie wskazywać czym klasa jest, a nazwy metod – jakie czynności wykonują. Każdy obiekt reprezentuje jedno pojęcie (przynajmniej powinien). Nie używa się obiektów realizujących dwa lub więcej obowiązków. Jeżeli przeglądając właściwości obiektu znajdujemy właściwości o wartości null lub w ogóle nie wykorzystywane, to może oznaczać, że obiekt pełni kilka ról. Jeżeli takie właściwości istnieją, a jesteśmy pewni, że obiekt pełni tylko jedną rolę w systemie to nieużywane właściwości powinniśmy wywalić do oddzielnej klasy. Cały kod który może ulec zmianie oddzielamy od tego który nie ulegnie zmianie. Takie działanie nazywa się hermetyzacją.

Jeżeli wydzielimy to, co może się zmienić, a potem faktycznie się zmieni – a zmiany które to spowoduje będziemy musieli dokonać w klasach innych niż wyodrębniona – to oznacza, że hermetyzacja jest źle wykonana.

Obiekt powinien mieć tylko jedno zadanie a wszystkie usługi powinny się koncentrować na jego realizacji. Bardzo łatwo sprawdzić czy ta zasada jest zachowana. Wystarczy dla każdej metody utworzyć zdanie gdzie nazwa metody jest czasownikiem, nazwa klasy podmiotem a obiekty podane jako parametry metody mogą służyć jako dodatkowe rzeczowniki (chyba że parametr jest nieistotny bo np. tylko zmienia ilość lub szyk). Gdy metoda jest bez parametrów dodajemy „się”(może być w domyśle, chodzi o to, że metoda wykonuje czynność na samym sobie). Jeżeli utworzone w ten sposób zdanie łamie sens jego rzeczywistego odpowiednika to zasada jednej odpowiedzialności jest złamana. Np. klasa Obiad posiadająca metody: liczbaKalorii(), podajSkład(), ugotuj(). Porównując klasę do rzeczywistego obiektu obiad wiemy, że obiad jest w stanie podać SWOJĄ liczbę kalorii albo SWÓJ skład, ale SAM SIĘ NIE ugotuje. Więc metoda ugotuj() łamie tę zasadę. Obiad gotuje kucharz, czyli Kucharz.ugotuj(Obiad).

Analiza ta jednak w dużej mierze zależy od znajomości systemu. Np. w powyższym przykładzie metody Kucharz.ugotuj(Obiad) jest zgodna z zasadą jednej odpowiedzialności. A metoda Kucharz.ugotuj()? Czy jest zgodna? Na pierwszy rzut oka nie jest. Nie ma logicznego sensu aby kucharz SAM SIEBIE gotował. Jednak system może być zaprojektowany tak, że każdy obiad ma swojego kucharza i obiekt Obiad jest przekazywana obiektowi Kucharz jako parametr konstruktora. Zatem metoda ugotuj() wie, którego Obiadu użyć i nie potrzebuje go jako parametru. Mając tą wiedzę – czy dalej twierdzimy, że metoda Kucharz.ugotuj() łamie zasadę jednej odpowiedzialności? Pamiętaj, że ocena o odpowiednim stosowaniu zasad ( lub ich łamaniu) jest wysoce zależna od znajomości systemu.

W naszym programie powinniśmy także odpowiednio zadbać o relacje między klasami. Rodzajów tychże nie ma dużo: dziedziczenie, implementacja lub asocjacja.

Z dziedziczeniem jest pewien problem. Dziedziczenie (czy też zgodnie z UML – generalizacja) powinno być wykonane w ten sposób aby była możliwość podstawienia typów pochodnych w miejsce ich typów bazowych (Zasada paradygmatu Liskov’a). Dziedziczenie w celu rozszerzenia funkcjonalności niesie za sobą ryzyko, że klasy pochodne nie będą potrzebne do ich działania i nie będą potrafiły tych metod zaadoptować. W takich sytuacjach należy poszukać innych rozwiązań, np. delegacja(jedna z grupy asoocjacji) lub kompozycja.

Kompozycja to jest używanie interfejsów. Z tym, że nie chodzi tylko o słowo kluczowe interface ale także klasy abstrakcyjne. Kompozycja pozwala stosować zachowanie udostępnione przez rodzinę innych klas i zmieniać to zachowanie w trakcie działania. Określamy w obiekcie, którym interfejsem jesteśmy zainteresowani (który realizuje niezbędne operacje) a w jego miejsce podsyłać klasy, które ten interfejs implementują. Stosują kompozycję nie jesteśmy uzależnieni od konkretnej implementacji. Kod jest elastyczny na rozszerzanie bo można utworzyć nową klasę o tym interfejsie i ją podstawić. Używając interfejsów a nie klas które je implementują pozwoli na napisanie kodu dla klas, które nawet jeszcze nie istnieją. Kompozycja jest dobrym sposobem aby program był otwarty na rozszerzanie i podatny na zmiany, co jest bardzo ważne: powinniśmy starać się powodować aby raz napisany kod nie był modyfikowany. Jednocześnie napisać go tak aby szło go rozszerzyć, jeżeli nie przez kompozycję to np. przez dziedziczenie.

Nie ma lepszego sposobu na sprawdzenie czy pogram jest odporny na zmiany niż sama zmiana.

Innym typem relacji jest asocjacja, która oznacza zależność jednej klasy od drugiej. Utworzenie obiektu klasy A w obiekcie klasy B jest asocjacją. Są dwa główne rodzaje asocjacji: delegacja i agregacja. W delegacji obiekt który ma wykonać pewną czynność nie wykonuje jej, ale przekazuje jej wykonanie do innej klasy. W agregacji jeden obiekt jest częścią drugiego, np. obiekt Adres jest częścią obiektu Pracownik.

Częstym problemem jest nie odróżnienie kiedy używać agregacji a kiedy kompozycji. Agregację wykorzystujemy wtedy, gdy obiekt agregowany istnieje poza obiektem agregującym, jako oddzielny byt. Jeżeli obiekt agregowany nie musi mieć własnego bytu – używamy kompozycji.

Kolejną ważną zasadą jest unikanie powtarzania kodu. Najłatwiej tego dokonać poprzez wyodrębnienie wspólnych fragmentów i umieszczenie ich w jednym miejscu. Czyni to kod łatwiejszym w utrzymaniu i przy ewentualnych zmianach. Chodzi tu także o to, aby nie powtarzać funkcjonalności w kilku miejscach. W takim przypadku trzeba przenieść kod dotyczący tej funkcjonalności w jedno miejsce. Jednym słowem: należy się starać, aby każda informacja i operacja była tylko w jednym miejscu.

Pracując z dużym programem koncentruj się tylko na jednej możliwości naraz. Nie pozwól się zdekoncentrować i nie zajmuj się innymi możliwościami. Najpierw należy się skupiać na głównych funkcjonalnościach programu. Potem – wchodząc w głąb – programujemy kolejne funkcjonalności jedną po drugiej tak długo, aż będą napisane wszystkie z tego poziomu. Potem piszemy bardziej szczegółowe i tak dalej.

Drugą szkołą jest skupianie się na przypadkach użycia. Tworzymy scenariusz przejścia przez aplikację i piszemy kod aby ten scenariusz obsłużyć. Potem kolejny (inny) scenariusz i kod. Tak długo aż scenariuszami opiszemy wszystkie funkcjonalności programu.

Opanowanie tych zasad pomoże zaznajomienie się z wzorcami projektowymi – co i moim zdaniem jest wielce zalecane.

Mam nadzieję, że teraz pisany kod będzie prześliczny a jeszcze bardziej elastyczny :D – po prostu dobry kod.


Jan 13 2009

Plany na rok 2009

Zeszłoroczne plany zrealizowałem z około 70%, więc nie jest tak źle. Na ten rok też sobie kilka rzeczy postanowiłem i będę dążył do ich realizacji. Z zawodowych planów na pierwszym miejscu są Design Patterns i TestNG. Chcę pisać czysty kod i pokrywać go testami co najmniej w 90% ( o ile się da oczywiście). Będzie to mój osobisty wkład w rozwój umiejętności programowania. Jeżeli zostanie trochę czasu (którego i tak mam mało :D )- zajmę się Groovy’m no i może uda się w tym roku zdać SCJP? Zobaczymy… Dwa pozostałe cele pozostaną w tajemnicy. Chciałbym także zrealizować chociaż jeden ze swoich projektów… Zobaczymy co nam ten rok przyniesie.


Aug 21 2008

Złota myśl dnia

W teorii nie ma żadnej różnicy między teorią a praktyką – w praktyce jest.