Tuesday, December 30, 2008

Jak pisać dobre oprogramowanie?

Dziś troszkę o standardach i zasadach tworzenia dobrego oprogramowania. Zadziwiające jak niewielu ludzi je zna.
  1. Jeśli używasz daty - zawsze używaj formatu daty zgodnego z ISO-8601. Jeśli nie znasz normy to nie wiesz jak zapisywać daty. Norma podaje również powody dla których należy z niej korzystać. I jest międzynarodowa. Po prostu - przeczytaj, ucz się i nie popełniaj błędów które inni popełnili.
  2. Jeśli tworzysz programowanie w językach wysokiego poziomu - używaj wzorców projektowych. Nie wiesz czym one są? To jakby zasady gramatyczne. Możesz znać litery nie umiejąc pisać. Możesz nawet umieć pisać nie znając gramatyki/ortografii (i robić błędy). Możesz też używać wzorców programistycznych/projektowych.
  3. Myślisz że wiesz coś na pewno? Poczytaj standardy - zapewne zmienisz zdanie. Poczytaj standardy - warto.
  4. Jeśli coś robisz - staraj się to robić dobrze. Nie najlepiej jak jest to możliwe - ale najlepiej jak możesz w danej sytuacji.
  5. Myślisz że coś robisz dobrze... więc sprawdź czy ktoś nie robił tego tak samo przed tobą. I nie popełnił tych samych błędów, które właśnie zamierzasz popełnić.
  6. Nie traktuj tych porad jako wiedzy absolutnej - ja się ciągle uczę nowych rzeczy.

Sunday, December 21, 2008

Dynamiczne definiowanie typów w PL/SQL

Ostatnio natknąłem się na pewien paskudny problem. Chciałem zdefiniować procedurę korzystającą z DBMS_UTILITY.FORMAT_CALL_STACK. Ta funkcja stworzona przez Oracle zwraca typ VARCHAR2(2000) (przynajmniej tak mi się wydaje). Zgodnie z dokumentacją Oracle tak ma właśnie być.
A teraz zastanówmy się nad definicją typów jakiej powinno się używać w PL/SQL:
nazwa tabela.kolumna%TYPE;
Zapewnia to elastyczność jeśli typ tabela.kolumna się zmieni (np. zmienimy go z VARCHAR2(10) na CLOB). Ale... przecież nie wiemy jak się odwołać do tego typu - Oracle nie daje nam tej informacji!
Wniosek: Kod Oracle nie jest elastyczny. Każdy programista PL/SQL jest skazany na nieelastyczność ponieważ korzysta z nieelastycznej bazy danych.

Reklamy na gazeta.pl

Otwieram dzisiaj stronę portalu gazeta.pl i co widzę? Nic nie widzę. Poza reklamami zasłaniającymi mi cały ekran. Całe szczęście, że moja przeglądarka nie wyświetla flasha - bo wtedy nie mógłbym nic zrobić przez kilka sekund zanim reklamy się załadują...
Brawo gazeta.pl.
Gadu-gadu kiedyś też tak robiło - pamiętam płacze współpracowników "mój komputer nie działa" i po kilku resetach komputera "to jakaś reklama gadu się wyświetla i zabija komputer" :)

Thursday, November 13, 2008

Oracle, cz. 3

Wygląda na to, że w ciągu niespełna 6 miesięcy zostałem zakwalifikowany do rangi speca od oracla. Nie wiem czy cieszyć się że jestem taki cudowny (i skromny), czy też płakać że poziom innych ludzi jest taki niski.
Na dzisiaj kilka praktycznych porad dotyczących nazewnictwa zmiennych w PL/SQL (best practices for PL/SQL).

W PL/SQL często tworzymy kod, który jest zawiły. I tworzymy go jeszcze bardziej zawiłym. Dzieje się tak dlatego, że jest to język najwyraźniej stworzony przez nie-programistów (chociaż programiści też mieli w przy spory udział). Spotkałem się z kilkoma konwencjami, ale mi najbardziej przypadły do gustu następujące:

l_* : zmienne lokalne
g_* : zmienne zdefiniowane na poziomie paczki (głównym poziomie kodu)
c_* : stałe
*_curh : uchwyty do kursorów (gdy używam DBMS_SQL)
*_cur : kursory
*_i : iteratory (przy niejawnym ich tworzeniu, tj. FOR zmienna_i IN 1..10 LOOP NULL; END LOOP;)
*_ri : iteratory wierszowe - jak wyżej ale dla listy typu "select", gdzie obiekt jest typu %ROWTYPE
*_str : jeśli mam zmienne typu VARCHAR2 i chcę dodatkowo oznaczyć, że są to stringi

Słowa kluczowe piszę zawsze kapitalikami (tj. wielkimi literami).
Nazwy zmiennych staram się pisać małymi literami.
Nazwy kolumn, table, itp. staram się zaczynać wielką literą i używać tzw. "Camel Notation".
Przez pewien czas starałem się używać wielkich liter do oznaczenia wszystkiego, co jest dla mojego kodu "zewnętrzne". Ta zasada sprawdza się do momentu, gdy coś "zewnętrznego" staje się naszą implementacją, lub coś naszego wyrzucamy na zewnątrz.

Procedury, wyjątki, funkcje - nie mają żadnych przedrostków ani przyrostków. Ich nazwa ma tłumaczyć co robią.

Komentarze: Pisz jak chcesz ale zawsze komentuj dlaczego, nigdy "jak".

Sunday, October 19, 2008

Windows Vista - czy warto?

Miałem jakiś czas temu okazję pobawić się vistą. Nie poraz pierwszy zresztą. No i potwierdziłem swoją opinię o tym systemie.

WSTĘP (nudne, pomiń ten akapit):
Powiedzmy to otwarcie: Programiści, którzy stworzyli windowsa vistę spartolili kilka spraw.
Ale jak to możliwe? Wiem już, że z oprogramowaniem tak jest często. W korporacjach są ludzie od cięcia kosztów, ludzie od organizacji pracy, ludzie od promocji produktu, projektanci i robole-programiści. Do tego testerzy i inni.
Ale czy to tylko programiści? Nie - to nigdy nie jest wina jednej ze stron.
Ci od cięcia kosztów skroili je zbyt mocno (dlatego w korporacjach trwa ciągła walka między nimi a pozostałymi szczeblami).
Ci od projektu nigdy nie są w stanie wszystkiego przewidzieć i zawsze robią błędy (dlatego zawsze powinni poprawiać projekt w trakcie tworzenia).
Ci od tworzenia oprogramowania na pewno też nie wszystko zrobili najlepiej - mieli zbyt małe kwalifikacje (dzięki temu są tani i dostali pracę) lub dano im zbyt mało czasu.
Menadżerowie nie rozumieją (albo nie chcą zrozumieć), że projekt trzeba zmieniać (a to wymaga znowu programowania).

ROZWINIĘCIE:
- W XP poziom bezpieczeństwa był zbyt niski - popracowano nad tym. W efekcie system Vista jest natrętny i wkurza ciągłymi pytaniami (uważam, że ta funkcjonalność byłaby świetna - gdyby jej nie z***no).
- W XP system wyglądał ładnie i to przekonało część klientów - dlatego vista jest ładniejsza. Ale warto by się zastanowić czy komputer ma być ładny, czy funkcjonalny => jeśli ma być ładny i funkcjonalny to kup Mac'a.
- W Viście spece od marketingu kombinowali jak zarobić więcej - dlatego aby zainstalować sterowniki - muszą być one podpisane cyfrowo przez Microsoft. A to kosztuje - kasę zgarnia Microsoft. Problem: Przez to (i nie tylko) trudno o sterowniki do visty.
- W Viście obcięto funkcjonalność i dodano kilka bajerów za potworną kasę - dzięki temu powstało kilka wersji visty. Tylko czy warto wydać kilka setek $ za odrobinę łądniejsze okienka?
- W Viście dorzucono szyfrowanie dysków (tylko droższe wersje visty). Ale przecież są inne sposoby na osiągnięcie tego samego celu - a do tego lepsze niż ten bit-locker.
Powyżej nie ma nic na korzyść visty.... ale może coś jednak jest w niej fajnego?
- Otóż jest! Spece od marketingu stwierdzili że ich gniot się nie sprzedaje. Aby zwiększyć sprzedaż - biblioteki graficzne DirectX wyszły tylko pod vistę - ale nie pod XP. Oficjalnie architektura XP na to nie pozwala (czyli oficjalnie powinni powiedzieć "spi*liśmy XP"). Ale jakoś w to nie wierzę...
- 64 bity! Ejże... przecież był XP 64. Czyli nic nowego. Poza tym pod 64 bitową vistą wszystko działą jeszcze wolniej niż pod 32-bitową.

