Piractwo w ACTA to najmniejszy problem

January 26th, 2012

A to dlaczego? Ano dlatego, że internet z samego swojego założenia jest uodporniony na wszelkie próby odcinania użytkowników czy skutecznego blokowania usług. ARPANETW był projektowany by przetrwać konflikt atomowy zatem kilku durni w garniturach z taniego armaniego nie zagrozi raczej sieci.

Zresztą był Napster, który nie trzymał się pierwszej zasady Jamesa Hetfielda, “jeżeni fanów nie stać na płyty Metallica’i to niech je ukradną”. Napster nie kradł. Później była Kazaa, czyli sieć wymiany wirusów i pornoli udających seriale. Kazaa przeszła na działalność komercyjną i chyba jeszcze żyje… o ile ktoś chce kupować zawirusowane pornole… choć z drugiej strony…

Później nastały czasy eDonkey i jego kolegi eMule, który działał tak jak się nazywał głupio i powoli. Teraz mamy torrenty, a jak ten sposób dystrybucji danych zostanie ograniczony to się wdroży coś innego. Jednym zdaniem ACTA-srakta siadamy wymyślamy nowy protokół wymiany danych (p2p + routing cebulowy + szyfrowanie). Zresztą samym korpo będzie zależało na jak najszybszym stworzeniu protokołów odpornych na ACTA. Nikt nie lubi jak mu władza grzebie w korespondencji.

ACTA to jednak nie tylko szeroko pojęte piractwo muzyczno programistyczne. ACTA to przede wszystkim umowa dotycząca patentów i własności przemysłowej. Po tygodniu sraczki związanej z zagrożeniem odcięciem od porno do dziennikarzy zaczyna powoli trafiać co oznacza ACTA dla przemysłu.

Ano będzie niewesoło. Producenci będą mogli bardzo szybko wykończyć rynek tzw. zamienników. Czy to części samochodowych czy to sprzętu komputerowego czy to w końcu najzwyklejszych wkładów do drukarek. Oczywiście nie nastąpi to od razu. Po prostu w miarę potrzeb będzie się przymykało oko albo producentów “podróbek”. Jeszcze gorszą wiadomością jest to, że ACTA dotyczy też rynku leków. Zatem żegnaj tania aspiryno z Polfy… trza będzie kupować znacznie droższą oryginalną aspirynę Bayera.

No i tyle w tej sprawie. W sumie może się za niedługo okazać, że bardziej niż wizyty policji z okazji pirackiej muzyki należy obawiać się wizyty na błogosławieństwo wymiany śrub w kole na pochodzące od innego dostawcy niż ten wskazany przez producenta.

// EDIT: Wśród sygnatariuszy są Japonia i Korea Południowa, czyli państwa w których dozwoloną praktyką jest szpiegostwo przemysłowe i generalnie podpierdalanie rozwiązań technicznych.

Różnica pomiędzy call i execution w AspectJ

January 23rd, 2012

Różnica wredna, która potrafi zepsuć dzień.

Generalnie zarówno call jak i execution nie różnią się jeżeli chodzi o moment wywołania. Jeżeli zdefiniujemy, że mają być wkompilowane przed to zostaną wkompilowane przed. Jeżeli po to po. Kompilator zapewnia, że w danym przepływie sterowania aspekt będzie umieszczony w odpowiednim miejscu. Oczywiście przy założeniu, że nie ma tam jakiś dodatkowych aspektów. Różnica leży w tym gdzie kompilator umieszcza kod.

Położenie call

Jeżeli używamy call to kompilator umieści kod porady w miejscu gdzie wywoływana jest dana metoda. Czyli jeżeli metoda A.a woła metodę B.b to kod zostanie umieszczony w metodzie A.a.

Położenie execution

Jeżeli używamy execution to kompilator umieści kod w wywoływanej metodzie. Przykładowo jeżeli A.a woła B.b to kod zostanie umieszczony w B.b.

Gdzie jest to istotne

W praktyce jeżeli wrzucamy kod aspektowy do naszych klas to nie ma różnicy czy użyjemy call czy execution. Kompilator i tak musi przeorać cały kod źródłowy… no właśnie. Kod źródłowy… Jeżeli wasza metoda jest wywoływana przez jakaś zewnętrzną bibliotekę np. chcecie dodać kod aspektowy do testu oznaczonego @Test to użycie call skończy się komunikatem Xlint:adviceDidNotMatch. Kompilator nie doda waszej porady ponieważ nie pracuje na kodzie wywołującym metodę. Dotyczy to też sytuacji gdzie do wywołania metody używacie refleksji. W takim wypadku macie dwa wyjścia. Po pierwsze użyć execution, co jest prostsze, ale narusza wasz kod (przyjmuję tu pracę z weaveringiem w czasie kompilacji). Po drugie użyć call wraz z weaveringiem w czasie ładowania klas.

Ekstremalna obiektowość w praktyce – część 9 – Nie używaj getterów/setterów/własności

January 20th, 2012

Część 0
Część 1
Część 2
Część 3
Część 4
Część 5
Część 6
Część 7
Część 8

Piątek, a zatem słuchamy Listy w Trójce. Przed nami ostatnia z zasad Jeff’a Bay’a

Nie używaj getterów/setterów/własności

Niewątpliwie jest to najbardziej obiektowa z zasad. By zrozumieć o co w niej chodzi porównajmy takie oto dwie klasy

Listing 1. klasa bardziej “obiektowa”

class Chłopiec{

	private String imię;

	private String nazwisko;

	private String wiek;

	public String getImię() {
		return imię;
	}

	public void setImię(String imię) {
		this.imię = imię;
	}

	public String getNazwisko() {
		return nazwisko;
	}

	public void setNazwisko(String nazwisko) {
		this.nazwisko = nazwisko;
	}

	public String getWiek() {
		return wiek;
	}

	public void setWiek(String wiek) {
		this.wiek = wiek;
	}

}

Listing 2. klasa mniej “obiektowa”

class Dziewczynka {

	public String imię;

	public String nazwisko;

	public String wiek;

}

Czym różnią się te dwie klasy?

Obiektowość to nie metody

Pomijając różne specyficzne elementy języka związane z współbieżną zmianą stanu obiektów tych klas to te dwa twory niczym się nie różnią. Mogę jednak założyć się, że jeżeli pokażemy je “nagie i bezbronne” to pierwsza z nich zostanie zakwalifikowana jako bardziej obiektowa. Druga będzie mniej obiektowa. Dlaczego? Jakoś tak się utarło, że o obiektowości decydują metody.
W Javie jest to szczególnie potęgowane przez specyfikację Java Beans:

Properties are always accessed via method calls on their owning object. For readable properties
there will be a getter method to read the property value. For writable properties there will be a
setter method to allow the property value to be updated.

Cóż… Ma to pewien cel i jest tu pewien pomysł, ale tylko gdy przyjrzymy się tej specyfikacji jako całości (szczególnie z obsługa zdarzeń i wzorcem obserwatora). Niestety jak to w życiu bywa, ktoś z całego dokumentu wyciągnął jeden fragment i tak oto znaleźliśmy się w życi.

Czym jest obiektowość?

Obiektowość to przede wszystkim enkapsulacja. Inaczej mówiąc obiekty nie powinny ujawniać swojego wnętrza, a jedynie udostępniać pewien interfejs, który będzie odwzorowywał operacje dokonywane przez obiekt. Oczywiście może się tak zdarzyć, że operacja polega na ustawieniu jakiejś wartości obiektu. Jednak są to specyficzne przypadki. W żadnym wypadku nie należy pozwalać na swobodną manipulację właściwościami obiektu.

Co zamiast?

Skoro nie powinniśmy mieć możliwości swobodnej manipulacji jak tworzyć i konfigurować obiekty? Z każdym z elementów zajmiemy się z osobna.

Settery

Generalnie obiekty powinny być niezmienne. Ma to wiele zalet. Najważniejszą jest możliwość swobodnego programowania współbieżnego bez obawy, że wątki wzajemnie pozmieniają sobie dane. W takim wypadku settery zostaną automatycznie wyrugowane przez mechanizmy języka wymuszające ustawienie pól w konstruktorze.
Jeżeli jednak z jakiegoś powodu nie możemy użyć pól finalnych to należy ustawić je z użyciem jakiegoś kontenera DI. Zazwyczaj mamy dostęp do tego typu bibliotek i nie ma problemów z ich wykorzystaniem.
Co jednak gdy z jakiś powodów kontener DI nie jest dostępny? W takim wypadku zostaje nam wykorzystanie wzorca fabryki wzbogaconego o użycie refleksji.

Właściwości

Unikamy sytuacji kiedy zachowanie obiektu zależy od właściwości. To właściwość powinna dostarczać odpowiedniego zachowania. Przykładowo w poprzedniej części mówiłem, że opakowane kolekcje powinny dostarczać metod “kontekstowych”. Podobnie w trzeciej części gdzie mowa była o opakowaniu typów prymitywnych wspominałem o możliwości zamknięcia w typie opakowującym pewnych prostych operacji np. walidacji czy operacji arytmetycznych.

Gettery

Najbardziej kłopotliwy element. Koniec końców zawsze musimy gdzieś pokazać uzyskaną wartość. Najprościej jest przesłonić toString. Nie zawsze się to da zrobić. O ile zadziała to w przypadku prostych obiektów to już obiekty złożone stanową duży problem. Pewnym rozwiązaniem może być użycie odpowiedniego prezentera, czyli wzorca MVP. Prezenter może dostać się do obiektu via refleksja względnie odpowiednio zinterpretować wyniki z metody toString. Wzorzec ten ma w tym przypadku wiele zalet. Jeżeli jednak chcemy zrobić coś małego to można użyć czegoś co roboczo nazywam obiektem “samopezentującym się”. W takim przypadku obiekt posiada metodę, do której można przekazać docelowe miejsce prezentacji np. strumień i tyle. Jest to rozwiązanie o tyle wygodne, że czasami chcemy ograniczyć możliwość prezentacji obiektu. W takim wypadku metoda pełni rolę swoistego “pasa cnoty” ponieważ ogranicza kanały prezentacji.

Podsumowanie

Uff… przebrnąłem. Nie było łatwo. Paweł Lipiński w komentarzu do siódmej części zwrócił uwagę, że są to przede wszystkim pewne heurystyki. W części zerowej wspomniałem, że zasady te są świetne jeżeli chcemy refaktoryzować kod. Są też doskonałym narzędziem do ćwiczenia. Zatem czy stosować zasady Jeff’a Bay’a? Moim zdaniem warto dążyć do kodu napisanego zgodnie z tymi zasadami. Ponieważ kod taki promuje przemyślane konstrukcje, pozwala na odnalezienie potencjalnie niebezpiecznych fragmentów i karkołomnych konstrukcji w architekturze oraz wymusza pisanie testów. Ja napisałem projekt zgodny z tymi zasadami mający około 1000 linii. Teraz czas byś usiadł i napisał swój projekt.

Wady użycia mocków z mock-frameworków

January 20th, 2012

Idzie sobie transakcja z banku. Trafia ona ci na moje biurko i muszę ją zwalidować. Biorę ci ja JSR-303 i przepuszczam ci ja transakcję przez tą zabawkę…

