czwartek, 2 sierpnia 2007

Ruby potęgą jest i basta!

Pisanie w języku Ruby może być miłą odmianą po codziennej używaniu języków o statycznej kontroli typów. To oczywiście subiektywna opinia, ale może uda mi się, szanowny Czytelniku, przekonać chociaż do zapoznania się z możliwościami, jakie daje Ruby.

Oto konkretny przykład. Potrzebny nam był w pracy niewielki skrypt, który miał zaktualizować adresy e-mail użytkowników wg określonego klucza. Razem z kolegą usiadłem więc do JEdit i po chwili 64-liniowy skrypcik Ruby był gotowy. Otwierał połączenie z Oracle, odczytywał dane z blisko 60 tys. kont, przerabiał e-mail dla tych, które spełniały określone kryteria, po czym zapisywał z powrotem do bazy danych. Po drodze tworzył plik z opisem zmian i wypluwał na ekran kilka komunikatów.

Nic nadzwyczajnego, prawda? Dlatego byliśmy mocno zdziwieni, kiedy skrypt po uruchomieniu zamarł. Zjadł 90% czasu procesora i... to tyle. Po przerwaniu jego męczarni, dopisaniu jeszcze kilku tekstów o postępie działania i ponownym uruchomieniu okazało się, że wbrew pozorom coś robi, tylko strasznie wolno. Kilka minut później skrypt zakończył działanie, pozostawiając bazę we właściwym stanie, mnie mocno zaniepokojonego, a kolegę zniesmaczonego. Miałem co prawda podejrzanego:

if emails.include? row[1]
...
else
emails << row[1]
end

gdzie "emails" to tablica (Array). Czyżby metody "include?" oraz "<<" na tablicy 60 tys. elementów się nie sprawdzały? Odpowiedź przyszła dzień później. Na grupie comp.lang.ruby ktoś pytał czy istnieje metoda "not-include?". Jak to zwykle na c.l.r dostał dużo odpowiedzi ("unless" zamiast "if", "if not", "if !"). Między innymi, Brett Simmers zasugerował użycie Set zamiast Array, jeśli istotne jest tylko czy dany element znajduje się w zbiorze. I to było to!

W moim skrypcie niezbędne były zaledwie te zmiany:
  1. require 'set' (Set jest w standardowych bibliotekach Ruby)
  2. emails = Set.new (zamiast emails = Array.new)
Po ich wprowadzeniu i ponownym uruchomieniu, skrypt wykonał się w kilkanaście sekund.

Jaki z tego morał? Imponująca jest elastyczność kodu pisanego w Ruby, w którym wprowadzanie zmian nie musi powodować konieczności pisania od nowa całych jego fragmentów. A wartość dodana, jaką stanowi społeczność Ruby, jest przysłowiową wisienką na torcie.

Brak komentarzy: