Warsjawa 2010 - moje wrażenia

Java, Konferencje Komentarze (0) »

Byłem wczoraj w Wawie na Warjawie 2010. Kto nie był niech żałuje. Konferencja była raczej mała (porównując z Javarsovią), ale bardzo ciekawa. Jechaliśmy początkowo 4 osobową ekipą - w wawie dołączyło do nas jeszcze 2 kolegów. Ok 6.00 wyjechaliśmy z Torunia ja dosiadłem się w Aleksandrowie. Na MIMUWie byliśmy już o 9.25 i w sumie nikogo nie było jeszcze :) Tylko ekipa jednego ze sponsorów rozkładała materiały informacyjne. Pogadaliśmy chwilę i powoli ludzie zaczynali się schodzić - pojawili się też organizatorzy. O 10 konferencja ruszyła.

Kawę w dłoń i na wykład o Play Framework - jeśli mam być szczery to zostałem przekonany :) Może Wojtek trochę zbyt ospale opowiadał jak na pobudkę o 5 rano, ale do framework’u mnie przekonał. Trochę mi się nie podobało w jaki sposób się view tworzy, ale może da się szybko do tego przyzwyczaić. Z całą pewnością spróbuje.

Chwila przerwy - dopchanie się po kolejną kawkę i wykład Pawła Lipińskiego, który zastępował Sławka Sobótkę. Jak dla mnie świetna prezentacja - prowadzona bardzo dynamicznie, mnóstwo analogi do życia - a to do Pawła dzieci, a to do płotu, a to do dywanu :) Paweł wszędzie widzi agile :) Bardzo fajny wykład.

Ostatnia prezentacją przed przerwą była o EGit - tutaj okazało się że ciężko jest coś na komputerze robić i mówić o tym jednocześnie. Ja bym proponował zrobić wszystkie kroki na slajdach. Wtedy można bardziej się skupić na mówieniu. Darek chciał pokazać jak najwięcej funkcji dostępnych z poziomu eclipse i pokazał tego w sumie sporo. Na pewno dało się też odczuć tremę Darka - niemniej dał mi do myślenia czy nie warto byłoby pogrzebać trochę w necie i spróbować samemu pobawić się z Gitem - parę fajnych ficzerów ma :)

OK nastała przerwa obiadowa i ludzie rzucali się na pizze :) Myślę że było jej na tyle dużo że każdy najadł się do syta. Sama przerwa wydawała mi się nawet nieco za długa.

Po przerwie czas na Clojure o ile pierwsza część była wprowadzeniem do języka więc raczej nie zaskoczyła to druga wywołała u mnie WOW :) Po pierwsze WOW - jak ta ich aplikacja szybko pokazuje wyniki :O Po drugie WOW - tylko 3500 linii :O Super integracja z Javą. Kiedyś muszę się przemóc i zacząć ogarniać temat. Boję się tylko że zmiana sposobu myślenia w clojure może nie być taka prosta.

Ostatnim wykładem na którym byłem było “Co w bajtkodzie piszczy?” Adama Michalika. I tu szok - ku**a wszystko co pisałem w zasadzie bez większych problemów da się sprowadzić do kodu źródłowego, mimo że go nie udostępniałem. Sprawa wydaje się w zasadzie bardzo prosta wystarczy nauczyć się znaczenia kilku instrukcji a bajtkod staję się dla nas jak otwarta księga. Super prezentacja - i widać było że Adam ma sporą wiedzę.

Niestety nie mogłem zostać do końca - PKP jest bezlitosne :)

Mam nadzieje że nie wygrałem PS 3 ;)

Ogólnie konferencję oceniam bardzo wysoko i jak zawsze twierdzę, że powinniśmy uczestniczyć jak najczęściej w takich eventach bo rozwijają one bezpośrednio lub pośrednio naszego programistycznego skilla.

Jak już napisałem na początku: Kto nie był niech żałuje — tak Lewy to do Ciebie :)

Clean Code w pigułce #1

Czysty Kod, Dobre praktyki, Java, Książki Komentarze (0) »

Jak już pisałem w poprzednim poście jestem w trakcie czytania książki Czysty Kod. Podręcznik dobrego programisty. Pomyślałem sobie, że w trakcie czytania będę starał się wypisywać zawarte tam rady. Efektem tychże notatek będzie właśnie ten wpis. Mam nadzieję, że komuś taki spis dobrych zasad w pigułce się przyda. A ja będę miał go w jednym miejscu :)

