Programista Java w Rubylandzie, część 2. Pierwsza aplikacja.

01.12.2011

Ok, w poprzednim odcinku okazało się, że daje się zainstalować Rubyego i Railsy. Zobaczymy teraz, że nasz naiwny obraz Świata zostanie zburzony.

Będziemy chcieli utworzyć aplikację blog, taką samą, która jest w tutorialu Railsów na ich stronie, tyle, że działającą z normalną bazą danych, czyli w tym wypadku z Postgresem. Brzmi prosto? O nie, nie, nie. Może pod Linuksem albo MacOs-em idzie to normalnie, ale nie pod Windowsem.

Pierwsza rzecz to instalacja Postgresa. Lepiej się nie rzucać na wersję 9 (nie jest oficjalnie wspierana przez Rails – chyba nie jest), i nie należy dotykać się wersji 64 bit. Jeżeli ktoś nie lubi ćwiczeń w rodzaju podawanie w różnych, losowo wybranych miejscach ścieżki do Postgresa jako C:\Progra~1\PostgreSQL\8.4\bin to lepiej nie instalować Postgresa w Program Files tylko gdzieś, gdzie nie ma spacji w ścieżce.

Druga rzecz, to sterownik (czyli w ichniej terminologii, adapter) Rubyego do Postgresa. W Rubym instalacja jest tożsama z instalacją odpowiedniego gem-a. Wchodzimy więc na stronę wiki, żeby się dowiedzieć, jak się ten gem nazywa. I od razu człowiek się cieszy, bo ma do wyboru aż 4 adaptery. Prawda, że super?

Sytuacja się na szczęście upraszcza. Rozwijanie adaptera postgres znudziło się jego twórcą w 2008 roku. Jego następcą jest pg, który jest “natywnym” adapterem, który wymaga zainstalowania kawałka linuksa pod Windowsem.

Jest też postgres-pr, który jest adapterem napisanym tylko w Rubym, co wróży nędzną wydajność, ale powinno pozwolić uniknąć kłopotów z instalacją. Dodatkowo ostatnio ktoś się do niego dotykał w marcu 2009, co jest według autora wiki “sign of active development”. Zdaje się, że ostatnia wersja jest z grudnia 2009.

Jest jeszcze ruby-postgres, ale strona projektu wskazuje, że wszyscy jego deweloperzy zajęli się dawno czymś innym.

Najbardziej sensowną opcją jest użycie pg. Weźmy się więc za to.

Pierwsza rzecz, to adapter ten jest napisany w C (czyli jest “natywny”), w związku z tym pod Windowsem trzeba sobie zainstalować Developnent Kit. Instrukcję na tej stronie należy wykonać dokładnie, sprawdzając czy się gdzieś nie pomyliliśmy. Tutaj problemów nie napotkałem.

Następnie instalujemy gem pg: gem install pg? He, he, he. Takie rzeczy to tylko działają w tutorialach na stronie Railsów. To, co trzeba zrobić to:

gem install pg --platform=mswin32 --version=0.9.0 -- --with-pg=c:\programs\PostgreSQL\8.4\

Uwagi:

  1. mimo, że najnowszą wersją pg jest 0.10.0, to nie udało mi się z nią ruszyć, zresztą nie tylko mi,
  2. te dodatkowe dwa minusy za numerkiem wersji a przed --with-pg są potrzebne, to nie literówka,
  3. ukośnik na końcu ścieżki Postgresa też jest potrzebny.

Ja wiem, że niektórzy teraz przecierają oczy, że jakiś kawałem teoretycznie produkcyjnego kodu ma numer wersji 0.10, ale najwyraźniej tak jest.

Jak się wszystko poinstalowało, to możemy zająć się utworzeniem aplikacji.

Piszemy w konsoli
rails new c:\katalog\z\projektami\blog -d postgresql

Railsy generują gotowy do uruchomienia szkielet projektu. To znaczy niby on jest gotowy do uruchomienia, ale nie jest. Można się o tym łatwo przekonać wchodząc do utworzonego katalogu blog i pisząc w konsoli rails server.

