Pokazywanie postów oznaczonych etykietą NoSQL. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą NoSQL. Pokaż wszystkie posty

poniedziałek, 12 grudnia 2011

Agile Development Day

W sobotę 10 grudnia odbył się w Warszawie Agile Development Day. Była to impreza zorganizowana przez firmy Sages i Pragmatis. Event polegał na wspólnym tworzeniu aplikacji, ćwiczeniu TDD, programowania w parach i innych zwinnych praktykach. Był do tego Continous Integration (build był uruchamiany co git push) i Continous Delivery (deployment co udany build).

Aby dostać się na warsztaty trzeba było się wcześniej zapisać. Z ponad 60 osób chętnych, wybrano 22 w tym mnie :) Została przygotowana startowa baza kodu i udostępniona na github’ie. Trzeba było więc wcześniej ściągnąć kod i przygotować środowisko. Technologicznie był Spring Core, Spring MVC, JSP, Casandra, Maven. Jako że nie miałem wcześniej możliwości korzystać ze Spring’a w warunkach bojowych (po za jakimiś szkoleniami / prezentacjami), to miałem z czym się bawić. Zaprzyjaźniłem się więc z książkami na ten temat i archetypami kodu, aby porozkminiać te technologie i aby było na czym bazować.

Event zaczął się o 8 rano w Millennium Plaza. Najpierw było przywitanie i omówienie zasad, co będziemy robić w ciągu dnia. Następnie było o aplikacji jaką mamy stworzyć. Mianowicie za pomocą pisanego serwisu internetowego można się chwalić czego się nauczyliśmy, ile czasu na to poświeciliśmy i ile punktów zebraliśmy. Taki jakby twitter, tyle że piszemy co poznaliśmy, jaki był stopień trudności, system nalicza jakieś tam punkty i chwalimy się tym przed znajomymi. Plus jeszcze jakieś pierdoły do tego.

Po omówieniu wymagań aplikacji było wprowadzenie do Casandry, gdyż była to najbardziej „dziwna” i nieznana technologia z używanego technology stack. Później było szybciutko o Spring MVC i zaczęło się. Uczestnicy mieli wybrać sobie couch’a i osobę do pary (najlepiej aby ktoś znał Springa MVC). Jako że znałem Piotra (jednego z prowadzących) to się z nim dogadałem i wraz z Marcinem usiedliśmy do pierwszego user story.

Wybraliśmy sobie na tapetę formatowanie czasu, ile zajęła nam nauka danej technologii. Napisaliśmy kilka testów i zaczęła się zabawa. Postanowiliśmy dodać do projektu bibliotekę JUnitParams do pisania sparametryzowanych testów w JUnit’cie. Swoją drogą jest to biblioteka napisana przez Pawła Lipińskiego, który organizował, prowadził i kodował na warsztatach. Pomogło nam to pisać ładniejsze, parametryzowane testy w JUnicie, podczas pierwszej iteracji.

Wcześniej ustalono, że iteracje będą trwały po półtorej godziny i pomiędzy nimi będą zmiany par, a co kilka iteracji będzie retrospekcja. Czyli jakby jeden dzień ze sprintu został skompresowany do 1,5h a cały Sprint do 5ciu dni (czyli pięciu iteracji). Taka organizacja pracy bardzo motywowała do jak najszybszego kończenia zadań. Nie inaczej było w naszej parze, gdyż chcieliśmy jak najszybciej zobaczyć choćby częściowy efekt naszej pracy na „live”, mimo że nie wszystkie przypadki mieliśmy obsłużone. No i tu zaczęła się prawdziwa walka z technologiami.

Gdy jeszcze wczoraj Piotrek w projekcie dodał Tiles’y zaczęła się cała aplikacja wysypywać. Doszedł on do wniosku, że Casandra z Tiles’ami nie funkcjonuje ;) i wycofał zmiany. W naszej historyjce chcieliśmy (wręcz musieliśmy) skorzystać z JSTL’owego Taga c:forEach, ale też nie chciało działać. Był ten sam błąd co w przypadku Tiles’ów. Nasza koncepcja zamknięcia wyświetlania czasu we własny Tag JSTL’owy również nie zadziałała i trzeba było to jakoś inaczej obmyślić. To wszystko pewnie przez Casandrę ;)

Akurat nadszedł koniec pierwszej iteracji i nastąpiła rotacja par. Jako, ze pracowaliśmy na moim laptopie, to Marcin odszedł, a dołączył się Michał. Porozmawialiśmy chwilę, co zrobić z naszym problemem niemożliwości użycia JSTL’a i zaproponowałem, aby stworzyć Data Transfer Object (DTO) i za jego pomocą wyświetlać już odpowiednio sformatowany tekst. Coś tam niby się udało, ale potem było trochę walki z merge’owaniem zmian. Niestety szybko się okazało, że user story bardzo nachodzą na siebie, wręcz się powtarzają. Powodowało to masę konfliktów i trudności z push’owaniem zmian, gdyż po pull’u, odpaleniu testów, i przy próbie ponownego push’a okazywało się, że ktoś w między czasie zdążył wypushować swoje zmiany i proces trzeba było powtarzać ponownie.

