Modyfikacje w layoucie – czekam na opinie

October 1st, 2014

Kilka drobnych zmian w wyglądzie bloga. Inna czcionka, większy rozmiar, trochę zmodyfikowane listingi. Generalnie nie jest to jeszcze coś co podbije wasze serca, ale…

Po pierwsze czekam na opinie czy zmiany idą w dobrym kierunku. Ponieważ nie chciałbym robić całkowitej rewolucji z wyglądem, a pewne zmiany związane ze wzrostem usability bloga są jednak konieczne to się zapytuję czy to dobry kierunek.

Po drugie co byście powiedzieli na wprowadzenie trochę innego sposobu wyświetlania postów na głównej. To znaczy chciałbym by na głównej pojawiały się tylko “lead” tekstu, a po kliknięciu “czytaj dalej” przechodzilibyście już na pełną wersję.

:)

Funkcje w Guavie i dekoratory

September 30th, 2014

Najprostszy do zaimplementowania wzorzec obiektowy, poza singletonem, w programowaniu z użyciem Function i Guavy, czyli dekorator. Dlaczego najprostszy? Ponieważ jest to podstawa działania funkcji wyższego rzędu (ang. High Order Function), które znowuż są podstawą tworzenia trochę bardziej zaawansowanych zabawek.

Motywacja

klasycznym przykładem dekoratora jest budowanie GUI gdzie kolejne elementy staramy się “udekorować” pewnymi dodatkami. W moim przypadku dekorator rozwiązał trochę inny problem, ale podobnej klasy. Okazało się, że potrzebujemy logować wejście, wyjście i czas wykonania funkcji. Banał. Można napisać kod loggera bezpośrednio w funkcji i olać, co IMO, nie jest rozsądne. Z kilku powodów, ale dwa najważniejsze to wiązanie kodu funkcji z logowaniem, co jest wtłaczaniem pewnej dodatkowej odpowiedzialności oraz silne wiązanie pomiędzy funkcją, a logiem.
Powiedzmy sobie szczerze, im prostsza funkcja tym lepiej. Proste funkcje w Guavie można składać za pomocą predykatów i kompozycji w bardziej rozbudowane przepływy. Jeżeli wszyjemy na sztywno jakieś dodatkowe elementy do funkcji – grób mogiła. Nie ma szans na wygrzebanie się z tego gówna. To wynika z pierwszego powodu. Jedna funkcja – jedna odpowiedzialność. Drugi powód ma źródło w pierwszym Jeżeli naszą funkcję w jakiś sposób powiążemy z logowaniem to nie pozbędziemy się tego wrzodu na dupie bez grzebania w kodzie samej funkcji.
Sytuacja idealna – tworzymy sobie projekcik w którym są same funkcje podstawowe, plus kilka funkcji wyższego rzędu, które będą intensywnie używane bądź reprezentują pewne wiadome elementy systemu. Klient dowolnie składa te nasze funkcje tworząc odpowiednie przepływy biznesowe. O tym jak prosta powinna być funkcja innym razem.
Jeżeli zatem klient chce mieć w jednym przepływie logowanie danej operacji, a w innym nie to nasz kod powinien być tak przygotowany, by dodanie logowania było deklaratywne.

Prosta implementacja, czyli tu nie ma rocket science

Oczywiście nasza implementacja powinna opierać się na funkcjach tak by nie zaburzać konstruowania przepływów. Ponad to nie powinna ona zmieniać interfejsu funkcji dekorowanej. Inaczej mówiąc potrzebujemy czegoś co przyjmie nam naszą oryginalną funkcję jako argument zrobi swoje “czary mary” i przy okazji odpali tą oryginalną funkcję bez modyfikowania wejścia, po czym zwróci jej niezmodyfikowany wynik.

Listing 1. To nie jest rocket science

public class DecoratorLogger<I, O> implements Function<I, O> {

	private final Function<I, O> originalFunction;
	private final Logger logger;
	private Level level;

	public static <I, O> Function<I, O> info(Function<I, O> originalFunction){
		return new DecoratorLogger<>(originalFunction, Level.INFO);
	}

	public static <I, O> Function<I, O> warning(Function<I, O> originalFunction){
		return new DecoratorLogger<>(originalFunction, Level.WARNING);
	}

	public static <I, O> Function<I, O> serve(Function<I, O> originalFunction){
		return new DecoratorLogger<>(originalFunction, Level.SEVERE);
	}

	private DecoratorLogger(Function<I, O> originalFunction, Level level) {
		this.originalFunction = originalFunction;
		this.level = level;
		this.logger = Logger.getLogger(originalFunction.getClass().getCanonicalName());
	}


	@Override
	public O apply(I input) {
		Stopwatch watch = Stopwatch.createStarted();
		O output = originalFunction.apply(input);
		Stopwatch stop = watch.stop();
		logger.log(level, "", new Object[]{input, output, "" + stop.elapsed(TimeUnit.MILLISECONDS)});
		return output;
	}
}

Implementacja naiwna jest naiwna i ja o tym wiem. W tym konkretnym przypadku jest ona silnie powiązana z konkretnym zadaniem. W dodatku używam loggera z JDK, co oznacza, że mam dostępne poziomy. W przypadku użycia slf4j nie mam metody w rodzaju log przyjmującej poziom logowania. Nie jest to też zbyt uniwersalne rozwiązanie. Spróbujmy zatem czegoś innego.

Abstrakcyjny dekorator

Co robi nasz dekorator w tym przypadku? Robi COŚ przed wywołaniem funkcji, wywołuje funkcję, po czym robi COŚ po jej wywołaniu i następnie zwraca wynik. Wygląda to jak metoda szablonowa…

Listing 2. Dekorator abstrakcyjny

public abstract class AbstractDecorator<I, O> implements Function<I, O> {

	protected final Function<I, O> originalFunction;

	protected AbstractDecorator(Function<I, O> originalFunction) {
		checkNotNull(originalFunction);
		this.originalFunction = originalFunction;
	}

