sobota, 28 maja 2011

Podświetlanie wystąpień zmiennych w kodzie w Eclipse

Jakiś czas temu mój Eclipse zwariował i nie chciał podświetlać wszystkich wystąpień zmiennych w kodzie Javy, gdy na jakiejś zmiennej był ustawiony kursor. Moja praca stała się bardziej uciążliwa, gdyż trudniej mi było przeczytać / zrozumieć nie swój kod.

Jako że nie znam dokładnie środowiska, chwilę się naszukałem co może być nie tak. Wszystko można zmienić w menu Window -> Preferences -> Java -> Editor -> Mark Occurrences.



Warto mieć tu wszystko włączone, aby widzieć co gdzie w kodzie występuje. Przykład poniżej:



Kursora bezpośrednio nie widać, ale proszę mi wierzyć, że jest on ustawiony na obiekt separator w linii 14. Dzięki temu w linii 16 widzimy podświetlenie tej samej zmiennej.

Podsumowując powiem jeszcze, ze pisząc ten post zrozumiałem, dlaczego w pewnym momencie to podświetlanie mi zniknęło. Otóż chcą sobie przypomnieć skrót klawiaturowy do wyświetlania Outline’a aktualnej klasy w oknie z kodem, omyłkowo wcisnąłem Alt + Shift + O, co jak się okazało wyłącza podświetlanie tych zmiennych. Natomiast skrót do wyświetlania Outline’a klasy (czyli zawartości) to Ctrl + O. Podwójne wciśnięcie tej kombinacji, to wyświetlenie całej zawartości klasy, wraz z klasami bazowymi.

Tyle na dziś.

Żródło:
Eclipse: Mark Occurrences for Quick Visual Help

poniedziałek, 16 maja 2011

Wrażenia po konferencji GeeCON cz.2 (Conference Day II i Community Day)

Wrażenia z pierwszego dnia konferencji opisałem już w poprzednim wpisie: Wrażenia po konferencji GeeCON: Conference Day I. W piątek (Conference Day II) jakoś ciężko mi było się wcześnie rano zebrać. Jako że znów początkowo musiałem być na stoisku firmowym, nie uczestniczyłem w porannych wykładach.

Pierwszy wykład na który dotarłem to była prelekcja: Eugene’a Ciurana The No-Nonsense Guide to Hadoop and HBase in Enterprise Apps. Autor opowiadał o framework’u Hadoop, który skupia w sobie sporo innych ciekawych technologii, wspomagających rozproszenie systemu. Było dużo wiadomości, ale bez konkretów. Trochę dokładniej było o bazie HBase podobnej do BigTable od Google. Na koniec prelegent namawiał do pracy w swojej firmie i sporo oferował, za polecenie pracownika.

Później był obiad, dokładnie taki jak wczoraj. Część uczestników zamiast niego poszła gdzieś indziej zjeść.

Następnie udałem się na prezentację Marka Matczaka pt. 10 common pitfalls when using Hibernate, z którym mam przyjemność współpracować. Słyszałem również tą prezentację kilka dni wcześniej i dokładnie wiedziałem o czym będzie. Marek pokazał pułapki na jakie można się natknąć używając Hibernate’a. Ciekawa prezentacja poparta przykładami z życia. Po prelekcji grupka ludzi otoczyła Marka, zasypując go pytaniami. Sporo ludzi nie zrozumiało idei session-per-conversation, czyli wzorca przydającego się w aplikacjach, gdzie mamy kilka kroków w jakimś procesie, jak np. bookowanie biletów lotniczych. Warto wówczas zacząć sesję Hibernate’ową na początku procesu rezerwacji biletu, a zakończyć ją, gdy już będzie zapłacone. Rozwiązanie takie jest zaimplementowane we framework'u Seam.

