<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"><channel><title>Mateusz Papiernik Blog</title><link>http://blog.maticomp.net/</link><description>Wpisy z dziennika internetowego Jogger, wspomaganego przez Jabbera</description><lastBuildDate>Mon, 13 Jun 2016 08:59:46 +0200</lastBuildDate><generator>JoggerPL</generator><item><title>SCJP - Zamawianie vouchera</title><link>http://blog.maticomp.net/2009/07/21/scjp-zamawianie-vouchera/</link><description>Zamawiając voucher szukałem w Internecie informacji o tym gdzie, na jakich zasadach, za ile należy zamówić voucher celem zdania SCJP. W zasadzie bezskutecznie, temat praktycznie w ogóle nieporuszany. Pewnie sam bym go nie poruszył, gdyby nie... drobna ciekawostka.



Voucher należy zamówić na stronie Polskiego centrum szkoleniowego Sun i kosztuje, w tej chwili, 750zł (wedle informacji z różnych źródeł, cena od dłuższego czasu pozostaje niezmienna). W tej chwili, niestety, nie trwa promocja &quot;drugie podejście gratis&quot; - zamierzam podejść do egzaminu mając absolutną pewność jego zdania, ale wydając 750zł taki plan B, lub innymi słowy dupochron, zawsze jest miłym dodatkiem.

Voucher ważny jest jedynie w kraju zakupu. jest ważny rok i można go zrealizować w dowolnym centrum egzaminacyjnym Prometric.

Najpierw należy wypełnić formularz zgłoszeniowy, następnie Sun deklaruje przysłanie faktuy pro-forma... um... właśnie, fomularz zgłoszeniowy.

Zabrałem się za jego wypełnianie. Podałem imię, nazwisko, adres e-mail, miasto, kod pocztowy i ... gdzie jest pole na ulicę, adres?! Nie ma! Skończyło się na podaniu adresu w komentarzach dodatkowych.

Z lekka mnie to rozbawiło - ale na szczeście na tym etapie moja kieszeń nie była pomniejszona o owe 750zł, więc uśmiechnąłem się szczerze i przeszedłem do dalszego kroku - wybrania adresu dostawy faktury pro-forma oraz vouchera licząc, że może tam odnajdę brakujące pole. Nie, tam również go nie było - i również pozostawiłem komentarz w polu dodatkowym.

Sun przysłał fakture pro-forma na adres e-mail w postaci elektronicznej, prosząc o wpłatę wymaganej kwoty. Przelewu dokonalem, na potwierdzenie otrzymania zapłaty i realizację zamówienia na voucher czekam. Akceptują jedynie przelewy, płatności kartą próżno szukać.

W międzyczasie dodzwoniłem się, wraz ze znajomym, który dzieli ze mną znoje przygotowań do SCJP, na infolinię Suna. Potwierdzili, że z adresem w komentarzu nie ma problemu, do braku odpowiedniego pola w formularzu się nie odnieśli. No nic, szczegół, prawda?

Cała procedura zamawiania certyfikacji w tak popularnej dziedzinie i u takiego partnera edukacyjnego mnie zaskoczyła, spodziewałem się raczej kilku kliknięć i płatności PayPalem, lub inną formą pozwalającą na płatność kartą... widocznie XXI wiek jeszcze nie tutaj. Tak, wiem, marudzę.

Jako miły dodatek muszę tylko podzielić się miłą informacją - przynajmniej do końca roku dla certyfikowanych SCJP vouchery egzaminacyjne na kolejne certyfikaty objęte są zniżką.

Update! Uwaga studenci! (dzięki Anonimowi, który komentował ten wpis)

Sun, choć zbytnio się tym nie chwali, oferuje zniżki studenckie na vouchery w ramach Sun Academic Initiative. Aby skorzystać ze zniżki, należy zarejestrować się na stronie AI (program obejmuje również polskich studentów). Do zamówienia zniżkowego vouchera konieczne jest przesłanie drogą mailową zeskanowanych dokumentów potwierdzających bycie studentem. Zniżkowe vouchery kosztują 40$ na całym świecie (wg informacji na stronie SAI). Nie ma zniżkowych voucherów na SCBCD.</description><pubDate>Tue, 21 Jul 2009 19:48:40 +0200</pubDate><guid>http://blog.maticomp.net/2009/07/21/scjp-zamawianie-vouchera/</guid><category>Ogólne</category><category>SCJP</category><category>java</category><category>voucher</category><category>sun</category><category>certyfikacja</category></item><item><title>Literały łańcuchowe - String Literal Pool</title><link>http://blog.maticomp.net/2009/07/21/literaly-lancuchowe-string-literal-pool/</link><description>Temat traktowania łańcuchów znaków w Javie jest standardowym tematem egzaminacyjnym, jak również ciekawym przypadkiem w codziennej pracy i w czasie nauki. Zacząłem pisać ten wpis pewien czas temu, do jego ukończenia zmobilizował mnie wpis na blogu dayt3k'a traktujący o tym temacie.

Łańcuchy znaków, a dokładnie - literały - traktowane są w Javie wyjątkowo, inaczej niż &quot;typowe&quot; obiekty. Zanim przejdziemy do ich traktowania, odpowiedzmy sobie najpierw na pytanie, czym w Javie jest literał znakowy?



Zgodnie z JLS§3.10.5:



Literał znakowy składa się z zera lub więcej znaków ujętych w znaki cudzysłowu. Literał znakowy jest zawsze typu String. Literał znakowy zawsze odnosi się do tej samej instancji klasy String.



Kluczem do zrozumienia sensu takiej definicji jest niezmienność obiektów typu String, które w Javie są immutable. Oznacza to dokładnie tyle, że raz utworzony obiekt typu String na zawsze zachowuje swoją tożsamość i nie ulega modyfikacjom.

Przykład, który ilustruje tą cechę:


String test = &quot;test&quot;;
System.out.println(test);
test.concat(&quot;test&quot;);
System.out.println(test);