Zdecydowałem się na wypisywanie porad zgodnie z rozdziałami książki.

1. Znaczące nazwy:

  • nazwy przedstawiające intencję
  • unikanie dezinformacji
  • wymawialne nazwy
  • nazwy łatwe do wyszukania

2. Funkcje:

  • możliwie jak najkrótsze (max 20 wierszy)
  • najlepiej bez lub jedno argumentowe
  • pojedyncza odpowiedzialność
  • jeden poziom abstrakcji
  • bloki try{} catch{} w osobnej funkcji

3. Komentarze:

  • jak najmniej (samo komentujący się kod)
  • dozwolone komentarze:
    • komentarz z rodzajem licencji
    • TODO
    • komentarze ostrzegające
  • nie komentujmy na siłę
  • nie zostawiajmy za komentowanych fragmentów kodu

4. Formatowanie:

  • małe pliki (klasy) są lepsze niż duże
  • u góry klas najogólniejsze metody poniżej coraz bardziej szczegółowe
  • pionowe odstępy między segmentami kodu
  • funkcja wywoływana zaraz pod funkcją wywołującą
  • wiersze maksymalnie 120 znakowe
  • spacje wokół operatorów
  • wcięcia poziome oddzielające bloki kodu
  • spójne formatowanie w całym zespole

5. Obiekty i struktury danych:

  • NIE dodawać na ślepo setterów i getterów
  • przestrzegajmy prawa Demeter
  • unikanie “wraków pociągów”, czyli kodu postaci: a.getB().getC().getD().getZ().doSth();
  • unikać hybryd (trochę obiekt, trochę struktura danych)

6. Obsługa błędów:

  • wyjątki zamiast kodów powrotu
  • NIE zwracamy null
  • NIE przekazujemy null
  • tworzenie komunikatów błędów z informacją o typie awarii i co miało się wykonać oraz przesłanie ich w wyjątku

7. Granice:

  • separacja obcego kodu od naszego
  • testy “uczące” obcego kodu
  • wzorzec Adapter

8. Testy jednostkowe:

  • kod testów jest tak samo ważny jak kod produkcyjny
  • czytelność testów
  • w testach nie jest tak istotna wydajność
  • jedna asercja na test - niekoniecznie
  • jedna koncepcja na test
  • testy powinny spełniać zasady F.I.R.S.T.
    • Fast - szybkie
    • Independent - niezależne
    • Repeatable - powtarzalne
    • Self-Validating - samo kontrolujące się
    • Timely - o czasie

9. Klasy:

  • organizacja klas (od góry):
    • publiczne stałe statyczne
    • prywatne zmienne statyczne
    • prywatne zmienne instancyjne
    • publiczne metody
    • prywatne metody
  • klasy powinny być małe
  • pojedyncza odpowiedzialność (SRP)
  • niewiele zmiennych instancyjnych
  • zachowanie dużej spójności

SCJP, Clean Code

Java Komentarze (0) »