Po drugiej iteracji postanowiono zrobić retrospekcję. Mieliśmy na małych, przylepnych karteczkach wypisać, co nam się podobało, a co nie i przykleić to na ścianę. Później trzeba było w ciszy to pogrupować (silent sorting) i ponazywać grupy. Po „uroczystym” przeczytaniu tego co jest fajne i niefajne, każda para wraz ze swoim mentorem miała się zastanowić, co zrobić, aby było lepiej. Super pomysłem było wprowadzenie stand-up meeting’ów - w trakcie trwania iteracji - [chyba] co 20 minut, aby poprawić komunikację w zespole i wiedzieć, kto co robi i na kiedy będzie. Innym ciekawym pomysłem było wpisywanie podczas commit'a / push’a jako autor numer implementowanego user story i nazwiska autorów. I rzeczywiście, początkowo brakło konwencji wypychania zmian do repozytorium, aby były one jednolite i czytelne.

Następnie był obiad i kolejna iteracja. Tym razem osoby, które przez dwie iteracje robiły jedną opowieść, miały się przesiąść. Może to trochę nieoptymalne posunięcie z punktu widzenia ukończenia zadania, ale podczas eventu chodziło o wspólną naukę. Trafiłem więc do zadania wyświetlania podpowiedzi. Mianowicie gdy wpisujemy technologię, której się właśnie nauczyliśmy, ma nam podpowiadać czy było to łatwe, średnie czy trudne. Wiązało się to z koniecznością napisania kawałka JavaScript’a, ale na szczęście to akurat poszło gładko. Problemem się jednak okazało, gdy coś co było zależne od naszego zadania (mianowicie dodawanie nowych umiejętności) czy jest już skończone i czy dane lądują tam, skąd je odczytujemy. Niestety ciężko w Casandrze cokolwiek podejrzeć, co wylądowało w bazie danych, gdyż zapisują się tam dane binarne. Nad tym zadaniem pracowałem przez dwie iteracje i później na ostatnią iterację, znów trzeba było się przesiąść.

Dosiadłem się więc do Bartka i tam nawet początkowo było fajnie (nie znaczy to wcale, że wcześniej było źle). Dostałem szybkie wprowadzenie co robimy, że właśnie jest test z nową funkcjonalnością i mam ją zaimplementować. Chwila ogarniania / czytania kodu i z pomocą Bartka udało się. Problem niemożliwości skorzystania z JSTL’a rozwiązano użyciem Skryptletów. Coś tam nawet się udało wyświetlić, ale nie można było wypchać zmian, gdyż najpierw trzeba było powalczyć  z kwestią, co wyświetlać, jak ktoś jest niezalogowany. Inny zespół pisał back-end do tej funkcjonalności i niestety czas warsztatów nie pozwolił już na połączenie naszych zmian.

Po piątej iteracji przejrzeliśmy backlog zapisywany na tinypm.com. Okazało się, że niewiele funkcjonalności udało się w pełni zaimplementować. Paweł pokazał jednak na żywym środowisku, że coś tam działa. Patrząc na statystyki na Jenkinsie, było widać, że w ciągu zmian udało się wypchnąć do repozytorium kod 54 razy z czego tylko 9 się wywaliło. Uważam to za niezły wynik, biorąc pod uwagę to, że dla uczestników był to świeży projekt, bez wypracowanych konwencji i nie każdy musiał znać wszystkie wykorzystywane technologie. Poniżej przedstawiam trend tesów.


Podczas warsztatów budowały się build’y od 88 do 142. Wcześniejsze build’y pochodziły z przygotowań do warsztatów. Widać wyraźnie że od 95 build’a liczba testów zaczęła znacząco rosnąć, z każdą nową zmianą.

Na koniec nadszedł czas na podsumowanie. Poprzestawialiśmy trochę stoły i ułożyliśmy krzesła w dwa kółka. W środku było 5 krzeseł, a  na zewnątrz reszta. Kto siedział w środku ten mógł mówić, pod warunkiem, że cztery wewnętrzne krzesła były zajęte. Jedno było wolne, aby kogoś mógł się dosiąść i oczywiście można było spokojnie opuścić wewnętrzny krąg. Osoby siedzące w środku mówiły o swoich odczuciach dotyczących warsztatów, co się nauczyły itd. Czyli taka runda feedback’owa dla innych uczestników i organizatorów.

Jako że ja nie miałem okazji zasiąść w środku, to swoją opinię wyrażę teraz. Ogółem event wyszedł bardzo fajnie. Organizacja w porządku: były kanapki rano, napoje i ciasteczka przez caly dzień, dobry obiad w trakcie (i nie była to pizza). Lokalizacja warsztatów bardzo dobra, mianowicie blisko centralnego – ważna kwestia dla osób przyjezdnych, a tych nie brakowało. Ja sam przyjechałem z Wrocławia, ale spotkałem również ludzi z Gdyni, Gdańska, Wrocławia, a nawet z Berlina. Organizacja pod względem technicznym również dobra – były dwa rzutniki, na jednym Jenkins, a na drugim live aplikacja. Bardzo dobrym pomysłem było przygotowanie zaczynu aplikacji i jej udostępnieniu w necie. Również Continous Integration i Delivery daje bardzo fajny efekt psychologiczny. Można było szybko zobaczyć swoje zmiany na Jenkinsie jak i na na środowisku „produkcyjnym”.

Niestety, jak to sami organizatorzy przyznali, rozpoczęcie przygotowywania tej aplikacji na tydzień przed warsztatami to było trochę za późno. Wynikały później z tego problemy z technologiami (niemożliwość użycia Tiles’ów i JSTL’a). Uważam również, że dobranie stosu technologicznego było nienajszczęśliwsze. Fajnie, że było cos egzotycznego (Casandra), ale mało kto wiedział, jak z tego odpowiednio korzystać. Do tego zastosowanie Springa MVC i JSP powodowało, że czasem trzeba było się męczyć z JavaScriptem (AJAX i jQuery). Te problemy technologiczne powodowały, ze ciężko było się skupić na czystym pisaniu kodu (nie wspominając już o TDD), a trzeba było się męczyć ze zgraniem technologii i merge’owaniem zmian.

Wcześniej wydawało mi się że w miarę ogarnąłem już Git’a, ale dopiero tutaj w warunkach bojowych zweryfikowałem swoje poglądy na ten temat. Problem scalania zmian występuje (pushowaliśmy do jednej gałęzi, aby Continous Server już dalej robił swoje), jak w każdym innym systemie kontroli wersji. Jakub Nabrdalik mówił, że jednym z możliwych sposobów jest zrobienie miecza z dwóch zwiniętych kartek papieru i ten kto aktualnie posiada miecz może push’ować. Jak ktoś innyc chce to robić, to musi uzyskać ten miecz. Wydaje mi się, że skorzystanie z Mercuriala mogło by trochę ułatwić sprawę z łączeniem zmian w kodzie, ale nie jestem ekspertem w tym temacie.

Innym poważnym minusem co do warsztatów, było przygotowanie user story’s. Bardzo często były one do siebie podobne, zachodziły na siebie i od siebie zależały. Jednak podczas wyboru user story nie posiadaliśmy tej wiedzy. Na przyszłość trzeba lepiej przygotować historyjki do zaimplementowania, wraz z grafem, co od czego zależy, co trzeba zrobić najpierw i z lepszym opisem. Większość opowiastek dotyczyła strony głównej, przez co wzajemnie sobie modyfikowaliśmy zawartość tych samych plików, co prowadziło do problematycznych konfliktów. Na przyszłość można kilka opowiastek udostępnić np. tydzień wcześniej, aby można było w domu coś na rozgrzewkę napisać. Zachęciło by to bardziej do zajrzenia w kod i do lepszego przygotowania do warsztatów. I najlepiej aby były one możliwie jak najbardziej rozłączne.

Również wybór Casandry na bazę danych nie było chyba najlepsze, gdyż z rozmów pomiędzy ludźmi słyszałem, że niektóre zespoły sporo się z nią męczyły. Fajnie poznać przy takiej okazji coś nowego, ale wybór chyba nie był najszęśliwszy. Jak bym proponował na następny raz jakąś bazę działającą w pamięci, inną NoSQL’ową (obiektową, key-value) lub jakąś lekką SQLową, którą wszyscy znają. Jako technologię widoku proponowałbym GWT (lub coś o podobnej koncepcji), gdyż tam nie trzeba się bawić z JavaScriptem, ani z JSP, a maksymalnie z niewielkimi kawałkami HTML’a.

Nie oznacza to, ze nic nie wyniosłem z warsztatów. Miałem w końcu motywację do lepszego poznania Springa, Git’a, JUnitParams… Zrozumiałem, że nie tylko testy jednostkowe są najważniejsze, ale obok nich musi się znajdować kilka integracyjnych i akceptacyjnych (już w początkowym stadium projektu). Przykładowo prosty test end-to-end uruchamiający przeglądarkę na stronie głównej i sprawdzający czy jakiś tam przycisk istnieje, pozwolił nam szybko wykryć, że Tagi w JSP nie chcą działać. Inna sprawa ze testy nie były podzielone na jednostokowe i inne (trwające dłużej), przez co ich uruchamianie było trochę przydługie.

Dowiedziałem się też o fajnej technice, podkreślającej współwłasność kod. Mianowicie po za wywaleniem z szablonów plików / klas i metod informacji o autorze, można dać wszystkim pracownikom z danego projektu, jedno konto i hasło do repozytorium. Dopiero wtedy powstaje wspólny kod i nikt się nie boi modyfikować nieswoich części. Poznałem również trochę bardziej w praktyce procesy zachodzące w procesie Agile'owym, jak i mogłem się dowiedzieć jak wygląda IT w innych miastach.