Trzeba zrobić dwie rzeczy:

  • w pliku blog\config\database.yml podajemy poprawne ustawienia dla baz danych: Rails pracuje z trzema bazami: deweloperską, testową i produkcyjną (i bardzo słusznie) – trzeba ustawić poprawnie nazwę użytkownika, nazwę bazy, itp,
  • w pliku blog\Gemfile poprawiamy gem 'pg' na gem 'pg', '0.9.0', w innym przypadku Rails sobie doinstaluje sam najnowszą wersję pg, która nie chciała mi działać.

Uff teraz piszemy w konsoli, w katalogu projektu, bundle install, a następnie rails server i na http://localhost:3000 powinna się pojawić strona powitalne naszej aplikacji.

Póki co aplikacja nic nie robi, ale to już temat na kolejny wpis.


Programista Java w Rubylandzie, część 1. Początki.

01.11.2011

Ruby to podobno fajny, miły i przyjemny język programowania. Spędziłem trochę czasu na pisaniu aplikacji w Ruby-on-Rails (zdaje się 90% wszystkiego pisanego w Ruby jest aplikacją Ruby-on-Rails) i chciałbym się podzielić swoimi doświadczeniami. Także z samym sobą, jak bym musiał sobie coś za rok przypomnieć.

Zacznijmy od instalacji. Dla porządku: instaluję wersję Rails 3.0.3, jak się przekonamy nawet zmiana na wersję 3.0.4 może spowodować, że poniższą instrukcję będzie sobie można wsadzić w railsa. Takie tu panują zwyczaje.

Dodatkowo używam Windows 7 64 bit, warto od razu zaznaczyć, że nie ma sensu instalować czegokolwiek 64 bit. Ruby, Railsy itp. pod Windowsem żyją w świecie x86. Ale ogólnie, to instalacja na wszystkich platformach wygląda podobnie.

Zacznijmy wreszcie. Wchodzę na stronę http://rubyonrails.org/ i klikam dużą ikonę Get Started (wiadomo, Web 2.0, duże ikony, pastelowe kolorki).
Ruby ma całkiem sympatyczny instalator windowsowy. Od razu mają plus. Ale co ja widzę:

We recommend Ruby 1.8.7 or Ruby 1.9.2 for use with Rails. Ruby 1.8.6 and earlier are not supported, neither is version 1.9.1.

Ok, rozumiem, że wersja wcześniejsza niż 1.8.7 nie jest wspierana (w Open Source to norma), ale dlaczego wersja 1.9.1 nie jest wspierana, a 1.9.2 jest??? Jak się człowiek przyzwyczaja, że aplikacja napisana w Java 10 lat temu ruszy na Java 6 z 2010, to się może lekko zdziwić.

Następna rzecz to RubyGems, czyli taki sprytny menadżer pakietów. Coś jak Maven.

Download (extract, then run “ruby setup.rb”)

I co?

source_index.rb:62:in `installed_spec_directories’: undefined method `path’ for Gem:Module (NoMethodError)

No pięknie, jeszcze nic nie zacząłem robić, a już dostaję wyjątek, tfu, error. Szukam w googlu i okazuje się, że to wszystko moja wina. Przecież powinienem wyśledzić w changelogach itp. miejscach, że wersja 1.4.2 Rubygems nie współpracuje z Ruby 1.9.2. Oczywiście można wykonać szereg hakierskich sztuczek, odpowiednich upgradów i downgradów, żeby można było użyć… no dobrze, nie ważne.

RubyGems jest dostarczony z Ruby 1.9.2, więc można sobie krok instalacji Gems odpuścić. Nie to, żeby w instrukcji było to napisane.

Szukam programu gem w katalogu bin instalacji Rubyego i wpisuje magiczne gem install rails i czekam, czekam, czekam. Wreszcie, bez dalszych niespodzianek, wszystko się pięknie instaluje. W katalogu bin rubyego pojawia się program rails. Czas na test:

rails new c:\TRASH\testapp
cd c:\TRASH\testapp
rails server

Pierwsza linijka powoduje utworzenia szkieletu aplikacji (jak by ktoś nie wiedział, to Rails jest sprytnie wymyślonym generatorem aplikacji i frameworkiem Model-View-Controller w jednym – JBoss Seam, Grails, Spring Roo właśnie z tego rżnęli pomysły); trzecia linia uruchamia serwer WWW z gotową do działania aplikacją. To znaczy nie uruchamia, bo dostajemy

Could not find gem ’sqlite3-ruby (>= 0, runtime)’ in any of the gem sources listed in your Gemfile.
Try running `bundle install`.