	protected abstract void before(I input);

	protected abstract void after(I input, O output);

	@Override
	public O apply(I input) {
		before(input);
		O output = originalFunction.apply(input);
		after(input, output);
		return output;
	}
}

Pozostało w sumie zrobić tylko kilka małych prac w naszym oryginalnym kodzie, ale to ćwiczenie dla ciebie. Pierwsza refaktoryzacja będzie oczywiście banalnie prosta, ale jak już ją zrobisz to zastanów się jak zachowa się kod w środowisku wielowątkowym.

Podsumowanie

Programowanie funkcyjne z użyciem Guavy choć jest bardzo mocno ograniczone w porównaniu do na przykład Scali to jednak daje nam możliwość wprowadzenie konstrukcji, których użycie będzie łatwe, proste i w miarę przyjemne. Możliwość użycia dekoratorów, które są najprostszymi funkcjami wyższego rzędu daje znowuż odpowiednie rozwiązania pozwalające na szybkie obudowywanie istniejącego kodu w pewne dodatkowe rozwiązania bez konieczności ingerowania w główny element. To już jest bardzo dobre :)

Jeżeli spodobał ci się wpis podziel się nim ze znajomymi korzystając z przycisków poniżej. Możesz też wysłać link do niego mailem lub przez komunikator.

Warsjawa 2014, czyli Koziołek strikes back

September 28th, 2014

W tym roku po raz pierwszy od dawien dawna wybrałem się na Warsjawę. I to w podwójnej roli jako uczestnik i jako prelegent/prowadzący warsztat.

Mój warsztat

Zacznę od mojego warsztatu. No nie wyszło… poszło do dupy :) Brak wprawy ale jak Venkat stwierdził

First three times sucks

Wnioski zostaną wyciągnięte i przeanalizowane. Poprawki wprowadzone, a za rok powinno być już zdecydowanie lepiej.

A teraz jako uczestnik

Piąteczek czyli dwie sesje.

Akka basics: remoting and clustering

Bardzo dobre warsztaty. Chłopaki (Piotr Kukiełka i Krzysztof Romanowski) przygotowali je bardzo dobrze i świetnie poprowadzili. Co prawda nagrody głównej nie wygrałem, ale nie żałuję, bo zabawa była przednia. Duża dawka wiedzy na początek i dużo radości jak udało się i całość “zaskoczyła”.
Co było na minus? IMO, chłopaki trochę nie docenili naszego talentu do psucia aplikacji. Postawili na szybko serwer, który miał zbierać informacje i nas oceniać, ale problemy sieciowe trochę zabiły fun.

Google App Engine – from 0 to working web application (with Eclipse)

Warsztaty Maćka Arkita zapowiadały się ciekawie, ale moim zdaniem dość efektownie “wybuchły”. Sam zresztą popełniłem dużo podobnych błędów (za dużo, za szybko i generalnie przeładowane), ale z oryginalnych elementów to trochę dystrybucja softu – jednak repo na githubie było by dobrym pomysłem.
Z rzeczy na plus to sposób przedstawienia materiału. Trochę metodyki żółtej kaczuszki, ale skutecznie. Świetna warsztato-prezentacja.

Sobota, czyli jedna sesja techniczna, jedna miękka i później moje warsztaty.

Electronics Fundamentals for Dummies (Arduino included)

Jacek Kunicki przyniósł Arduino i płytki prototypowe. Zatem nie było lutownicy. Za to był “olśnienie”, że warsztaty są całodzienne… auć… Co mi się spodobało to wstęp teoretyczny poświęcony podstawom działania prostej elektroniki. Prawo Ohma, budowa diody P-N, tranzystora NPN, generalnie lepiej niż na studiach tyle, że trochę bardziej “for dummies”. Później złożyłem sobie migadełko z użycie arduino i urwałem się na obiad. W popołudniowej sesji nie brałem udziału.
Co mi osobiście bardzo się spodobało to możliwość przełamania się jeśli chodzi o elektronikę. Jak siadasz do prądu to zazwyczaj jest taki trochę strach, że zaraz układ odwali Habemus Papam i zjarasz kasę. Tu było na spokojnie. Bez stresu… Super wyszło.
Za bolało, że warsztaty były całodniowe. Niestety braki organizacyjno-informacyjne wyszły :( Ale kod mam, listę części mam. Dokonam zakupów i będę się bawił :)

The Art of Giving Technical Presentations

Venkat… ok chyba tyle starczy. Prezentacja, a nie warsztaty. Było super.

Sama Warsjawa

Fajnie było, bo konferencja była świetnie zorganizowana. Ekipa zadbała o wszystko. Począwszy od dostępu do sieci, poprzez wodę, chillout room, a kończąc na zdawać by się mogło dupereli jaką był kindergarden.

Są jednak dwie rzeczy, które mnie trochę zaskoczyły i jedna, która była do dupy. Do dupy była organizacja afterparty po drugim dniu. Trzy knajpy, oddalone od siebie, gdzie trzeba przejść przez niezbyt dobrze zagospodarowane Pola Mokotowskie… mówię nie. Sorry, ale to nie było dobre. Nie służyło integracji uczestników. Pomysł sam w sobie OK. realizacja nie to miejsce i nie ten czas. Coś takiego można by zrobić np. we Wrocławiu, gdzie jest silne zagęszczenie klubów. Względnie jak jest nas mała, zwarta grupa przemieszczająca się w zorganizowany sposób (patrz angolskie wieczory kawalerskie).

Dwie rzeczy, które mnie trochę zaskoczyły to przede wszystkim lekki rozjazd pomiędzy wymaganiami co to języka prezentacji, a rzeczywistością. Odwrotne podejście polski jako baza i angielski opcja było by lepsze. No ale to nie bolało. Choć nastawiałem się na trzy godzinną pogadankę w ponglishu.
Druga rzecz to mocno randomowa rejestracja i drobne lekki bałagan z salami pierwszego dnia. Brakowało mi takiego jakiegoś spójnego sposobu informowania o tym gdzie co się dzieje. Szczególnie, że numeracja sal na MiMUW-ie jest hm… specyficzna…