Wynikiem tego działania będzie dwukrotne wyświetlenie napisu test. Użycie metody concat na rzecz obiektu test nie modyfikuje tego obiektu. W zamian tworzy w pamięci nowy obiekt typu String zawierający testtest i następnie zwraca go. Ponieważ wartości zwracanej nigdzie nie zachowujemy, już w chwili jej zwrócenia nie istnieje do niej żadna referencja i może zająć się nią Garbage Collector. Z naszego punktu widzenia natomiast nic się nie zmieniło, obiekt wskazywany przez test pozostaje dokładnie tym samym obiektem.

O co zatem chodzi z fragmentem



Literał znakowy zawsze odnosi się do tej samej instancji klasy String.



z JLS?

W javie istnieje pojęcie String Literal Pool. Bardzo często ten byt określany jest jako zbiór obiektów typu String zbudowanych z literałów. Nie jest to jednak prawda. String Literal Pool jest zbiorem referencji do obiektów typu String utworzonych z literałów.

W Javie wszystkie obiekty tworzone są na stercie, łańcuchy znaków nie lądują magicznie w innym miejscu - podlegają dokładnie tym samym regułom. Jedyną różnicą jest fakt, że dla obiektów stworzonych z literałow tworzona jest referencja w String Literal Pool. Każdy literał w programie ma zatem zagwarantowaną przynajmniej jedną referencję do siebie - tą tworzoną w zbiorze literałów. Co więcej, w przypadku obiektów tworzonych z literałów w czasie działania programu istnieje zawsze dokładnie jeden obiekt typu String o danej zawartości - założeniem koncepcyjnym była oszczędność pamięci. Po co bowiem trzymać dwa obiekty zawierające dokładnie ten sam łańcuch znaków, skoro już na etapie kompilacji wiemy, że będą to duplikaty? Takie podejście do problemu umożliwia nam właśnie niezmienność obiektów typu String. Ponieważ obiekt na pewno nie ulegnie zmianie, można bezpiecznie korzystać z jednego wspólnego obiektu dla wielu referencji.


String a = &quot;test&quot;;
String b = &quot;test&quot;;
System.out.println(a==b);


Operator == zawsze porównuje referencje, także w tym przypadku. Mimo to wynikiem działania programu będzie true. Powodem tego jest fakt, że &quot;test&quot; jest literałem.

W chwili uruchomienia programu tworzony jest dokładnie jeden obiekt String zawierający łańcuch test. Do tak stworzonego obiektu umieszczana jest referencja w String Literal Pool, gdzie pozostaje ona do końca działania programu. Referencje a oraz b wskazują na dokładnie ten sam, jeden obiekt. Dlatego też porównanie z użyciem operatora == zwraca prawdę. W powyższym przykładzie do pojedynczego obiektu typu String przetrzymywane są trzy referencje - dwie zmienne lokalne oraz referencja w stałym zbiorze łańcuchów.

Żeby uściślić - podczas kompilacji literały znakowe, podobnie jak inne stałe, umieszczane są w pliku wynikowym. Podczas ładowania maszyna wirtualna dla każdego literału sprawdza, czy obiekt o takiej zawartości już nie istnieje. Jeżeli nie, tworzy obiekt typu String na stercie, oraz pojedynczą referencję do niego w String Literal Pool. Napotykając kolejne wystąpienie identycznego literału, JVM podstawia referencję do już istniejącego obiektu pobraną z String Literal Pool.

Bardzo ważne jest, że tak opisane zachowanie prawidłowe jest jedynie dla literałów. Obiekty tworzone dynamicznie w czasie uruchomienia programu - bądź to utworzone za pomocą słowa kluczowego new, bądź pobrane ze strumieni lub uzyskane w inny sposób, nie podlegają przedstawionym regułom.


public class Main {
    public static void main(String[] args) {
        String a = &quot;test&quot;;
        String b = new String(&quot;test&quot;);
        String c = args[0];
        System.out.println(a == b);
        System.out.println(a == c);
        System.out.println(b == c);
    }
}


Powyższy program uruchomiony przy użyciu polecenia java Main test wypisze trzykrotnie false. Ani obiekt utworzony słowem kluczowym new, ani utworzony z wartości przekazanej do maszyny wirtualnej w trakcie uruchomienia nie jest tożsamy z obiektem wskazywanym przez a. Wszystkie trzy referencje wskazują na trzy różne obiekty.

Użycie słowa new wymusza utworzenie nowego obiektu. Zgodnie z mechanizmem działania String Literal Pool wiemy też, że w chwili ładowania klasy - gdy tworzona jest pula łańcuchów - JVM nic nie wie o wartości args[0], nie jest ona odnotowana w pliku klasy w wyniku kompilacji. Również i tu obiekt wskazywany przez c nie będzie związany z obiektem tworzonym przez mechanizm puli łańcuchów.

Przyjrzyjmy się bliżej przypadkowi z new


public class Main {
    public static void main(String[] args) {
        String b = new String(&quot;test&quot;);
    }
}


Ile obiektów typu String tworzonych jest w tym programie? Dwa. Kompilator odnotowuje wystąpienie literału &quot;test&quot;. Podczas ładowania klasy tworzony jest obiekt zawierający łańcuch &quot;test&quot; oraz referencja do niego w String Literal Pool. Referencja ta jednak nie jest przypisywana do zmiennej b - w zamian tworzony jest drugi obiekt zawierający łańcuch &quot;test&quot; i referencja do tegoż obiektu przypisana zostaje zmiennej b.

Klasa String oferuje natomiast metodę intern(). Działanie jej jest bardzo proste - JVM przeszukuje String Literal Pool w poszukiwaniu referencji do obiektu o zawartości identycznej z obiektem, na rzecz którego wywołaliśmy intern(). Jeżeli referencja taka zostanie znaleziona, zostaje przez intern() zwrócona.


public class Main {
    public static void main(String[] args) {
        String a = &quot;test&quot;;
        String b = new String(&quot;test&quot;);
        String c = args[0];
        System.out.println(a == b.intern());
        System.out.println(a == c.intern());
        System.out.println(b.intern() == c.intern());
    }
}