Rzecz w tym, że mam kilka własnych walidatorów, które korzystają z danych pobranych z bazy. Dane sa pobierane raz i zapisywane w takim pseudo cache, który potrafi odpowiedzieć na różne pytania dotyczące poszczególnych banków (czy mają włączone pewne usługi, czy są aktywne itp.). Zatem chcąc przetestować to rozwiązanie należało by użyć mocka. Na tapetę trafia zatem Mockito i koleżanka Whendy, która będzie udawała nam bazę danych.

// offtopic:
koleżanka Whendy zawdzięcza swoje imię temu, że konfigurując mocka używamy metod when i then.
// koniec offtopicu

Szyba konfiguracja i dla mniejszych testów śmiga. Przy okazji chciałem sprawdzić jak to zagra w przypadku większego testu. Nadal bez bazy danych, ale już odpalając wszytko na raz. Wziąłem zatem dyżurny zestaw 100k transakcji testowych. Napisałem prosty test “profilujący” pod kątem czasu, odpaliłem i OutOfMemmoryError się stos skończył. Nosz… na razie bez przekleństw. Zaparzyłem świeżą kawę i dawaj sprawdzamy. Plik wejściowy ~41MB co daje jakieś ~70MB w obiektach. Do dyspozycji jest 256MB RAM dla JVM w TestNg. Hm… szybko dopinam Dupaprofiler dla pamięci i widzę, że wykłada się przy około ~40K obiektów. Na Twittera idą bluzgi w temacie JSR-303. Pól dnia walki i co się okazało?

Każdy mock ma dodatkowe featury

Generalnie każdy mock tworzony przy pomocy frameworku ma kilka fajnych fearturów. Jednym z nich jest zbieranie informacji o wywołaniach, argumentach przekazanych do obiektu itp. Te dane zżerają pamięć w zastraszającym tempie. Skończyło się na pseudoimpelentacji interfejsu. Działa tak samo jak mock, ale nie zbiera informacji o wywołaniach. Jeżeli zatem w trakcie testów kończy ci się pamięć to sprawdź czy twoje mocki nie są zbyt zasobożerne.
Jeżeli tak jest to sprawdź czy potrzebujesz informacji o wywołaniach. Jeżeli nie to wystarczy zamiast mocków z frameworku napisać własną pseudo implementację. Jeżeli potrzebujecie jednak pewnych informacji to nie pozostaje nic innego jak dołożyć pamięci.

SOPA była do przewidzenia

January 18th, 2012

Mamy sobie rok 1455 w Moguncji niejaki GutenbergW wydaje pierwszą drukowaną biblię zwaną Biblią GutenbergaW. Oczywiście wynalazek druku jest dla Europy przełomowy (choć jesteśmy pod tym względem daleko za murzynami… wróć… Azjatami). Co nam on daje? Przede wszystkim przyspiesza obieg informacji. Informacja przestaje być wyceniana na podstawie nośnika. W praktyce cena nośnika gwałtownie spada. Cały myk z Gutenbergiem polega na tym, że zaproponował on użycie tzw. ruchomych czcionek, które usprawniły proces druku. Zredukował w ten sposób koszty.
Mija sobie 49 lat i w roku 1504 w Anglii zostaje nadany przez Henryka VII Przywilej Drukarza Królewskiego. Cóż to jest? Otóż szybkość z jaką zaczęła przepływać informacja stała się bardzo niebezpieczna dla władzy. Byle dupek mógł sobie postawić drukarnię i masowo drukować oraz kolportować nieprzychylne dla władzy ulotki. Wspomniany przywilej był tak naprawdę koncesją służącą kontroli druku. Każdy drukarz musiał uzyskać zezwolenie od władzy na druk publikacji. Zatem w przeciągu niecałych 50 lat od upowszechnienia się szybkiego druku mamy narzucone ograniczenia na operatorów tego nośnika informacji.

Mam rok 1971 DARPAW otwiera sieć ARPANETW publikując specyfikację TCP/IP. Dokonuje się kolejna rewolucja w przepływie informacji. Informacja może zostać przesłana z jednego końca świata na drugi w niewyobrażalnym tempie. W przeciągu kilkudziesięciu lat ilość informacji przesyłanych tą drogą rośnie do gigantycznych rozmiarów. Sieć okazuje się jednak niebezpieczna dla władzy. I to takiej rozumianej w normalny sposób – demokratycznej i kontrolowanej przez obywateli. Najzwyczajniej w świecie władza traci możliwość rządzenia – nikt nie jest wstanie ogarnąć takich ilości informacji. Jest jednak inna gorsza niż władza siła. Jest nią grupa gości, którzy odkrywają, że w epoce sieci komputerowych ich produkty i usługi nie są nikomu potrzebne. Tą grupą są wydawcy. Wykorzystują zatem swoje możliwości i zaczynają na wszelkie sposoby wpychać różne mechanizmy koncesjonowania sieci.

Za Janem Kochanowskim:

Nikomu, albo raczej wszytkim, swoje księgi
Daję. By kto nie mniemał (strach to bowiem tęgi),
Że za to trzeba co dać, wszyscy darmo miejcie.
O drukarzu nie mówię, z tym się zrozumiejcie

Ważna rzecz. Kochanowski jasno określił, że jego dzieła kosztują tyle ile uzgodnimy z drukarzem. Mówiąc językiem współczesnym Kochanowski wydał swoje dzieła na licencji CC-BY-ND. Jedyne co kosztuje to nośnik. W epoce internetu udało się wyeliminować “najdroższy” element – nośnik. Napisałem najdroższy w cudzysłowie ponieważ patrząc na rozkład kosztów płyty łatwo zauważymy, że lwia część trafia to dystrybutorów i wydawców. Sensem istnienia wydawców jest produkcja nośników. Eliminując nośnik eliminujemy wydawcę. Rozwój sieci spowodował realne zagrożenie dla fundamentalnego elementu decydującego o istnieniu wydawcy – nośnika. Nie jest to odkrywcze, ale dobrze tłumaczy dlaczego to wydawcy, a nie artyści są główną silą napędową cenzury.