Następnie poszedłem na Anton’a Arhipov’a Bytecode for discriminating developers. Początkowo było o drzewach AST, czyli krótkie wprowadzenie do kompilatorów. Muszę przyznać że slajdy były bardzo ładnie przygotowane, zwłaszcza te pokazujące operacje wykonujące się na stosie. W ogólności jest 256 słów kluczowych w maszynie wirtualnej Javy, i praca z bytecode’m nie jest taka straszna dzięki narzędziom javap (do podejrzenia kodu JVM) i Javassist (do modyfikowania kodu w locie). Później trochę przysnąłem i obudziłem się pod koniec. Anton jest współautorem narzędzia JRebel, służącego do szybkiego redeploy’a naszych aplikacji, bez konieczności restartowania serwera. Szkoda, że rozwiązanie jest płatne:/

Następnie wybór prezentacji był bardzo ciężki i w końcu poszedłem na Andres’a Almiray’ego z prezentacją Polyglot Programming. Prelegent porównywał jave, groovy’ego, scalę, i clojure. Mi to trochę przypominało onanizm składniowy. Może przykłady były źle dobrane do tego, aby pokazać przewagę pewnych języków nad innymi? Później autor pokazał, że można łączyć te języki ze sobą.

Na koniec poszedłem jeszcze na prezentację dra Jim’a Webber’a pt. A programmatic introduction to Neo4j. Prześmieszny koleś i na scenie robił niezłe show. Biegał, rzucał żartami i cieszył się jak publiczność atakowała go pytaniami. Co do wykładu, to najpierw ogółem opowiadał o NoSQL, że coraz więcej danych przechowujemy i że są one coraz bardziej skomplikowane. Najpierw kilka godzin modelujemy nasze dane, rozpisujemy relacje, tworzymy bazę danych, a na koniec i tak robimy denormalizację, bo nasza baza nie wyrabia. Jim podał dobre przykłady, gdzie można wykorzystać bazy grafowe. Porównał szybkość wyszukiwania naszych przyjaciół w typowym serwisie społecznościowym. Przewaga Neo4j w stosunku do relacyjnej bazy danych była tutaj miażdżąca. Jim polecał ściągnięcie tutoriala o Neo4j z github’a: https://github.com/jimwebber/neo4j-tutorial.

Dodatkowo dostęp do Neo4j z poziomu innych języków, może łatwo się odbywać przez REST’a. Jeśli chodzi o poziom rozdzielenia transakcji w Neo4j to jest to dostęp serializowany, ale na używanym podgrafie. Bardzo fajna prezentacja, szkoda, że dopiero na koniec konferencji.

Gdzieś tam w międzyczasie było jeszcze losowanie książek i innych nagród na stoiskach sponsorskich, ale na nic się nie załapałem.

Zostałem jeszcze w Krakowie na sobotę na Community Day. Tam już organizatorzy byli kompletnie wyluzowani, gdyż odbywało się to w pobliskim hotelu i było o wiele mniej uczestników (większość w piątek wieczorem pojechała do domu).

Na Community Day najpierw uczestniczyłem w Visage Android Hands-on Lab, prowadzonym przez Stephen’a Chin’a. Przedstawiał on coś co się nazywa Visage i służy do budowania GUI w JavaFX m.in. na Androida. Niby mniej tekstu i przyjemniejszy w czytaniu niż XML, ale jakoś nie do końca się przekonałem. Prezentacja była trochę niedopracowana i właściwie pomagaliśmy Stephan’owi ją usprawnić.

Autor przygotował obraz wirtualnej maszyny z kompletnym środowiskiem. Pomysł dobry, ale wykonanie trochę słabe. Początkowo dużo grzebaliśmy w podstawowym edytorze tekstu, dodając nowe funkcjonalności do naszej aplikacji. Wiązało się to ze zgadywaniem, w którym pakiecie może leżeć dana klasa. Później kopiowaliśmy pliki do świeżego projektu, modyfikowaliśmy XML’e, po to aby móc w końcu uruchomić całe cudo w NetBeans’ie (akurat był zainstalowany na wirtualnym obrazie). Ze względu na różne problemy uczestników po drodze, nie udało nam się zrealizować całości.