W wyniku działania tego programu, dzięki zastosowaniu intern(), program wypisze trzykrotnie true. Funkcja intern() w każdym przypadku zwraca referencję do obiektu utworzonego z literału &quot;test&quot; w trakcie ładowania klasy.

Pozostaje jeszcze jedna kwestia - jak ta cecha łańcuchów w Javie wpływa na Garbage Collector? Otóż literały znakowe nigdy nie są usuwane przez GC. Powód jest bardzo prosty - do literałów znakowych zawsze istnieje przynajmniej jedna referencja - ta w String Literal Pool.


String a = &quot;test&quot;;
a = null;


Choć może wydawać się, że obiekt wskazywany w pierwszej linii przez a po wykonaniu drugiej będzie mógł zostać usunięty przez Garbage Collector, nie jest to prawda - do obiektu typu String zawierającego &quot;test&quot; nadal wskazuje jedna referencja w puli łańcuchów stałych.

JLS zwraca uwagę na 6 szczegółów:



Literały w tej samej klasie i w tym samym pakiecie reprezentują referencję do tego samego obiektu.
Literały w różnych klasach w tym samym pakiecie reprezentują referencję do tego samego obiektu.
Literały w różnych klasach i w różnych pakietach również reprezentują referencję do tego samego obiektu.
Łańcuchy obliczone z wyrażeń stałych są wyznaczane w czasie kompilacji, a następnie traktowane tak jakby były literałami.
Łańcuchy wyznaczone w czasie wykonania są tworzone w czasie wykonania, a co za tym idzie, zawsze różne.
Wynikiem jawnego internowania (intern()) łańcucha jest dokładnie ten sam łańcuch, jak już istniejący literał o tej samej treści.



Chciałbym zwrócić tutaj uwagę na punkt 4.


public class Main {
    public static void main(String[] args) {
        String a = &quot;a&quot;;
        String b = &quot;b&quot;;
        int c = 0;

        final String x = &quot;a&quot;;
        final String y = &quot;b&quot;;
        final int z = 0;


        System.out.println((a + b + c) == &quot;ab0&quot;);
        System.out.println((x + y + z) == &quot;ab0&quot;);
    }
}


Wynikiem działania będzie wypisanie false a następnie true. Wyrażenia zbudowanie z użyciem compile time constant expressions, czyli stałych wyrażeń znanych w trakcie kompilacji, w momenie kompilacji sprowadzane są do literałów i w taki też sposób traktowane.</description><pubDate>Tue, 21 Jul 2009 16:40:32 +0200</pubDate><guid>http://blog.maticomp.net/2009/07/21/literaly-lancuchowe-string-literal-pool/</guid><category>Java</category><category>SCJP</category><category>Techblog</category><category>certyfikacja</category><category>string</category><category>łańcuchy</category><category>literały</category></item><item><title>Tablice a kolekcje parametryzowane - reifiable types</title><link>http://blog.maticomp.net/2009/07/09/tablice-a-kolekcje-parametryzowane-reifiable-types/</link><description>Kolekcje i typy generyczne są wdzięcznym tematem na egzaminie, zwłaszcza przy próbach integracji ich z kodem używającym typów niegenerycznych, a także wtedy, gdy do koła fortuny dodamy jeszcze zwykłe tablice.


Które z linii prawidłowo deklarują 5-elementową tablicę list?


List[] x1 = new ArrayList[5];
List[] x2 = new ArrayList[5];
List[] x3 = new ArrayList[5];
List[] x4 = new ArrayList[5];





Tylko linia pierwsza nie spowoduje błędu kompilacji. Jak to możliwe, skoro w większości tekstów o typach generycznych wbijają nam do główy, że wildcard (?) nie może być używany przy tworzeniu obiektów?

Przy tworzeniu obiektów faktycznie nie może być używany, lecz nie tworzymy tutaj żadnego konkretnego obiektu typu ArrayList, a jedynie tablicę referencji. Linia kodu


List x1 = new ArrayList();


faktycznie nie skompilowałaby się - zgodnie z powyższym, nie można tworzyć konkretnych obiektów z użyciem wildcardów.

Co jest zatem powodem, że jedynie pierwsza linia w przykładzie z tablicami prawidłowo się skompiluje, a niemożliwe jest stworzenie tablicy listy parametryzowanej dowolnym typem, tutaj - Integerem? Cały problem leży w istotnych cechach implementacji zarówno tablic jak i typów generycznych.

W Javie typy generyczne implementowane są poprzez wymazywanie typów (ang. type erasure). Informacje o parametryzacji dostępne są jedynie na etapie kompilacji, potem natomiast są usuwane i w skompilowanym kodzie nie ma śladu po parametryzacji.

Istotnie przeczy to silnemu typowaniu tablic, których dokładne informacje o typie zachowywane są po kompilacji i zgodność typów sprawdzana jest także w czasie wykonania. Ilustruje to przykład:


Integer[] x7 = new Integer[5];
Number[] x8 = x7;
x8[0] = 3.0;
System.out.println(x8[0]);


Tablica Integerów rzutowana jest do tablicy typu Number (co jest możliwe dzięki polimorfizmowi, który w przypadku tablic działa tak samo jak dla pojedynczych referencji). Po takim rzutowaniu możliwe jest przypisanie liczby typu double (dokładnie - obiektu typu Double, następuje autoboxing) do naszej tablicy. Kompilator nie wygeneruje błędu, nie wie bowiem, że pierwotnie tablica ta stworzona była do przechowywania liczb całkowitych (pozwalam sobie tutaj na pewną nieścisłość, żeby ciągle nie pisać o referencjach do wrapperów). Co się natomiast stanie po uruchomieniu tego kodu?


Exception in thread &quot;main&quot; java.lang.ArrayStoreException: java.lang.Double
        at Main.main(Main.java:19)


Pojawi się wyjątek ArrayStoreException - informacja o typie tablicy została zachowana, program w trakcie wykonania wie, że w tablicy mogą znajdować się jedynie Integery. Zachowanie informacji o typach w czasie wykonania w przypadku tablic zostało w Javie wymuszone poprzez ograniczenie tego, jakie typy mogą zostać użyte przy deklaracji tablicy.