Podsumowanie całości

Super było. Naprawdę fajna impreza, gdzie mogłem spotkać świetnych ludzi i nauczyć się wielu nowych rzeczy. Zarówno od strony technicznej (Akka, Arduino) jak i “miękkiej” (mój warsztat to było pasmo porażek). Dziękuję wszystkim za super zabawę i do zobaczenia za rok.

Jeżeli podobał ci się ten wpis podziel się nim ze znajomymi korzystając z przycisków poniżej.

Strażnicy, czyli coś czego mi brakuje w Javie

September 23rd, 2014

W sumie brakuje mi dobrej implementacji tego rozwiązania, bo można taką funkcjonalność mieć z wykorzystaniem np. AspectJ czy Type Annotations. Jednak o co chodzi?

Guardians of Erlang

Erlang posiada bardzo fajną konstrukcję zwaną strażnikami (guardians). Cóż to jest? Otóż mając jakąś funkcję możemy walidować argumenty w deklaratywny sposób. Nie wywołujemy żadnego wywołania czy też nie odwołujemy się do żadnej dodatkowej biblioteki. Całość opiera się na konstrukcjach języka.
Przykładowo funkcja attack_mod przyjmuje argument w postaci krotki, której drugi element musi być większy bądź równy 0. W Javie taki kod wyglądał by następująco:

Listing 1. Metoda attackMod

public int attackMod(UnitType type, int numberOf){
    checkArgument(numberOf>=0, "Number of unit must be >= 0");
    //...
}

Kod ten wykorzystuje klasę Preconditions z Guavy. Inną metodą w javie jest napisanie aspektu i użycie adnotacji @Min

Listing 2. Metoda attackMod z adnotacją

public int attackMod(UnitType type, @Min(0) int numberOf){
    //...
}

Ten kod już dużo bardziej przypomina to co chcemy osiągnąć. Jest deklaratywny i stworzony w oparciu o meta dane. Problemem będzie uruchomienie go. Mianowicie trzeba napisać sobie aspekt w rodzaju @Around(“execution(public * * (.., @Min (*), ..))”) oraz wpiąć go w trakcie uruchamiania.
Strasznie to upierdliwe, a w dodatku nie tak mocarne jak rozwiązanie w Erlangu. Tu implementacja będzie wyglądać następująco:

Listing 3. Funkcja attack_mod

attack_mod({Unit_name, Number_of}) when Number_of >=0 ->
  %%% ...
.

Strażnikiem nazywamy ciąg pomiędzy słowem when, a strzałką. Dlaczego rozwiązanie to jest znacznie fajniejsze niż te dostępne w Javie.

Strażnicy i dopasowania

Chyba najciekawszą cechą strażników jest możliwość ich wykorzystania w dopasowaniach (pattern matching). Wyobraźmy sobie, że o ile warunek nie mniejszy niż 0 będzie ok, dla wszystkich rodzajów UnitType, to już w zależności od rodzaju jednostki i liczebności inaczej będzie wyliczany modyfikator. Przykładowo niech orkowie jak będzie ich co najmniej 20 mają wyższy modyfikator (cecha “w kupie siła”), ale jednocześnie istnieje 10% szansy na to, że pokłócą się i modyfikator będzie wynosił 0 (cecha “Moja racja jest najmojsza”).
Wprowadzamy tu zatem dwa nowe elementy. Pierwszym jest dodatkowy zakres wartości, a drugim zmiana algorytmu w zależności od tego w którym zakresie wylądowaliśmy. Wyobraźmy sobie jak ten kod mógłby wyglądać w Javie. W najprostszym niezbyt obiektowym wykonaniu wyglądało by to mniej więcej tak:

Listing 4. Metoda attackMod po modyfikacjach

public int attackMod(UnitType type, int numberOf) {
	checkArgument(numberOf >= 0);
	switch (type) {
		case Marine:
			return 2 * numberOf;
			break;
		case Ork:
			if (numberOf >= 20) {
				return (int) (1.5 * numberOf * quarrel());
			}
			return (int) (1.3 * numberOf);
		break;
		case Human:
			return 1 * numberOf;
			break;
	}
}

Metoda quarrel zwraca 0 albo 1 w zależności od warunku losowego. Strasznie to syfne. W wersji bardziej obiektowej i bardziej javowej switch zastąpiony by został mapą, w której kluczami były by wartości enuma, a wartościami fabryki (wzorzec ProblemFactory) zwracające odpowiedni algorytm (strategię) w zależności od parametru numberOf. Z lekka masakra. Osobiście nie mam nic przeciwko tworzeniu dużej ilości wyspecjalizowanych klas. Java to język taki, a nie inny i ma swoje “odchyły”, a jednym z nich jest konieczność tworzenia specjalizowanego kodu by uzyskać dużą elastyczność. Popatrzmy jak problem można rozwiązać w Erlangu.

Listing 5. Funkcja attack_mod

-export([attack_mod/1]).

attack_mod({Unit_name, Number_of}) when Number_of >=0 ->
  attack_mod(Unit_name, Number_of).

attack_mod(marine, Number_of) ->
  2 * Number_of;

attack_mod(ork, Number_of) when Number_of < 20 ->
  1.3 * Number_of;

attack_mod(ork, Number_of) when Number_of >= 20 ->
  1.5 * Number_of * quarrel();

attack_mod(human, Number_of) ->
  1 * Number_of.

quarrel() ->
  Chns = random:uniform(10),
  if Chns == 1 -> 0;
    Chns > 1 -> 1
  end.

Chyba wygląda to trochę lepiej? W tym przypadku VM-ka erlanga sama dopasuje odpowiednią wersję funkcji do argumentów. Jest to zdecydowanie lepsze rozwiązanie niż to w Javie.

Oddziały strażników