Zawsze z takich wydarzeń można wynieść ciekawe skróty klawiaturowe. I tak dla IDEI: Crtl + Shift + Enter - Statement Comlete, czyli dodanie średnika na końcu linii. Z analogicznych skrotów korzystałem w NetBeans’ie, ale tam to było to Ctrl + ; i Ctrl + Shift + ;. Innymi interesującymi skrótami w Idei są: Ctrl + Shift + T czyli przejście do klasy, która testuję aktualną klasę, w której jesteśmy i Ctrl + Shift + N (odpowiednik Eclipsowego Ctrl + Shift + R), czyli wyszukiwanie po nazwie pliku z projektu.

Ciekawe, nowopoznane skróty dla Eclipse’a to Ctrl + Shift + M - zaimportowanie statyczne danej metody na której znajduje się aktualnie focus. Przydatne zwłaszcza jak mockujemy z Mockito i chcemy samo when() zamiast Mockito.when(). Ponadto Ctrl + Shift + O czyli organizacja importów (w Idei można zrobić, aby automatycznie narzędzie przed commitem zmian, odpowiednio organizowało importy). I na koniec syso + Ctrl + Spacja, czyli skrót od System.out.println();. W Idei jest to sout + Tab co jest według mojego gustu fajniejsze.

Dobra to chyba tyle z podsumowania wydarzenia. W tym roku już się żadna konferencja / warsztaty nie szykują, więc trzeba będzie z tym poczekać do przyszłego roku. Mam nadzieję na kolejną edycję Agile Development Day lub podobny tego typu event.

sobota, 7 maja 2011

Inne podejście do przechowywania danych w systemie Android, z wykorzystaniem db4o i NetBeans 6.9

W systemie Android domyślnie mamy dostęp do relacyjnej bazy danych SQLite w której możemy zapisywać informacje z naszej aplikacji. Jest to typowy sposób dostępu do danych w tym systemie. Nie jest dziwne, że do tego systemu została wybrana ta baza. Nie posiada ona wielu magicznych dodatków (jak obecnie popularne kombajny) i założenia jest „Lite” (przynajmniej z nazwy). Z innej strony jest to baza o ciekawym stosunku kodu źródłowego do testów. Odsyłam do artykułu: Extremalne testowanie w SQLite Pawła Lipińskiego. Jak skorzystać z tej bazy jest już opisane na blogu Mirosława Stanka (część 1, część 2, część 3) jak i na helloandroid.  Ja nie będę po raz kolejny opisywał tego rozwiązania, ale postaram się poniżej pokazać inne (ciekawsze?) podejście do tematu, z wykorzystaniem obiektowej bazy danych.

DataBase For Objects, zwana powszechnie db4o, to interesująca alternatywa dla SQLite w systemie Android, jeśli chodzi o składowanie danych. Od wersji 7.5 biblioteka daje wsparcie dla tej platformy. Poniżej przedstawię jak zbudować projekt w NetBeans’ie 6.9 z wykorzystaniem tej biblioteki.

Tworzymy w NetBeans’ie nowy projekt typu AndroidApplication. Następnie do bibliotek dodajemy JAR’a zawierającego db4o.


Następnie warto skorzystać z klasy Db4oHelper przedstawionej przez Damasia Maneiro (niestety nie mam pojęcia jak to po polsku odmienić) w artykule na dzone.com: Using db4o in an Android application. Jest tam sporo kodu odwołującego się do klas z tamtejszego projektu, więc pozwoliłem sobie trochę ten kod zmienić do naszych potrzeb. Listing poniżej.

public class Db4oHelper {

    private static ObjectContainer oc = null;
    private Context context;

    public Db4oHelper(Context ctx) {
        context = ctx;
    }

    public ObjectContainer db() {
        try {
            if (oc == null || oc.ext().isClosed()) {
                oc = Db4oEmbedded.openFile(dbConfig(), 
                        db4oDBFullPath(context));
            }
            return oc;
        } catch (Exception ie) {
            Log.e(Db4oHelper.class.getName(), ie.toString());
            return null;
        }
    }

    private EmbeddedConfiguration dbConfig() throws IOException {
        EmbeddedConfiguration configuration = 
                Db4oEmbedded.newConfiguration();
        return configuration;
    }

    private String db4oDBFullPath(Context ctx) {
        return ctx.getDir("data", 0) + "/" + "database.db4o";
    }

    public void close() {
        if (oc != null) {
            oc.close();
        }
    }
}

Mamy do dyspozycji publiczny konstruktor, który jako argument przyjmuje Context – podobnie jak w SQLite. Potrzebne nam to będzie do umieszczenia pliku z bazą danych w miejscu, gdzie znajdują się dane aplikacji. Następnie mamy metodę db(), która zwraca nam instancję klasy odpowiedzialnej za połączenie z bazą. Mamy jeszcze metodę zwracającą nam konfigurację bazy (domyślna nam początkowo wystarczy) i ścieżkę do pliku z bazą. Na koniec metoda do zamknięcia połączenia z bazą.