Są to tzw. reifiable types, co w skrócie oznacza typy, które są kompletne i nie tracą żadnej części informacji o sobie po kompilacji. Do typów tych zaliczamy:


Prymitywy
Typy nieparametryzowane
Typy parametryzowane, w których wszystkie argumenty są wildcardami [] x1 = new List[5];
x1[0] = Arrays.asList(3.0);
x1[1] = Arrays.asList(3);
System.out.println(x1[0].get(0));
System.out.println(x1[1].get(0));


Nie mając informacji o typach bez trudu do tablicy list dodamy listę liczb całkowitych oraz listę liczb zmiennoprzecinkowych. Kompilator nam w niczym nie pomoże, bo niby jak? Czy zatem jest mozliwość obejścia problemu i użycia w tablicach typów parametryzowanych?

Po części. Legalne jest zadeklarowanie referencji z typem parametryzowanym.


List[] x1;


Jest jak najbardziej w porządku. Problemem jest inicjalizacja. Czy z pomocą może przyjść rzutowanie?


List[] x1 = (List[])new List[5];


Kod się prawidłowo skompiluje i uruchomi. Również IDE oraz kompilator pomogą nam w pilnowaniu prawidłowo dodawanych typów do tej tablicy.


List[] x1 = (List[])new List[5];
x1[0] = Arrays.asList(3);
x1[0] = Arrays.asList(3.0);


zaowocuje błędem kompilacji


Exception in thread &quot;main&quot; java.lang.RuntimeException: Uncompilable source code - incompatible types
  required: java.util.List
  found:    java.util.List
        at Main.main(Main.java:9)


musimy jednak pamiętać, że o ile kompilator pilnuje nas na etapie kompilacji, o tyle - mimo iż jest to tablica - nie mamy kontroli nad czasem wykonania. Z powodu wymazywania typów w czasie wykonania informacje o parametryzacji typem Integer zostają bezpowrotnie utracone. Nie uświadczymy wyjątku ArrayStoreException. Łatwo to udowodnić:


List[] x1 = (List[])new List[5];
List</description><pubDate>Thu, 09 Jul 2009 18:16:55 +0200</pubDate><guid>http://blog.maticomp.net/2009/07/09/tablice-a-kolekcje-parametryzowane-reifiable-types/</guid><category>Java</category><category>SCJP</category><category>Techblog</category><category>certyfikacja</category><category>tablice</category><category>kolekcje</category><category>reifiable</category><category>generyki</category></item><item><title>try {} catch {} finally {} - obsługa wyjątków</title><link>http://blog.maticomp.net/2009/07/08/try-catch-finally-obsluga-wyjatkow/</link><description>Z cyklu &quot;Przygotowania do SCJP&quot; - pewne aspekty obsługi wyjątków w Javie zwróciły moją szczególną uwagę. Obsługa wyjątków jest stosunkowo prosta, a przede wszystkim logiczna - w wielu sytuacjach trzeba się jednak podeprzeć rozdziałem 14.20 Java Language Specification traktującym o sposobie obsługi bloków try {} catch {} finally {}.

Trzeba pamiętać, że blok finally wykonywany jest zawsze - niezależnie od tego czy wyjątek wystąpił, czy nie wystąpił, czy został przechwycony, czy też nie (jest od tej reguły jeden wyjątek, o którym za chwilę*).

Co więcej - trzeba pamiętać, że blok finally wykonuje się również wtedy, kiedy na logikę powinien zostać pominięty. 




Jaką wartość zwróci poniższa funkcja?



public int exceptionTest() {
  try {
    throw new Exception();
  }
  catch (Exception e) {
    return 1;
  }
  finally {
    return 2;
  }
}




1
2
Nie można określić
Kod nie skompiluje się




Jeżeli odpowiedziałeś/aś na to pytanie a) 1, przyjrzyjmy się specyfikacji:



If the catch block completes abruptly for reason R, then the finally block is executed.



oraz



An abrupt completion always has an associated reason, which is one of the following:


(...)
A return with no value
A return with a given value




Dowiadujemy się z tego fragmentu, że nawet gdy blok catch zakończy swoje działanie niespodziewanie (a instrukcja return jest wg specyfikacji niespodziewanym zakończeniem), block finally zostanie wykonany.


W podanym przykładzie wartością zwracaną będzie 2.

Co jednak tak naprawdę dzieje się z wywołaniami instrukcji return? Przeanalizujmy następujący przykład:



public class ExceptionTest {
	public int returnValue(int x) {
		System.out.println(&quot;Returning value: &quot; + x);
		return x;
	}
	
	public int testException() {
		try {
			throw new Exception();
		}
		catch (Exception e) {
			return returnValue(1);
		}
		finally {
			return returnValue(2);
		}
	}
	
	public static void main(String args[]) {
		System.out.println(&quot;Returned value: &quot; + new ExceptionTest().testException());
	}
}



Wynikiem działania tego programu będzie



Returning value: 1
Returning value: 2
Returned value: 2




Mimo iż ostatecznie zwróconą wartością jest 2, funkcja wołana w instrukcji return wykonuje się dwukrotnie - zarówno w bloku catch jak i finally. Może mieć to poważne konsekwencje w sytuacji, gdy podczac zwracania wartości modyfikowane są jakieś dane i dwukrotne wywołanie funkcji może prowadzić do nieoczekiwanych wyników.



Niezależnie od tego jak dziwna i niecodzienna jest ta sytuacja - rozważamy bowiem aspekty języka, a nie dobrego stylu - warto w wolnej chwili przejrzeć fragment specyfikacji mówiący o regułach wykonywania try {} catch {} finally {}.



Nawiązując do już przytoczonego fragmentu specyfikacji mówiącego o niespodziewanym zakończeniu wykonania, mówiąc o try {} finally {} można zwrócić uwagę na jeszcze jedną sytuację.




public int testException() {
	try {
		throw new Exception();
	}
	finally {
	}
}



Powyższy fragment kodu nie skompiluje się, owocując błędem:


Exception in thread &quot;main&quot; java.lang.Error: Unresolved compilation problem: 
	Unhandled exception type Exception


