Wspomnienia podevcrowdowe 2014

April 18th, 2014

Tegoroczny DevCrowd był dla mnie nie lada wyzwaniem. Dwie prezentacje wymagały nie tylko dość mocnego ogarnięcia się, ale też okazały się dużym obciążeniem jeśli chodzi o gadane. Z drugiej strony oznaczało to też, że zamiast jednej przegapiłem dwie fajne prezentacje. No ale po kolei…

StackOverflow, GitHub i twitter jako narzędzia profesjonalnego rozwoju programisty – Jacek Laskowski

Jacek (@jaceklaskowski) opowiedział jak z jego punktu widzenia działają twotter, github i stackoverflow w kontekście rozwoju i samodoskonalenia. Otrzymaliśmy zatem solidną dawkę przykładów oraz recept na to jak zaistnieć w środowisku jako profesjonalista oraz osoba, która jest postrzegana jako chętnie dzieląca się wiedzą.
Całkiem fajna prezentacja :)

Programista to za mało – Bartłomiej Nićka

Bartek skupił się na tym co poza twardymi umiejętnościami warto rozwijać w życiu. Jakie są relacje na linii programista – klient i dlaczego we współczesnym świecie tak ważne są zdolności komunikacji. Mam na to trochę inne zapatrywanie i nie zgadzam się ze wszystkimi tezami prezentacji. Jednak programiści to ludzie, do których należy podchodzić z ogromnym szacunkiem, a relacja musi być oparta na zaufaniu. Smutnym wnioskiem z prezentacji było to, że zawód programisty nie jest postrzegany jako prestiżowy. I ciężko się z tym nie zgodzić.

Javascript development done right – Paweł Szulc

Paweł (@paulszulc) w swoim stylu opowiedział o różnicach mentalnych pomiędzy javascriptem, a programistami java. Termin na dziś “Mordor script”. Prezentacja bardzo wartościowa pod względem merytorycznym ponieważ pokazał w niej rzeczy, które zazwyczaj stają się pułapkami na programistę java zabierającego się za javascript.

Scrum, but… – Matt Harasymczuk

Matt (@TheAgileMatt) opowiedział trochę o tym jak scrum działa w praktyce. Kiedy go stosować, a kiedy iść w stronę innych metodyk. Sama prezentacja bardzo ciekawa, choć styl z serii tych, które średnio lubię. Ogólne wrażenie jednak pozytywne.

How To Tackle Java EE 7 – prezentacja zdalna – Adam Bien

Adam (@AdamBien) zrobił nam krótki kurs javy ee 7. Bardzo tutorial, bardzo podstawy…. such not wow. Choć prelegent to superman javy, jeden z Java Champions, to temat jak i wykonanie mnie zawiodły. Nic ponad to co mogę znaleźć w podstawowych tutkach.

Podsumowanie

Jak zwykle było super. I mam nadzieję, że za rok też się spotkamy :)

Pomocna Guava – informacje o domenie

March 30th, 2014

Dawno nic technicznego nie było… zatem wracamy do tematyki związanej z Guavą. Na dziś krótko o narzędziu, które ułatwia pracę z domenami, czyli o klasie InternetDomainName.

Chwila teorii

Jak zapewne wiecie po sieci poruszamy się z pomocą adresów internetowych, czyli domen. Domena z jednej strony mapuje się na odpowiedni IP serwera (to robi za nas system DNS), a z drugiej siedzi w “drzewie domen” nad którym nadzór sprawuje ICANN. Ale nie o tym chciałem.

Konkretne domeny, które są “własnością” firm, instytucji czy osób prywatnych, są w rzeczywistości pod-domenami albo dziećmi, jeżeli używamy drzewiastej nomenklatury, domen wyższego poziomu. Domeny wyższego poziomu dzielimy na dwie grupy. Pierwsza to Top Level Domain (TLD), czyli korzenie drzewa domen. Należą do nich na przykład .com, czy .net. Druga grupa to Top Public Domain (TPD) zwana też Public Suffix. Domeny te pozwalają na rejestrowanie domen dzieci w swoim drzewie każdemu kto ma na to ochotę. Przykładem takiej domeny jest co.uk.
Kilka regułek:

  • TLD może być TPD np. .com
  • TPD nie zawsze jest TLD np. .co.uk
  • Są domeny, które pomimo, że są korzeniem drzewa domen nie są TLD ani TPD.

Ta ostatnia grupa czasami jest nazywana prywatnymi TLD. Koszt takiej domeny to około 1000USD. Jest tylko jeden drobny problem… Otóż ICANN nie oferuje tego typu wynalazków, a do alternatywnych dostawców usług DNS zazwyczaj nie podpinają się ISPki. Zatem taka domena to dość drogi mało skuteczny substytut viagry.

Do tego dochodzą zasady związane z umieszczaniem plików cookie na poziomie poszczególnych domen… znaczy na domenach publicznych tego nie zrobimy i tyle.

Ok… wiemy, że TLD są dostarczane przez ICANN to co z TPD? Otóż jest sobie taka stronka http://publicsuffix.org, która zawiera listę większości publicznych sufiksów dla domen. Klasa InternetDomainName pozwala ogarnąć ten burdel :D

Klasa InternetDomainName

Jest to jedna biedna klasa jedynaczka. Ma zarówno metody fabrykujące jak i narzędziowe. Na listingu 1. zamieściłem przegląd możliwości tej klasy.

Listing 1. Klasa InternetDomainName i jej metody

public class InternetDomainNamesBasics {

	public static final String KOZIOLEKWEB_PL = "koziolekweb.pl";
	public static final InternetDomainName KOZIOLEKWEB_PL_IDN = from(KOZIOLEKWEB_PL);

	public static final String APPSPOT_COM = "appspot.com";
	public static final InternetDomainName APPSPOT_COM_IDN = from(APPSPOT_COM);

	public static final String TYRSOFT_PL = "tyrsoft.com";
	public static final InternetDomainName TYRSOFT_PL_IDN = from(TYRSOFT_PL);

	public static final String ETH = "8thcolour";
	public static final String ETH_TYRSOFT_PL = "8thcolour.tyrsoft.com";
	public static final InternetDomainName ETH_TYRSOFT_PL_IDN = from(ETH_TYRSOFT_PL);


	public static void main(String[] args) {
		isValidExample();
		childExample();
		parentExample();
		hasParentExample();
		hasPublicSuffixExample();
		isPublicSuffixExample();
		isTopPrivateExample();
		isUnderPublicSuffixExample();
		partsExample();
		publicSuffixExample();
		topPrivateDomainExample();
	}

	public static void isValidExample() {
		System.out.printf("Domain %s is %s\n", KOZIOLEKWEB_PL, validInvalid(isValid(KOZIOLEKWEB_PL)));
		System.out.printf("Domain %s is %s\n", "Koziołekłeb.pl", validInvalid(isValid("Koziołekłeb.pl")));
		System.out.printf("Domain %s is %s\n", "$#%$##.com", validInvalid(isValid("$#%$##.com")));

	}

	public static void childExample() {
		InternetDomainName child = TYRSOFT_PL_IDN.child(ETH);
		System.out.printf("Domain %s has child %s and it is %s to %s\n", TYRSOFT_PL, child,
				equalNotEqual(child.equals(ETH_TYRSOFT_PL_IDN)),
				ETH_TYRSOFT_PL);

	}

	public static void parentExample() {
		InternetDomainName parent = ETH_TYRSOFT_PL_IDN.parent();
		System.out.printf("Parent of %s is %s and is %s to %s\n", ETH_TYRSOFT_PL, parent
				, equalNotEqual(parent.equals(TYRSOFT_PL_IDN)), TYRSOFT_PL);

		System.out.printf("Parent of %s is %s\n", TYRSOFT_PL, TYRSOFT_PL_IDN.parent());

	}

	public static void hasParentExample() {
		System.out.printf("Is domain %s has parent? %s\n", TYRSOFT_PL, yesNo(TYRSOFT_PL_IDN.hasParent()));
	}

	public static void hasPublicSuffixExample() {
		System.out.printf("Has domain %s public suffix? %s\n", TYRSOFT_PL, yesNo(TYRSOFT_PL_IDN.hasPublicSuffix()));
		System.out.printf("Has domain %s public suffix? %s\n", ETH_TYRSOFT_PL, yesNo(ETH_TYRSOFT_PL_IDN.hasPublicSuffix()));
	}

	public static void isPublicSuffixExample() {
		System.out.printf("Is domain %s public suffix? %s\n", TYRSOFT_PL, yesNo(TYRSOFT_PL_IDN.isPublicSuffix()));
		System.out.printf("Is domain %s public suffix? %s\n", APPSPOT_COM, yesNo(APPSPOT_COM_IDN.isPublicSuffix()));
	}

	public static void isTopPrivateExample() {
		System.out.printf("Is domain %s TPD? %s\n", TYRSOFT_PL, yesNo(TYRSOFT_PL_IDN.isTopPrivateDomain()));
		System.out.printf("Is domain %s TPD? %s\n", ETH_TYRSOFT_PL, yesNo(ETH_TYRSOFT_PL_IDN.isTopPrivateDomain()));
		System.out.printf("Is domain %s TPD? %s\n", APPSPOT_COM, yesNo(APPSPOT_COM_IDN.isTopPrivateDomain()));
	}

	public static void isUnderPublicSuffixExample() {
		System.out.printf("Is domain %s under public suffix? %s\n", ETH_TYRSOFT_PL, yesNo(ETH_TYRSOFT_PL_IDN.isUnderPublicSuffix()));
		System.out.printf("Is domain %s under public suffix? %s\n", APPSPOT_COM, yesNo(APPSPOT_COM_IDN.isUnderPublicSuffix()));
	}

	public static void partsExample() {
		System.out.printf("Domain %s parts: %s\n", ETH_TYRSOFT_PL, on(", ").join(ETH_TYRSOFT_PL_IDN.parts()));
	}
	public static void publicSuffixExample() {
		System.out.printf("Domain %s public suffix is %s\n", ETH_TYRSOFT_PL, ETH_TYRSOFT_PL_IDN.publicSuffix());
	}
	public static void topPrivateDomainExample() {
		System.out.printf("TPD of %s is %s\n", ETH_TYRSOFT_PL, ETH_TYRSOFT_PL_IDN.topPrivateDomain());
	}

}

Po kolei.

Metoda from

Statyczna metoda fabrykująca. Tworzy nowy obiekt na podstawie przekazanego String-a (NIE IP). Jeżeli przekazany String nie pozwala na stworzenie prawidłowej domeny… no cóż…

Metoda isValid

Żadnej magii. Metoda sprawdza poprawność String-a pod kątem RFC3490. Znaki diakrytyczne w nazwach są poprawne… choć nie wszystkie przeglądarki się z tym lubią.

Metoda child

Niestatyczna metoda fabrykująca, która na podstawie przekazanego parametru tworzy nowy obiekt reprezentujący pod-domenę dla obiektu na rzecz którego jest wołana. Oczywiście wywali się gdy podamy null oraz gdy nowy twór będzie nieprawidłowy.

Metoda parent

Odwrotnie do poprzedniej. Zwraca obiekt reprezentujący nad-domenę dla tej reprezentowanej przez obiekt, na rzecz którego ją wywołano.

Metoda hasParent

Metoda weryfikuje czy dana domena (reprezentowana przez obiekt.. ble, ble, ble…) ma rodzica czy też jest korzeniem.

Metoda hasPublicSuffix

Podobna do poprzedniej, ale dodatkowo sprawdza czy rodzic jest publicznym sufiksem.

Metoda isPublicSuffix

Sprawdza czy mamy do czynienia z publicznym sufiksem. Przydatna gdy chcemy ustawić ciastko “na rodzicu” i nie wiemy czy wywołanie jest z poziomu naszej domeny czy też z którejś z pod-domen.

Metoda isTopPrivate

Podobna do poprzedniej. Sprawdza jednak czy nasza domena jest prywatna i jej rodzić przez przypadek nie jest prywatny.

Metoda isUnderPublicSuffix

Sprawdza czy domena znajduje się w drzewie publicznego sufiksu, ale nim nie jest.

Metoda parts

Metoda działa jak split po kropkach.

Metoda publicSuffix

Metoda zwraca publiczny sufiks domeny. Albo null jak taki nie istnieje.

Metoda topPrivateDomain

Podobnie jak poprzednia, ale tym razem zwraca nam najwyższa domenę prywatną w naszym drzewie.

Podsumowanie

Po co? Ponieważ czasami musimy popracować z nazwami domen w ramach naszych serwletów (spraw ciastków) i przydało by się mieć jakieś ogarnięcie w tym temacie. Klasa dostarcza tak naprawdę jedną ważną funkcjonalność – walidację w ramach RFC 3490 wraz ze sprawdzaniem listy publicznych sufiksów. Po prostu nie musimy robić tego sami.

LambdaDays 2014, czyli funkcyjnie

March 1st, 2014

Plan wyjazdu na konferencję LambdaDays pojawił się w naszych zespołowych głowach gdzieś w okolicy kolejnej nieudanej próby naprawienia jakiegoś dziwnego buga w aplikacji GWT.
Pomysł był prosty – 27 i 28 lutego jedziemy do Krakowa. Świat i projekt się nie zawalą. Co pomyśleli to i uczynili i tak oto w środę wieczorem wylądowaliśmy w mieście Krakowie. Powitała nas policja ganiająca się z jakimś blokersem… dzień jak co dzień.
W czwartek udaliśmy się na wydział informatyki AGH, tak na TO AGH.

The Emperor’s New Clothes: The Problem With Software Products – Garrett Smith

Prezentacja dotyczyła problemu używania narzędzi, “bo są zajebiste”. Garrett (@gar1t) na przykładzie własnych doświadczeń oraz baśni Andersena pokazał co może się stać jeżeli używamy narzędzi tylko dlatego, że są fajne, albo akceptujemy propozycje cwanych i skomplikowanych rozwiązań tylko po to by nie wyjść na idiotę.
Bardzo fajne.

Keynote: Idioms for building distributed fault-tolerant applications with Elixir – José Valim

@josevalim tym razem już stricte technicznie o tym jak tworzyć odporne na zwałę rozwiązania w erlangu z użyciem elixira. Dość fajne, a dla osoby która nie ma do czynienia z tym językiem na co dzień na pewno dobry popularnonaukowy keynote.

Keynote: Akka in Heterogenous Environments – Jan Macháček

Jan (@honzam399) zaprezentował prosty system rozpoznawania obrazu napisany w Akka z wykorzystaniem dodatkowo RabbitMQ i magii kodeków. To już było mi bliższe ponieważ co scala to scala.
Prezentacja o tyle ciekawa, że pomimo kodowania na żywo nic się w sumie nie wywaliło :)

Peeling Onions Without Tears – Reading and Writing Intuitive Abstractions in Scala – Jon Pretty

Prezentacja Jona (@propensive) była z tych dziwnych. Odniosłem wrażenie, że choć mówi o rzeczach ważnych to jednocześnie gdzieś zgubił sens tego co chciał przekazać. Dodatkowym utrudnieniem było dość mało czasu co spowodowało, że wdarł się chaos.

An intro to F# – Anthony Brown

W swoim czasie Jacek Laskowski dużo pisał o F#. Tu temat powrócił został naprawdę super zaprezentowany. Anthony (@BlueYolkStudios) nie bawił się w piękne slajdy… po prostu w ramach jednego długaśnego skryptu w F# zaprezentował wszystkie podstawowe elementy języka oraz omówił co można, a czego nie można z nimi zrobić. Genialna w swej prostocie prezentacja.

Migrating to Clojure. So much fn. – Jan Stępień

Prezentacja bardzo fajna. Świetnie omawiająca problemy z jakimi można się spotkać gdy chcemy naprawiać świat poprzez poprawianie gównokodu. Tu Jan omówił problem migracji z aplikacji RoR, która stała się “nieutrzymywalna” i jednocześnie potwornie powolna na Clojure. Świetnie się tego słuchało. Naprawdę.

Benefits and challenges of migration from Java to Scala.- Wojciech Durczyński

Prawem sponsora jest zrobienie prezentacji… i na tym poprzestańmy. Jedyna prezentacja w języku polskim.
Jakoś do mnie nie przekonali do scali jako rozwiązania, które ma naprawić chujowo napisany kod w javie… kod, który można poprawić w wielu przypadkach tylko poprzez dodanie jednej biblioteki… o której miałem pisać, a nie mam czasu :D

Smyrna: An easy Polish concordancer in Clojure – Daniel Janus

Daniel (@nathell) opowiedział trochę o swoim projekcie wyszukiwarki leksykalnej (uwzględniającej formy słów) oraz o tym jak użera się ze wzbogaceniem jej o wyszukiwanie oparte o rozpoznawanie znaczenia w ramach kontekstu. W sumie bardzo fajna i znowuż bardziej popularnonaukowa prezentacja.

Prezentacja dodatkowa – Jamie Allen

Rzecz, której nie było w programie. Jamie opowiedział trochę o tym dlaczego lambdy nie są takie fajne i jakie problemy będziemy mieli w najbliższym czasie gdy trafią do Javy 8.
Na bazie jego prezentacji chciałbym przygotować własną w podobnej tematyce. Zatem oczekujcie na c4p z Confitury ;)

Co działo się na afterparty po pierwszym dniu niech pozostanie na afterparty… tak będzie dobrze dla nas wszystkich ;)

FP Performance and Scala: Beyond Big O Notation – Jamie Allen

Kolejny dzień zaczęliśmy od prezentacji Jamiego poświęconej wydajności i temu jak należy na nią patrzeć. Kolejna świetna i pouczająca prezentacja.

Erlang Patterns Matching Business Needs – Torben Hoffmann

Antyprezentacja dla poprzedniej. Inaczej… To co Jamie pochwalił Torben (@LeHoff) zjechał i na odwrót. To co wyniosłem to metodę wprowadzania nowych technologii do firmy. Naprawdę fajnie się słuchało o tym jak można gadać z biznesem i na podstawie twardych argumentów pokazać, że niech biznes zajmie się piciem i nie wpieprza się w technologię.

From 1000 to 10k users per server – concurrency rediscovered with Akka – Piotr Gabryanczyk

Bardzo, bardzo dobra prezentacja pokazująca na co tak naprawdę trzeba zwracać uwagę gdy tworzymy kod. Fajnie przedstawiona została skala optymalizacji w odniesieniu do bardziej ludzkich wymiarów.
Piotr (@piotrga) przedstawił sposób na to jak z aktorów Akka wyciągnąć naprawdę 120% normy.

An Open Erlang PaaS Done Right – Vladimir Kirillov

Fajnie opowiedziane. Erlang jest jednak mocarnym rozwiązaniem, a możliwość bezpiecznego ukatrupienia procesu to duży plus… Co tu więcej dodać.

Delivering User Value in Post-Functional World – Rafał Pokrywka

Kolejna prezentacja sponsora… wszyscy wiedzieli o co chodzi, a prowadzący tylko siał zamęt. Taki biztalk…

LuvvieScript – an OTP-ish compile-to-javascript dialect of Erlang (plus runtime…) – Gordon Guthrie

Gordon (@gordonguthrie) poopowiadał o narzędziu pozwalającym na pisanie aplikacji www client-side w erlangu. Czy mówi wam coś GWT? ;)

Types of Types… in Scala – Konrad Malawski

Konrad (@ktosopl) opisał system typów w scali. Dzięki niemu już wiem, że mój dreadnought będzie nazywał się Robert (robot, co ma w sobie coś z człowieka).
Prezentacja powinna w sumie być zamieniona z kolejną. Ta była bardziej zaawansowana i wymagała już trochę wiedzy na temat tego jak scala operuje typami.

Type classes 101 – Jerzy Müller

Prezentacja uzupełniająca poprzednią o podstawy. Razem stanowiły całkiem niezłą lekcję scali.

Podsumowanie

Miło jest oderwać się od smutnej javy i posłuchać o czymś kompletnie innym. Sama konferencja była dobrze przygotowana, a jedyny problem to brak przerw pomiędzy prezentacjami w ramach poszczególnych bloków. To trochę bolało lecz zostało szybko wyjaśnione co i jak.

Za rok pewno też pojadę.

Czas spierdalania, czyli suplement

January 21st, 2014

Do wczorajszego wpisu.

Niech mi ktoś powie jak to jest, że w poniedziałek mogłem rozliczyć całą moją pracę jako przedsiębiorca, a już we wtorek nie mogę? Przepisy się nie zmieniły… Biurwokratyczna kurwa zadziałała…

Dlaczego uciekają?

January 20th, 2014

W sumie miało być o guavie, bo coś się ostatnio zaniedbałem w temacie, ale nie chce mi się…

Będzie o czymś innym.

Wizyta w urzędzie działa na mnie intensywniej niż litr czystej kofeiny. Po prostu na samą myśl, że muszę spotkać się z biurwokracją dostaję cholery.
Rzecz w tym, że biurwokracja w Polsce siedzi w głębokiej mentalnej może nie komunie, ale w ustroju podobnym do złotej wolności szlacheckiej. Przy czym biurwa jest panem, a petent chamem.

Wynika to jednak nie z natury biurwokratów, lecz ze środowiska w którym przyszło im działać. Na przykładzie. Zmiana miejsca zameldowania na pobyt stały. Podkreślmy ZMIANA i POBYT STAŁY.

Procedura powinna składać się z jednego kroku – złożenia wniosku o zameldowanie w nowym miejscu. Nic więcej… niestety nie w Polsce. W Polsce poza wnioskiem o zameldowanie w nowym miejscu należy też złożyć wniosek o wymeldowanie z poprzedniego miejsca zameldowania, bo oczywistym jest, że można posiadać tylko jedno miejsce zameldowania na pobyt stały… wróć…

Oczywistym jest, że skoro można posiadać tylko jedno miejsce zameldowania na pobyt stały to w momencie zameldowania w nowym miejscu wymeldowujemy się z poprzedniego. “Automagicznie”, bez konieczności składania kolejnego wniosku nawet jeżeli wniosek ten składa się na tym samym druku. Niestety nikt nie wpadł na ten genialny pomysł i cham musi uniżenie składać kolejne podpisy pod kolejnymi kopiami papierów zawierających te same dane.

Jak już się przemeldujemy to musimy złożyć wniosek o dowód osobisty. Oczywiście jest to osobny wniosek ponieważ rzeczą niezwykłą jest konieczność zmiany dowodu w momencie przemeldowania. Cóż… kolejny papierek. Kolejny podpis. Kolejne wypełnianie kratek. Pomijam tu kompletną bezsensowność samej procedury wypełniania formularza w momencie gdy dowód osobisty ma na rewersie odpowiednie “zakodowane” oznaczenia do automatycznego odczytu…

Jak już jesteśmy po nowy dowód to znowuż musimy złożyć dwa podpisy. Pierwszy, że nowy dowód nam wydano i drugi, że stary anulowano… na tym samym kwicie… czy nie prościej było by oznaczyć odpowiednie pole… nie… nie w Polsce.

Oczywiście po zmianie dowodu należy też wymienić prawo jazdy, a i tablice rejestracyjne zmienić należy (co jest majstersztykiem inteligencji)…

Czas na udzielenie odpowiedzi na tytułowe pytanie.

Z 2mln ludzi, którzy uciekli z Polski tylko część pojechała za płacą. Nie pracą, a właśnie płacą pozwalającą na spokojne utrzymanie rodziny. Część jednak nie potrzebowała “większych pieniędzy”, bo miała dobrze płatny fach w ręku. Ludzie ci uciekli właśnie od tego bezsensownego biurwokratycznego systemu, który pozbawiony jest logiki i zamiast wspierać tylko niszczy ludzi…

ps. Ostatni gasi światło, bo emisja CO2 ;)

Prosta metoda na “pijanych kierowców”

January 15th, 2014

Tak naprawdę na kierowców, którzy utracili uprawnienia, bo na wsiadających za kierownik na bani nie ma metody.

Zamiast alkomatu w każdym aucie czy czujnika alkoholu przygotować coś innego. Czytnik prawa jazdy. Podobny do tego jaki obecnie montuje się w droższych samochodach do czytania kluczyków.

Wkładasz prawko do czytnika jedziesz. Nie wkładasz możesz odpalić silnik, ale nie pojedziesz szybciej niż 10km/h (manewrowanie na parkingu jest dzięki temu możliwe).

Kwestia “lewych” praw jazdy. Czytnik komunikuje się z CEPiKiem (o ile ten powstanie, bo łapówki poszły, a CEPiK nie działa na 100%).
Kwestia “pożyczania” praw jazy. Odpowiedzialność karna taka jak obecnie przy “pożyczaniu” np. dowodu osobistego dla obu stron.
Kwestia “podmiany” prawa jazdy w czytniku. Matkę oszukasz, księdza oszukasz, ale logów nie oszukasz.

Dodatkowe bonusy

  • Ograniczenie liczby użytkowników pojazdu do zdefiniowanych praw jazdy (problem “urodzinniania” samochodów służbowych).
  • Integracja z GPS pozwalająca na np. odcinkowe pomiary prędkości – dupa będzie boleć, bo trzeba przestrzegać przepisy.
  • Integracja z GPS w celu prowadzenia “książki przejazdów”.
  • Ułatwienie kontroli pojazdów – wymagany w pełni funkcjonalny CEPiK.

Niech Omnissiah was prowadzi i wspiera, a Duch Maszyny nie zawodzi.

Kolekcje w Guavie I – Ordering, czyli komparatory po nowemu

January 12th, 2014

Jak wspomniałem w pierwszym tekście o guavie w tym cyklu najczęściej wykorzystywaną funkcjonalnością tej biblioteki jest ta związana z obsługą kolekcji. Nie ma się czemu dziwi ponieważ Guava jako taka wyrosła z Google Collections.

Dziś przyszedł czas na pierwszy tekst poświęcony pracy z kolekcjami w Guavie. Przyjrzymy się klasie Ordering, czyli guavowej “implementacji” interfejsu Comparator.

Wartość dodana

Jak wiadomo Java jest takim śmiesznym językiem, który ma wiele fajnych rozwiązań, ale zazwyczaj brakuje mu “tego czego” co jest potrzebne i co trzeba w końcu samemu wyrzeźbić. Tak jest w przypadku Optional, będących odpowiedzią na brak wartości domyślnej parametru, tak jest z funkcjami, które “naprawiają” brak domknięć, itd.
W przypadku Ordering główna motywacją do użycia jest dostarczenie kilku podstawowych metod pracujących na interfejsie Comparator, a przydatnych przy pracy z kolekcjami.

Rodzaje Ordering

Sama klasa Ordering jest abstrakcyjna i od klas dziedziczących wymaga implementacji tylko jednej metody – compare pochodzącej z interfejsu Comparator. Jeżeli zatem chcemy użyć tej klasy na takiej samej zasadzie jak zwykłego komparatora odpuśćmy sobie. Nie ma to większego sensu. Względnie jeżeli zależy nam na ujednoliceniu kodu możemy wykorzystać metodę natural w celu stworzenia obiektu dla klasy implementującej Comparable tak jak na listingu 1.

Listing 1. Tworzenie naturalnego komparatora

public class OrderingExamples {

	public static void main(String[] args) {
		Ordering<Name> forName = Ordering.natural();
		// not complie - Mongy is not Comparable
		Ordering<Mongy> forMongy = Ordering.natural();

	}
	

}


class Name implements Comparable<Name>{

	public final String value;

	Name(String value) {
		this.value = value;
	}

	@Override
	public int compareTo(Name o) {
		return value.compareTo(o.value);
	}
}

class Mongy{

	public final String value;

	Mongy(String value) {
		this.value = value;
	}
}

Próba stworzenia obiektu dla klasy Mongy nie przejdzie nawet kompilacji. Można to oczywiście spróbować obejść wykorzystując “pseudo naturalną” kolejność opartą o metodę toString:

Listing 2. Tworzenie komparatora opartego o toString

class Mongy {

	public final String value;

	Mongy(String value) {
		this.value = value;
	}

	@Override
	public String toString() {
		return "Mongy{" +
				"value='" + value + '\'' +
				'}';
	}
}
//...
Ordering<Object> forMongy = Ordering.usingToString();

W tym przypadku możemy mówić o stworzeniu swoistej “protezy”, dla obiektów nieporównywalnych, która pozwoli na na uogólnienie kodu… na przykład w funkcjach… znowu eliminujemy efekty uboczne… To zresztą nie jest istotne. Jeżeli przyjrzymy się innym implementacjom tej klasy

Metoda allEqual

Dostarcza nam komparator traktujący wszystkie obiekty jako równe sobie… powinno się posiadać specjalną zmienną globalną w kodzie COMUNISM by trzymać tam ten obiekt..

Metoda arbitrary

W tym przypadku tego komparatora obiekty są równe jeżeli są tym samym, operator ==. Jeżeli prawy jest null zwracane jest 1 jeżeli lewy -1. Jeżeli to nie daje rady porównywane są wyniki System.identityHashCode(metoda zwraca rezultat hashCode, ale taki jaki byłby gdyby nie nadpisano tej metody). Jeżeli to zawiedzie… cóż… idź puść lotka bo masz farta.

Metoda compound

Ten komparator będzie już bardziej cwany niż koledzy. W momencie gdy porównanie zwróci 0 odpalany jest “komparator drugiej szansy”. Argumentem jest zbior komparatorów odpalanych jeden po drugim w celu osiągnięcia jakiegoś niezerowego rezultatu. Tu przykład na komparator złożony nasuwa się samemu.

Metoda explicit

Tu sprawa jest prosta. Przekazujemy już uporządkowaną kolekcję i na jej podstawie dokonywane jest porównanie.

Metoda from

Tworzy obiekt klasy Ordering na bazie istniejącego komparatora.

Rozbudowa komparatorów

Stworzenie komparatora, nawet trochę bardziej złożonego nie jest niczym szczególnym. Z powyższej listy na uwagę zasługuje tylko “łańcuchowanie” komparatorów ponieważ pisanie tego z palucha jest kapkę upierdliwe, ale się da. Guava pozwala na bardziej przyjazne konfigurowanie komparatorów.

Metoda compound

Podobna do omówionej wcześniej, ale nie statyczna i pozwalająca na zastosowanie “komparatora drugiej szansy” w stosunku do istniejącego już rozwiązania. Dobra sprawa w połączeniu z komparatorem tworzonym za pomocą arbitrary w przetwarzaniu funkcyjnym.

Metoda lexicographical

Rzecz z tym komparatorem opiera się o dziwaczną nazwę. Generalnie porównywanie leksykalne, bo nie słownikowe czy językowe, oznacza porównanie wg. długości. Jak to działa. Przekazujemy dwa iterowalne zbiory. Większy jest zbiór dłuższy. Jeżeli zbiory są równe to porównywane są kolejne elementy aż do wystąpienia wyniku innego niż 0. Jeżeli zbiory są równe i wszystkie ich elementy w kolejności też są równe to zwracamy 0. Przy czym jest to zmyłka, bo nie jest to komparator słownikowy i na przykład próba porównania tablicy stringów [1, 0] i [2] da nieoczekiwany wynik.

Metody nullsFirst i nullsLast

Wzbogacają nasz komparator o obsługę null w sposób “przewidywalny”.

Metoda onResultOf

To jest naprawdę fajna metoda. Tworzy nam nowy komparator, który przed porównaniem obiektów zaaplikuje im funkcję i porówna wyniki. Pozwala to na zbudowanie komparatora dla danego typu o ile tylko mamy funkcję, która zmieni nam inny typ do którego posiadamy komparator na oczekiwany. Zawsze trochę mniej roboty, a i jakoś tak fajnie to wygląda w kodzie.

Metoda reverse

Metoda zwraca komparator odwrotny.

Mamy Ordering i co dalej

Dotychczas opisując sposoby tworzenia i konfigurowania poprzez komparator rozumieliśmy obiekt klasy Ordering. Jak już go mamy to czas najwyższy zobaczyć co on może i czego nei musimy implementować na własną rękę.

Metoda binarySearch

Wywołuje metodę z klasy Collections o tej samej nazwie. Jako trzeci argument, komparator, przekazuje siebie tzn. obiekt klasy Ordering.

Metoda greatestOf

Metoda zwraca K największych obiektów w zbiorze w kolejności od największego.

Metoda leastOf

Metoda zwraca K najmniejszych obiektów w zbiorze w kolejności od największego. Czyli bez rewelacji jak na razie…

Metoda immutableSortedCopy

Otrzymujemy posortowaną, niezmienną kopię oryginalnego zbioru. Oznacza to, że nie jest to widok podatny na zmiany oryginalnego zbioru. Oznacza to też, że można się tu przejechać robiąc memoryleaka w postaci dodatkowych referencji w nowej liście…

Metody isOrdered i isStrictlyOrdered

Pierwsza z nich sprawdza tylko czy zbiór został posortowany (n<=n+1). Druga dodatkowo sprawdza czy nie zawiera on elementów równych (n

Metody min i max

Ok… to wiadomo…

Metoda sortedCopy

Posortowana kopia… co tu dużo mówić…

Podsumowanie

Nie wygląda to jakoś super bogato, ale nie zapominajmy, że dzięki tej klasie możemy uniknąć pisania duperelnego kodu w stylu n-największych/najmniejszych, pierwsze nulle, ale tylko w tym miejscu itp. Klasa warta zastosowania, tam gdzie dotychczas rzeźbiliśmy ręcznie tego typu “dodatki”.

Własne układy w Vaadin

January 8th, 2014

Krótka przerwa od Guavy i przesiadka na Vaadin. Dziś o własnych szablonach układów.

Problem wyglądu

Często gęsto jest tak, że chcąc uzyskać jakiś konkretny układ graficzny dla bardziej skomplikowanych komponentów graficznych tworzymy własne komponenty. Własne komponenty składamy w bardziej skomplikowane by finalnie uzyskać pożądany efekt.
Doskonałym przykładem tego typu sytuacji są wszystkie aplikacje zarówno webowe jak i desktopowe. Sam też niejednokrotnie na forum 4programmers pisałem, że “jak nie potrafisz ułożyć skomplikowanego layout podziel go na mniejsze i spróbuj znowu”. Jest to oczywiście kolejne zastosowanie metody “dziel i zwyciężaj” lecz w przypadku Vaadin niesie ona duże niebezpieczeństwo.

Problem spotykany jest też w Swingu – spadek wydajności przy renderowaniu okien. Rzecz oczywiście rozbija się o to jak wiele dodatkowej pracy związanej z wyliczaniem pozycji komponentów ma aplikacja. Co więcej, jest to robione “pod spodem” i tym samym ma magiczną zdolność do bycia ignorowanym.

W przypadku Vaadin niepisana zasada mówi, żeby nie zagnieżdżać więcej niż trzy LayoutManagery. Pierwszym będzie zatem główny układ aplikacji. Drugim układ okna, trzecim układ komponentu… i zaczyna być ciasno w przypadku skomplikowanych komponentów.

Jak to ogarnąć?

Paradoksalnie najprościej ten problem rozwiązać stosując stary dobry CSS w połączeniu z klasami rozszerzającymi CustomLayout. Layout ten to nic innego jak swoisty “trik” pozwalający na wykorzystanie szablonów napisanych w czystym html-u jako layoutów w Vaadin.

Część HTML + CSS

W trakcie generowania aplikacji za pomocą mavena możemy podać nazwę wykorzystywanej skórki (theme). Podajemy coś tam, coś tam i teraz w src/main/webapp/VAADIN/themes/ mamy katalog o nazwie jaką podaliśmy. W nim są obecnie tylko pliki css i scss, ze stylami naszej aplikacji. Tworzymy zatem tu katalog layouts, a w nim plik MyCustomLayout.html.

Listing 1. Plik MyCustomLayout.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
<nav location="button" id="button-box"></nav>
<div location="label" id="label-box"></div>
</body>
</html>

Jak widać jest to zwykły, “goły” plik html. Jedyna różnica w stosunku do innych plików tego typu polega na dodatkowych atrybucie location w elementach, które mają być miejscami “wstrzyknięć” komponentów Vaadin. Następnie w pliku styles.css konfigurujemy nasz układ:

Listing 2. konfiguracja układu w styles.css

#button-box{
    border: 1px solid #afafff;
    height: 4em;
    width: 12em;
}
#label-box{
    border: 1px solid #afafff;
    height: 4em;
    width: 12em;
    font-family: garamond;
}

Tyle. Oczywiście można to dowolnie rozbudowywać, przekształcać i dostosowywać do potrzeb. Co więcej jeżeli zastosujemy taki układ jako główny dla aplikacji możemy dodać statyczne grafiki tak jak w HTMLu.

Część javowa

Tu sprawa troszkę się komplikuje jeżeli chcemy sobie ułatwić życie w przyszłości. Po pierwsze musimy przygotować klasę reprezentującą nasz nowy układ:

Listing 3. Klasa MyCustomLayout

public class MyCustomLayout extends CustomLayout {

	private final static String NAME = "MyCustomLayout";

	public MyCustomLayout() {
		super(NAME);
	}

	public void addComponent(Component c, Placeholders p) {
		addComponent(c, p.placeholder);
	}
//...
}

Pole NAME po przekazaniu do konstruktora klasy nadrzędnej będzie traktowane jako nazwa pliku przy czym nie należy dodawać sufiksu .html, bo się zjebie.

Kolejnym elementem jest enum Placeholders:

Listing 4. Enum Placeholders

public class MyCustomLayout extends CustomLayout {
//...
	public static enum Placeholders {
		BUTTON("button"),
		LABEL("label");
		private final String placeholder;

		Placeholders(String label) {
			this.placeholder = label;
		}
	}
}

Który będzie sobie siedział w naszym layoucie. Dlaczego tak? Ponieważ możemy popełnić literówkę w nazwie punku “wstrzyknięcia”. Łatwiej poprawić ją w jednym miejscu niż w wielu.

La grande finale

Czas to wszystko złożyć do kupy w postaci naszej aplikacji testowej. Przerobiłem po prostu wygenerowany kod na taki:

Listing 5. Aplikacja testowa

@Theme("mytheme")
@SuppressWarnings("serial")
public class MyVaadinUI extends UI {

	@Override
	protected void init(VaadinRequest request) {
		final MyCustomLayout layout = new MyCustomLayout();
		setContent(layout);

		Button button = new Button("Click Me");
		button.addClickListener(new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				layout.addComponent(new Label("Thank you for clicking"), LABEL);
			}
		});
		layout.addComponent(button, BUTTON);
	}

	@WebServlet(value = "/*", asyncSupported = true)
	@VaadinServletConfiguration(productionMode = false, ui = MyVaadinUI.class)
	public static class Servlet extends VaadinServlet {
	}

}

Śmiga całkiem miło.

Kiedy wyjątek to za dużo, a null jest złem, czyli opcje w Guava

January 4th, 2014

W poprzednim wpisie dotyczącym Guavy omówiliśmy klasę Preconditions, która mówiąc najprościej dostarcza zamienników dla często występujących idiomów, które służą do “twardego” sprawdzania parametrów metody. “Twarde” oznacza, że w przypadku niespełnienia warunku jest rzucany wyjątek.

Dziś przyjrzymy się sytuacji gdzie pomimo braku parametru, wartość null, możemy kontynuować pracę ponieważ potrafimy sobie poradzić z takim brakiem. Nie jest to sytuacja rzadka czy nietypowa. Bardzo często w przypadku braku parametru tworzymy kod w rodzaju:

Listing 1. Kod wykorzystujący wartości domyślne

public void method(Object p1){
    if(p1 == null)
       p1 = DEFAULT_VALUE;
    //...
}

Co więcej, miejsc w kodzie, gdzie powstają takie konstrukcje jest zazwyczaj od groma i ciut ciut. Szczególnie często występują one tam gdzie korzystamy ze wzorców “łańcuchowych” (Chain of Constructors/Methods) wołając coraz to kolejne wersje i przekazując im null. Co zabawne w ostatniej, najbardziej rozbudowanej wersji metody zazwyczaj następuje ifologia zastępująca null wartościami domyślnymi. W sumie i tak ta ifologia musi się tam znajdować zatem nie ma tu lepszego rozwiązania… no może poza przekazywaniem wartości domyślnych ze wcześniejszych wywołań i tym samym jakiejś tam pseudo optymalizacji omijającej w takim przypadku nieużywane IF-y… nieee…. fuuj…

Klasa Optional pozwala na pozbycie się tego jakże szkodliwego kodu jednocześnie dostarczając metodę (jedną biedaczkę), która w razie czego zachowa się jak Preconditions.chechNotNull i walnie błędem.
Samo działanie klasy, w tej fajniejszej wersji, przypomina trochę to jak działa Option ze Scali, ale jak to w czystej javie bywa jest z nią więcej pieprzenia.

Tworzenie instancji Optional

Na zdrowy chłopski rozum klasa ta powinna dawać możliwość stworzenia się w dwóch wersjach. Pierwszej, która powstanie gdy przekażemy obiekt, który nie jest null i w drugiej dla null. I generalnie to tak działa. Klasa Optional jest jako taka klasą abstrakcyjną i posiada dwie podklasy – Present dla istniejących obiektów i Absent, która jest singletonem reprezentującym wartości null.

Proces tworzenia obiektu może zatem przebiegać bardzo prosto:

Listing 2. Tworzymy obiekt Optional

public Integer forceNPE(Integer param) {          
	Optional<Integer> oParam = of(param);   
	return oParam.get();
}