Po „laborce” był obiad. I tu o dziwo był obiad hotelowy, smaczny i całkiem spory wybór. Kto chciał mógł również sobie zamówić piwko.

Po obiedzie poszedłem jeszcze na prezentacje Tomasza Kaczanowskiego, pt. Who watches the watchmen? - on quality of tests. Właściwie jakieś 85% omawianych zagadnień już gdzieś wcześniej słyszałem i wiele nowego się nie nauczyłem. Mimo wszystko prezentacja była fajna z dobrym angielskim prelegenta i kameralnym gronem słuchaczy.

Tego dnia jeszcze dostałem od kolegi Krzyśka fajną nalepkę na klawiaturę, ze skrótami do IntelliJ IDEA. Podobno rozdawali to dzień wcześniej na jakimś wykładzie, ale mnie to ominęło. Jak wygląda taka klawiatura (i nalepki) można zobaczyć na blogu Hamlet’a D'Arcy.Tak samo okleję swoją klawiaturę w laptopie:) Przydało by się jeszcze coś takiego dla Eclipse’a.

Podsumowując uważam konferencję za udaną. Jedynie trochę obiad był kiepski, ale poziom prezentacji był wysoki. Wiadomo, że czasem się trafiło tak, że nie bardzo było na co iść, no ale trudno. Niemal na każdej konferencji się tak zdarza. Teraz zostaje czekać na publikacje prezentacji i nagrywanych filmów z wystąpień. Za rok trzeba się znów tam pojawić.

A już niedługo: Confitura (dawniej Javarsovia). Obecnie trwają prace na wyborem tematów, ale już wkrótce powinna ruszyć rejestracja uczestników. Już się nie mogę doczekać.

Wrażenia po konferencji GeeCON: Conference Day I

Dzięki uprzejmości mojego aktualnego pracodawcy, firmy Capgemini  mogłem wziąć udział w konferencji GeeCON. Co prawda musiałem przez część czasu stać na stanowisku sponsorskim, ale i tak sporo skorzystałem z wykładów. Zacznijmy od początku.

Do Krakowa przyjechałem razem z kolegą z pracy w środę wieczorem. Po zameldowaniu się w hotelu i chwili odpoczynku, poszliśmy zobaczyć kino, w którym miała się odbywać konferencja. Część stanowisk sponsorskich była już rozłożona, a że było już późno, postanowiliśmy się rozłożyć następnego dnia z samego rana. Pojechałem jeszcze się spotkać z ziomkiem z rodzinnego miasta i do hotelu wróciłem około północy. Poprosiłem jeszcze w hotelu o żelazko i deskę do prasowania, ale się nie doczekałem :/

W czwartek wstałem około 5.40, aby móc pójść jak najwcześniej na miejsce konferencji i rozłożyć stanowisko sponsorskie. Na miejscu byliśmy chwilę po 6 i dobrą godzinkę zajęło nam składanie całości. Później jeszcze powrót do Hotelu na śniadanko i z powrotem na konferencję.

Chwilę po 8.00 zaczęli się schodzić pierwsi uczestnicy. Dla każdego uczestnika był zestaw: duża ekologiczna torba, koszulka i kubek. Bardzo podobała mi się ulotka IntelliJ IDEA, na której były wypisane skróty klawiaturowe. Fajna pomoc na początek nauki nowego środowiska. Trzeba powiesić w widocznym miejscu i często zerkać. Ponadto był jeszcze program z opisem konferencyjnych wykładów, gazetka Open Source Journal i trochę spamu.

Z początku konferencji stałem na stoisku sponsorskim, a pierwszy wykład na który dotarłem to była prelekcja: Dra Heinz’a Kabutz’a pt. Reflection Madness. Autor jest jednym z redaktorów serwisu javaspecialists.eu. Było to szczególnie widać po formatce prezentacji i sporej liczbie odwołań do artykułów w tym serwisie. Generalnie sporo prelegentów nie trzymało sie standardowej formatki, co mi się nie podobało.