Pewnie słyszeliście, że Sun prowadził takie cudo jak SAI. Sun oferował członkom programu (studentom, wykładowcom) sporą zniżkę na egzaminy certyfikacyjne. I tak egzamin na SCJP zamiast kosztować 750zł, kosztował 40$ (120zł). Niestety Sun został przejęty przez Oracle’a, który jak widać nie do końca zgadza się z sposobem zniżek. W tak korzystnej cenie voucher na egzamin można było zamówić tylko do 31 marca 2010, ale tylko jeśli było się wcześniej zarejestrowanym w SAI. Teraz Oracle owszem daje zniżkę członkom swojej wersji SAI, ale zniżka nie jest już taka super. Dostajemy o 40% tańszy voucher, czyli zamiast płacić 750zł zapłacimy około 450zł. Widać sporą różnicę względem 120zł za czasów starego dobrego Sun’a :(

Całe szczęście w porę się ogarnąłem i 2 dni przed deathline’em zamówiłem sobie taniutki voucher’ek. Aby go otrzymać należało wpłacić kaskę (prawie 120zł) i wysłać mailem/faxem skan legitymacji studenckiej. No i tak uczyniłem. W odpowiedzi dostałem takiego o to maila:

Thank you for your Sun Academic Initiative exam voucher order.

We are currently experiencing extremely high order volume, which has affected our order processing time.  Orders are being processed in the order received and will be processed as quickly as possible.  Your order may require several weeks for fulfillment.

We will contact you if additional information is required.  Please avoid sending multiple emails as the additional email volume will cause further processing delays.

We appreciate your patience.

Best regards,

SAI Voucher Team

Nie dość że człowiek ledwo się załapał to jeszcze mnie tu dobijają “several weeks” :( No ale miejmy nadzieję, że pójdzie to w miarę sprawnie. Jak już będę pewny voucher’a to zabieram się za naukę do SCJP.

A tym czasem zmykam do lektury książki Czysty kod. Podręcznik dobrego programisty, którą udało mi się wyhaczyć w promocji Helion’a kilka dni przed świętami. Jak na razie przeczytałem coś około 50str i czyta się ją całkiem spoko. Może po przeczytaniu pokuszę się o małą recenzję.

EDIT:

Zapomniałem dodać, że mam jeszcze 2 vouchery na egzaminy Microsoftu z serii 70—. Jako, że uczęszczałem na koło naukowe .NET mogłem sobie wymienić zebrane w ten sposób punkty na książki lub vouchery. Mam w planach zdać jakiś .NET’owy egzamin jeszcze w tym roku. Może się uda, w końcu mam aż 2 podejścia :)

GWT - upload plików

GWT, Java Komentarze (1) »

Pisałem niedawno małą aplikację webową na zlecenie. Aplikacja była oczywiście napisana w GWT :) Z rzeczy, których wcześniej nie pisałem aplikacja musiała korzystać z Hibernate i uploadwać pliki na serwer. No i z czym miałem najwięcej problemów ? Właśnie z uploadem :( Hibernate okazał się bardzo fajnym narzędziem (ale o tym pewnie osobny wpis kiedyś będzie). Ok więc najpierw jak zrealizować fileupload w GWT, a potem co ja spartoliłem :)

Ok wiec najpierw przyjrzyjmy się części po stronie klienta. GWT dostarcza nam komponent FileUpload, który zajmie się czarą robotą przy uploadzie. Co jest istotne ? Żeby dało się coś przesłać na serwer musimy umieścić to w formularzu, (klasa FormPanel). Musimy nadać formularzowi odpowiednią akcję tj. podać url-pattern do servletu, który zajmie się odebraniem pliku i zapisaniem go na serwerze. Oczywiście do przesyłania pliku użyjemy metody POST :)

[java]

final FileUpload plik = new FileUpload();

final FormPanel form = new FormPanel();
form.setAction("fileupload");
form.setEncoding(FormPanel.ENCODING_MULTIPART);
form.setMethod(FormPanel.METHOD_POST);

form.setWidget(plik);

//Gdy chcemy wysłać formularz z plikiem(np po kliknięciu na przycisk) wywołujemy:

form.submit();

[/java]
Jaki był mój błąd skoro cały ten upload jest taki prosty ? Najpierw zrobiłem sobie GUI, nie było FormPanelu tylko w głównym panelu miałem dodany FileUpload. Podczas zmian zapomniałem usunąć this.add(plik), i w ten sposób FileUpload zamiast znajdować się w formularzu znajdował się w głównym panelu. Wyglądało tak jak trzeba - ale nie działało :) Kilka godzin myślałem co jest nie tak.

Ok. Jak wygląda servlet odbierający nasz plik? Skoro przesyłamy plik o trzeba w nim zaimplementować swoją metodę doPost(). A servlet wygląda tak:

[java]

public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 3404817164861510193L;

@SuppressWarnings("unchecked")
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

if (ServletFileUpload.isMultipartContent(req)) {

FileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(factory);

try {
List<FileItem> items = upload.parseRequest(req);
for (FileItem item : items) {
if (item.isFormField()) continue;
String fileName = item.getName();
if (fileName != null) {
fileName = FilenameUtils. getName(fileName);
}

File uploadedFile = new File(getServletContext().getRealPath(getServletContext().getContextPath()), fileName);
if (uploadedFile.createNewFile()) {
item.write(uploadedFile);
resp.setStatus(HttpServletResponse.SC_CREATED);
resp.getWriter().print("The file was created successfully.");
resp.flushBuffer();
} else
throw new IOException("The file already exists in repository.");
}
} catch (Exception e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"An error occurred while creating the file : " + e.getMessage());
e.printStackTrace();
}

} else {
resp.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE,
"Request contents type is not supported by the servlet.");
}
}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
super.doGet(req, resp);
}

}