Czyli rzecz o tym jak składać warunki. Jeżeli chcemy nałożyć więcej niż jedno ograniczenie na nasze argumenty możemy połączyć strażników. W takim przypadku przecinek będzie działać jak logiczne AND, a średnik jak logiczne OR.

Więcej niż deklaracja funkcji

Strażników możemy używać nie tylko na poziomie deklaracji funkcji. Znacznie przyjemniej używa się ich na poziomie konstrukcji case, która jest podobna do tej ze Scali i służy do obsługi dopasowań. W takim wypadku powyższy kod można przerobić na coś takiego:

Listing 6. Funkcja attack_mod z wykorzystaniem case

-export([attack_mod/2]).

attack_mod(Unit_name, Number_of) when Number_of >= 0 ->
  Mod = case Unit_name of
          marine -> 2;
          ork when Number_of < 20 -> 1.3;
          ork when Number_of >= 20 ->
            1.5 * Number_of * quarrel();
          human -> 1
  end,
  Mod * Number_of.

quarrel() ->
  Chns = random:uniform(10),
  if Chns == 1 -> 0;
    Chns > 1 -> 1
  end.

Całkiem ładne rozwiązanie. W dodatku bardziej zwięzłe niż to w Javie.

Podsumowanie

W Javie brakuje niestety takiego fajnego mechanizmu. Dodatkowym atutem Erlanga jest możliwość użycia atomów, które dodatkowo wprowadzają dodatkowe możliwości w przypadku dopasowań. Pozostając jednak przy deklaratywnym weryfikowaniu parametrów warto zapoznać się z możliwościami Javy w tym zakresie, bo choć użycie aspektów jest upierdliwe, to jest to całkiem efektywny sposób na pozbycie się nadmiarowego kodu.

Jeżeli podobał ci się ten wpis podziel się nim ze znajomymi korzystając z przycisków poniżej.

Suplement do Suppliera

September 18th, 2014

Na ostatnim spotkaniu wrocławskiego JUGa padło pytanie co do Suppliera z poprzedniego wpisu dotyczące tego jak należy zamykać BufferedReader. Trochę się niestety zamotałem i nie byłem wstanie udzielić dobrej odpowiedzi na to pytanie, ale po spokojnym przemyśleniu sprawy rzecz jest bardziej niż prosta.

Błogosławione niech będą rzeczy nowe w Javie 7

Dokładnie zaś konstrukcja try-with-resource, czyli możliwość trochę lepszego zapisu syfu związanego z zamykaniem zasobów. Efektywnie oznacza to, że wystarczy by nasz Supplier implementował interfejs Closeable:

Listing 1. Samo zamykający się Supplier

public class FileReaderViaSupplier implements Supplier<Optional<String>>, Closeable {

	private BufferedReader reader;

	public FileReaderViaSupplier(String filePath) {
		this(new File(checkNotNull(filePath)), UTF_8);
	}

	public FileReaderViaSupplier(File file, Charset charset) {
		checkNotNull(file);
		checkNotNull(charset);
		checkArgument(file.exists(), "File %s does not exist", file.getAbsolutePath());
		try {
			reader = Files.asCharSource(file, charset).openBufferedStream();
		} catch (IOException e) {
			checkState(false, e.getMessage());
		}
	}

	@Override
	public Optional<String> get() {
		try {
			String reference = reader.readLine();
			return Optional.fromNullable(reference);
		} catch (IOException e) {
			return Optional.absent();
		}
	}

	@Override
	public void close() throws IOException {
		reader.close();
	}
}

I to tyle.

Tradycyjnie już na koniec mała prośba jeżeli spodobał ci się ten wpis udostępnij go w mediach społecznościowych korzystając z przycisków poniżej. Jak masz pytania zadaj je w komentarzu. Postaram się zaspokoić twoją ciekawość.

Supplier z Guavy jako narzędzie odczytu plików

September 13th, 2014

Interfejs Supplier opisałem już pewien czas temu. Dziś chciałbym przedstawić pewne specyficzne zastosowanie tego interfejsu. Mianowicie stworzymy klasę, która będzie w oparciu o ten interfejs odczytywać pliki.

Prawie leniwe czytanie plików

Generalnie w Javie da się czytać pliki w sposób leniwy. Bierzemy sobie BufferedReader i wpinamy go w jakiś listener. Następnie uderzamy zdarzeniem “następna linia” i pobieramy linię. I tak aż się plik skończy.
W przypadku Supplier-a mechanika działania jest bardzo zbliżona. Z jedną małą różnicą. Musimy czytać “do przodu” jeżeli chcemy by odczyt był następnie wykorzystywany w ramach iteratorów. Te ostatnie zapewnią nam spójny interfejs z Guavą.
Co więcej o ile w przypadku “zwykłego” czytania plików możemy sobie zaryzykować zwrócenie wartości null lub wymuszenie obsługi weryfikowalnego wyjątku to gdy idziemy w kierunku idiomów funkcyjnych dobrze by było zamknąć jakoś te problemy.

Catched Exceptions i Guava

Dziś na skróty. Generalnie jedną z cech programowania funkcyjnego jest brak efektów ubocznych. Jednym z takich efektów jest rzucenie wyjątku. Wszystko ładnie pięknie, ale uruchommy sobie interpreter Erlanga (który językiem funkcyjnym jest) i napiszmy coś takiego:

Listing 1. “Brak efektów ubocznych”

Liczba = 1.
Wynik = Liczba / 0.

Oczywiście dostaniemy wyjątek. Jako, że Erlang hołduje idei “Let it crash” to jeżeli doprowadzilibyśmy do takiej sytuacji w programie to maszyna wirtualna by ubiła nam proces, a następnie go wznowiła.
My nie będziemy aż tak mili. Jeżeli coś się wywali to przepchniemy to na chwilę obecną do wyjątku nieweryfikowalnego i wyrzucimy… Let it crash :D

Przy czym należy pamiętać, że Guava udostępnia klasę narzędziową Throwables, która pozwala na opakowywanie i konwertowanie wyjątków. Tu będzie ona średnio przydatna ;)