Co do samej prezentacji to było dużo o mechanizmie refleksji w Javie. Początkowe możliwości które autor pokazywał były mi znane, gdyż używałem je intensywnie w pracy magisterskiej. Późniejsze przykłady były jednak bardziej zaawansowane i dzięki temu mechanizmowi można wszystko zrobić, na co domyślnie kompilator Javy nam nie pozwala. Nie jest to mechanizm, który się wykorzystuje w codziennej pracy, ale znajomość tego się przydaje. Końcowa konkluzja jest taka, że warto stosować SecurityManager w miejscach narażonych na hakowanie naszego kodu. No i w wolnym czasie trzeba będzie przejrzeć posty publikowane na javaspecialists.eu.

Po wykładzie był obiad. Nie był on rewelacyjny: ryż z kawałkami mięsa i sos. Do tego nie było gdzie usiąść, no ale trudno. Kino nie było w całości wynajęte (jedynie 3 sale i hol), więc nawet organizacyjnie było by to trudne. Organizatorzy poszli trochę po kosztach, ale miejsce konferencji rekompensuje to niedociągnięcie. Możliwość oglądania prezentacji na ekranie kinowym, z porządnym nagłośnieniem i wygodnymi fotelami sprawia, że nawet w ostatnim rzędzie można w pełni skorzystać z konferencji.

Po obiedzie udałem się na prezentację Michaël’a Figuière’a i Cyrille’a Le Clerc’a pt. NoSQL & DataGrid from a Developer Perspective. Panowie byli przedstawicielami firmy Xebia i pochodzili z Francji. Gdybym wcześniej zwrócił na to uwagę, to bym się zastanowił, czy iść na ten wykład. Słuchanie francuskiego angielskiego nie jest łatwe, ani przyjemne. Prelegenci pokazywali dużo obrazków i wiedzy, ale bez konkretów, reklamując na końcu swoją firmę. Fajnie, że pokazali podejście do transakcji w rozwiązaniach NoSQL. Mianowicie można dodać obiektom metody typu DO i UNDO. Przykładowo jeśli mamy koszyk internetowy na sprzedawane produkty i ograniczoną ilość produktów, to jedna metoda wkłada do koszyka towar, zmniejszając liczbę dostępnych produktów w bazie danych, a druga cofa tą operację. Gdy dojdzie do realizacji zamówienia i się okaże, że któryś z produktów jest niedostępny i gdy użytkownik wycofa się z zakupów, to dla dostępnych produktów wywołujemy metodę typu UNDO. A wszystko odbywa się bez transakcji. Dodatkowo mieli fajny styl rysunków, z taką kreską, jakby malowaną grubym ołówkiem lub kredką świecową.

Podczas całej konferencji brakowało mi pani z dzwoneczkiem, informującej o rozpoczęciu wykładów. Widziałem takie rozwiązanie na którejś z poprzednich konferencji i było ono bardzo praktyczne. Brak „naganiacza / przypominacza” powodował, że się prelekcje ciągle opóźniały i przeciągały. Przerwy jednak miały sporo zapasu czasowego i pozwalały / dopuszczały takie sytuacje.

Kolejną prezentacją, którą odwiedziłem, było drugie wystąpienie dra Heinz'a Kabutz'a pt.
Productive Coder. Szkoda, że prelegent nie wyświetlał na ekranie skrótów klawiaturowych z których korzysta. Używał on środowiska IntelliJ IDEA. Co mi się spodobało, to równoczesne dodawanie kilku polom w klasie tego samego zakresu, wyświetlanie linii w IDE oddzielających kolejne metody, hotkey do przejścia w tryb pełnego okna… Musze poszukać, jakie to są skróty. Prezenter twierdził, ze powinniśmy poświęcić 10 godzin na poznawanie hotkey’ów w naszym środowisku programistycznym. Całkowicie się zgadzam. Uważam, że warto tu zastosować programowanie w parach i oglądanie screencast'ów lub pracy innych programistów.