[/java]

Nowe GWT, nowe problemy ;/

GWT, Java Komentarze (2) »

W końcu zabrałem się za projekt na MASI (Modelowanie i Analiza Systemów Informatycznych). Teoretycznie jest to kontynuacja projektu Desty z Programowania Zespołowego, teoretycznie dlatego, że kontynuowana jest w zasadzie tylko idea praktycznie cały kod mamy zamiar pisać od nowa.  No i jako, że od nowa to przecież nie będę pisał w przestarzałej wersji GWT tylko w najnowszej.  Desty 1.0 był pisany w GWT 1.4 albo 1.5, teraz dostępna jest juz wersja 2.0, i muszę przyznać, że sporo się pozmieniało.

A o to pierwszy problem na jaki się natknąłem:

Stworzyłem klasę która w zasadzie ma działać tylko jako DTO . No i jednym z “fieldów” miałbyć ArrayList<String>. Żeby obiekty takiej klasy puścić przez GWT RPC w starym GWT nie trzeba było robić nic więcej poza konstruktorem bez argumentowym, W nowym GWT dostaniemy ładny exeption, coś w stylu:

'fullpacketclassname.NaszaKlasa' was not included in the set of types which can be serialized by this
SerializationPolicy. For security purposes, this type will not be serialized.

Więc co trzeba zrobić, żeby dało się używać wszelkiego rodzaju Array’i ?

Musimy przed polem z arrayem dodać JavaDoc’owa adnotację

@gwt.Args<typ_z_pakietem_>

i po co takie utrudnienie ? Mam nadzieje, że dzięki temu wpisowi ktoś zaoszczędzi trochę czasu na szukaniu przyczyny błędu.

EDITED:

Zacząłem się zastanawiać czy owa adnotacja jest nowością w GWT 2.0 i wychodzi na to, że nie.  Widocznie w poprzedniej wersji projektu nie przesyłaliśmy naszych klas które zawierają array’ie, a jedynie Array’ie złożone z naszych klas.

GWT 1.7

GWT, Google, Info, Wtyczki do eclipse Komentarze (0) »

Wyszła “nowa” wersja Google Web Toolkit oznaczona numerkiem 1.7. Dlaczego użyłem cudzysłowu ? Ano dlatego, że tak w zasadzie jest to GWT 1.6 z poprawioną obsługą dla najnowszych wersji przeglądarek: Internet Explorer 8,
Firefox 3.5, i Safari 4

Zamiana biblioteki z 1.6 na 1.7 nie powinna wymagać zmian w kodzie !! Jedyne co trzeba zrobić to ponowna kompilacja do JavaScript’u.

GWT + Google AppEngine

Eclipse, GWT, Google, Java Komentarze (0) »

Mam chwile to opisze jak wystartować z Google Web Toolkit. Jakoś po prezentacjach z Programowania Zespołowego ktoś mnie poprosił żebym przybliżył troche GWT w wolnym czasie. Wtedy pisałem jeszcze w GWT 1.5 i porzadnego “Hello World” z uwzględnieniem komunikacji przez RPC nie dało się zrobić tak jak teraz w kilka sekund. No dobra to co bedzie nam potrzebne ? Nie wiele ; ] Odpalamy eclipse’a i doinstalowujemy plugin podając eclipsowi ten url: http://dl.google.com/eclipse/plugin/3.4 . OK gdy już mamy zainstalowany plugin i zresetujemy eclipse’a pojawią nam się m.in 3 nowe ikonki:

  • New Web Aplication Project
  • GWT Compile Project
  • Deploy App Engine Project

Aby stworzyć przykładowy projekt klikamy na New Web Aplication Project lub tradycyjnie tworzymy projekt poprzez New -> Other… -> Google -> Web Application Project. Wpisujemy nazwę i pakiet- zwróćmy uwage by pozostawić zaznaczone checkboxy przy Use Google Web Toolkit i Use Google App Engine gdyż bez nich nie stworzy nam się przykład korzystający z GWT a jedynie przykładowy servlet. No dobra po kliknięciu na Finish mamy już gotową aplikacje w GWT która korzysta z RPC do komunikacji z serwerem. Szkoda że nie było tak fajnie gdy zaczynałem zabawe z GWT - żeby takie coś uzyskać to dosyć długo się naszukałem : ) No ale ok przyjrzyjmy się temu co nam sie wygenerowało. Po pierwsze wygenerowały nam się 3 pakiety w moim przypadku są to:

  • pl.kedziorski.examples.GWT (w tym pakiecie znajduje się plik xml opisujący moduł GWT)
  • pl.kedziorski.examples.GWT.client (klasy klienckie - kompilowane do JavaScript’u)
  • pl.kedziorski.examples.GWT.server (klasy serwerowe - serwlety i to co obliczane po stronie serwera)

[xml]

<module rename-to=’gwt_hello’>
<inherits name=’com.google.gwt.user.User’/>
<inherits name=’com.google.gwt.user.theme.standard.Standard’/>
<entry-point class=’pl.kedziorski.examples.GWT.client.GWT_Hello’/>
</module>

[/xml]

Tag inherits definiuje z z jakich modułów ma dziedziczyć nasz moduł, tag entry-point natomiast definiuje strone startową / punkt wejścia. To ta klasa będzie wywoływana po odwołaniu do modułu.W pakiecie serwera wygenerowała nam się klasa GreetingServiceImpl.java :

[java]

public class GreetingServiceImpl extends RemoteServiceServlet implements
GreetingService {

public String greetServer(String input) {
String serverInfo = getServletContext().getServerInfo();
String userAgent = getThreadLocalRequest().getHeader("User-Agent");
return "Hello, " + input + "!<br><br>I am running " + serverInfo
+ ".<br><br>It looks like you are using:<br>" + userAgent;
}
}

[/java]

Servlet dziedziczący po RemoteServiceServlet z jedna metodą. Od normalnych (nie w GWT) servletów odróznia go jeszcze to, że implementuje interface GreetingService znajdujący się w pakiecie klienckim. W tej klasie bedą wszystkie metody do komunikacji z serwerem. W pakiecie klienckim znajdują się 3 pliki.

Wspomniany wcześniej interface GreetingServic.java

[java]

public interface GreetingService extends RemoteService {
String greetServer(String name);
}

[/java]

Jego asynchroniczna wersja GreetingServiceAsyn.java

[java]

public interface GreetingServiceAsync {
void greetServer(String input, AsyncCallback<String> callback);
}

[/java]

Oba interfejsy musze deklarować te same metody z tym że w wersji asynchronicznej zamiast typu zwracanego dorzucamy jeden argument typu AsyncCallback<typ_tego_co_zwraca_metoda>.

Jest tu jeszcze nasza klasa wejścia GWT_Hello.java z której powybieram tylko ważniejsze części.

[java]

public class GWT_Hello implements EntryPoint {

////////////////////////////////////////////////////

private final GreetingServiceAsync greetingService = GWT
.create(GreetingService.class);

////////////////////////////////////////////////////

public void onModuleLoad() {/*wyciety kod*/}

////////////////////////////////////////////////////

greetingService.greetServer(textToServer,
new AsyncCallback<String>() {
public void onFailure(Throwable caught) {

}

public void onSuccess(String result) {

}
});

}

[/java]

Klasa jest punktem wejścia więc implementuje EntryPoint stąd też metoda onModuleLoad() - która jest jakby odpowiednikiem main’a. AsyncCallback wymaga zaimplementowania 2 funkcji onFailure() i onSuccess() które zostaną wywołane w zależności od tego czy uda nam się przesłać dane z serwera czy też nie (bo akurat nam się router zrestartował np).  To by było chyba tyle jeśli chodzi o sturtup w GWT. Teraz możemy odpalić nasz projekt klikając na zwykły eclipsowy Run ; ] Projekt włączy nam się w tzw. Hosted mode, czyli mówiąc w duuuużym skrócie uruchamiamy go z klas Javy bez kompilacji do JavaScript co m.in umożliwia bardzo wygodne debugowanie np z eclipse’a. Aby umieścić aplikacje na serwerze trzeba by ją skompilować (np klikając wspomniany na początku nowy przycisk) albo bezpośrednio wrzucić na serwer Google App Engine (3. z nowych przycisków).

Google App Engine

GWT, Google, Java Komentarze (0) »