Jeśli natomiast zmodyfikujemy ów fragment do postaci



public int testException() {
	try {
		throw new Exception();
	}
	finally {
		return 0;
	}
}



Kod prawidłowo skompiluje się. Utworzony i rzucony w bloku try wyjątek zostanie zjedzony i pominięty, funkcja testException() natomiast zwróci wartość 0.

Zachowanie takie uzasadnia fragment specyfikacji:


If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:

(...)

If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).


Blok finally zakończy się z &quot;powodem&quot; zwrócenia wartości, pomijając wcześniej stworzony wyjątek.

* Jeżeli w bloku try {} catch {} pojawi się System.exit(0); blok finally nie wykona się.</description><pubDate>Wed, 08 Jul 2009 01:49:36 +0200</pubDate><guid>http://blog.maticomp.net/2009/07/08/try-catch-finally-obsluga-wyjatkow/</guid><category>Java</category><category>SCJP</category><category>Techblog</category><category>certyfikacja</category><category>try</category><category>catch</category><category>finally</category><category>wyjątki</category></item><item><title>Przygotowania do SCJP</title><link>http://blog.maticomp.net/2009/07/08/przygotowania-do-scjp/</link><description>Ostatni rok dość mocno związał mnie i zainteresował z Javą, w szczególności z platformą JEE. Temat długi i szeroki, który powoli odkrywam. Co najważniejsze - z dużą satysfakcją i zainteresowaniem. Korzystając z wytchnienia od studiów i codziennej pracy, z Javą (niestety) niezwiązaną, postanowiłem zintensyfikować swoje działania poznawcze.

Mam (również niestety)  to do siebie, że nie lubię uczyć się nie mając konkretnego celu, w postaci np. realizowanego komercyjnie projektu. Nauka i pisanie kodu do szuflady skutecznie mnie zniechęca, choć wiem, że samorozwój jest bardzo istotny i jak go zaniedbam, pozostanę w tyle za innymi, lepszymi specjalistami. 

Obrałem sobie zatem cel w postaci wstąpienia na ścieżkę certyfikacyjną Sun'a, zaczynając od SCJP (oraz, oczywiście, w miarę możliwości - zaangażowanie się w pracę zawodową z tą platformą). Cel mobilizujący do systematycznej i regularnej pracy, a zarazem pozwalający na poznanie różnych aspektów języka, które nie rzucają się w oczy w codziennej pracy, a które potrafią zaskoczyć.


Nie będę dokumentował szeroko i soczyście swoich zmagań z kolejnymi rozdziałami Study Guide, wiele blogów w Polsce bardzo szeroko traktuje w tym temacie i nie sądzę, bym w ten sposób wniósł coś nowego. Postaram się natomiast publikować notki dotyczące aspektów języka, które do tej pory nie były dla mnie oczywiste i które mogą wydawać conajmniej zastanawiające na pierwszy rzut oka. To od kolejnej notki.


Na teraz natomiast - z czego korzystam:


Sun Certified Programmer &amp; Developer for Java 6 Study Guide (Exam 310-065), tzw. K&amp;B
JavaBlackBelt - społecznościowy serwis certyfikacyjny. Obecnie jestem posiadaczem zielonego pasa
Javaranch - świetne forum dla Javowców


Plan: do połowy sierpnia podejść do egzaminu. Czy się uda? Zobaczymy.
</description><pubDate>Wed, 08 Jul 2009 01:11:03 +0200</pubDate><guid>http://blog.maticomp.net/2009/07/08/przygotowania-do-scjp/</guid><category>Java</category><category>SCJP</category><category>certyfikacja</category></item><item><title>Magento</title><link>http://blog.maticomp.net/2008/01/09/magento/</link><description>Od pewnego czasu z zainteresowaniem śledzę rozwój Magento - systemu e-commerce rozwijanego na zasadach OpenSource przez firmę Varien.

Nauczony kilkukrotnym doświadczeniem we wdrożeniach projektów klasy osCommerce/Zen Cart bez mrugnięcia okiem mogę powiedzieć - nigdy więcej. Dostosowanie sklepu do zaprojektowanego wyglądu wymaga sporych nakładów pracy ze względu na niekompletne rozdzielenie prezentacji od treści, oraz bardzo sztywne sposoby prezentowania pewnych informacji. Oczywiście - można nazmieniać dowoli, ale utrudniając sobie proces aktualizacji platformy do nowych wersji - bo modyfikacje obejmują dużo więcej miejsc, niż tylko katalog szablonów.
Magento jest inne - system oparty został o Zend Framework, tworzony jest w zamkniętym środowisku kilkudziesięciu doświadczonych programistów w Varien w celu użycia projektu do firmowych zastosowań. Rozwój idzie zgodnie ze ściśle zaplanowaną ścieżką, kod systemu jest spójny - a co najważniejsze dla nas, developerów, wyjątkowo elastyczny. Wymaga przyzwyczajenia się do dość złożonego w porównaniu z Zen Cartem sposobu integracji własnych rozwiązań w tej plaformie, ale moim zdaniem zdecydowanie warto. Większość rzeczy, włącznie z kompletnie dostosowanym designem, da się zrobić out-of-the-box, a te które się nie da - da się zrealizować w pełni niezależnymi modułami bez ingerencji w jądro Magento.
Projekt ciągle jest w fazie public beta - autorzy nie zalecają używania Magento w celach produkcyjnych ze względu na ciągle rozwijane API, niekompletną dokumentację wielu elementów, oraz potencjalne zmiany mogące poważnie utrudnić uaktualnienie bety do kolejnych wersji. Mimo to, bacznie przyglądam się i testuję w domu możliwości sklepu w kolorze magenty, bo naprawdę warto. Finalna wersja 1.0 od której dostępne będzie stabilne API i możliwość rozwijania modułów regionalnych (np. systemów płatności, integracji z porównywarkami, systemami aukcyjnymi, itp.) planowana jest na przełom marca i kwietnia. Ja tymczasem zaangażowałem się w tłumaczenie Magento na nasz ojczysty język, wychodząc z założenia, że warto dołożyć kamyczek do produktu, którego zamierzam używać w swoich wdrożeniach.
Tak czy inaczej - tym, którzy jeszcze nie widzieli, a borykają się z Zen Cartem, polecam uwadze.</description><pubDate>Wed, 09 Jan 2008 23:59:45 +0100</pubDate><guid>http://blog.maticomp.net/2008/01/09/magento/</guid><category>Ogólne</category><category>Praca</category><category>Techblog</category><category>Web design</category></item><item><title>Cisco CCNA - semestr 1</title><link>http://blog.maticomp.net/2008/01/05/cisco-ccna-semestr-1/</link><description>Pierwszy semestr akademii sieciowej Cisco ukończony. W związku z niezłym poziomem grupy, idziemy względnie szybko do przodu z materiałem - w ciągu dwóch miesięcy zrealizowaliśmy pierwszy semestr. Nie wiem, czy gdybym musiał za kurs zapłacić, również wziąłbym udział - ale obiektywnie uważam, że warto było. Moja wiedza sieciowa się uszczegóławia i gruntuje, wiele kwestii które brałem &quot;na wiarę&quot;, lub wydawało mi się, że tak jest, teraz wiem na pewno, wiem też dlaczego. Za tydzien bierzemy się za zabawę z zabawkami Cisco wraz z rozpoczęciem drugiego semestru akademii...</description><pubDate>Sat, 05 Jan 2008 17:10:22 +0100</pubDate><guid>http://blog.maticomp.net/2008/01/05/cisco-ccna-semestr-1/</guid><category>Ogólne</category></item><item><title>Pionowe centrowanie obrazków</title><link>http://blog.maticomp.net/2007/09/13/pionowe-centrowanie-obrazkow/</link><description>
Pionowe centrowanie w CSS to temat wałkowany po wielokroć, w dłuższych bądź krótszych artykułach. Często wywlekane są armaty na muchy, często rozwiązania mają braki w obsłudze dla Internet Explorera, czasem... mniejsza o to. Pionowe centrowanie obrazka w 'ach o określonych rozmiarach wykorzystuje się stosunkowo często, a większości przypadków wystarcza bardzo prosta metoda:


HTML:

</description><pubDate>Thu, 13 Sep 2007 20:20:45 +0200</pubDate><guid>http://blog.maticomp.net/2007/09/13/pionowe-centrowanie-obrazkow/</guid><category>Techblog</category><category>Web design</category><category>xhtml</category><category>css</category><category>standardy</category><category>workaround</category></item><item><title>... i jego koniec</title><link>http://blog.maticomp.net/2007/08/28/i-jego-koniec/</link><description>Wszystko co dobre szybko się kończy - urlop nie jest wyjątkiem od tej reguły. Wracam do pracy ze zdwojoną siłą. Tyle w ramach powakacyjnego powitania :)</description><pubDate>Tue, 28 Aug 2007 14:18:20 +0200</pubDate><guid>http://blog.maticomp.net/2007/08/28/i-jego-koniec/</guid><category>Ogólne</category></item><item><title>Urlop</title><link>http://blog.maticomp.net/2007/07/07/urlop/</link><description>Jutro wyjeżdżam na wypragniony i w sumie zasłużony urlop. Nie jeden projekt zrealizowałem, teraz pora odpocząć. Kosztem kilku kolejnych okazji do zrealizowania - ale kondycja psychiczna też się liczy.
Do początku sierpnia na wsi, potem tygodniowy wypad nad morze, a potem znów na wsi. W międzyczasie gdzieś tam kiedyś tam egzamin na prawo jazdy.
Pogoda ssie, ale pewnie będzie ładniej.
Szerokiej drogi wyjeżdżającym, udanej pracy tym, którzy zostają. Do usłyszenia!</description><pubDate>Sat, 07 Jul 2007 00:58:53 +0200</pubDate><guid>http://blog.maticomp.net/2007/07/07/urlop/</guid><category>Ogólne</category><category>praca</category></item><item><title>Lepszy wróbel w garści...</title><link>http://blog.maticomp.net/2007/06/12/lepszy-wrobel-w-garsci/</link><description>Z pamiętnika pracownika
Często łapię się na tym - właściwie to znów się złapałem - że staję przed idiotycznie wrednym i trudnym wyborem. Klient chce zamówić stronę/aplikację/whatever - budżet ma niższy niż bym oczekiwał w podstawowej wycenie, ale dostatecznie duży, żeby trudno było odrzucić, zapomnieć i puścić gościa z kwitkiem.
Jak się robota trafia... no właśnie. Z jednej strony bardzo, ale to bardzo nie lubię robić poniżej swojej standardowej średniej, żeby nie przyzwyczajać ludzi do zbyt taniej pracy i nie psuć rynku, który jest już dostatecznie bardzo zepsuty przez stado aukcji na allegro ze stronami za 300PLN. Z drugiej następuje pewna granica, przy której zarobek byłby dostatecznie konkretny przy niskim nakładzie pracy, żeby się zastanowić, czy jednak nie zrobić wyjątku.
Powtarzam sobie, żeby tych wyjątków nie robić, a zawsze jednak trafi się taki, że go robię. Projektuję sam, bo gdybym zapłacił grafikowi, z którym współpracuję, zostałaby ujemna figa dla mnie za realizację. A jednak robię. Na szczęście rzadko, coraz rzadziej, ćwiczę asertywność i staram się trzymać pułap...
</description><pubDate>Tue, 12 Jun 2007 15:42:24 +0200</pubDate><guid>http://blog.maticomp.net/2007/06/12/lepszy-wrobel-w-garsci/</guid><category>Praca</category><category>zarobki</category><category>www</category><category>webdesign</category></item><item><title>application/xhtml+xml - zło, dobro, mniejsze zło</title><link>http://blog.maticomp.net/2007/06/03/application-xhtml-xml-zlo-dobro-mniejsze-zlo/</link><description>Wreszcie wziąłem się za dopracowanie kilku szczegółów na swojej stronie domowej. Od tej pory wysyłana jest prawidłowym application/xhtml+xml, a JS został zastąpiony prawidłową wersją opartą o DOM i jQuery. Jednocześnie kwestia DOCTYPE i mime type zaczęła mnie nękać.