Taka konstrukcja tworzy pod spodem obiekt klasy Present, która może zostać użyta w dalszym kodzie. Rzecz w tym, że uruchomienie kodu takiego jak ten:

Listing 3. Tworzymy obiekt Optional i mamy NPE

@Test(expectedExceptions = NullPointerException.class)
public void testForceNPEThrowNPE() {                  
	assertThat(oe.forceNPE(null)).isEqualTo(5);          
}

ujawnia pewien mankament. Jak wspomniałem wcześniej klasa posiada jedną metodę, która zachowuje się jak Prconditions.chechNotNull i jest to właśnie metoda tworząca of. Czyli cały nasz plan można wywalić, bo po co Optional skoro mamy Preconditions.
Nie załamujmy się jednak. Wbrew pozorom to nie metoda or jest najważniejsza. Znacznie ważniejsza jest metoda fromNullable.
Zamieńmy nasz kod na następujący:

Listing 4. Tworzymy obiekt Optional drugie podejście

public Integer supressNPE(Integer param) {         
	Optional<Integer> oParam = fromNullable(param);   
	return oParam.or(DEFAULT_INT);                    
}

Jeżeli teraz odpalimy proste testy:

Listing 5. Tworzymy obiekt Optional i nie ma NPE

@Test                                                                       
public void testSupressNPE() throws Exception {                             
	assertThat(oe.supressNPE(5)).isEqualTo(5);                                 
	assertThat(oe.supressNPE(null)).isEqualTo(OptionalExamples.DEFAULT_INT);   
}

to naszym oczom ukaże się zielony pasek. Jest zatem całkiem nieźle. Użycie metody fromNullable powoduje, że biblioteka wybiera w zależności od parametru jaki dokładnie rodzaj Optional nam dostarczyć. Następnie wywołując metodę or może zajść jedna z dwóch ścieżek. Pierwsza to ta gdy oryginalny obiekt jest null, wtedy to po sprawdzeniu czy zastępnik też nie jest or zostaje on zwrócony. Druga to ta gdy oryginalny obiekt nie jest null. Wtedy metoda or zachowuje się jak inna metoda, get i zwraca oryginalny obiekt.

Na chwilę obecną klasa Optional nie przedstawia nam się zbyt zachęcająco. W sumie jej “wartość dodana” wynikająca z dołączenia jej do kodu jest ograniczona do eliminacji IF-ów. Przyjrzyjmy się jednak co więcej zawiera ta klasa, czyli czas na klasyczne omówienie API.

Metoda absent

Metoda statyczna zwracająca instancję klasy Absent. Nic ciekawego, ale zapewne znajdzie się dla niej zastosowanie wraz ze wzorcem null object.

Metoda asSet

Po drodze oryginalny obiekt jest opakowywany w niezmiennego Seta. Jeżeli przekażemy null to w efekcie otrzymamy pusty, niezmienny Set. Niby mało ciekawe, ale jeżeli zastanowić się nad tym dokładniej to w ten sposób otrzymujemy bardzo elegancki mechanizm do eliminacji efektów ubocznych w funkcjach, które stosujemy na zbiorach albo zwracających zbiory.

Metody equals, hashCode i toString

Metody te są zaimplementowane w intuicyjny sposób. Pierwsza z nich wywołuje metodę equals na referencjach do oryginalnych obiektów (o ile oczywiście trafi do niej Optional, a tak na prawdę Present). Druga wywołuje hashCode oryginalnego obiektu “domieszkując” go o swoje przesunięcie. Trzecia z metod też domieszkuje oryginalne wywołanie o informację, że jest to jednak Optional.

Metoda fromNullable

W zależności od przekazanego argumentu zwraca Present jeżeli nie jest on null albo Absent w przeciwnym wypadku.

Metoda get

Metoda ta zwraca referencję do obiektu. Jeżeli zostanie wywołana na obiekcie klasy Absent to rzuci IllegalStateException.

Metoda isPresent

Zwraca true…. a zresztą czy trzeba tłumaczyć?

Metoda of

Jeżeli jako argument przekażemy jej istniejący obiekt to otrzymamy Optional. Przekazując null otrzymamy NullPointerException. Metodę tą omówiłem już wcześniej. Generalnie może wprowadzić trochę zamieszania, bo zamiast eleganckiej obsługi null wali wyjątkiem.

Metoda or

Metoda ta występuje w trzech wersjach. Z pierwszą, przyjmującą domyślna wartość, już się spotkaliśmy. Druga wersja przyjmuje jako parametr inny obiekt Optional i ją zwraca. Trzecia wersja metody przyjmuje jako parametr Supplier i zwraca jego produkt.
Oczywiście dotyczy to tylko null. W przypadku normalnych obiektów zostanie zwrócony oryginał.

Metoda orNull

Metoda zwróci dokładnie to co jej przekażemy jako argument. Jak przekażemy null to dostaniemy null.

Metoda presentInstances

Parametrem tej metody jest coś po czym można się iterować. Z oryginalnego zbioru zostaną usunięte wszystkie wystąpienia obiektów Abasent. Zwrócony zbiór będzie zawierać tylko te wartości, które nie są wartościami domyślnymi.

Metoda transform

Jako argument przyjmuje funkcję, która o ile istnieje oryginalny obiekt, zostanie zaaplikowana i zwróci Optional przechowujący wynik jej działania. Jeżeli mamy do czynienia z null zostanie zwrócony Absent.

Podsumowanie

Przedstawione tu rozwiązanie nie jest najlepsze. Pozwala jednak na pójście “trzecią drogą” gdzieś pomiędzy wyrzucaniem wyjątku, a ręczną obsługą wartości null. Doskonale nadaje się też jako wsparcie w programowaniu funkcyjnym gdy trzeba jakoś eliminować niepożądane efekty uboczne wynikające z przekazywania do funkcji i predykatów wartości null.

O Vaadin w Magazynie Programista

January 3rd, 2014

W najbliższym numerze Magazynu Programista znajdzie się mój artykuł na temat Vaadin. Będzie to druga część tekstu, który ukazał się w listopadzie.

Przy okazji zapraszam na pod-forum Magazynu na 4programmers.