27 czerwca 2013

Pauzowanie projektowe i przedwakacyjne zmiany służbowe = opuszczam IBM

10 komentarzy
Minęło parę już dni od ostatniego wpisu z cyklu "moje pierwsze kroki przy tworzeniu aplikacji pisanej w Scali, której daję czas od pomysłu do realizacji najwyżej 1 miesiąc." I nic się nie pojawiło od owych kilku dni! Projekt zamarł...niestety, bo obowiązków sporo i to rodzinnych głównie!

Najpierw zaczęło się od wyjazdu weekendowego, podczas którego napracowałem się bardzo. "Upodliłem" się pracując fizycznie i kiedy dopadłem już kompa, zaraz zatwittowałem o moim powrocie.

Powrót nie trwał jednak długo :(

We wtorek żonka obchodziła urodziny, więc znowu przytrafiło mi się odciąć od sieci. Dosłownie. Nie miałem ze sobą komputera, a w dodatku padła mi komórka, więc sieci nie widziałem przez dobre 2 dni! Odświeżające. Najbardziej zachwycona była moja żoncia (której nota bene też padła komórka!)

I tak dobrnąłem do czwartku, w którym również nie znalazłem wiele czasu na boje projektowe przy taskassinie. Widziałem komentarz Radka dotyczący stworzenia cechy (trait), który podzielam, ale niestety i dzisiaj przyszło mi zająć się innymi sprawami.

Z dniem jutrzejszym, 30 czerwca, kończę pracę w IBM.

Postanowiłem podreperować moją znajomość branży finansowej i od 1 lipca (poniedziałek) przechodzę do Citi na stanowisko (użyję mojego tłumaczenia) szefa technicznego zespołu programistycznego (Credit Front Office - Warsaw Team Lead).

Będzie Scala, Clojure i problemy analizy dużej ilości danych finansowych. Będą też ludzie, których znam osobiście i z którymi zawsze marzyłem usiąść przy jednym kompie, aby spędzić kilka dłuższych chwil, chociażby na dyskusji o niczym. Teraz dostaję to na tacy! Raportuję do kierowników w Londynie i Nowym Jorku, co podtrzymuje mój entuzjazm doskonalenia języka angielskiego. Słowem wszystko, co dusza moja pragnęła bardzo. Dodać należy również, że zawsze zastanawiało mnie, jak to jest być po drugiej stronie flanki - poza sektorem IT. Teraz będzie okazja zmaterializować marzenia.

Nie zostawiam WebSphere i rozwiązań IBM, bo uważam je za stosunkowo dobre, aby poświęcać im swój czas. Przyjdzie moment, w którym rozważę "kapitalizację" swojej wiedzy, ale na razie odkładam to na półkę z pomysłami. To z pewnością będzie ciekawie doświadczenie móc obserwować rozwój rynku WebSphere nie będąc już IBMerem.

Mówi się, że do końca roku zespół programistyczny ma liczyć 40 osób i potrzeba osób do programowania, jak i prowadzenia zespołów programistów od strony technicznej. Jeśli uważasz, że to robota dla Ciebie, napisz. Skontaktuję Cię z moim szefem, który zawiaduje procesem rekrutacji. To będzie niezwykła grupa pod względem osób i stosowanych technologii. Wprost robota marzenie (technicznie).

Dla zainteresowanych wycinki z opisu stanowisk:

"We are seeking highly motivated candidates to join on the ground floor of building our Framework Development Team in Warsaw, Poland.

The candidates will have responsibility for leading a team focused on development of core technology used by Citi’s Credit Trading business.

The Credit Front Office Development Team supports Credit Trading businesses in London, New York, and Asia.

Global Credit Technology is establishing a development center in Warsaw to work on core technology for our Credit Trading Businesses. This work will provide critical components for our new global strategy.

Thorough familiarity with algorithms & data structures.

Exposure to any of the following technologies is a bonus: WPF/XAML, Clojure, Scala, Hadoop, Apache Camel, HBase"

20 czerwca 2013

Dzień 7 z taskassin - wsparcie dla zadań cyklicznych

3 komentarzy
Przez ostatnie dni doświadczam powtarzającego się olśnienia użyteczności testów pisanych przed pisaniem kodu produkcyjnego. Pozostawię purystom językowym rozwikłanie zagadki, czy można być oświecanym tym samym zdarzeniem wielokrotnie (bo w końcu raz oświeconym trudno oczekiwać, że można zostać nim ponownie powtórnie przez to samo wydarzenie) i wracam do taskassin, w którym pojawiło się wsparcie dla...powtarzających się...zadań (a niechby to były zadania olśniewające).

I tu pojawia się dylemat młodego (stażem) programisty scalowego - czy, aby nie przeładowuję klasy pl.japila.taskassin.Task nadmiarowymi atrybutami? Dzisiaj dodałem recurring, recurTimes oraz intervalUnits. Czy, aby nie za wiele jak na jedno pojęcie w aplikacji?! Co zasugerujesz młodszemu (stażem)?

Dodatkowym problemem mentalnym jest jednostka czasu, która się pojawia tu i tam. Na razie jest to po prostu Int, ale coś mi mówi, że powinienem już teraz zwrócić uwagę na wyrażenie czasu w bardziej specjalizowany sposób, np. z użyciem faktycznych jednostek czasu jak minuta, godzina, nawet jeśli jedyną byłaby godzina lekcyjna (aka kwadrans). Sugestie rozwiązań wielce pożądane.
case class Task(label: String, due: DateTime, timeUnits: Int = 6,
  recurring: Boolean = false, recurTimes: Int = 0, intervalUnits: Int = 0)

object TaskUtils {

  def collectTasks(ts: List[Task], hours: Int): List[Task] = {
    @tailrec
    def collectTasks(ts: List[Task], accTs: List[Task], remHours: Int): List[Task] = {
      ts match {
        case t :: tail if (remHours >= 0 && remHours - t.timeUnits >= 0) =>
          if (t.recurring) {
            val tt = t.copy(recurTimes = t.recurTimes - 1)
            val tss = tt :: tail
            collectTasks(tss, t :: accTs, remHours - t.timeUnits - t.intervalUnits)
          } else
            collectTasks(tail, t :: accTs, remHours - t.timeUnits)
        case _ => accTs reverse
      }
    }
    collectTasks(ts, Nil, hours)
  }
}
Całość dostępna jako projekt taskassin na GitHubie.

19 czerwca 2013

Dzień 6 z taskassin w Scali - funkcja zliczająca zadania z @tailrec

3 komentarzy
Ależ to mi czasu zajęło, aby wpaść na pomysł skompletowania zadań na zadaną liczbę godzin! Próbowałem foldLeft i takeWhile z List, ale potrzebowałem nie tylko gromadzić dane o wielu elementach w liście (tutaj foldLeft mógłby być pomocny), ale również przerwać jej przetwarzanie w momencie zebrania wystarczających danych (takeWhile tylko z nazwy tutaj pasował, ale operuje wyłącznie na pojedynczych elementach). Co skłoniło mnie do intensywniejszej pracy umysłowej było obsłużenie sytuacji, w której należałoby przerwać przetwarzanie przy obsłudze list nieskończonych. Paradoks polegał jednak na tym, że najprawdopodobniej taka sytuacja nie ma prawa nastąpić, albo przynajmniej nie jest tematem w obecnym stanie aplikacji (!)

Rozwiązaniem okazało się stworzenie funkcji z rekurencją ogonową (użyłem dodatkowo @scala.annotation.tailrec dla wymuszenia tej cechy podczas kompilacji), której warunkiem końcowym byłoby właśnie zebranie wystarczającego zbioru zadań na daną jednostkę czasu.
object TaskUtils {

  def collectTasks(ts: List[Task], hours: Int): List[Task] = {
    @tailrec
    def collectTasks(ts: List[Task], accTs: List[Task], remHours: Int): List[Task] = 
      ts match {
        case t :: tail if (remHours >= 0 && remHours - t.timeSpanInHours >= 0) =>
          collectTasks(tail, t :: accTs, remHours - t.timeSpanInHours)
        case _ => accTs reverse
      }
    collectTasks(ts, Nil, hours)
  }
}
Uwagi i spostrzeżenia są wielce pożądane. Całość dostępna w projekcie taskassin na GitHubie.

18 czerwca 2013

taskassin na GitHubie dzień 3-5 = trait do zestawienia środowiska testu oraz ignore

4 komentarzy
Kontynuuję moje boje przy realizacji pomysłu napisania aplikacji w Scali - taskassin - w jeden miesiąc i mimo braku spektakularnych postępów, w pewnym sensie jestem zadowolony - zaczynam dostrzegać zalety pisania testów zanim powstanie kod produkcyjny aplikacji.

Lektura scaladoc dla org.scalatest.FunSpec zwróciła moją uwagę na Instantiating fixture traits jako mechanizm tworzenia środowiska wykonania testu. W ten sposób zarzuciłem cechę org.scalatest.BeforeAndAfter.
trait Fixture {
  val now = DateTime.now
  val t1 = new Task("t1", now, 10)
  val t2 = new Task("t2", now + 2.hours)
  val t3 = new Task("t3", now - 2.hours)

  def compByDueDate(t1: Task, t2: Task) = t1.due < t2.due
  val ts = List(t1, t2, t3) sortWith compByDueDate
}

describe("List of three tasks (with 2 hours in between)") {
  it("should pop tasks by due order") {
    new Fixture {
      assert(ts.head === t3)
    }
  }
}
Już widziałem taką konstrukcję w trakcie kursu Functional Programming Principles in Scala, ale nie bardzo rozumiałem tej konstrukcji. Tym razem trafiłem na nią z innej strony - jakby od dołu, gdzie trafiłem na problem, którego rozwiązaniem było właśnie zastosowanie tej konstrukcji z utworzeniem instancji cechy. To lubię!

Poza tym przez moment mogłem nacieszyć się z dobrodziejstw metody ignore dla nowej funkcjonalności, którą niestety nie wiedziałem, jak oprogramować. Piszę test, aby się dowiedzieć - liczę, że implementacja wyjdzie w praniu, kiedy będę realizował stronę użytkownika (czym jest właśnie test). Tylko dlaczego nie mogę znaleźć scaladoc dla ignore?! Może ktoś mógłby mi pomóc, proszę?

Zmiany są dostępne w projekcie taskassin na GitHubie.

15 czerwca 2013

Męk intelektualnych kontynuacja - taskassin na GitHubie dzień 2

5 komentarzy
Wczorajszych, piątkowych męk intelektualnych związanych z tworzeniem aplikacji taskassin w Scali nie mniej i dzisiaj, w sobotę. Mimo braku czasu na specjalnie długie zastanawianie się, co i jak należałoby zrobić, aby poprawić moją sytuację, usprawniłem TaskListTest, w którym próbuję się odnaleźć i przekuwam idee w kod.

Dzisiaj postanowiłem zanurzyć się w dokumentacji ScalaTest, aby nie skończyć z przekopiowaniem części kodu testu. W ten sposób znalazłem metodę pending, która (jak możnaby wywnioskować z jej nazwy) w ciele metody testującej pozwala na opóźnienie momentu, w którym test faktycznie powstanie. Innymi słowy, wiesz, że taki test musi powstać, ale nie bardzo wiesz, jak należałoby go napisać (aka zaimplementować). Sprytne.

W ten sposób powstał test jak poniżej.
describe("List of three tasks (with 5 minutes in between)") {
  it("should return the tasks for today") (pending)
}
Wykonanie takiego testu przechodzi poprawnie, ale oznaczone jest żółtym kolorem.

To lubię!

Skorzystałem również z potrójnej równości, która przy niepomyślnym porównaniu wyświetla różnice w bardziej zrozumiałej postaci, z dokładną informacją o różnicy.

Ostatnią zmianą było użycie before z traitu org.scalatest.BeforeAndAfter.
before {
  val t2 = new Task("t2", DateTime.now + 2.minutes)

  /* http://mkaz.com/solog/how-to-sort-collections-in-scala */
  /* sort by due date */
  def compByDueDate(t1: Task, t2: Task) = t1.due < t2.due

  ts = List(t2, t1) sortWith compByDueDate
}
Krótka lektura Getting started with FunSpec, która zajęła mi bagatela 10 minut, a wiedzy i zmian ogrom (na długie godziny). Niestety kodu produkcyjnego wciąż mało. Zmiany są dostępne w projekcie taskassin na GitHubie.

14 czerwca 2013

Taskassin na GitHubie dzień pierwszy (oficjalnie)

0 komentarzy
Cóż za kuriozalna sytuacja! Wiem, że potrzebuję aplikację, potrafię ją napisać, a jednak wciąż nie wiem, od czego zacząć. Mam wszystko, a jakbym nie miał niczego.

Ktoś z głową powiedziałby, że wystarczy przecież zacząć od pierwszej funkcjonalności, która miałaby znaleźć się w aplikacji. A mimo wszystko, nie wiedziałem wciąż, jak zacząć. To znaczy, wiem, co chcę, ale nie wiem, jak zacząć.

Nie miałeś/-aś tego wcześniej? Mnie ciągle dopada. A szczególnie, kiedy znajduję się w nowym środowisku, a Scala właśnie takim środowiskiem jest...wciąż.

To był ten właśnie moment, w którym zacząłem zastanawiać się nad stworzeniem testów, które "wymusiłyby" na mnie napisanie wyłącznie koniecznej funkcjonalności mojej przyszłej aplikacji. To jest nie pierwszy już raz, kiedy doświadczam tego olśnienia, w którym przekonuję się o słuszności metody "najpierw testy, później kod aplikacji".

I tak właśnie zacząłem moje pierwsze kroki przy tworzeniu aplikacji pisanej w Scali, której daję czas od pomysłu do realizacji najwyżej 1 miesiąc. Nie będzie lekko, ale muszę spróbować. Właśnie teraz jest odpowiedni moment.

Zaintrygowany/-a? Można śledzić moje poczynania na GitHubie - projekt taskassin.


29 maja 2013

giter8 i sbt - pierwsze kroki przy tworzeniu projektów ze Scalą

0 komentarzy
Zawsze zastanawiało mnie, jak rozpocząć pracę z językiem Scala z linii poleceń. Potrzebowałem mechanizmu, który utworzyłby mi katalog na potrzeby projektu w Scali, z odpowiednio ułożonymi podkatalogami na kody źródłowe samej aplikacji oraz jej testów.

giter8 - narzędzie tworzenia plików i katalogów na podstawie szablonów w GitHub

Był czas, kiedy żyłem w błogiej niewiedzy istnienia Scala Build Tools (sbt). Potrzebowałem narzędzia do zarządzania projektem - budowania go z pobraniem zależnych bibliotek, kompilacją, wykonaniem testów, itp. To właśnie zadanie dla sbt.

Wszystkie znaki na niebie i ziemi mówiły mi, że ostatnią rzeczą, jaką robi sbt, to utworzenie nowego projektu z właściwą strukturą katalogową. Okazało się, że sbt jest na tyle "wyrafinowane", że potrafi pracować z każdą strukturą katalogów, co w zasadzie powinno mnie cieszyć, ale przy mojej niewiedzy, tylko komplikowało sprawę. Skąd miałbym wiedzieć, jak rozłożyć pliki źródłowe aplikacji, aby było dobrze, jeśli...wszystko może być dobrze (czy właśnie nie odpowiedziałem sobie na to pytanie?)

To zapewne był powód odpalenia projektu giter8 (w skrócie g8). Już nie pamiętam, kto mi go wskazał, ale to miało być rozwiązaniem moich bolączek. I faktycznie było.

"Giter8 is a command line tool to generate files and directories from templates published on github or any other git repository. It's implemented in Scala and runs through the Simple Build Tool launcher, but it can produce output for any purpose."

Instalacja opisana jest na stronie Installation. Jej zakończenie obwieszcza uruchomienie g8.
$ g8

giter8 0.5.3
Usage: g8 [TEMPLATE] [OPTION]...
Apply specified template.

OPTIONS
    -b, --branch
        Resolves a template within a given branch
    --paramname=paramvalue
        Set given parameter value and bypass interaction.


Apply template and interactively fulfill parameters.
    g8 n8han/giter8

Or
    g8 git://github.com/n8han/giter8.git

Apply template from a remote branch
    g8 n8han/giter8 -b some-branch

Apply template from a local repo
    g8 file://path/to/the/repo

Apply given name parameter and use defaults for all others.
    g8 n8han/giter8 --name=template-test

g8 typesafehub/scala-sbt - Scala sbt template

I co teraz?

W Usage do g8, napisano: "Template repositories must reside on github and be named with the suffix .g8. We're keeping a list of templates on the wiki." I to cieszy, że komuś zależy i zebrał pomocne szablony w jednym miejscu!

Właśnie dzisiaj trafiłem na projekt Scala sbt template, który jest "A giter8 template for Scala projects using sbt."

Skoro należy do repozytorium projektów Typesafe Inc., to można założyć, że jest projektem błogosławionym przez samych twórców Scali (niekoniecznie gwarancja jakości, ale chociaż aktualności). Coś mi jednak mówi, że ostatnia zmiana "authored a year ago" nie jest specjalnie obiecująca w kontekście aktualności projektu. Ale co robić?

Odpalam g8 typesafehub/scala-sbt i korzystam wstępnie z projektu.
$ g8 typesafehub/scala-sbt

Scala Project Using sbt

organization [org.example]: pl.japila
name [Scala Project]:
scala_version [2.9.2]: 2.10.1
version [0.1-SNAPSHOT]:

Template applied in ./scala-project

jacek:~/sandbox
$ cd scala-project/
jacek:~/sandbox/scala-project
$ tree
.
├── README
├── project
│   └── ScalaProjectBuild.scala
└── src
    └── main
        └── scala
            └── pl
                └── japila
                    └── ScalaProject.scala

6 directories, 3 files
$ cat README
A sample for the Typesafe Stack (http://typesafe.com/stack).

Scala sample project using Scala and SBT.

To run and test it use SBT invoke: 'sbt run'

jacek:~/sandbox/scala-project
$ sbt run
[info] Loading project definition from /Users/jacek/sandbox/scala-project/project
[info] Updating {file:/Users/jacek/sandbox/scala-project/project/}default-9e49ab...
[info] Resolving org.scala-sbt#precompiled-2_10_0;0.12.2 ...
[info] Done updating.
[info] Compiling 1 Scala source to /Users/jacek/sandbox/scala-project/project/target/scala-2.9.2/sbt-0.12/classes...
[info] Set current project to Scala Project (in build file:/Users/jacek/sandbox/scala-project/)
[info] Updating {file:/Users/jacek/sandbox/scala-project/}scala-project...
[info] Resolving org.scala-lang#scala-library;2.10.1 ...
[info] Done updating.
[info] Compiling 1 Scala source to /Users/jacek/sandbox/scala-project/target/scala-2.10/classes...
[info] Running pl.japila.ScalaProject
Hello, Scala Project
[success] Total time: 13 s, completed May 29, 2013 10:08:54 PM
"Hello, Scala Project" oraz "success" na końcu dają mi pewne poczucie spełnienia moich oczekiwań. Mam swój pierwszy projekt w Scali z udziałem g8!

g8 kobmic/plain-scala

Jeszcze na koniec swojej wyprawy w świat uruchomienia projektów scalowych z g8 przeszukałem sieć i trafiłem na kobmic/plain-scala. Wydaje się być świeższą i bardziej kompletną alternatywą do szablonu z Typesafe.

Projekt scala-project idzie do kosza i odpalam g8 kobmic/plain-scala.
jacek:~/sandbox
$ g8 kobmic/plain-scala

Plain Scala project with scalatest and/or specs2

version [0.1.0-SNAPSHOT]:
organization [my.organization]: pl.japila
name [MyScalaProject]:

Template applied in ./myscalaproject
I już widzę miejsce do poprawy w szablonie - nazwa tworzonego projektu jest bez (ostatnio ulubionych) myślników.

Kontynuuję prace...
jacek:~/sandbox
$ cd myscalaproject
jacek:~/sandbox/myscalaproject
$ tree
.
├── build.sbt
├── project
│   └── plugins.sbt
└── src
    ├── main
    │   └── scala
    │       └── Stub.scala
    └── test
        └── scala
            ├── StubSpec.scala
            └── StubTest.scala

6 directories, 5 files
Tym razem stawiam na pisanie testów do mojego wymyśl(o)nego projektu w Scali. Stąd też powód uruchomienia sbt test.

// pół pobranego Internetu później...
jacek:~/sandbox/myscalaproject
$ sbt test
[info] Loading project definition from /Users/jacek/sandbox/myscalaproject/project
[info] Set current project to MyScalaProject (in build file:/Users/jacek/sandbox/myscalaproject/)
[info] StubTest:
[info] you description here
[info] - should do something
[info] StubSpec
[info]
[info] The 'Hello world' string should
[info] + contain 11 characters
[info] + start with 'Hello'
[info] + end with 'world'
[info]
[info]
[info] Total for specification StubSpec
[info] Finished in 27 ms
[info] 3 examples, 0 failure, 0 error
[info]
[info] Passed: : Total 4, Failed 0, Errors 0, Passed 4, Skipped 0
[success] Total time: 4 s, completed May 29, 2013 10:57:20 PM
W Usage projektu można przeczytać, że odpalenie sbt eclipse lub sbt gen-idea pozwala na łatwiejsze wczytanie projektu do ulubionego IDE. Wybieram IntelliJ IDEA.