ZAKOŃCZENIE:
XP jednoznacznie wygrywa z vistą (pomimo niedociągnięć) - został jednak wykluczony z walki przez sędziów (spece od marketingu) czyniąc Vistę zwycięzcą.

POSŁOWIE:
Po-słowie - nie chodzi mi o nierobów polityków (choć nie wszyscy z nich są nierobami), tylko o to, co się dodaje po zakońćzeniu części właściwej.
Odpowiem (przynajmniej spróbuję odpowiedzieć) poniżej na 3 pytania:
(1)Dlaczego jest tak niewiele oprogramowania 64-bitowego? (2)I dlaczego jest ono wolniejsze? (3)Na co komu 64-bity?

(3) Bez wdawania się w szczegóły - systemy 32-bitowe bez problemu dają radę z niecałymi 4 GiB pamięci. Nie oznacza to jednak, że obsłużenie większej ilości pamięci nie jest możliwe.
Niewiele jest aplikacji wykorzystujących tyle pamięci. Są to zazwyczaj gry i skomplikowane aplikacje obliczeniowe. Zazwyczaj jednak możnaby bez problemu przepisać takie oprogramowanie tak, aby działało na mniejszej ilości pamięci. Problem w tym, że programista woli zrobić tandetę na szybko, ale za to często, niż jedną perłę w życiu - ale za to przez cały swój żywot nie mieć kasy na życie.

(2) Dlaczego 64-bity są wolniejsze?
i od razu
(1) Dlaczego jest tak niewiele oprogramowania 64-bitowego?
W programowaniu używa się wskaźników do miejsc pamięci. To tak jak np. numer telefonu.
32-bitowy wskaźnik jest mniejszy niż 64-bitowy.
Tak samo, jak wybranie/zapisanie numeru telefonu składającego się z 4 cyfr jest szybsze i zajmuje więcej miejsca niż wybranie/zapisanie 8-cyfrowego numeru - tak samo operowanie na takich wskaźnikach może być wolniejsze i wymaga więcej miejsca w pamięci.
Teraz niespodzianka - w systemach 64-bitowych (w zasadzie mówi się o architekturze x86_64) wszystko działa szybciej. Problem w tym, że na x86_64 można uruchomić oprogramowanie 32-bitowe. Po co więc robić osobno plik na 32 i 64 bity jak wystarczy jeden? A jak się tworzy oprogramowanie 64-bitowe to zazwyczaj wstarczy ten sam kod (32-bitowy) wykorzystać aby zrobić coś 64-bitowego.
Tutaj rodzi się problem - rezygnujemy z części przyspieszenia które daje nam x86_64. Ale skoro na pierwszy rzut oka nie widać różnicy to po co przepłacać za tworzenie oprogramowania? Tak przynajmniej myślą wielkie firmy tworzące to oprogramowanie.

Jest jeszcze jedna sprawa. Sterowniki na 64-bity (jeśli w ogóle są) - nie są tak dopracowane jak te na 32-bity. Dlatego cały system jest wolniejszy.

Jeśli ktoś to przypadkiem czyta to serdecznie pozdrawiam :)

Thursday, October 2, 2008

Oracle, cz. 2

Dzisiaj napiszę o czymś, co mnie nieco zakręciło i jest związane z agregacją.
Już jakiś czas temu korzystałem z funkcji MAX oraz GREATEST. Ale aż do dzisiaj nie miałem z nimi problemu.
W najprostszym przypadku można korzystać z nich zamiennie. Ale czasem różnice są znaczące.
Wyobraź sobie tabelę zawierającą pojedynczą kolumnę Col1 z liczbami od 1 do 9. Zapytanie SELECT MAX(Col1),GREATEST(Col1) FROM ... powinno zwrócić te same dane (ale nie sprawdzałem tego).
Jeśli chcesz znaleźć największą wartość w kolumnie - użyj MAX.
Jeśli chcesz dorzucić kolumnę zawierającą największą z wartości - użyj GREATEST.
Przykład:
INSERT INTO T VALUES (1,2,3),(5,6,2),(8,2,2)
SELECT Day1,Day2,Day3,GREATEST(Day1,Day2,Day3) FROM T
Otrzymasz wiersze (1,2,3,3),(5,6,2,6),(8,2,2,8)
SELECT MAX(Day1),MAX(Day2),MAX(Day3) FROM T
Otrzymasz wiersz (8,6,3)