Czytamy plik linia po linii z użyciem Supplier

Zakładam, że czytamy linia po linii, plik np. csv, a nie plik binarny, gdzie chcemy odczytać blok. Ogólne zasady będą takie same komplikuje się tylko zasady określające ile danych chcemy odczytać.

Zastanówmy się przez chwilę co powinno być efektem przeczytania linii z pliku? Zapewne obiekt typu String. Co jeżeli linia jest pusta? Nasz String powinien być pusty. W przypadku końca pliku będzie oczywiście null. Czy to nam odpowiada? Raczej nie. Szczególnie ten ostatni przypadek. Co prawda można by zamienić do na zwracanie pustego stringa, ale wtedy nie wiemy, że odczytujemy ostatnią linię, a nie np. pustą linię w środku pliku.

Pamiętajmy, że odczyt pliku będzie obudowany w dostawcę, a ten nie dostarcza metod iteratora typu hasNext. Oczywiście można napisać taki iterator (kolejny post będzie o tym). Jednak my skupimy się na samym odczycie.

Jak wybrnąć z tego problemu? Użyć Optional. To było proste. Zasady też są proste. Jeżeli dojdziemy do końca pliku to zwracamy Absent inaczej Present. Do odczytu plików tekstowych linia po linii posłuży nam stary dobry BufferedReader. WIemy zatem jak będzie wyglądał “core” naszej aplikacji

Listing 2. Metoda get naszego readera

public class FileReaderViaSupplier implements Supplier<Optional<String>> {

	private BufferedReader reader;

	@Override
	public Optional<String> get() {
		try {
			String reference = reader.readLine(); // 1
			return Optional.fromNullable(reference).or(Optional.<String>absent()); // 2
		} catch (IOException e) {
			return Optional.absent(); // 3
		}
	}
}

Na początku odczytujemy pojedynczą linię (1), a następnie na jej bazie tworzymy obiekt Optional, który będzie istniał o ile tylko odczytaliśmy coś co nie jest null-em. W przeciwnym wypadku zostanie zwrócony Absent. Absent zostanie zwrócone też w przypadku błędu.

Jak to zainicjować

Mamy co prawda reader, ale nadal nie mamy kodu odpowiedzialnego za jego inicjalizację. Przedstawię tylko jeden konstruktor. Można go potraktować jako ostatni w ścieżce delegacji pomiędzy różnymi wersjami (bo jak zwykle operując na plikach mamy od cholery konstruktorów).

Listing 3. Konstruktor naszego readera

public FileReaderViaSupplier(File file, Charset charset) {
	checkNotNull(file);
	checkNotNull(charset);
	checkArgument(file.exists(), "File %s does not exist", file.getAbsolutePath());
	try {
		reader = Files.asCharSource(file, charset).openBufferedStream();
	} catch (IOException e) {                                                                    
		checkState(false, e.getMessage());
	}
}

W pierwszych trzech liniach sprawdzamy czy w ogóle możemy sobie pozwolić na utworzenie readera. Wykorzystuję tu Preconditions, które opisywałem pewien czas temu. Następnie próbujemy utworzyć BufferedReader. Jeżeli to się nie uda to walimy kolejnym wyjątkiem.

W przeciwieństwie do odczytu gdzie błąd oznaczał tylko zakończenie działania tu przyjąłem trochę inną strategię. Proces odczytu jest leniwy. Zatem możemy zabezpieczyć się przed warunkami zewnętrznymi inaczej niż w przypadku zachłannego procesu tworzenia obiektu. Tu chcemy od razu powiedzieć “nie wiem, nie znam się, zarobiony jestem, przyjdź pan jurto”. Natomiast w przypadku odczytu po prostu mówimy “nic więcej nie mogę odczytać”. Nie ważne jest czy wynika to z problemów z plikiem czy też jest po prostu koniec pliku.

Podsumowanie

Mamy zatem podstawowy element pozwalający na leniwe odczytywanie plików. W dodatku napisaliśmy to w sposób pozwalający na wykorzystanie razem z innymi elementami Guavy.

O tym jak dobrać rozwiązanie do problemu i czy opłaca się pisać rozwiązania uogólnione będę mówił w trakcie warsztatów “Beginning Functional Programming in Java world” na Warsjawie już 26-27 września.

Na koniec mała prośba jeżeli spodobał ci się ten wpis udostępnij go w mediach społecznościowych korzystając z przycisków poniżej. Jak masz pytania zadaj je w komentarzu. Postaram się zaspokoić twoją ciekawość.

Funkcja niezmieniająca i konsumenci w Guavie

September 8th, 2014

W poprzednim wpisie poświęconym Guavie wspomniałem, że przyjrzymy się sprawie wywołania loggera w naszym if-potworku.

Listing 1. If-potworek

for (ReportRunHistory reportRunHistory : reportRunsHistory) {                     
	LOG.info(reportRunHistory.toString());                                        
	if (reportRunHistory.status.equals(CANCELED.getStatusText())                                  
			|| reportRunHistory.status.equals(FAILED.getStatusText())                             
			|| reportRunHistory.status.equals(COMPLETED.getStatusText())){
        // ...
        }                                       
}

Sprawę ifów mamy już rozwiązaną. Czas przyjrzeć się temu co można zrobić z pierwszą linijką. Tak naprawdę to co tu potrzebujemy to monadaW. Taka zwykła, smutna, haskellowa monada. Na monadę składają się dwie operacje (ok to uproszczenie, ale tu wystarczy) wiązanie i powrót… ok nie będzie o monadach, bo takie rozwiązanie choć możliwe do zaimplementowania zapewne zniszczy nam mózgi. My naprawdę żyjemy w świecie obiektowym więc i rozwiązanie będzie obiektowe. Co prawda mamy sobie coś co się nazywa Option i jest to taka dość prymitywna w użyciu monada, ale my chcemy mieć rozwiązanie problemu, a nie kolejny problem zastępczy (w razie jak by pierwszego nie było).
Zapomnijmy więc o monadach.