Od dłuższego czasu robię strony używając XHTML 1.0 Strict bądź Transitional. Ale przecież wysyłanie ich jako text/html to strzelanie w stopę. XHTML wysyłany w ten sposób nie wnosi do specyfikacji HTML 4.01 (Strict) nic nowego, poza slashami na końcu tagów, które... przy interpretowaniu strony jako zupy są nieprawidłowe. O ile chwalenie się zgodnością ze standardami przy prawidłowym HTML 4.01 (layout z CSS!) jest na miejscu, bo zgodność faktycznie jest,  o tyle XHTML 1.0 Strict wysłany jako text/html to pic na wodę fotomontaż.

Czasem dopilnowanie, aby XHTML Strict miał 100% prawidłowe drzewo dokumentu, co przy wysyłaniu jako application/xhtml+xml jest obligatoryjne, jest niemożliwe lub bardzo utrudnione. Choćby wtedy, gdy klienci oczekują edytorów WYSIWYG do przeklejania tekstów z Worda. Co wtedy robić i co jest mniejszym złem? Robić XHTML 1.0 Transitional, który wyświetla się prawidłowo wysyłany jako text/html, ale tak naprawdę jest niepoprawny? Niby W3C pisze should not be w kwestii wysyłania jako text/html, a nie jawnie zabrania, ale jednak. Może jednak wysyłać HTML 4.01 bez fancy slashes przed zamknięciami tagów i być pewnym faktycznej, a nie pozornej zgodności ze specyfikacją?

Sam do końca nie wiem. Oczywiście, najlepiej byłoby pilnować drzewa dokumentu i wysyłać XHTML Strict. Choć z drugiej strony, specyfikacja HTML5 opartego na SGMLu powstaje i na pewno będzie mieć się dobrze. XHTMLe to alternatywa, a nie następstwo HTMLa - mająca swoje zalety, ale i wiele wad i utrudnień.

Do napisania tej notki skłoniła mnie strona http://pornel.net/xhtml oraz to, że nawet joggerowy adwokat diab^H^H^H^H standardów - Riddle - wysyła swój jog jako text/html</description><pubDate>Sun, 03 Jun 2007 14:28:06 +0200</pubDate><guid>http://blog.maticomp.net/2007/06/03/application-xhtml-xml-zlo-dobro-mniejsze-zlo/</guid><category>Ogólne</category><category>xhtml</category><category>html</category><category>standardy</category><category>w3c</category><category>xml</category></item><item><title>Cisco Certified Network Associate</title><link>http://blog.maticomp.net/2007/06/01/cisco-certified-network-associate/</link><description>Ano decyzja zapadła - wygrany kurs CCNA warto odbyć. Zeszłoroczny się nie zrealizował, bo nie było czasu, ale zaczynając od października studia można by już myśleć o rozwijaniu kompetencji i potwierdzaniu ich certyfikatami.
Czemu jednak regulamin Cisco mówi o tym, że kurs należy ukończyć w czasie nie krótszym niż 6 miesięcy?


Program nauczania CNA jest podzielony na 4 kursy zwane semestrami. Czas trwania semestru nie jest określony, dlatego mogą być organizowane ścieżki o różnym czasie trwania w zależności od stopnia przygotowania kandydatów. Cały cykl szkolenia nie może być jednak realizowany w czasie krótszym niż 6 miesięcy. Semestr pierwszy ma charakter wprowadzający i jest jedynym semestrem obejmującym głównie zajęcia teoretyczne. Z uwagi na przyjęte założenie, że od kandydatów nie jest wymagane przygotowanie informatyczne, semestr ten obejmuje podstawowe zagadnienia dotyczące sieci komputerowych, a także pewne elementy wiedzy ogólnoinformatycznej niezbędne w realizacje dalszej części szkolenia.



Z tego wynika, że de facto pierwszy semestr, przeznaczony dla nieobeznanych z sieciami, można by szybko zrobić i zaliczyć - niestety, nie da się. Minimum 6 miesięcy bujania. Znając jednak kursy, które dostosowują się do poziomu grupy, może skończyć się nawet na pełnym roku kalendarzowym zajęć. Cóż, trudno.

Zrobi się ;)

Potem jednak będę miał twardy zgryz. Uwielbiam linuksy i administrowanie nimi, ale poważnie rozważam zrobienie także MCSA i szukanie zarobku w sieciach opartych o W2k3 a w przyszłości W2k7. Możecie mnie zlinczować ;)



UPDATE: Od października co sobotę od 8 do 16 przez rok cały czterosemestralny kurs. Twardo.</description><pubDate>Fri, 01 Jun 2007 11:33:44 +0200</pubDate><guid>http://blog.maticomp.net/2007/06/01/cisco-certified-network-associate/</guid><category>Nauka</category><category>cisco</category><category>ccna</category><category>mcsa</category><category>studia</category><category>certyfikaty</category></item><item><title>Mała wygrana</title><link>http://blog.maticomp.net/2007/05/30/mala-wygrana/</link><description>
No tak, udało mi się osiągnąć niespodziewany koniec dnia :) Wystartowałem w tym roku, po raz trzeci z rzędu, w &quot;Konkursie Wiedzy Informatycznej WSHE 2007&quot;. Konkurs wybitny może nie jest, ale zawsze są ciekawe nagrody.


Po odbyciu części teoretycznej i zdobyciu 2 miejsca zabrałem się za część praktyczną kolejnego dnia, składającą się z programowania, administracji sieciami i grafiki. Nieco wybuchowe połączenie, rzadko kiedy ludzie specjalizują się we wszystkich trzech dziedzinach jednocześnie (co było dobrze widać po wynikach).


Przeczochrałem się przez administrację sieciami. Przygotowałem sobie 3m prostej skrętki, skonfigurowałem WWW, FTP, DNS i DHCP na W2K3 Server i zabrałem się za konfigurację routera Cisco. Tam poległem po skonfigurowaniu hostname'a i podniesieniu dwóch interfejsów. Pierwszy raz widziałem na oczy Cisco - było to na pewno widać w moich działaniach na konsoli routera :)