Wniosek. W przeciągu kilkunastu kolejnych lat będziemy mieli jeszcze kilka prób wprowadzenia cenzury w sieci pod hasłem walki z piractwem. Broń nie jest jednak skierowana w piratów, ale ma na celu jak najdłuższą ochronę przestarzałej technologicznie płyty CD jako nośnika treści. Jeżeli udało by się wyeliminować z rynku fizyczny nośnik to w przeciągu kilkunastu lat znikną i wydawcy.

Ekstremalna obiektowość w praktyce – część 8 – opakowywanie kolekcji w klasy specyficzne dla kontekstu wykorzystania

January 14th, 2012

Część 0
Część 1
Część 2
Część 3
Część 4
Część 5
Część 6
Część 7

Gladius Noctis, a na blogu ósma z zasad Jeff’a Bay’a

Klasa której polem jest kolekcja nie powinna mieć żadnych innych pól (opakowywanie kolekcji w klasy specyficzne dla kontekstu wykorzystania)

Nazwa trochę długa, ale nie ważne. Powróćmy na chwilę do pierwszej części tego cyklu. Na koniec przykładu z tablicami mieliśmy tam następujący kod:

Listing 1. Kod z pierwszej części

package pl.koziolekweb.eowp1;

public class Array3DFiller {

	public static void main(String[] args) {
		int[][][] array3d = new int[3][3][3];
		fillArray(array3d);

		printArray(array3d);

	}

	private static int fill2dArray(int[][][] array3d, int current, int i) {
		for (int j = 0; j < array3d[i].length; j++) {
			current = fillRow(array3d, current, i, j);
		}
		return current;
	}

	private static int fillArray(int[][][] array3d) {
		int current = 0;
		for (int i = 0; i < array3d.length; i++) {
			current = fill2dArray(array3d, current, i);
		}
		return current;
	}

	private static int fillRow(int[][][] array3d, int current, int i, int j) {
		for (int k = 0; k < array3d[i][j].length; k++, current++) {
			array3d[i][j][k] = current;
		}
		return current;
	}

	private static void print2dArray(int[][][] array3d, int i) {
		for (int j = 0; j < array3d[i].length; j++) {
			printRow(array3d, i, j);
			System.out.println();
		}
	}

	private static void printArray(int[][][] array3d) {
		for (int i = 0; i < array3d.length; i++) {
			print2dArray(array3d, i);
			System.out.println();
		}
	}

	private static void printRow(int[][][] array3d, int i, int j) {
		for (int k = 0; k < array3d[i][j].length; k++) {
			System.out.print(String.format("%2s ", array3d[i][j][k]));
		}
	}

}

Przy tamtych założeniach było ok. Krawetko podał jeszcze zgrabniejszą wersję. Ja jednak zmienię tu wszystko.

Co robimy z kolekcjami?

Przede wszystkim iterujemy. Przeciskamy przez różne formy pętli w celu wykonania operacji na wszystkich elementach kolekcji. W Javie jest to dość upierdliwe. Za każdym razem należy napisać te klika linijek kodu by przepuścić daną kolekcję przez pętlę. W dodatku może okazać się, że coś skrewiliśmy albo nasz kod dostał się w niepowołane ręce, które wykonały kilka niefajnych operacji bezpośrednio na kolekcji.
W Scali jest trochę lepiej mamy metodę foreach, która opakowuje pętlę:

Listing 2. foreach w Scali

val x = 1 to 10
x foreach ($ => println($*$))

I już mamy kwadraty liczb od 1 do 10. W javie trzeba na to dwóch pętli.

Oczywiście jest tu ukryty mały "fakap" ponieważ zarówno metoda to jak i foreach maskują nam odpowiednie pętle. W przypadku to jest to jeszcze wzbogacone o lazy-init, ale to insza inszość.

Dlaczego opakowywać kolekcje?

Kod w Scali fajny jest. Dlatego warto stworzyć sobie podobne możliwości. W Javie nie jest to trudne generalnie poniższy kawałek kodu rzucił mi się kiedyś w oczy, ale skąd pochodzi ta koncepcja nie jestem wstanie powiedzieć.

Listing 3. foreach w Javie

interface Foreach {

	interface Action {
		void perform(T t);
	}

	abstract class ForeachImpl implements Foreach {

		private static class ArrayDelegate implements Foreach {

			private T[] array;

			public ArrayDelegate(T[] array) {
				this.array = array;
			}

			@Override
			public void foreach(Action action) {
				for (T t : array) {
					action.perform(t);
				}
			}
		}

		private static class Delegate extends ForeachImpl {

			public Delegate(Collection collection) {
				super(collection);
			}
		}

		public static  Foreach delegate(Collection collection) {
			return new Delegate(collection);
		}

		public static  Foreach delegate(D[] collection) {
			return new ArrayDelegate(collection);
		}

		private Collection collection;

		private ForeachImpl(Collection collection) {
			this.collection = collection;
		}

		@Override
		public void foreach(Action action) {
			for (T t : collection) {
				action.perform(t);
			}
		}
	}

	public void foreach(Action action);
}

Jest to trochę karkołomna konstrukcja w tej postaci, ale wiadomo o co chodzi. Odpowiednie zagłębienia służą tu odwaleniu roboty podobnej do tej jaką odwala scalac przy dodawaniu traita do klasy. Dla przypomnienia jeżeli trait nie zawiera implementacji to jest traktowany jak interfejs. Jeżeli zawiera implementacje to tworzone są klasy abstrakcyjne zawierające zaimplementowane metody i w klasie docelowej następuje delegacja zachowania do takiej wewnętrznej klasy. Tyle w skrócie zainteresowanych odsyłam do konsoli i polecenia javap.