Konsument konsumuje

Tyle tylko, że w Guavie nie ma interfejsu Consumer<T>. samodzielne dopisanie go nie stanowi problemu

Listing 2. interfejs Consumer<T>

public interface Consumer<T> {

	public void consume(T t);
}

Trochę większym problemem jest jego zastosowanie. Jeżeli na ten przykład zamiast takiej implementacji zastosowalibyśmy coś co rozszerza istniejącą funkcjonalność w rodzaju

Listing 3. interfejs Consumer<T> jako rozszerzenie funkcji

public interface Consumer<T> extends Function<T, Void>{
}

I następnie użyli znanej nam metody compose to byśmy mieli poważny problem. Metoda ta jak pamiętamy przyjmuje dwie funkcje i zwraca trzecią spełniającą zależność

Zależność compose
// offtopic
obrazek wygenerowany za pomocą apki EqGraph. Czyli kolejnego wielkiego niedokończonego projektu ;)
// koniec offtopicu

W naszym przypadku oznaczało by to funkcję zwracającą Void, co było by równoznaczne z operacją kończącą. Nie za dobrze. Dlatego też można to zrealizować w trochę koślawy sposób:

Listing 4. Funkcja przyjmująca interfejs Consumer<T>

public class InConsumerFunction<I> implements Function<I, I> {

	private final Consumer<I> consumer;

	public InConsumerFunction(Consumer<I> consumer) {
		this.consumer = consumer;
	}

	@Override
	public I apply(I input) {
		consumer.consume(input);
		return input;
	}
}

Nie jest to najlepsze możliwe rozwiązanie, ale jak na nasze potrzeby na obecnym etapie wystarczające. Co tu się dzieje jest chyba jasne. Tworząc instancję naszej funkcji przekazujemy jej jakiegoś konsumenta, który robi swoje, a następnie funkcja zwraca oryginalny obiekt.

Dlaczego jest to koślawe?

Po pierwsze dlatego, że konsument może zmienić stan naszego obiektu. Programowanie funkcyjne opiera się o niezmienność poszczególnych bytów. Tu nie mamy możliwości zagwarantowania braku zmiany w konsumencie… bywa…
Po drugie sama funkcja posiada stan. To znacząco ogranicza możliwość jej powtórnego użycia. Z drugiej strony dobrze przemyślany system logowania powinien pozwolić na wywołania silnie typowane. Co to oznacza? Ano oznacza tyle, że treść komunikatów jest sobie zamknięta w jakiejś klasie i nie mamy dostępu do nich z zewnątrz. Jedyne co możemy zrobić to przekazać im listę argumentów.
Da się to nawet napisać i zapewne kolejny post będzie poświęcony tej tematyce, ale to nadal jest konieczność pałowania się z czymś na co nie mamy ochoty.
Po trzecie musieliśmy wprowadzić dodatkowy byt, którego użycie wprost z poziomu Guavy jest niemożliwe. Wymaga on każdorazowego opakowania. Nie za dobrze.

Podsumowanie

Guava daje nam bardzo dużo możliwości. Jednocześnie brakuje w niej “duperelków”, których dopisanie jest uciążliwe i wymaga stosowania haków o ile chcemy napisać coś w możliwie ogólny sposób. Jednocześnie pisanie rozwiązań dla konkretnych problemów może okazać się znacznie prostsze i efektywniejsze.

O tym jak dobrać rozwiązanie do problemu i czy opłaca się pisać rozwiązania uogólnione będę mówił w trakcie warsztatów “Beginning Functional Programming in Java world” na Warsjawie już 26-27 września.

Na koniec mała prośba jeżeli spodobał ci się ten wpis udostępnij go w mediach społecznościowych korzystając z przycisków poniżej. Jak masz pytania zadaj je w komentarzu. Postaram się zaspokoić twoją ciekawość.

Blog Day 2014

August 31st, 2014

W tym roku będzie trochę “prywaty”

Paragraf na kozetce – blog poświęcony prawu i psychologii w procesie postępowania sądowego (oraz około sądowego).
Simply Home About – dla tych co remontują i urządzają… bo to kolejny raz w tym roku przerabiałem
Subiektywnie o finansach – chyba najlepszy polski blog dziennikarski o finansach.
Czas Dżentelmenów – trochę męskiej, klasycznej mody, trochę historii, troch ciekawostek. Generalnie warto poczytać ponieważ niektóre informacje są bezcenne.
Ciekawostki historyczne – świetne czytadło historyczne dla tych, co chcą posiąść wiedzę nietypową.

Predykaty z Guavy i enumy, czyli praktyki dwa łyki

August 31st, 2014

Mamy sobie taki sprytny inaczej system uruchamiania raportów w innym systemie, gdzie z jednej strony mamy status raportu jako enum, a z drugiej jako String. Klasyczny przypadek prowadzący do “potworkowania” kodu takimi oto ifami:

Listing 1. If-potworek

for (ReportRunHistory reportRunHistory : reportRunsHistory) {                     
	LOG.info(reportRunHistory.toString());                                        
	if (reportRunHistory.status.equals(CANCELED.getStatusText())                                  
			|| reportRunHistory.status.equals(FAILED.getStatusText())                             
			|| reportRunHistory.status.equals(COMPLETED.getStatusText())){
        // ...
        }                                       
}

Tomek Nurkiewicz na Confiturze w 2012 roku opowiadał o tym jak pozbywać się Ifów z kodu. Ten kod podpada pod “jest prosto nie trzeba upraszczać”. Mnie jednak osobiści drażni takie coś. Można to naprawdę sprowadzić do czegoś co będzie wyglądać dobrze i co najważniejsze będzie łatwe do przeczytania. Jak używamy Guavy rzecz staje się jeszcze prostsza.

Do czasu…

Pierwszy problem każdego korpo