Później Heinz pytał się publiczności o to, czy obiekt typu String jest mutable czy immutable. My programiści de facto z niego korzystamy jako immutable, ale w rzeczywiśtości jest mutable, czyli modyfikowalny. Ilustruje to poniższy kod:

String myText = "My Example String";
Set<String> mySet = new HashSet<String>();
mySet.add(myText);
System.out.println(myText);

Gdy ustawimy breakpointa na trzeciej linii to zobaczymy, że wewnętrzne pole hash w obiekcie myText ma wartość 0. Po wykonaniu 3ciej linii zmieni się ono na inną wartość. Obiekt zmienia więc swój stan. Skąd sie to bierze? Mianowicie podczas dodawania tekstu do zbioru, wywoływana jest metoda hashCode() na obiekcie myText i obliczana jest wartość hash’a. Żeby nie obliczać jej wielokrotnie, to jest ona zapamiętywana do późniejszego użycia. Jako, że obiekty typu String są używane zazwyczaj w kontekście, gdzie wartość ta nie ma znaczenia, to nie jest ona obliczana w trakcie tworzenia obiektu – wiadomo wydajność.

Doktor zachęcał również do wykorzystywania inspekcji kodu dostępnych w IntelliJ IDEA (menu Analyze -> Inspect Code...). Narzędzie potrafi między innymi wyszukać pola, które mogą mieć mniejszy zakres widoczności, pola które można zmienić na finalne, lub są niezainicjowane itd. Generalnie to potężne narzędzie do statycznej analizy kodu, które od razu potrafi wprowadzić poprawki do projektu. Szczególnie warto je wykorzystać, przy otrzymaniu odziedziczonego kodu po kimś. Dzięki niemu można znacząco pozbyć się nieużywanego kodu, który zaśmieca cały projekt.

Prelegent pokazywał jeszcze ciekawe komentarze w kodzie SDK, które nic nie wnoszą i jak się zmieniają w kolejnych wersjach SDK. Proponował on wyłączyć wszelkie automatyczne generowanie komentarzy, gdyż to nic nie daje. Nawiązała się dyskusja ze słuchaczami, czy warto stosować komentarze czy nie. Publiczność twierdziła, że należy pisać kod tak, aby był zrozumiały sam przez siebie. Heinz twierdził jednak, że kod mówi jak, a komentarz dlaczego tak a nie inaczej. Pokrywa się to z informacjami, które ostatnio przeczytałem w książce: Kod doskonały Steve’a McConnell’a. Ponadto jak nie jesteśmy w stanie napisać dobrego komentarza, to oznacza to, że sami nie wiemy jak nasz kod funkcjonuje i powinniśmy go poprawić.

Później miałem iść na prezentację Hamlet’a D'Arcy’ego  pt. New Ideas for Old Code, ale jakoś długo się zbierałem i w końcu nie doszedłem, czego później żałowałem.

Następnie chciałem iść na Aslak’ena Knutsen’a na prezentację Arquillian: Real Java enterprise testing, ale gdy się dowiedziałem, że chodzi o testowanie EJB z całym kontekstem kontenera, to sobie dałem spokój. Staram się trzymać od takich ciężkich rzeczy z daleka. Ostatecznie poszedłem więc na Nicolas’a Leroux’a, Morten’a Kjetland’a: Play! framework: a revolution in the Java world. I znów Francuzi. Co prawda jeden miał dobry angielski, ale mało mówił, gdyż stał obok, lub kodował na żywo, a drugi opowiadał, co ten pierwszy pisze. Szkoda tylko, że nie korzystał ze skrótów klawiaturowych, tylko właściwie wszystko pisał ręcznie, prawie jak w notatniku. Generalnie fajny pomysł na prezentację – jeden koduje, a drugi mówi o co chodzi.