W części programistycznej bezczelnie używałem STLa z C++, który wszak był całkiem jawnie dozwolony, nie implementując własnego sortowania czy mieszania tablic. STLowych algorytmów jest całkiem wiele, działają też wystarczająco szybko. Jedno zadanie zrobiłem wyjątkowo nieoptymalnie (przez stres, nieuwagę?) - zauważyłem to jednak po zapisaniu rozwiązań.


Część graficzną przemilczę - bo mimo, iż rodzinnie jestem wykształconym grafikiem, zadania były absurdalne, sprzęt do pracy nieprzygotowany, możliwość obiektywnej oceny zerowa... cóż, bywa.


W sumie, ku swojemu zdziwieniu - spodziewałem się, że będą lepsi ode mnie w każdej z dziedzin - wylądowałem z wynikiem 40/50pkt z sieci, 40/50pkt z programowania i 39/50pkt z grafiki, otrzymując jednocześnie 1 miejsce w owym konkursie ;D


Z opadniętą szczęką wróciłem do domu z laptopem w ręku, i voucherem na 4 semestralny kurs Cisco CCNA oraz całoroczny Cisco WLAN. Dali też zwolnienie z czesnego przez pierwszy rok, ale nigdy nie rozważałem WSHE jako uczelni dla siebie, więc pomijam milczeniem.


Przypadki chodzą po ludziach ;D
</description><pubDate>Wed, 30 May 2007 21:17:05 +0200</pubDate><guid>http://blog.maticomp.net/2007/05/30/mala-wygrana/</guid><category>Ogólne</category><category>sieci programowanie cisco windows</category></item><item><title>RoR, Django, a hosting - za ciosem</title><link>http://blog.maticomp.net/2007/05/25/ror-django-a-hosting-za-ciosem/</link><description>Jak już się dziś rozpisałem, to skrobnę jeszcze jeden wpis.
Często budując bardziej złożone rozwiązanie, które wymaga stworzenia autorskiego systemu, gdyż gotowe nie sprawdzają się i nie spełniają wymagań, staję przed wyborem narzędzia. I... niestety, praktycznie zawsze kończy się na PHP + MySQL, często z wykorzystaniem Symfony, CakePHP lub innego frameworka. Powód? Hosting. Klienci mają wykupione usługi w Polsce, a jeżeli nie mają - takich hostingów właśnie oczekują (nawiasem mówiąc za granicami naszego kraju wcale nie jest wiele lepiej). Ilekroć korci mnie, żeby zrobić coś w Pythonie - ot, na przykład używając Django, jestem hamowany przez oferty firm hostingowych. Te, oferujące obsługę pythona, można policzyć na palcach jednej ręki (nie mówię o serwerach dedykowanych, bo to inna skala kosztów). To samo ma się z Rubym i Ruby on Rails, o PostrgreSQL nie wspomnę. Jaki jest właściwie powód tego, że aplikacji w innych językach niż PHP zwyczajnie nie ma gdzie hostować? ... Eh.
Ten wpis ma charakter czysto refleksyjny.</description><pubDate>Fri, 25 May 2007 14:23:16 +0200</pubDate><guid>http://blog.maticomp.net/2007/05/25/ror-django-a-hosting-za-ciosem/</guid><category>Praca</category></item><item><title>Wdrażanie rozwiązań OpenSource</title><link>http://blog.maticomp.net/2007/05/25/wdrazanie-rozwiazan-opensource/</link><description>
Wielokrotnie spotykam się ze zdaniem, że wdrażanie rozwiązań OpenSource w komercyjnych zastosowaniach jest be. Podawane argumenty obejmują zazwyczaj rzeczy w stylu:



autor strony nie potrafił napisać autorskiego systemu więc użył gotowca
systemy opensource są bardziej podatne na włamania
użycie gotowca to pójście na łatwiznę
JAK MOŻNA KLIENTOWI ZAPROPONOWAĆ DARMOWY SYSTEM CMS/e-commerce/wstaw co chcesz??????



W swojej zawodowej praktyce niejednokrotnie stawałem przed podobnymi dylematami. Z większością kwestii poruszonych na tej liście nauczyłem się nie zgadzać. Postanowiłem garstkę swoich spostrzeżeń umieścić na jogu:



Bardzo wiele dobrych produktów OpenSource idealnie trafia w potrzeby klienta, nawet bez konieczności głębszych modyfikacji funkcjonalności.
Dostosowanie projektu OpenSource i jego wdrożenie często zajmuje dużo mniej czasu i wymaga mniejszego nakładu pracy - jednocześnie pozwala na realizację projektu z mniejszym budżetem i w krótszym czasie
ograniczenia zarówno finansowe jak i czasowe po stronie klienta uniemożliwiają budowę autorskiego systemu - w takich sytuacjach jednocześnie jest on zazwyczaj niepotrzebny (wymagania spełnia nawet prosty system opensource)
autorzy poważnych projektów opensource dbają o uaktualnienia w przypadku znalezienia luki bezpieczeństwa - argument o podatności na włamania często okazuje się nietrafiony
oddanie gotowca tak naprawdę nie następuje - przy każdym wdrożeniu można projekt dostosować do potrzeb klienta, a także odpowiednio &quot;ubrać&quot; w otoczkę dedykowaną specjalnie dla niego


To oczywiście nie wszystko. Argumenty zarówno za, jak i przeciw, można mnożyć. Uważam jednak, że wybór rozwiązania powinien zależeć jedynie od specyfikacji projektowej i wymagań klienta. W innych sytuacjach i w innym budżecie warto tworzyć autorskie systemy, w innych zaś warto wykorzystać już istniejące (oraz dostosować je do potrzeb), zamiast wynajdować koło na nowo.

A jakie są Wasze praktyki?</description><pubDate>Fri, 25 May 2007 13:48:23 +0200</pubDate><guid>http://blog.maticomp.net/2007/05/25/wdrazanie-rozwiazan-opensource/</guid><category>Praca</category><category>sieć standardy opensource</category></item></channel></rss>