Trochę się po korpo nie informatycznych włóczyłem i zaobserwowałem, że istnieje w nich pewna wspólna cecha dotycząca kodu. Można by ją opisać, jako mieszankę niechęci do zmian z silną separacją zespołów. Wyobraźmy sobie, że nasz system raportowy ma klienta, który jest napisany w Javie i dostarczony nam przez zespół zajmujący się apką raportową. Rzecz w tym, że jak znajdziemy jakiś błąd to procedura wdrożenia poprawki jest drogą przez mękę. W praktyce napisanie własnego lokalnego haka na bibliotekę jest prostsze…
Inaczej mówiąc w korpo jak dostajesz coś zapaczkowane w jara, to choć by zespół odpowiedzialny za ten kod siedział po sąsiedzku to uzyskanie poprawki jest długotrwałe.
A co w przypadku gdy chcesz uzyskać nową funkcjonalność? Zapomnij.

Miej więcej taki problem mamy z naszym systemem raportowym. Choć klient mógłby zwracać enum to zwraca String, a my musimy robić brzydkie haki w naszych enumach w rodzaju:

Listing 2. “Hakowany” enum

public enum RunReportStatusEnum {

	QUEUED("queued"), RUNNING("running"), COMPLETED("completed"), FAILED("failed"), CANCELED("canceled");

	private final String statusText;

	private RunReportStatusEnum(String statusText) {
		this.statusText = statusText;
	}

	public String getStatusText() {
		return statusText;
	}

}

String w konstruktorze enuma, który mapuje nasz kod na zasadzie enum-String. Można to rozwiązać mapą, ale… nadal zostaje ten pieprzony If z Listingu 1 gdzie jakoś musimy w pewnym momencie przefiltrować sobie to co przychodzi na nasze enumy.

No ale mamy Guavę

A Guava ma predykaty. Pisałem już o predykatach i funkcjach, a teraz chcę pokazać jedno z ciekawszych zastosowań, moim zdaniem oczywiście.

Krok 1. Enum – predykat

Pierwszym krokiem refaktoryzacji jest zauważenie, że w IFie kod składa się z trzech identycznych pod względem konstrukcji warunków. Można je zgeneralizować w następujący sposób:

Listing 3. Metoda uogólniająca dla Ifa

boolean is(ReportRunHistory reportRunHistory, RunReportStatusEnum e){
	return reportRunHistory.status.equals(e.getStatusText());
}

Co w samo w sobie jest może i ładne, ale użycie tego w kodzie nadal paskudne. Zatem w zamiast czegoś takiego można napisać własny enum implementujący Predicate:

Listing 4. Enum – predykat

public enum RunReportStatusEnumPredicate implements Predicate<String> {
	IS_QUEUED(QUEUED), 
	IS_RUNNING(RUNNING), 
	IS_COMPLETED(COMPLETED), 
	IS_FAILED(FAILED), 
	IS_CANCELED(CANCELED);

	private final RunReportStatusEnum statusEnum;

	private RunReportStatusEnumPredicate(RunReportStatusEnum statusEnum) {
		this.statusEnum = statusEnum;
	}

	@Override
	public boolean apply(String input) {
		return statusEnum.getStatusText().equals(input);
	}
}

W praktyce nie wychodzi to poza to co na listingu 3. Główna różnica polega na tym, że całość można sprawnie przetestować (banalne) oraz mamy zapewniony interfejs zdatny do użycia z Guavą.

Krok 2. Składamy predykat

Kto czytał tekst o predykatach ten wie, że można składać predykaty wykorzystując metodę Predicates.or. Złóżmy zatem nasz predykat:

Listing 5. Enum – predykat

or(IS_CANCELED, IS_FAILED, IS_COMPLETED)

LOL… jakie to proste… nasz wyjebany w kosmos IF zamienił się w jednolinijkowca… Nope…

Krok 3. Transformata

Jak przyjrzycie się interfejsowi naszego predykatu to przyjmuje on typ String, a w pętli mamy do czynienia z ReportRunHistory. Jak zatem wtłoczyć do naszego kodu inny typ? Tu z pomocą przychodzi kolejna metoda Predicates.compose, która przyjmuje predykat i funkcję, która zwraca typ zgodny z typem wejściowym predykatu.

Listing 6. Funkcja konwertująca

public class ReportRunHistoryStatusAsStringFunction implements Function<ReportRunHistory, String> {
	public static final ReportRunHistoryStatusAsStringFunction REPORT_RUN_HISTORY_STATUS_AS_STRING_FUNCTION
			= new ReportRunHistoryStatusAsStringFunction();
	
	private ReportRunHistoryStatusAsStringFunction(){}

	@Override
	public String apply(ReportRunHistory input) {
		return input.status;
	}
}

W efekcie nasz kod można przepisać do:

Listing 7. Funkcja i enum

compose(
		or(IS_CANCELED, IS_FAILED, IS_COMPLETED),
		REPORT_RUN_HISTORY_STATUS_AS_STRING_FUNCTION
)

Co zwraca predykat przyjmujący ReportRunHistory i odpalający warunek z predykatu gdzie potrzeba String.

Pułapka

Kod zaczął się trochę “rozwlekać”. Można mu zarzucić, że stworzyłem wiele małych klas, których powtórne użycie jest wątpliwe, a trzeba je jakoś utrzymywać. Powiem tak, jeżeli boisz się tworzyć nowe klasy “na masę” to idź pisać w pascalu gdzieś indziej. Kluczem do sukcesu w tym przypadku jest duża granulacja kodu. W praktyce ( i w rozwiązaniu z korpo) z pojedynczej konstrukcji for-if-for-if-logika można wygenerować nawet 10-12 klas, a każda z nich będzie odpowiadać, za jakąś pojedynczą funkcjonalność. Choćby była to obsługa ifa.
Ten przykład jest niekompletny, ponieważ if znajduje się w pętli to nie do końca widać siłę tej refaktoryzacji. Ale o tym następnym razem, bo nie o tym tu chciałem teraz napisać.