Nie pamietam już kiedy złożyłem request do Googla o konto na App Engine - w każdym bądź razie dostałem je po paru dniach. Potem reqest żeby obsługa Javy działała i …. nic. A tu dziś patrze DZIAŁA. W sumie możliwe że juz ze 2-3 miesiace - nie sprawdzałem długo : ( Ale skoro działa to mam hosting na którym moge stawiać coś Javowego : )

Tak więc zaraz po zaliczeniu sesji (jeszcze D mi zostało: ) ) zabieram się za jakąś aplikacje w GWT, w międzyczasie czytając Head Firs Servlets & JSP.

Infinitest - sprawdźmy to

Eclipse, Java, Wtyczki do eclipse Komentarze (0) »

W sumie stratą czasu byłoby jeżdżenie na konferencje jeśli kończyłoby się jedynie na wysłuchaniu tego co miał do powiedzenia prelegent. Postaram się powoli po testować narzędzia i praktyki, o których miałem przyjemność usłyszeć na JAVArsovia 2009. Na pierwszy ogień pójdzie wtyczka do eclipse (do InteliJ też jest dostępna) Infinitest. Co to takiego? Jest to wtyczka do IDE, która w tle przeprowadza testy jUnit i informuje nas o ich powodzeniu. Co to nam daje? Ano to, że już w chwili pisania testu wiemy czy on przechodzi czy też nie. Jakie ja z tego widzę korzyści?

  • eliminacja prostych pomyłek przy pisaniu samych testów
  • Oszczędność czasu (nie uruchamiamy testów czekając aż się skończą tylko kodujemy dalej bo wiemy że przeszły)

Żeby zainstalować Infinitest wrzucamy link http://eclipse.infinitest.org jako update site w eclipse i instalujemy : ) Po restarcie eclipse plugin już działa. No dobra to co teraz ? Napiszmy trywialny przykład:

[java]
import junit.framework.Assert;
import org.junit.Test;

public class NaszTest {
   @Test
   public void shouldDoSth() throws Exception {
      //given
      Integer liczba = new Integer(10000);
      //then
      Assert.assertEquals(10000, liczba.intValue());
   }
}
[/java]

Ten test jest poprawnie napisany bo faktycznie wartością liczby jest 10000. Ale załóżmy że nam się jedno 0 za dużo wpisało:

[java]
import junit.framework.Assert;
import org.junit.Test;

public class NaszTest {
@Test
public void shouldDoSth() throws Exception {
//given
Integer liczba = new Integer(10000);
//then
Assert.assertEquals(100000, liczba.intValue());
}
}
[/java]

Dodałem “niechcący” jedno zero więcej i kod teraz już by nie przeszedł. Co robi Infinitest ? Informuje, że oczekujemy 100000 podczas gdy liczba ma wartość 10000. I tą informacje dostajemy praktycznie zaraz po zapisaniu pliku. I to w formie do której jesteśmy przyzwyczajeni - przypominającej błąd w składni. No to by było na tyle jeśli chodzi o Infinitest.

infinitest

Sun Java Programmer Plus Certification

Info, Inne, Java Komentarze (0) »

Sun planuje wprowadzić do swojej ścieżki certyfikacyjnej kolejny egzamin, który wydaje się być pójściem krok naprzód. Dlaczego? Ano dlatego, że ów egzamin ma sprawdzać praktyczną umiejętność pisania w JAVIE, a nie wykucie się testów. Nie będzie to kilkadziesiąt pytań typu “multiply choice” jak w dotychczasowych egzaminach, a kilka programistycznych problemów do rozwiązania. Podczas egzaminu korzystać będziemy z Java 6.

Więcej na ten temat możemy znaleźć na stronie Suna.

Dodatkowo (a może przede wszystkim) Sun wraz z wprowadzeniem nowego egzaminu przeprowadza beta-exam, na który możemy się zapisać pod tym linkiem. Ze wszystkich chętnych zostanie wybranych 200 osób, które będą miały okazję zdobyć jako pierwsze na świecie : ) Sun Java Programmer Plus Certificate - oczywiście NIC ZA TO NIE PŁACĄC.

Silnik: Wordpress - Theme autorstwa N.Design Studio. Spolszczenie: Adam Klimowski.
RSS wpisów RSS komentarzy Zaloguj








2zł Nordic Gold