A z czym miałem dzisiaj problem?
SELECT Col1, GREATEST(MAX(Day1), MAX(Day2), MAX(Day3)) Maximum FROM T GROUP BY Col1
Tutaj słowo wyjaśnienia: GROUP BY jest zbliżone do PARTITION BY (to drugie daje większe możliwości). Pozwala ono wykonać operację "SELECT Col1,MAX(Col2) FROM T GROUP BY Col1" - jak zapewne widzisz - chcę otrzymać wartości wkolumnie Col1. Dzięki GROUP BY otrzymam między 0 a n wierszy (gdzie n to ilość wierszy w tabeli T). Jeśli wartości w kolumnie Col1 się powtarzają - zostanie z nich wybrana największa. Inaczej mówiąc: podziel tabelę na grupy i wykonaj operację MAX/SUM/etc. na każdej grupie osobno.
Teraz wyjaśnienie mojego problemu: chciałem otrzymać kolumnę zawierającą największe z maksimów. Niestety Oracle nie poradzi sobie z tak nielogicznym zapytaniem: nie wiadomo czy do grupowania się tyczy funkcja MAX, czy też GREATEST (chciałem najpierw MAX a później GREATEST).
Rozwiązanie , które znalazłem, jest proste:
SELECT Col1, GREATEST(Max1,Max2,Max3) FROM ( SELECT Col1, MAX(Day1) Max1,MAX(Day2) Max2, MAX(Day3) Max3) FROM T GROUP BY Col1)

Tuesday, September 30, 2008

Czas na OpenGL :)

Miałem do czynienia z DirectX za czasów DX7. Pamiętam, że z DX8 były problemy (Microsoft Visual Studio się wywalało przy kompilacji i trzeba było ściągać/instalować nową wersję). A z OpenGL... problemów nie było :)

Dlaczego OpenGL? Dlaczego nie DirectX?
Wydajność podobna.
DirectX jest nieprzenośny - ale przyjemny w implementacji.
OpenGL jest przenośny - ale mniej przyjemny w implementacji. Czyżby?
DirectX jest bardziej obiektowy. Jeśli nie używamy klas - wybieramy OpenGL.
DirectX wymaga sprzętu. Jeśli chcemy aby nasz kod można było odpalić bez najnowszej karty graficznej XXX model 999999 - wybieramy OpenGL.
Jeśli chcemy stworzyć małym kosztem grę dla Windows/XBox - wybieramy DirectX.
To tylko wierzchołek góry lodowej :D

Jak?
Właśnie czytam najnowszą specyfikację jeszcze nie zaimplementowanego OpenGL 3.
OpenGL nie ma wbudowanej obsługi plików ani podobnych. Wymaga nieco więcej pracy. Ale w zamian daje większą kontrolę.
Istnieją biblioteki GLU, GLUT, GLX. Dają... sporo. Ale można się obejść i bez nich.
Zaleta (?) OpenGL to nie-klasowy interfejs. Wywołujemy procedury/funkcje i tyle.
W DirectX tworzymy interfejsy, klasy, rozszerzamy je.... i gubimy się w klasach jeśli nie mamy języka obiektowego (np. MASM32).
Za czasów DX8 należało stworzyć interfejs DX5, później DX6, później DX, DX8.... koszmar. Ale poprawili się.
A OpenGL... on działa :)

Brak ci wiedzy i umiejętności? Zacznij z OpenGL - start jest łatwiejszy.

Masz wiedzę i umiejętności? Baw się z DirectX.

Masz duże wiedzę i umiejętności - wróć do OpenGL - daje możliwości takie same jak DirectX, lecz jest przenośny i fajniejszy.

W planach mam jakiś krótki tutorial o OpenGL. Na razie sam czytam i uczę się. Ale może kilak drobiazgów.

1. Aby zachować aktualny "stan świata" używany pushmatrix i popmatrix.

2. Aby stworzyć nowy obiekt (2D lub 3D) tworzymy świat i go konfigurujemy, po czym wpisujemy w BEGIN(); ... END(); kod tworzenia obiektów 3D. Wybór typów obiektów jest szeroki. Ustawiamy vertexy (trójwymiarowe położenia pixeli) oraz ich kolor (odpowiednik 2D to kolor piksla). Dodatkowo możemy ustawić mgłę czy też teksturę. Kolor to PrimaryColor i SecondaryColor. Kolor może się składać np. z wartości RGBA (Red, Green, Blue, Alpha - RGB pozwala wybrać dowolną barwę a wartość A przezroczystość obiektu). I wektory normalne do powierzchni - czyli informacje o tym, jak się od obiektu odbija światło.

3. Chyba już i tak wystarczająco skomplikowałem. Starczy na dziś :)

Wstęp do Oracle

Od kilku miesięcy pracuję z bazą danych Oracle, a dokładniej z danymi w niej gromadzonymi (w tym ładowanymi z plików .CSV za pomocą ORA*LOADERa) oraz procedurami składowanymi PL/SQL.
Moje początki były ciężkie. ALe uczę się szybko - zawsze się szybko uczyłem gdy mnie coś interesowało. Mam nadzieję, że poniższe wskazówki okażą się dla kogoś pomocnymi.

1. Nie bój się tworzenia nowych tabel. Oracle jest w stanie udźwignąć ich na prawdę wiele.

2. Nigdy nie twórz tabel typu "CREATE TABLE (AttributeName VARCHAR(100),AttributeValue(100)". Baza danych Oracle nie jest obiektem C++ - nie dodaje się do niego atrybutów. Jeśli myślisz na sposób C++ - to musisz się nauczyć myśleć inaczej aby sprawnie korzystać z Oracle.
Jeśli stworzysz taką tabelę to m.in. tracisz możliwość kontrolowania wartości, jakie są wpisywane do bazy (np. tylko dane numeryczne... albo ścieżki do plików... albo...).

3. Nie używaj typu VARCHAR - Oracle wyraźnie zachęca do używania typu VARCHAR2 i ostrzega, że VARCHAR zostanie za jakiś czas zmieniony.

4. Nigdy nie twórz zapytań rodzaju "SELECT 1 FROM AuthTable WHERE Username = 'zdzisiek' AND Password = 'ala ma kota'". Chyba, że chcesz stworzyć kod podatny na ataki typu SQL-iniection.
Poprawna forma to: "SELECT 1 FROM AuthTable WHERE UserName = :UserName AND PasswordHash = :PassHash" USING username,passHash.

5. Nigdy nie zapisuj w bazie danych haseł - co najwyżej ich hash. Chyba że masz do czynienia z jednym z tych nielicznych wyjątków, gdzie hasło trzeba zapisać.
Jeśli zapiszesz hasło i ktoś włamie się do bazy - pozyska hasła, które użytkownicy zapewne wykorzystali również w innych miejscach.

6. Metoda w 4. pozwala wykorzystać mechanizm cache bazy danych. Jeśl Oracle zobaczy 2 identyczne zapytania - wykorzysta jeden obiekt do ich obsłużenia - co jest szybsze niż tworzenie odrębnego obiektu.
Zapytania "SELECT 1 FROM Dual" i "SELECT 2 FROM Dual" są różne.
Zapytania "SELECT :1 FROM Dual" USING 1 oraz "SELECT :1 FROM Dual" USING 2 są "takie same".

7. Skoro już wspomniałem o tabeli Dual - jest to tabela stworzona po to, aby wyciągnąć jeden wiersz danych z bazy. Nie z tabeli - z bazy. Patrz na Dual jako na pustą skrzynkę z jednym pustym wierszem. Możesz w ten wiersz wrzucić dowolny inny wiersz - ale tylko jeden.
Przykład: SELECT SYSDATE FROM Dual"

8. Punkt 6. odnosi się do PL/SQL, PERL, Python, oraz wszelkich innych języków. ZAWSZE!

9. Oracle jest drogi. Jeśli nie masz kasy - wybierz PostGreSQL. Jeśli jednak cię na to stać - uderz w Oracle. To na prawdę fajna bazka - choć jak wszystko - tak i ona posiada pewne ograniczenia.

10. Oracle wprowadził typy BLOB i CLOB. Mogą one przechowywać duże ilości danych. Zanim jednak ich użyjesz przemyśl to 10x - korzystanie z nich jestdużo wolniejsze niż np. VARCHAR2.

To na tyle na dzisiaj.