Teraz można już napisać klasy, które chcemy składować w bazie danych. Mamy kilka możliwości jak to zrobić. Ja poniżej przedstawię prosty obiekt POJO i odpowiadającą mu klasę DAO. Można oczywiście to wszystko w jedną klasę wrzucić, ale tak będzie ładniej i poprawniej. Poniżej przykładowy kod klasy User.

public class User {

    private String login;
    private String password;

    public User(String login, String password) {
        this.login = login;
        this.password = password;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

W klasie są definiowane 2 pola typu String o nazwach login i password oraz odpowiadające im gettery i settery. No i jeszcze konstruktor przyjmujący te parametry. Jeśli ktoś woli programować w stylu funkcyjnym, to można zrobić pola final i wyrzucić settery. Db4o i tak zadziała, gdyż do ustawiania wartości wykorzystuje refleksje do pól składowych, a nie do setterów.

Proszę zwrócić uwagę, że klasa nie posiada żadnego pola w stylu ID. Dodawanie do klas persystentnych identyfikatorów, to niemalże konieczność w świecie relacyjnym, gdyż dzięki identyfikatorom tworzy się relacje i złączenia przy zapytaniach. W bazach obiektowych tego nie potrzebujemy! Mamy przecież referencje i kolekcje.

Poniżej kod klasy DAO dla klasy User:

public class UserDao {

    private ObjectContainer db;

    public UserDao(Context context) {
        Db4oHelper db4oHelper = new Db4oHelper(context);
        this.db = db4oHelper.db();
    }

    public void saveOrUpdate(User user) {
        db.store(user);
    }

    public void delete(User user) {
        db.delete(user);
    }

    public List<User> getAll() {
        return db.query(User.class);
    }
    
    public List<User> getByLogin(String login) {
        User example = new User(login, null);
        return db.queryByExample(example);
    }

    public List<User> getByLoginAndPassword(
                 String login, String password) {
        User example = new User(login, password);
        return db.queryByExample(example);
    }
}


Klasa posiada konstruktor, za pomocą którego do klasy przekazujemy obiekt typu Context. Jest to klasa android’owa, za pomocą której Db4oHelper może się dostać do odpowiedniego miejsca na zapisanie pliku z bazą. Następnie pobieramy i zapamiętujemy obiekt typu ObjectContainer pochodzący z biblioteki db4o i za jego pomocą odbywa się dostęp do danych. Dalej mamy operacje tworzenia, modyfikacji, usuwania i pobierania wszystkich obiektów - nic specjalnego, ot proste wywołanie pojedynczych metod.

Trochę (ale tylko troszkę) ciekawsza jest metoda getByLogin(), która korzysta z query by example. W skrócie, ta metoda wykonywania zapytań, polega na utworzeniu najpierw obiektu, który będzie przykładem, a następnie wywołaniu odpowiedniej metody zwracającej wszystko, co do danego wzrorca pasuje. Domyślne wartości pól klasy są dopasowywane dowolnie, a te zmodyfikowane dokładnie. W tym przypadku zostaną zwrócone obiekty posiadające ustawione pole login na takie samo jak przekazane w argumencie metody. No prościej się chyba nie da. Istnieją w db4o jeszcze inne bardziej wyrafinowane metody zapytań, ale to nie temat na ten wpis.

Ludzie doświadczeniem z dużymi systemami i relacyjnymi bazami danych, widząc powyższy kod, zaraz zaczną krzyczeć: „a co z dostępem równoległym?”, „a gdzie początek i koniec transakcji?”, itd. Otóż w ogólności db4o wspiera ACID, a poziom izolacji transakcji ma ustawiony na Read Committed. Pytanie z mojej strony: czy rzeczywiście wszędzie tego potrzebujemy? Z tego, co mi wiadomo, to zdarzenia z aktywności w Androidzie są obsługiwane synchronicznie, tzn. w tym samym wątku co GUI. Jeśli nie tworzymy dodatkowych wątków do obsługi zdarzeń (ze względu na ich banalność i szybkość), to nie potrzebujemy transakcji.

Dobra, to teraz by się przydało jakieś GUI dorobić, aby można było zobaczyć jakiekolwiek efekty działania. Po uruchomieniu aplikacji będą się pojawiać dwa przyciski: Create New User i Login. Te będą kierować już do następnych ekranów. Tam będzie można utworzyć nowego użytkownika (i oczywiście go zapisać w bazie), albo się zalogować do aplikacji (na podstawie loginu i hasła zapisanego w bazie). Nie pokazuję tutaj jak utworzyć GUI, gdyż nie jest to tematem tego artykułu. Całkowity kod zamieszczam na końcu wpisu.

Przy pierwszej próbie uruchomienia tak skonstruowanej aplikacji dostaniemy błąd. Jeżeli nie zepsuliśmy niczego po drodze to problem jest jasny. Samo dołączenie biblioteki db4o do projektu nie spowoduje jej dołączenia w trakcie budowy projektu. Należy jeszcze dodać do build.xml następujący target (lub podobny):


    
        
    


Uważam, że środowisko programistyczne powinno być na tyle inteligentne, aby się troszczyło za nas takimi detalami. No ale cóż, nie można mieć wszystkiego. Teraz już powinno pójść gładko i jeśli nic nie popsuliśmy w XML’ach to powinniśmy zobaczyć naszą aplikację. Przykładowe screeny poniżej:



Pod koniec chcę zaznaczyć, ze NetBeans 6.9 nie jest idealnym środowiskiem do pisania aplikacji androidowych (może trzeba jeszcze poczekać?). W trakcie pracy nad projektem natrafiłem na sporo utrudnień. Przykładowo, podczas refaktoringu, po przeniesieniu klasy aktywności, aplikacja przestawała działać. Trzeba było wówczas w AndroidManifest.xml trochę pogrzebać i poprawić nazwy klas. Również zmiana nazwy pakietu wymuszała dodatkowe grzebanie w project.properties.

Z ciekawości sprawdziłem jeszcze jak sobie ze wsparciem Androida radzi IntelliJ IDEA (tak w końcu ją zainstalowałem :) ). Tutaj przeniesienie klasy do innego pakietu nie stanowi problemu. Podobnie z dodaniem biblioteki db4o do projektu. Co do zmiany nazwy pakietu to napiszę o tym w następnym poście (aby wszystko na raz nie było w jednym). Dodatkowo Idea od razu pokazuje Log konsolę z Androida. Chcą ją aktywować w NetBeans'ie trzeba kliknąć: Window -> Output -> ADB Log.

Jeszcze w między czasie tworzenia tego wpisu (nie powstał on w jeden dzień) pojawił się NetBeans 7.0. Tam jednak nawet nie mogłem dodać żadnej zewnętrznej biblioteki do projektu android'owego, więc ewentualna migracja do nowego środowiska musi poczekać.

Link do kodu:

db4oOnAndroid.zip

git://github.com/mstachniuk/db4oOnAndroid.git

//Update (25.09.2011)
Jak słusznie zauważył mój przyjaciel Michał, skoro otwieramy połączenie do bazy danych, to musimy je również zamknąć. Można to zrobić w MainActivity.java w przeciążając metodę onDestroy():

@Override
protected void onDestroy() {
    Db4oHelper db4oHelper = new Db4oHelper(this);
    db4oHelper.close();
    super.onDestroy();
}

czwartek, 23 grudnia 2010

Db4o jak zacząć?


W tym poście opowiem jak zacząć swoją przygodę z db4o. Nie będę pisał kolejnego tutoriala na ten temat, gdyż zostało to już niejednokrotnie zrobione. Skupię się raczej na przygotowaniu środowiska, pokazaniu przydatnych narzędzi i odesłaniu do ciekawych artykułów. Zaczynajmy.

Chcąc się bawić z db4o musimy na początek wybrać wersję z której będziemy korzystać. Ja na co dzień korzystam z wersji 7.4 określanej jako Stable. Mamy jeszcze wersje 7.12 (określaną jako Production) i 8.0 (Development). Podstawowe funkcjonalności powinny być takie same, ale z tego co kojarzę to poszczególne wersje różnią się pewnymi bardziej zaawansowanymi mechanizmami.

Chcąc więc skorzystać z db4o należy podpiąć odpowiedniego JAR’a pod projekt. Możemy takowego bezpośrednio ściągnąć ze strony producenta: db4o for Java, version 7.4.155.14653 ZIP W tym pliku, katalogu lib mamy min. dostępne odpowiednie wersje JAR’ów przygotowane dla różnych wersji Javy:

  • db4o-7.4.155.14653-java1.1.jar
  • db4o-7.4.155.14653-java1.2.jar
  • db4o-7.4.155.14653-java5.jar

Ja oczywiście korzystam z wersji dla Javy 5. Jeżeli korzystamy z mavena, to musimy dodać następujący wpis:


  
    db4o
    http://source.db4o.com/maven/
  



  com.db4o
  db4o-java5
  7.4-SNAPSHOT


Teraz już możemy się bawić. Na początek polecam przejście tutoriala: doc\tutorial\db4o-7.4-tutorial.pdf z archiwum ściągniętego wraz z db4o. Pokazuje on za pomocą przykładów funkcjonalności db4o. Nie ma tu jakiś wielkich teorii jak całość działa, tylko raczej ukazanie funkcjonalności za pomocą przykładu i krótkiego komentarza. Budowana jest w nim aplikacja odnosząca się do wyścigów F1 i w kolejnych rozdziałach przedstawia kolejne dostępne funkcjonalności.

W tutorialu tym brakuje pokazanego kodu klasy Util. Musimy więc sami stworzyć sobie taką klasę w naszym projekcie, lub zastąpić wszelkie wywołania Util.DB4OFILENAME nazwą pliku w którym będzie przechowywana nasza baza danych. Ewentualnie skorzystać z kodu dostępnego w tym samym katalogu co tutorial.

Znalazłem nawet niemalże tłumaczenie tego tutoriala na polski. Fakt faktem nie dotyczy on najnowszej wersji, a jedynie 6.3. Kiedyś przeczytałem to całkiem dokładnie i było nie było to najgorsze tłumaczenie. Można się na nim opierać. Czasami są wywoływane w tym „tutorialu" metody, które są obecnie @deprecated, ale poza tym jest całkiem ok. Opisywane tłumaczenie jest zawarte w pracy magisterskiej Pawła Protasia pt. Pomost pomiędzy SBQL a Db4o.

Jeżeli chcielibyśmy stworzyć prostego CRUD’a z wykorzystaniem db4o i JSP polecam artykuł z 8mego numeru Java exPress  pt.: DB4O - Obiektowa baza danych. Autorem artykułu jest Paweł Cegła, który również na swoim blogu pisze o db4o.

To tyle na początek jeśli chodzi o chęć zrozumienia działania samej bazy db4o. Chcąc tworzyć już bardziej skomplikowane, wielowątkowe aplikacje, powinniśmy zapoznać się z klasą Db4oUtil. Pierwszy raz znalazłem ją na blogu Space Program we wpisie: Db4oUtil (aka. The Easiest Way to Get Started With Db4o). Kopia tej klasy (troszkę zmodyfikowana) znajduje się również na stronie db4o: Db4oUtil (aka. The Easiest Way to Get Started With Db4o). Podaje obydwa linki, gdyż jakiś czas temu strona db4o przechodziła renowacje i wówczas wiele linków nie działało.

Db4oUtil jest thread safe i proste w użyciu. Ja akurat zazwyczaj korzystam ze zmodyfikowanej przez mnie wersji tego pliku w zależności od aktualnych potrzeb projektowych. Schemat użytkowania jest podany w przytoczonych artykułach.

Mamy jeszcze do dyspozycji oczywiście dokumentację javadoc. Miejscami nie jest ona „wylewna”, ale na pewno warto ją podpiąć pod ulubione IDE. Jest jeszcze Reference Documentation (doc\reference\db4o-reference-java.pdf), ale to już jest ponad 1000 stron w pdf’ie i początkowo odradzam. Dopiero jak czegoś nie znajdziemy w tutorialu, ani w javadoc to można tego szukać w dokumentacji referencyjnej.

Na koniec chciałbym polecić narzędzie ObjectManagerEnterprise (OME). Jest to aplikacja służąca do podglądu bazy db4o (nawet jak nie wiemy jakie klasy tam siedzą). Narzędzie jest dystrybuowane razem z biblioteką db4o. Działa ono jako wtyczka do Visual Studio (w przypadku gdy korzystamy z wersji db4o dla C#) lub Eclipse (w przypadku gdy korzystamy z wersji Javowej). Jest jeszcze rozszerzenie dla Netbeans’a: db4o-netbeans, ale jest ono już nie rozwijane od 3ch lat i z nowym NB nie współpracuje (a szkoda).

OME wywodzi się bezpośrednio z projektu db4o Object Manager działającego jako aplikacja standalone. Jednak i ten projekt nie jest już rozwijany i nie wspiera nowszych wersji db4o.

Jeszcze mogę polecić własną prezentację pt.: Inicjatywa NoSQL na przykładzie db4o, którą miałem ostatnio okazję prezentować w ramach WrocJUG. Więcej o samej prezentacji w poprzednim wpisie: Wrażenia po pierwszej mojej prezentacji w ramach Wrocław Java User Group.

To chyba na tyle co mógłbym polecić na początek, jeśli ktoś chciałby się pobawić db4o. Wszelkie komentarze z interesującymi linkami na temat db4o mile widziane.

sobota, 18 grudnia 2010

Wrażenia po pierwszej mojej prezentacji w ramach Wrocław Java User Group


We wrotek (14.12.2010) miałem przyjemność prowadzić prezentację w ramach Wrocław Java User Group (WrocJUG). Było to moje pierwsze wystąpienie na tym poziomie trudności. Wielokrotnie prowadziłem prezentacje w ramach koła naukowego ISA^2 czy PWrJUG, ale na WrocJUG jest trochę inaczej. O ile studenci w miarę wierzą w to co się do nich mówi, to na WrocJUG padają już trudne pytania i byle odpowiedź jest tu niewystarczająca. Tutaj trzeba mieć większą wiedzę i mocne argumenty, aby przekonać do siebie słuchaczy.

Mój temat prezentacji to: Inicjatywa NoSQL na przykładzie db4oDb4o zajmuję się już od jakiegoś czasu, a zaczynałem od studenckiego projektu, później była magisterka i kilka małych projekcików dla własnych celów. O rozwiązaniach NoSQL miałem okazję trochę posłuchać w ramach polskich konferencji. Prezentacją chciałem trochę przybliżyć i rozpropagować te obydwie rzeczy we Wrocławiu.

Do samej prezentacji przygotowywałem się dość długi czas. Już podczas wakacji miałem pierwsze pomysły, jakie triki mogę wykorzystać w prezentacji, aby widownię trochę rozbawić i zmusić do dyskusji. Samą prelekcję musiałem trochę odwlec w czasie, gdyż chciałem się najpierw obronić, a dopiero potem przemówić na WrocJUG. Jak już zgłosiłem gotowość do prezentowania, to trzeba było jeszcze chwilę poczekać na wolną salę (spotkania nie są regularne, więc nie mamy jej na stałe zarezerwowanej).

Jak poszła prezentacja? Po prelekcji zgarnąłem kilka pozytywnych opinii, z czego się cieszę. Zależało mi na tym, aby zmusić widownię do dyskusji, co mi się udało. Padało tyle pytań, że całe wystąpienie przeciągnęło się do 2 godzin i 15 minut! Udało mi się ponadto poprowadzić prezentację na luzie i sala często się śmiała.

Czy udało mi się przekonać uczestników do korzystania z db4o? Chyba nie do końca. Jeżeli przedstawił bym produkt, który ma funkcjonalność zbliżoną do obecnych komercyjnych, relacyjnych baz danych, to wtedy może tak. Db4o jednak ma troszkę inne przeznaczenie (małe i średnie projekty, aplikacje standalone) niż duże relacyjne kombajny, przechowujące ogromne ilości danych.

Podczas prezentacji dało się odczuć, jak bardzo jesteśmy zakorzenieni w relacyjnym modelu danych i jak ciężko jest nam się odnaleźć w nowym środowisku. Znamy bardzo dobrze programowanie obiektowe, ale ciężko nam jest sobie wyobrazić, aby przechowywać dane w postaci obiektów. Bardzo też się przyzwyczailiśmy do innych możliwości jakie oferuje nam relacyjna baza danych i nie chcemy z nich tak łatwo rezygnować.

Uwagi jakie zebrałem na temat samej prezentacji:

  • Nie wszystko było czytelne na slajdach, np. czarny tekst na czerwonym tle na jednym z obrazków. Wynikało to trochę z wypalenia się lampy rzutnika. Z drugiej strony chciałem zachować kolorystyke stosowaną w dokumentacji db4o.
  • Nie zawsze udawało mi się ładnie złamać linię kodu na slajdach. No niestety miałem trochę „tasiemcowate” warunki w if-ach, a nie chciałem czcionki w kodzie pomniejszać, ze względu na pogorszenie widoczności.
  • Ładniej również kod uruchamiany można było dopracować, np. nie tworzyć metod statycznych. Wynikło to trochę z mojego lenistwa, gdyż chciałem aby wszystko co ciekawe w danym przykładzie, działo się w metodzie main(). Niektórzy jednak oceniają programistę po jego kodzie i niezaspecjalnie na tym polu wypadłem. Trzeba się poprawić na przyszłość! Na przykład zamiast pokazywać kolejne możliwości w metodzie main(), można przygotować testy uczące (chyba tak to się nazywa). Chodzi mi o testy, które piszemy dla siebie, gdy chcemy poznać działanie nowej biblioteki. W ten sposób sprawdzamy, czy dobrze zrozumieliśmy dokumentację.
  • Zamiast używać SVN’a można by kopiować odpowiednie pliki projektów z uprzednio przygotowanych katalogów. Nie chciałem tworzyć kodu na żywo, gdyż bardzo dobrze wiem, że to ciężkie zajęcie pisać kod i jednocześnie opowiadać o nim, a najczęściej i tak wychodzi, że o czymś zapominamy i nie działa. Zaczyna się wtedy desperackie poszukiwanie przyczyny, a publika się zaczyna nudzić. Dlatego postanowiłem skorzystać z SVN’a i przełączać się pomiędzy kolejnymi rewizjami kodu. Z widowni słyszałem szmery, że to fajny pomysł, ale rzeczywiście kopiowanie pliku mogło by być trochę szybsze.
  • Mało wiedziałem o komercyjnym zastosowaniu db4o i jakie sprawia problemy. No cóż nie mam komercyjnego doświadczenia z db4o, ani informacji jak to się sprawdza na produkcji.
  • Odpalanie prostych przykładów kodu nie zawsze jest potrzebne.
  • Warto zainstalować program typu ZoomIt, aby jakby coś nie było czytelne, można było powiększyć ekran.
  • Brakowało mi trochę takiej aplikacji, która wyświetlała by slajdy w trybie prezentacji. Tzn. abym na ekranie laptopa widział aktualny slajd i następny, a na rzutniku był tylko aktualny slajd wyświetlany. Z tego co mi wiadomo to pakiet MS Office i OpenOffice mają taką funkcjonalność, ale niestety one nie obsługują pdf'ów. Jakby ktoś znał taką aplikację proszę o info.

Więcej uwag nie pamiętam, jak mi się cos przypomni to dopiszę :)