Duża granulacja kodu to też pewna pułapka. Z jednej strony bardzo łatwo jest taki kod przetestować, ale z drugiej strony kto będzie pisał testy dla getterów (nasza funkcja to opakowanie gettera). tym samym może okazać się, że po większej refaktoryacji, gdzie dodaliśmy dużo nowych małych klas bez testów, nagle nasze pokrycie testami spada i wywala buildy. Bywa… choć testowanie małych klas wydaje się zawracaniem dupy to należy się zmusić i to robić.
Można też ułatwić sobie życie testując trochę większe kawałki kodu. Tu dobrym kandydatem na napisanie testu jest nie funkcja i enum, ale predykat powstały z ich kompozycji. Choć nadal duża część testu to sprawdzenie “czy guava działa” to jednak jest to już test, który już napisaliśmy. Kiedy? Gdy przystępowaliśmy do refaktoryzacji i mieliśmy pokrycie testami dla całego Ifa. Pamiętajcie, że nadal testujemy jakiś większy kawałek kodu – serwis czy coś w ten deseń, gdzie w środku w wyniku refaktoryzacji udało się wyciągnąć ileś tam małych klas.

Podsumowanie

Przedstawiona tu technika radzenia sobie z ifem jest dobrym punktem zaczepienia jeżeli chcecie wprowadzać elementy programowania funkcyjnego do swojego kodu. Nie jest to oczywiście programowanie funkcyjne jako takie, ale ma jego naturę (funkcja i predykat są bezstanowe, nie zmieniają stanu obiektu itp.). To już dużo. Znacznie więcej niż można sobie wyobrazić gdy widzimy przeciętny kod korpo-potworka i chcemy się w nim rozeznać.

Jest to oczywiście fragment większej refaktoryzacji, a kolejnym ciekawym jej elementem jest to jak wywołać logger z pierwszej linii pętli.

O tym między innymi będę mówił w trakcie warsztatów “Beginning Functional Programming in Java world” na Warsjawie już 26-27 września.

Na koniec mała prośba jeżeli spodobał ci się ten wpis udostępnij go w mediach społecznościowych korzystając z przycisków poniżej. Jak masz pytania zadaj je w komentarzu. Postaram się zaspokoić twoją ciekawość.

Clean services, albo mikro architektura…

August 24th, 2014

Jak cholerę zwał tak zwał. Generalnie ostatnie spotkania Wrocławskiego JUGa dały mi trochę do myślenia.

Pierwsze z Wujkiem Bobem było poświęcone Clean Architecture. Wcześniej Andrzej Bednarz opowiadał nam o swoich doświadczeniach z tym rozwiązaniem, ale tu mieliśmy okazję “u żródła”.
Drugie poświęcone architekturze mikroserwisów poprowadzone przez Roberta Firka było swoinstym dopełnieniem.

O co chodzi?

Clean Architecture jest koncepcją takiego tworzenia funkcjonalności by były one jak najbardziej odseparowane od świata zewnętrznego. Interaktor (ciężko mi znaleźć polskojęzyczny odpowiednik) ma swój interfejs komunikacyjny i korzysta z pewnych obiektów – encji domenowych (wspólnych dla wielu aplikacji nie tylko dla tej konkretnej). Gdy potrzebuje dostać się do danych korzysta z interfejsu dostępowego, ale nie DAO lecz czegoś w rodzaju gateway-a. Co jest za nim… who cares. Po prostu dostajemy dane w pewnym określonym formacie i czy będzie pod spodem baza danych, czy jakiś sawant… W efekcie dostajemy aplikację, która ma charakter kontenera pluginów. Jest sobie jakiś core biznesowy reprezentujący use casy, a reszta to tylko łatwo wymienialne pluginy.

Mikroserwisy są znowuż podejściem gdzie stawiamy duży nacisk na separację poszczególnych funkcjonalności i ich niezależność. W tym podejściu liczy się przede wszystkim duża granulacja kodu, tak by zmiana nie trwała tygodniami, a raczej godzinami. Poszczególne fragmenty komunikują się ze sobą i każde wywołanie powinno nieść ze sobą wszelką wiedzę i informacje potrzebną do wykonania danej operacji. Mikroserwisy mogą powstawać w różnych technologiach i nie mogą współdzielić zasobów.

Widzicie na czym polega myk?

Mikro architektura, czyli clean services

Projektowanie zaczynamy zgodnie z Clean Architecture. Naszą bazą mentalną jest konkretny use case. Reprezentuje on jeden niezależny scenariusz w aplikacji. W tym momencie projektujemy kod, spisując kolejne kroki i korzystając z bazy pojęć CA. Mamy więc interaktora, boundaries, entyties, gateways.
Następnie zaczynamy kod pisać i na poziomie pojedynczego use casa nadal trzymamy się CA.
Gdy jednak dokładamy realizację elementów “plugowalnych” chociażby jakiś testowy gateway to staje się on mikroserwisem. Staramy się tak zaprojektować interfejs by wywołanie jakiegoś pluginu realizowane było w oparciu o MiS.

Co to nam daje?

Dwa słowa podsumowania. CA i MiS są to dwa podejścia, które kładą nacisk na dwa inne elementy architektury. W CA staramy się modularyzować kod tak by reprezentował on poszczególne zagadnienia biznesowe. Każdy niezależny element w kodzie ma odbicie w use caseie. MiS kładzie znowuż nacisk na to jak poszczególne moduły ze sobą współpracują oraz na to by awaria jednego z nich nie wywaliła nam aplikacji.
Moim zdaniem połączenie tych dwóch podejść pozwala na stworzenie z jednej strony aplikacji, która będzie dość odporna na awarie. Jednocześnie każda pojedyncza jednostka organizacyjna będzie miała jasno określony zakres odpowiedzialności biznesowej.
Ponad to, jako że w każdej aplikacji istnieją pewne byty konieczne z punktu widzenia prawidłowego działania, ale nie niezbędne biznesowo (administracja uprawnieniami, składowanie danych, audyt), będzie można tak zorganizować kod by ich istnienie miało jak najmniejszy wpływ na logikę biznesową.