Prelegenci to autorzy przedstawianego framework’a. Fajnie, że nie trzeba kompilować całego kodu po wprowadzeniu małej zmiany, tylko wystarczy odświeżyć stronę w przeglądarce. Ciekawe jak to we wnętrzu jest zorganizowane? I jak coś się sypnie, to bezpośrednio w przeglądarce widzimy w której linii kodu i co w niej jest! Prelegenci napisali na szybko czat przez przeglądarkę i pozwolili publiczności się połączyć i popisać. Po kilku testowych wpisach zaczęły się zgodnie z moimi przewidywaniami „ciekawsze” wpisy, typu: „Euro 2012 w Łodzi”. Na koniec ktoś jeszcze napisał Cross-site scripting i wyświetlił komunikat na ekranie, ukazując słabość framework’a. Podobno w Lift’cie jest to wbudowane we framework.

I to był ostatni wykład pierwszego dnia konferencji. Wieczorem jeszcze byłem na imprezie konferencyjnej w klubie Pauza na Florianskiej. Można było tam pogadać z innymi uczestnikami, wypić piwko i powymieniać się spostrzeżeniami. Wiadomo, że nie można było poszaleć, gdyż jeszcze czekał nas drugi dzień konferencji, o którym w kolejnym wpisie.

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();
}

poniedziałek, 2 maja 2011

Warunkowa kompilacja j2me w srodowisku NetBeans

Pisanie aplikacji na urządzenia mobilne w j2me nie jest prostą sprawą. Niby specyfikacja KVM (Kilobyte Virtual Machine) jest jedna i narzucona przez Oracle’a (dawniej Sun’a), ale konkretną implementację dostarcza producent danego telefonu komórkowego. Ponadto mamy sporo różnych modelów telefonów, różniących się od siebie wielkością ekranu, ułożeniem przycisków, szybkością procesora itd. Często przychodzi potrzeba dostarczenia aplikacji zoptymalizowanej pod konkretny telefon. Przedstawię poniżej w artykule jak można tego dokonać za pomocą warunkowej kompilacji w NetBeans’ie.

Warunkowa kompilacja to bardzo stary pomysł znany mi z czasów języka C (a może i był używany wcześniej). Polega ona na dodaniu do kodu źródłowego pewnych instrukcji, które zostaną wykonane jeszcze przed właściwą kompilacją. Spowoduje to wybranie odpowiednich fragmentów kodu, które zostaną dołączone do wynikowego programu. Projektanci języka Java całkowicie zrezygnowali z warunkowej kompilacji ze względu, że jest ona wrogiem numer 1 obiektowości. Gdy J2ME ujrzała światło dzienne i gdy coraz więcej telefonów zaczęło wspierać tą funkcjonalność, zrozumiano że jednak pewna możliwość konfigurowania kodu przed właściwą kompilacją jest niezbędna. I tak się narodziła warunkowa kompilacja w NetBeans'ie. Oczywiście wiem, że obecnie mamy XML’e, Dependency injection, Inversion of control i inne możliwości konfiguracji naszych aplikacji, ale nie mają one zastosowania w świecie j2me. Powstały co prawda projekty Signal Framework i Spring ME coś ala IoC dla j2me, ale jak dla mnie to sztuka dla sztuki i zastosowanie zerowe (i tak trzeba całość kompilować).

Dobra czas przejść do konkretów. Poniżej prezentuję fragment kodu, który używam w swojej aplikacji, z wykorzystaniem warunkowej kompilacji:

private void drawHelpMenu(Graphics g) {
//#if MobileTouchScreen
    helpSprite.setPosition(getWidth() - helpSprite.getWidth(),
            getHeight() - helpSprite.getHeight());
    helpSprite.paint(g);
//#else
    String  back = I18n.getText(I18n.LESSON_HELP);
    g.setFont(getSmallFont());
    g.drawString(back, getWidth(), getHeight(),
            Graphics.RIGHT | Graphics.BOTTOM);
//#endif
}