Jak ktoś chce być cool i używać dżezi technologies, to się musi trochę napocić.

Może porada Try running `bundle install’ pomaga? Pomaga, jeżeli mamy zainstalowaną bazę sqlite. Ja nie mam i nie mam zamiaru mieć, więc poprzestańmy na tym, co mamy: jest Ruby, są Railsy, coś tam działa.

Konfiguracją normalnej bazy danych i odpaleniem prostego projektu zajmiemy się następnym razem. Dopiero wtedy zacznie się prawdziwa zabawa.


Java FX na Olimpiadzie zimowej

02.12.2010

Jeszcze się okaże, że będę musiał zmienić swoje sceptyczne nastawienie do JavaFX. JavaFX zostało wybrane jako technologia do wizualizacji danych o medalach na stronie Olimpiady Vancouver 2010.

Wygląda toto faktycznie dobrze, nie da się odróżnić od Flasha, można złośliwie powiedzieć. Jak Oracz zainwestuje w poprawienie narzędzi deweloperskich i sensowną bibliotekę komponentów, to może coś z tego będzie.


Extreme Programming w San Diego

02.12.2010

Ubawił mnie niezwykle wpis Bruce Eckela na Artima.com:

Last night I went to the Extreme Programming San Diego meeting (it should probably be called “Agile” but I suspect the group is old enough that XP was what started it). A reader knew that I was in San Diego visiting my folks so he suggested it. I thought I’d dip my toe in the water and see if programming was any more interesting to me than the last time I checked. Especially since Agile practices tend to be more focused on people issues, which is where I seem to continue to drift.

The first thing I noticed was the turnout. I’m guessing there are thousands of programmers in San Diego, but we got maybe 10 people to show up.

Chyba w San Diego już się połapali, że 90% Agile to wynalazek cwanych konsultantów… 10 osób to i tak niezły wynik.


Sun w łapach Oracla

02.02.2010

No i stało się, firma Sun przeszła do historii. Oracle szumnie zapowiada, jak to będzie rozwijał i inwestował. Zapowiedzi mają niewielkie znaczenie, nawet pierwszy rzut oka wyglądają pięknie, ale parę nieprzyjemnych rzeczy z nich wynika. Nieprzyjemnych dla użytkowników produktów SUN-a.

Weźmy NetBeans. Oracle ogłosił:

Oracle will invest in the NetBeans IDE and NetBeans.org community, but it will be limited to Java Standard Edition, scripting languages, mobile Java, JavaFX and Solaris. Oracle’s own Java IDE, JDeveloper IDE, will be Oracle’s enterprise application development tool.

Czyli NetBeans będzie środowiskiem programistycznym do wszystkiego, tylko nie do Java EE. Ponieważ gro aplikacji Javowych jest pisanych właśnie w Java EE, to praktycznie oznacza utrupienie NetBeans na rzecz JDevelopera. Kto będzie chciał się wozić ze środowiskiem Javowym, w którym nie można napisać aplikacji JEE? Szkoda.

GlassFish ma być wspierany i rozwijany, ale jako serwer do aplikacji intranetowych:

WebLogic will be sold as the company’s enterprise application server, while the free and open source Glassfish server will be Oracle’s department-level application server.

Myślałem, że Oracle będzie chciał podgryzać GlassFishem JBoss-a, ale wygląda na to, że nie. W takim razie, kto będzie chciał się bawić w serwer, który w założeniu ma być “gorszy” od WebLogic-a. GlassFish, czyli tak na prawdę Sun GlassFish Enterprise Server (dawniej Sun ONE Application Server), jakoś szczególnie nie ustępuje WebLogicowi, co więc zamierza Oracle? Ma już dwa serwery aplikacyjne, teraz dochodzi trzeci; obawiam się, że GlassFish może szybo odejść w odstawkę pod pretekstem nie przynoszenia zysków. Chyba, że faktycznie Oracle ma jakiś dobry pomysł na niego.

Wygląda na to, że z kolei Oracle zamierza inwestować w JavaFX. To akurat mocno mnie dziwi, bo póki co na tle Silverlighta czy Flex-a JavaFX nie wygląda najlepiej, przynajmniej od strony potencjału bycia czymś równie popularnym, jak konkurenci. Technologicznie JavaFX jest bardzo fajnym pomysłem, ale funkcjonalność, dostępne komponenty są lata świetlne za innymi wynalazkami. Może tutaj Oracle ma jakiś ciekawy pomysł na biznes?


Wstrzykiwanie zależności czyli Dependency Injection. Część 5: wykorzystanie Google Guice

07.09.2009

W poprzednim odcinku widzieliśmy, jak można sobie ułatwić życie wstrzykując zależności do klas przy pomocy Springa [reszta cyklu: część 1., część 2., część 3.]. Dzisiaj czas na coś prostszego i przyjemniejszego: Google Guice!
Czytaj resztę wpisu »


Wstrzykiwanie zależności czyli Dependency Injection w 9 minut i 59 sekund. Część 4: wykorzystanie Spring-a

04.30.2009

Jak widzieliśmy [część 1., część 2., część 3.] wstrzykiwanie zależności jest całkiem sympatycznym pomysłem (o ile się go poprawnie używa), ale można zapytać się, na ile jest to kosztowne? Przez koszty rozumiem tutaj nakład pracy, jaki trzeba włożyć w używanie architektury wykorzystującej DI.

Wyobraźmy sobie, że nasza aplikacja często wykorzystuje klasę NewsService. Co to oznacza w praktyce? Za każdym razem musimy wstrzykiwać do niej zależność, których potrzebuje. Nasz przykład jest dość prosty, zależności nie ma zbyt wiele, ale nawet tutaj powtarzanie przy każdym użyciu kodu

public class Client {
  public static void main(String[] args) {
    Authenticator authenticator = new UsernamePassAuthenticator("beer","beer");
    Driver driver = new SqlDbDriver();

    //inject dependency #1
    Storage storage = new DBStorage(driver);
    //inject dependency #2
    NewsService newsService = new NewsService(storage);
    //inject dependency #3
    newsService.setAuthenticator(authenticator);

    newsService.addNews("ble ble ble");
  }
}

nie jest zbyt zachęcające. Czy nie lepiej jest użyć jednak jakiego wzorca factory czy service locator, żeby jednak NewsService sam sobie znalazł potrzebne klasy?
Czytaj resztę wpisu »


Wstrzykiwanie zależności czyli Dependency Injection w 9 minut i 59 sekund. Część 3: jak źle używać DI

04.10.2009

Kontynuujemy dalej naszą przeprawę z DI [część 1., część 2.]. W tym odcinku postaramy się w końcu coś popsuć – radosny marsz ścieżką usłaną różami jest przyjemny ale nie zawsze pouczający.

Zastanówmy się na ile użycie wstrzykiwania zależności czyni nasze oprogramowanie odpornym na błędy przy projektowaniu architektury aplikacji. W końcu nawet najwspanialszy wzorzec projektowy nie zabroni nam popełniania błędów.

Przyjrzyjmy się nieco zmodyfikowanej klasie NewsService

public class NewsService {

  Storage storage;
  Authenticator authenticator;

  public NewsService(Driver driver) {
    storage = new DBStorage(driver);
  }

  public Authenticator getAuthenticator() {
    return authenticator;
  }

  public void setAuthenticator(Authenticator authenticator) {
    this.authenticator = authenticator;
  }

  public void login(String uname, String pass){
    ((UsernamePassAuthenticator)authenticator).setUname(uname);
    ((UsernamePassAuthenticator)authenticator).setPass(pass);
  }

  public void addNews(String news){
    if(authenticator != null){
      authenticator.authenticate();
    }
    storage.save(news.getBytes());
    System.out.println("News saved...");
  }
}

Różni się ona od poprzedniej wersji w jednym drobnym, ale bardzo istotnym szczególe. Klasa NewsService w konstruktorze pobiera jako parametr sterownik (obiekt Driver), a nie, jak poprzednio Storage. W rezultacie NewsService sam sobie musi utworzyć obiekt Storage.

Kod NewsService jest wówczas związany na sztywno z konkretną implementacją kontenera na dane DBStorage, co jest oczywiście niepożądane. Co się zatem stało, co zrobiliśmy nie tak – w końcu używamy DI? A no popełniliśmy błąd polegający na tym, że wstrzykujemy do NewsService nie ten obiekt, co trzeba!

NewsService nie potrzebuje do niczego informacji o użytym sterowniku, NewsService potrzebuje tylko konkretnej implementacji Storage i to ona już ma się martwić o sterownik.

Ok. tutaj przypadek był prosty i ewidentny. W większych aplikacjach łatwo popełnić błąd polegający na wstrzyknięciu nie tego obiektu, który tak na prawdę jest wymagany. Także jeżeli widzimy, że gdzieś inicjalizacja klasy wymaga tworzenia obiektów, albo przekazujemy klasie jako parametr obiekty, które, logicznie rzecz biorąc, nie są jej potrzebne, to znaczy, że gdzieś położyliśmy architekturę aplikacji i błędnie użyliśmy DI.

Użycie DI wcale nie uwalnia nas od dobrego zaprojektowania aplikacji!


Wstrzykiwanie zależności czyli Dependency Injection w 9 minut i 59 sekund. Część 2: o tym, co tak właściwie robi DI

12.28.2008

W poprzednim wpisie znęcaliśmy się nad niezbyt gramotnie napisanym kawałkiem oprogramowania. Teraz przyszedł czas na napisanie wszystkiego tak, jak trzeba, w czym nam pomagać będzie właśnie wstrzykiwanie zależności.

Co nas najbardziej uwierało w poprzedniej wersji aplikacji? Tak na prawdę były to dwie rzeczy:

  1. Powiązania między klasami były zrealizowane przy użyciu referencji do konkretnych klas: jeżeli NewsService potrzebował mechanizmu do przechowywania informacji, to dawaliśmy mu referencję do klasy, która potrafiła przechowywać dane w SQL-owej bazie danych. Zmiana sposobu przechowywania danych na inny wymagała zmian w wielu miejscach w kodzie.
  2. Jeżeli klasa potrzebowała do pracy innej klasy, to sama musiała sobie utworzyć odpowiedni obiekt: NewsService potrzebując klasy do przechowywania danych sam sobie tworzył jej instancję.

Co w takim razie robi wstrzykiwanie zależności? Mówiąc ogólnie, w DI chodzi o to, żeby nie wiązać się z inną klasą poprzez użycie jej implementacji, tylko poprzez interfejs, pod który można podpiąć dowolną klasę go implementującą.

Dodatkowo, jeżeli nasza klasa potrzebuje konkretnej implementacji tego interfejsu, to nie powinna tej implementacji sama szukać czy jej tworzyć. Odpowiedni obiekt musi zostać do klasy “wstrzyknięty” w momencie inicjalizacji.

Zobaczmy, jak to wygląda w praktyce.
Czytaj resztę wpisu »


Wstrzykiwanie zależności, czyli Dependency Injection w 9 minut i 59 sekund. Część 1: podręczny przewodnik tworzenia złych aplikacji

12.23.2008

Gdzie się człowiek nie obejrzy tam się czai Dependency Injection (DI), czyli wstrzykiwanie zależności. Żeby jeszcze było tego mało, jak się zaczyna grzebać w internecie, to się co chwila można potknąć o jakiś framework, kontener czy coś takiego, co nam samo może zrobić Dependency Injection.

Co to w ogóle jest, po co takie coś komukolwiek, jak tego używać? Okazuje się, że sprawa jest prosta, wręcz banalna, a jednocześnie prowadzi do całkiem interesujących zastosowań. Za chwilę postaramy się zrozumieć jak DI działa, zrobimy to w sposób praktyczny, obdarty z krążących wokół DI ideologii i zupełnie zbędnego adżajlowego bełkotu.

Przekonamy się, że DI jest jednym z wielu możliwych sposobów budowania architektury aplikacji tak, by była łatwa w rozbudowie i testowaniu.

Będziemy chcieli zobaczyć coś więcej, niż zupełnie trywialny przykład (takich jest mnóstwo w internecie), po którym w zasadzie można wzruszyć ramionami, bo nie specjalnie widać tam jakiekolwiek zalety architektury wykorzystującej DI.

Naszym celem będzie zbudowanie bardzo prostej aplikacji służącej do przechowywania informacji, będzie składała się ona z trzech warstw (trójka jest nieprzypadkowa, sporo aplikacji Java EE jest rozbijane na tyle warstw) i tyluż komponentów.

Naszą aplikację napiszemy na kilka sposobów:

Zatem, do dzieła!
Czytaj resztę wpisu »