Nasza klasy wystarczy, że zaimplementuje interfejs i wydeleguje obsługę metody do klasy Delegate. Już dużo mniej roboty :D później przy iterowaniu przez kolekcję wystarczy zaimplementować clou pętli czyli to co pomiędzy { i }. Można to też łatwo przetestować. Ba! Można implementację przerzucić na użytkownika API. Niech powie co robi z pojedynczym elementem kolekcji, a to jak będzie przechodził przez kolekcję to już nie jego sprawa. Tu dochodzimy do takiego modelu, który jest już blisko programowania funkcyjnego. Klient mówi CO i nie martwi się JAK.

Wypełniamy tablicę

Powróćmy do pierwszego kodu. W pierwszym kroku opakujmy tablicę jednowymiarową o zadanej ilości elementów w coś przyjaznego dla środowiska:

Listing 4. Opakowana tablica intów

class ArrayOfInt {

	private Integer array[];

	public ArrayOfInt(int size) {
		array = new Integer[size];
	}

	public int fill(final int start) {
		return fill(start, 1);
	}

	public int fill(final int start, final int step) {
		int next = start;
		for (int i = 0; i < array.length; i++) {
			array[i] = next;
			next += step;
		}
		return next;
	}

	public void print() {
		ForeachImpl.delegate(array).foreach(new Action() {

			@Override
			public void perform(Integer t) {
				System.out.print(String.format("%2s ", t));

			}
		});
	}

}

Ok, na razie nic groźnego. O ile inicjację tablicy i jej wypełnienie musimy przeprowadzić iterując z palucha to już wypisanie robimy za pomocą delegowania.
Teraz czas na tablicę dwu wymiarową. W tym przypadku musimy powiedzieć ile kolumn i ile rzędów chcemy mieć. Jednak czy aby na pewno? Opakowujemy w końcu kolekcję kolekcji... zatem...

Listing 5. Opakowana dwu wymiarowa tablica intów

class Array2dInt {

	private class Next {
		int next;
	}

	private ArrayOfInt array[];

	public Array2dInt(int rows, int cols) {
		array = new ArrayOfInt[rows];
		for (int i = 0; i < array.length; i++)
			array[i] = new ArrayOfInt(cols);
	}

	public int fill(final int start) {
		return fill(start, 1);
	}

	public int fill(final int start, final int step) {
		final Next next = new Next();
		next.next = start;
		ForeachImpl.delegate(array).foreach(new Action() {

			@Override
			public void perform(ArrayOfInt t) {
				next.next = t.fill(next.next, step);
			}
		});

		return next.next;
	}

	public void print() {
		ForeachImpl.delegate(array).foreach(new Action() {

			@Override
			public void perform(ArrayOfInt t) {
				t.print();
				System.out.println("");
			}
		});
	}
}

Whoa... inicjacja w konstruktorze nadal z palucha (tego nie przeskoczymy). Reszta przez delegaty. Tablica trójwymiarowa to już formalność.

Listing 5. Opakowana trójwymiarowa tablica intów

class Array3dInt {

	private class Next {
		int next;
	}

	private Array2dInt array[];

	public Array3dInt(int rows, int cols, int depth) {
		array = new Array2dInt[depth];
		for (int i = 0; i < array.length; i++)
			array[i] = new Array2dInt(rows, cols);
	}

	public int fill(final int start) {
		return fill(start, 1);
	}

	public int fill(final int start, final int step) {
		final Next next = new Next();
		next.next = start;
		ForeachImpl.delegate(array).foreach(new Action() {

			@Override
			public void perform(Array2dInt t) {
				next.next = t.fill(next.next, step);
			}
		});

		return next.next;
	}

	public void print() {
		ForeachImpl.delegate(array).foreach(new Action() {

			@Override
			public void perform(Array2dInt t) {
				t.print();
				System.out.println("");
			}
		});
	}
}

Całość można oczywiście ładnie rozdzielić na nieanonimowe klasy wewnętrzne (albo wyrzucić do osobnych klas o ograniczonej widoczności) czy uczynić generycznym. Cały kod jest, wbrew pozorom, prostszy i łatwiejszy w testowaniu.

Podsumowanie

Bardzo istotną rzeczą w takim podejściu do kodowania jest umiejętność rozdzielenia swojej osobowości na klienta i dostawcę. W przeciwnym wypadku możemy nieźle przestraszyć się ilością kodu.

Najistotniejszą cechą jest jednak ograniczenie klientowi pola manewru w pracy z kolekcją. Mając ograniczone API i pozbawiając go możliwości dowolnego manipulowania elementami możemy się zabezpieczyć przed nieprzyjemnymi sytuacjami jak chociażby usunięcie elementu z kolekcji (boli jak używasz JPA), głębokie klonowanie kolekcji albo nieskończonego iterowania.
Dodatkowo operacje biznesowe są jasno określone przez co zmniejsza się prawdopodobieństwo "hakierowania" i tworzenia obejść we właściwym kodzie biznesowym.

Gdzie warto używać