Interesujące fragmenty to te zaczynające się od //#. Są to instrunkcje preprocesora. Jak to działa? Gdy mamy ustawione ability MobileTouchScreen, to wówczas linijki 3-5 zostaną skompilowane, w przeciwnym wypadku linijki 7-10 zostaną wstawione w ciało metody drawHelpMenu(...). Prawda ze proste?

Teraz nadszedł czas na zarządzanie naszymi “zdolnościami” (chyba nienajlepsze tłumaczenie). Klikamy prawym przyciskiem myszy na nazwę projektu i wybieramy z menu opcję Properties. Tam w kategorii Abilities możemy zobaczyć jakie mamy ustawione właściwości dla obecnej konfiguracji naszego projektu. Właściwości mogą posiadać wartość, ale nie muszą.


Proponuję teraz utworzyć sobie nową konfigurację. Z pola Project Configuration wybieramy Add Configuration I wpisujemy nazwę nowej konfiguracji I następnie klikamy OK. Możemy tutaj jeszcze wybrać szablon, na podstawie którego zostanie utworzona konfiguracja.


Po kliknięciu OK wracamy do poprzedniego ekranu i teraz możemy modyfikować naszą konfigurację. Najpierw musimy odznaczyć pole Use Values from „DefaultConfiguration”. Dzieki temu przycisk Add staje się aktywny. Klikamy i w nowym oknie wpisujemy nasze ability MobileTouchScreen.


Klikamy OK i w oknie z właściwościami naszego projektu pojawiła się nowa pozycja w tabelce właściwościami danej konfiguracji.

Teraz chcąc skompilować projekt, używając nowej konfiguracji, należy ją wybrać z menu w górnej części okna.


Jak popatrzymy na nasz kod to zobaczymy, że NetBeans koloruje tło pod kodem nalezącym do warunkowej kompilacji:


Dodatkowo dodał komentarze na początku linii pomiędzy //#else a //#endif. Dzięki temu kod nie będzie dołączony do kompilowanej aplikacji. Zmiany te są zapisywane w pliku na dysku (polecam sprawdzić) i NetBeans nie zawsze chce się odświeżyć (w sensie widoku pliku źródłowego). Warto wtedy zamknąć i otworzyć na nowo plik, aby wiedzieć co edytować. Ponadto mechanizm ten zapewnia bezbolesny eksport do innego środowiska IDE, które nie wspiera tego mechanizmu. Całość zostanie potraktowana jako zwykły komentarz.

Z drugiej strony mechanizm może utrudniać merge’owanie i śledzenie zmian w kodzie. No chyba że wszyscy będą pamiętać, aby przed commit’em jedną, zawsze tą samą konfigurację ustawić.

Czy blok if else endif to wszystko co daje nam warunkowa kompilacja w NetBeans? Nie. Z ciekawszych opcji mamy jeszcze //#condition NAZWA_ABILITY i dzięki której decydujemy czy dany plik ma być dołączony do danego build’a, czy nie. Deklaracja musi być jednak umieszczona na początku pliku!

No dobra, mamy już skonfigurowany kod, ale co z innymi zasobami? Np, z grafiką, którą np. potrzebujemy tylko do wersji z obsługiwanym ekranem dotykowym? Mamy możliwość zdefiniowania zasobów, które mają się w takiej konfiguracji znaleźć. W tym celu przechodzimy do właściwości projektu i wybieramy Librares & Resources. Odznaczamy Use Values from „DefaultConfiguration” i już możemy dodawać katalogi, biblioteki i inne wymagane projekty.

Nie pozostaje teraz nic innego jak wziąć się do roboty i zacząć odpowiednio dostosowywać nasze mobilne aplikacje.