Przede wszystkim warto opakowywać kolekcje, które wychodzą z bazy danych/DAO. W ten sposób można ograniczyć manipulowanie obiektami w ramach kodu biznesowego. Wszelkie operacje związane ze zmianą stanu bazy będą dokonywane poprzez interfejs opakowanej kolekcji. Dzięki czemu można kontrolować kto co może. W takim układzie aplikacja nie widzi DAO jako takiego. Widzi tylko interfejs dostarczający pewne dane na których można wykonać ściśle określone operacje.
Po drugie MVP. W tym przypadku kolekcja staje się pomocnikiem dla prezentera. Można dzięki temu wprowadzić np. dodatkowe filtrowanie danych tuż przed ich wyświetleniem. To pozwala na stworzenie jednego prezentera, który będzie prezentował dane w zależności od potrzeb, ale będzie jednocześnie na tyle elastyczny by móc z niego skorzystać w wielu miejscach. Przykładowo kolekcja A przed wyświetleniem wymaga wycięcia części danych, których nie bardzo można pozbyć się na etapie pobierania z bazy. Jednocześnie kolekcja B nie ma tych danych już domyślnie. Obie mają metodę show przyjmującą jako parametr prezenter. Następnie w środku wywołują tylko wybrane metody prezentera.
Po trzecie filtry. W takim przypadku zamiast pozwolić iterować po kolekcji możemy udostępnić klientowi ileś tam predefiniowanych metod, które filtrują kolekcję w określony sposób. Tu mała uwaga. Szkoda, że w Javie nie ma eleganckich domknięć i trzeba stosować haki w stylu anonimowych klas.

O różnicach pomiędzy wstrzykiwaniem via setter, a via pole z wykorzystaniem @PostConstruct

January 13th, 2012

Szybko o tym dlaczego ta druga metoda jest zdecydowanie lepsza.

Generalnie po ustawieniu pola chcemy wykonać pewne operacje.

Wstrzykiwanie via setter

W guice adnotujemy @Inject metodę (dowolna nazwa, widoczność itp.) i to wszystko. Problem polega na tym, że obiekt jest w stanie nieokreślonym. Raz, że jego tworzenie jeszcze trwa, a dwa, że nie mamy kontroli nad kolejnością wywoływania metod.

Wstrzykiwanie via pole + @PostConstruct

W tym przypadku w momencie gdy metoda/y oznaczone @PostConstruct są wywoływane mamy pewność, że obiekt jest już zainicjowany i spójny. Plusem jest tu też możliwość ukrycia implementacji (brak setterów, metoda może być niewidoczna). Nadal nie mamy kontroli nad kolejnością wywołań w przypadku wielu metod @PostConstruct, ale zazwyczaj jedna wystarczy by w niej wykonać określone akcje w zadanej kolejności.

Gdzie to jest ważne

Takie coś może okazać się bardzo istotne w momencie gdy robicie DI na elementach GUI. Większość silników UI ma to do siebie, że dodając komponenty robi to w kolejności wywołania metod. Jedynym wyjątkiem są siatki, gdzie można kontrolować położenie komponentu w przestrzeni. Trochę inaczej ma się to w przypadku managerów wyglądu typu Vertical/Horizontal. Tam istotna jest kolejność wywołania metody. Zatem jeżeli nie chcecie stopki na górze strony…

Szczyt HR-owskiej bezczelności

January 12th, 2012

Siedzę ci ja sobie i przeglądam pocztę zaległą dzisiejszą. Taki oto kwiatek:

Szanowny Panie,

Chciałbym sie z Panem skontaktować, w sprawie służbowej i chciałbym przedstawić Panu szczegóły.

Proszę w tym celu o podanie do siebie kontaktu telefonicznego.

Pozdrawiam,

Nazwisko pana Emila pozwolę sobie litościwie pominąć by nie robić mu wstydu. Tak samo jak i nazwę firmy, która pana Emila zatrudnia. Wynika to z tej prostej zasady, że nad ludźmi niepełnosprytnymi nie należy się (publicznie) pastwić. Pan Emil pozostaje zatem anonimowym, pozbawionym mózgu, skretyniałym do cna, nie mającym za grosz inteligencji oraz instynktu samozachowawczego, zidiociałym przedstawicielem firmy zarządzanej przez podobnych sobie durniów, którzy byli na tyle światli by zatrudnić osobnika o nikłych umiejętnościach, braku manier oraz wyczucia co wolno, a czego nie jak chce się przedstawić komuś ofertę pracy. Skąd wiem, że pan Emil ma dla mnie ofertę pracy… cóż email służbowy ma służbową domenę, a tam zazwyczaj można sprawdzić czym zajmuje się dana firma.

Szanowny panie Emilu. Ponieważ wykazał się pan szczątkową inteligencją, wyjątkowo kiepskim podejściem i nikłą umiejętnością przewidywania reakcji drugiej strony postanowiłem upamiętnić pana poprzez ufundowanie nagrody pańskiego imienia. Nagroda ta nosić będzie nazwę “Nagrody dla najgorszego pracownika firmy rekrutacyjnej im. Pana Emila”. Propozycję proszę zgłaszać na maila albo jako komentarze do tego posta. Zwycięzca otrzyma Nagrodę oraz będzie mógł osobiście otrzymać Uścisk Dłoni Kozła. O ile oczywiście będzie miał odwagę by się ze mną spotkać.

ps. Ja nie żartuję podsyłajcie swoje typy do nagrody. Najlepsze na pewno opublikuję.

Prywatne moduły w Guice – kto zacz…

January 9th, 2012

Na początek małe profanum muzyczne…

Już doszliście do siebie… to dobrze…

Słowo wstępne

Na spotkaniu WJUGa, na którym wraz z Wojtkiem Ebertowskim omawialiśmy Guice Paweł Szklarz zarzucił temat “Guice to ma a Spring nie” na przykładzie modułów prywatnych. Rzecz jest to o tyle ciekawa, że świetnie obrazuje podstawową różnicę pomiędzy Guice, a Springiem. Sposób konfiguracji.

Ogólnie rzecz ujmując. W springu wszystko co zostanie użyte w ramach taga bean jest przetwarzane tylko w kontekście tego taga. Jeżeli zatem macie dwa beany springowe implementujące ten sam interfejs i zależne od jakiegoś tam, ale identycznego, interfejsu w dwóch różnych implementacjach to możecie skonfigurować wszystko w osobnych tagach bean. Zależności uczynić anonimowymi (nie ustawiać id) i generalnie pozbyć się problemu. W Guice nie za bardzo idzie tak zrobić, ponieważ chcąc uzyskać jak najogólniejsze łączenie interfejsu z implementacją musimy takie mapowanie upublicznić. Powoduje to, że nie można dodać kolejnego identycznego mapowania.

Przykład z życia

Potrzebujemy w ramach aplikacji odwoływać się do dwóch identycznych baz danych. Te same mapowania, te same operacje, itd. tylko inne adresy. W Springu stworzylibyśmy klasę i skonfigurowali ja jako dwa niezależne beany, każdy w własną konfiguracją. W Guice taka sztuczka nie przejedzie ponieważ konfiguracja JpaPersistModule nie pozwala na wykorzystanie wielu jednostek utrwalania. Dodatkowo nie idzie tego skonfigurować. Z pomocą przychodzą tu moduły prywatne.

Moduł prywatny kto zacz

Moduł prywatny jest to specjalna implementacja modułu Guice, która w trakcie tworzenia w danym injectorze tworzy injector pochodny i do niego dowiązuje swoją konfigurację. W ten sposób konfiguracja jest niewidoczna w nadrzędnym injectorze, a tym samym można stworzyć wiele identycznych konfiguracji, które nie będą się wzajemnie widzieć. Można oczywiście pewne elementy konfiguracji upublicznić co pozwala na np. użycie dwóch identycznych jednostek utrwalania w ramach jednego projektu.

Przykładzik

Zadanie przepisać tabelę z jednej bazy do drugiej.

Na początek konfiguracja baz danych. Wykorzystuję tu dwie instancje HSQLDB umieszczone w pamięci. Jedyny problem z tym związany to konieczność dodania danych do źródła za pomocą DAO. Jak chcesz to przerzuć się na postgresa i wykorzystaj DBUnit.

Listing 1. konfiguracja baz – persistence.xml




org.hibernate.ejb.HibernatePersistence
		pl.koziolekweb.guice.SomeEntity









		
	

org.hibernate.ejb.HibernatePersistence
		pl.koziolekweb.guice.SomeEntity









		
	

Następnie interfejs DAO:

Listing 2. DAO

package pl.koziolekweb.guice;

import java.util.Collection;

public interface SomeEntityDao {

	void saveAll(Collection someEntities);

	Collection getAll();
}

Implementacja

Listing 3. implementacja DAO

package pl.koziolekweb.guice;

import java.util.Collection;

import javax.inject.Inject;
import javax.persistence.EntityManager;

import com.google.inject.persist.Transactional;

public class SomeEntityDaoImpl implements SomeEntityDao {

	@Inject
	private EntityManager em;

	@Transactional
	@Override
	public void saveAll(Collection someEntities) {
		for (SomeEntity se : someEntities)
			em.merge(se);
		em.flush();
	}

	@Transactional
	@Override
	public Collection getAll() {
		return em.createQuery("Select se From SomeEntity se", SomeEntity.class).getResultList();
	}

}

oraz nasza encja

Listing 4. SomeEntity

package pl.koziolekweb.guice;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;

@Entity
public class SomeEntity {

	@SequenceGenerator(name = "Gen", sequenceName = "Seq")
	@GeneratedValue(generator = "Gen")
	@Id
	public Long id;

	public String name;

	public SomeEntity() {

	}

	public SomeEntity(String name) {
		this.name = name;
	}
}

Jak widać nie ma tu nic niezwykłego.

Aplikacja

Kolejnym elementem jest aplikacja przepisująca dane. Klasa posiada ona dwa pola reprezentujące dao powiązane z różnymi PU.

Listing 5. Wybitnie skomplikowana klasaApp

package pl.koziolekweb.guice;

import java.util.LinkedList;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Named;

import com.google.inject.Guice;
import com.google.inject.Injector;

public class App {

	@Inject
	@Named("source")
	private SomeEntityDao source;

	@Inject
	@Named("target")
	private SomeEntityDao target;

	public static void main(String[] args) {
		Injector injector = Guice.createInjector(new MainModule());
		App instance = injector.getInstance(App.class);
		instance.prepare();
		instance.verify();
		instance.copy();
		instance.verify();
	}

	public void verify() {
		System.out.println(source.getAll().size());
		System.out.println(target.getAll().size());
	}

	public void copy() {
		target.saveAll(source.getAll());
	}

	public void prepare() {
		List data = new LinkedList();
		data.add(new SomeEntity("A"));
		data.add(new SomeEntity("B"));
		data.add(new SomeEntity("C"));
		source.saveAll(data);
	}

}

Jak widać instalujemy tylko jeden moduł – MainModule. Przyjrzyjmy się mu :)

Listing 6. główny moduł aplikacji

package pl.koziolekweb.guice;

import com.google.inject.AbstractModule;

public class MainModule extends AbstractModule {

	@Override
	protected void configure() {
		install(new DaoModule("source-pu", "source"));
		install(new DaoModule("target-pu", "target"));
	}

}

Nie ma tu nic nadzwyczajnego. Instalujemy dwa moduły DaoModule. Przyjrzyjmy się tej klasie (zaczyna się robić wpis ginekologiczno-pornograficzny wnikamy głębiej).

Listing 7. Moduł zarządzający DAO

package pl.koziolekweb.guice;

import com.google.inject.PrivateModule;
import com.google.inject.name.Names;
import com.google.inject.persist.jpa.JpaPersistModule;

public class DaoModule extends PrivateModule {

	private String jpaUnit;
	private String emMarker;

	public DaoModule(String jpaUnit, String emMarker) {
		super();
		this.jpaUnit = jpaUnit;
		this.emMarker = emMarker ;

	}

	@Override
	protected void configure() {
		install(new JpaPersistModule(jpaUnit));
		bind(DaoInitializer.class).asEagerSingleton();
		bind(SomeEntityDao.class).annotatedWith(Names.named(emMarker)).to(SomeEntityDaoImpl.class);
		expose(SomeEntityDao.class).annotatedWith(Names.named(emMarker));
	}

}

Tu zaczyna być ciekawie. Zanim omówię co i jak to dla porządku klasa DaoInitializer:

Listing 8. Klasa DaoInitializer

package pl.koziolekweb.guice;

import javax.inject.Inject;

import com.google.inject.persist.PersistService;

public class DaoInitializer {

	@Inject
	public DaoInitializer(PersistService service) {
		System.out.println(service.toString());
		service.start();
	}
}
ale co się dzieje

Na listingu 8 mamy sobie klasę – moduł guice, która zamiast AbstractModule rozszerza PrivateModule. W konstruktorze przyjmuje ona sobie dwa parametry. Pierwszy to nazwa PU z pliku konfiguracyjnego, a drugi to nazwa pod jaką będziemy udostępniać DAO. Generalnie mamy tu dość dużą swobodę. Można przyjąć, że pola trzymające DAO muszą mieć taką samą nazwę (w sensie adnotacji @Named) jak używany PU. Można dać opcję na własną adnotację. Można przyjąć, że nazwa podana w kodzie ma odpowiednik w xmlu z jakimś przedrostkiem, przyrostkiem, wrostkiem, wyrostkiem czy innym tego typu tworem (brak ci inwencji w nazewnictwie – sięgnij po podręcznik do dermatologii, na pewno coś znajdziesz).
Następnie jest sobie metoda configure, a w niej instalujemy w pierwszej kolejności moduł do obsługi JPA. Następnie tworzymy i inicjujemy (użycie asEagerSingleton) obiekt DaoInitializer, który uruchamia nam usługę JPA. Teraz możemy już powiązać interfejs i implementację DAO koniecznie wykorzystując tu informację, że pole jest adnotowane. Ostatnim akordem tej zabawy jest wywołanie metody expose, która udostępnia definicję naszej konfiguracji innym modułom (umieszcza ją w nadrzędnym injectorze). Co ważne wszystko co znajduje się w tym module jest odseparowane od świata. Zatem nie ma możliwości by nadpisać sobie konfigurację w innym module.

Uruchamiamy…

Listing 9. uruchomienie aplikacji

com.google.inject.persist.jpa.JpaPersistService@77158a
com.google.inject.persist.jpa.JpaPersistService@a7c45e
Hibernate:
    insert
    into
        SomeEntity
        (id, name)
    values
        (null, ?)
Hibernate:
    call identity()
Hibernate:
    insert
    into
        SomeEntity
        (id, name)
    values
        (null, ?)
Hibernate:
    call identity()
Hibernate:
    insert
    into
        SomeEntity
        (id, name)
    values
        (null, ?)
Hibernate:
    call identity()
Hibernate:
    select
        someentity0_.id as id0_,
        someentity0_.name as name0_
    from
        SomeEntity someentity0_
3
Hibernate:
    select
        someentity0_.id as id2_,
        someentity0_.name as name2_
    from
        SomeEntity someentity0_
0
Hibernate:
    select
        someentity0_.id as id0_,
        someentity0_.name as name0_
    from
        SomeEntity someentity0_
Hibernate:
    select
        someentity0_.id as id2_0_,
        someentity0_.name as name2_0_
    from
        SomeEntity someentity0_
    where
        someentity0_.id=?
Hibernate:
    insert
    into
        SomeEntity
        (id, name)
    values
        (null, ?)
Hibernate:
    call identity()
Hibernate:
    select
        someentity0_.id as id2_0_,
        someentity0_.name as name2_0_
    from
        SomeEntity someentity0_
    where
        someentity0_.id=?
Hibernate:
    insert
    into
        SomeEntity
        (id, name)
    values
        (null, ?)
Hibernate:
    call identity()
Hibernate:
    select
        someentity0_.id as id2_0_,
        someentity0_.name as name2_0_
    from
        SomeEntity someentity0_
    where
        someentity0_.id=?
Hibernate:
    insert
    into
        SomeEntity
        (id, name)
    values
        (null, ?)
Hibernate:
    call identity()
Hibernate:
    select
        someentity0_.id as id0_,
        someentity0_.name as name0_
    from
        SomeEntity someentity0_
3
Hibernate:
    select
        someentity0_.id as id2_,
        someentity0_.name as name2_
    from
        SomeEntity someentity0_
3

…i się cieszymy.

Podsumowanie

Prywatne moduły wprowadzają nam funkcjonalność, która nie jest spotykana w Springu. Jednocześnie należy zaznaczyć, że Spring reprezentuje zupełnie inne podejście do problemu konfiguracji i zakresów widoczności poszczególnych beanów. Tym samym nie można mówić o tym, które rozwiązanie jest lepsze. One są po prostu diametralnie różne.

Świąteczne boje z formatem TOD

December 25th, 2011

Mam sobie kamerkę JVC. Chcieliśmy rodzinie rozdać płyty z filmami małego. Rzecz w tym, że żaden rozsądny program nie czyta formatu TOD.
Format TOD to wynalazek JVC, który należy konwertować do jakiegoś rozsądnego formatu. W naszym przypadku MPEG. Poniżej jar z konwerterem mojego autorstwa.
tod2mpg

Uruchomienie:

Listing 1. uruchomienie konwertera

$> java -jar tod2mpg.zip -h

Ci, którzy cenią porządek mogą se zmienić rozszerzenie na jar. Licencja BeerwareW. Źródła wrzucę na githuba wieczorem.

// edit:

całość na Githubie:
git://github.com/Koziolek/tod2mpeg-converter.git

Swoją drogą proszę się nie przerazić trywialnością rozwiązania. Trochę się wkurzyłem jak odkryłem CZYM są pliki TOD :D