Your SlideShare is downloading. ×
0
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Lekcja stylu
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Lekcja stylu

3,739

Published on

Lekcja Stylu - czy w Javie można jeszcze dostrzec piękno? …

Lekcja Stylu - czy w Javie można jeszcze dostrzec piękno?

Przeglądając listy prezentacji na konferencjach związanych z Javą z ostatnich lat można dostrzec pewien wzorzec. Przedstawia się coraz to bardziej wyrafinowane zręby aplikacji, wskazówki integracyjne dla kolejnych JBusinessComponents oraz zręby aplikacji webowych, gdzie wypisanie "Hello World" zajmuje trzy linijki zamiast pięciu. Czyżby zapomniano już o samym języku Java? Czyżby wszyscy już przesiedli się na Scalę, Groovy lub JRuby?

Swoją prezentacją chcę wrócić do korzeni, do samego języka Java. Będę pokazywał dobre przykłady, jak należy programować, aby czytanie kodu było miłym doświadczeniem. Nie będzie jednak to wykład o wzorcach projektowych, ale o codzienności programisty, który właśnie po wypiciu porannej kawy i otwarciu edytora, pisze pierwszą tego dnia instrukcję warunkową.

Będzie to hołd książce "Implementation Patterns" Kenta Becka. W prezentacji zostaną przedstawione także ułatwiające życie biblioteki takie jak Google Guava, Google Guice oraz Mockito.

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,739
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
16
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • Cześć wszystkim. Cieszę się, że jest was tutaj tak dużo. Zastanawiam się, czy przyszliście na prezentacje zwabieni jej tytułem, czy bardziej przyciągnął was fakt, że pracuję dla firmy Google.
    Tadaaa. Witam na prezentacji Lekcja Stylu, czyli czy w Javie można jeszcze dostrzec piękno, czy da się jeszcze ładnie i radośnie programować.
  • Nazywam się Wiktor Gworek. Tak wygląda mój obecny avatar, gdybyście mnie szukali. A znaleźć możecie mnie na Twitterze oraz na Blipie. Od czasu do czasu coś ciekawego napiszę na swoim blogu.
  • Pracuję przy serwisie Blogger.com. Blogger jest największą platformą blogową na świecie, gdzie 275 tysięcy słów jest pisanych w ciągu każdej minuty.

    Jest to serwis w całości napisany w Javie. Od pierwszego dnia.

    Co więcej, w sierpniu skończy on 11 lat. Był on 7 lat temu przepisany na technologie Google’owe. Możecie sobie wyobrazić, że przez ten szmat czasu wiele, na prawdę wiele inżynierów pracowało przy Bloggerze. Potrzeba było włożyć w niego bardzo dużo wysiłku, aby kolejni dochodzący do niego inżynierowie mogli efektywnie pracować.
  • Pracuję przy serwisie Blogger.com. Blogger jest największą platformą blogową na świecie, gdzie 275 tysięcy słów jest pisanych w ciągu każdej minuty.

    Jest to serwis w całości napisany w Javie. Od pierwszego dnia.

    Co więcej, w sierpniu skończy on 11 lat. Był on 7 lat temu przepisany na technologie Google’owe. Możecie sobie wyobrazić, że przez ten szmat czasu wiele, na prawdę wiele inżynierów pracowało przy Bloggerze. Potrzeba było włożyć w niego bardzo dużo wysiłku, aby kolejni dochodzący do niego inżynierowie mogli efektywnie pracować.
  • Do Bloggera przyszedłem półtora roku, jako świeżak prosto ze studiów. Myślałem, że potrafię programować. Bardzo się myliłem.
    Lekcja stylu, to moja historia, którą wam przedstawię, jak poznawałem Javę i małymi krokami dostrzegałem jej piękno. Chcę, żeby ta prezentacja była dla was inspiracją, żeby pisać ładniejszy kod, ale także żeby to była dla was zachęta, żeby bawić się z kodem.

    1) Piękny kod to taki, który łatwo się czyta. To taki kod, w którym brak jest szelmowskich sztuczek piekielnie zdolnego programisty.
    2) pozbywanie się nisko poziomowego zbędnego kodu (tzw. boilerplate code). przykładem dla mnie jest JDBC, gdzie ilość nadmiarowego kodu to około 80%. Mimo to, jeśli chcemy skorzystać z JDBC ten kod musimy napisać.
    3) to taki kod, który można łatwo testować, gdzie wszystkie zależności obiektu są jasno zdefiniowane -- tak aby można było wstrzyknąć do niego obiekty mockujące sprawdzające poprawne zachowanie obiektu.
    4) to taki kod, który wykorzystuje typowanie statyczne, aby jak najwcześniej wykrywać błędy w kodzie. Jeśli piszemy już w Javie to wykorzystujmy moc, którą nam daje kompilator.
    5) A także piękny kod można uzyskiwać poprzez używanie odpowiednich narzędzi, które spowodują, że pisanie kodu stanie się łatwiejsze

  • Narzędzia, które stosuje każdego dnia podczas mojej pracy to Guava (open-sourceowany wycinek wewnętrzych wspólnych bibliotek Googleowych), Guice (aby nadać aplikacji architektoniczny porządek) oraz Mockito - do testowania. Czyli 2 biblioteki Google’owe oraz jedna krakowska :).

    Wymienione tutaj biblioteki upraszczają twój kod. Z nimi jest łatwiej pisać, czytać i utrzymywać kod w projekcie. Chociaż moglibyśmy przetrwać bez nich i rzeczy, które one wprowadzają, to jednak zwiększą one moją produktywność jako programisty. Redukują one sporą ilość zbędnego nisko poziomowego kodu, który musiałbym napisać.

    Została tutaj wymieniona biblioteka wspomagająca mockowanie Mockito. Z dumą mogę powiedzieć, że w Bloggerze większość testów jest oparta o Mockito.

    Na tej prezentacji skupię się na tej pierwszej - Guava.
  • Prezentację podzieliłem na 2 części.
    - Na początku pokażę, jak małymi kroczkami będziemy modyfikować nasz kod, aby stawał się bardziej czytelny.
    - a następnie zaprezentuję, w jaki sposób można się bawić z Javą na przykładzie programowania funkcyjnego.

    Do dzieła.
  • Zacznijmy od poprawiania kodu. Wyznaczmy sobie jakiś cel, do którego będziemy dążyć.
  • Oto nasz cel. Miejmy ten cytat w głowie i zaczynajmy.
  • Treść treścią, ale także trzeba dbać o formę prezentacji.

    Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli:
    * szerokość linii to 100 znaków, nie ma wyjątków
    - ciekawostka a propos 80 znaków i osób niedowidzących
    * (pamiętajcie, że zło czai się wszędzie) bezwzględny zakaz używania tabulatorów
    * wcięcia w blokach kodu stosujemy 2 znaki, a nie 4 znaki; kod wówczas optycznie jest mniej rozwleczony, lepiej się go czyta
    * oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod którymi jest tylko jedna instrukcja.


  • Treść treścią, ale także trzeba dbać o formę prezentacji.

    Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli:
    * szerokość linii to 100 znaków, nie ma wyjątków
    - ciekawostka a propos 80 znaków i osób niedowidzących
    * (pamiętajcie, że zło czai się wszędzie) bezwzględny zakaz używania tabulatorów
    * wcięcia w blokach kodu stosujemy 2 znaki, a nie 4 znaki; kod wówczas optycznie jest mniej rozwleczony, lepiej się go czyta
    * oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod którymi jest tylko jedna instrukcja.


  • Treść treścią, ale także trzeba dbać o formę prezentacji.

    Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli:
    * szerokość linii to 100 znaków, nie ma wyjątków
    - ciekawostka a propos 80 znaków i osób niedowidzących
    * (pamiętajcie, że zło czai się wszędzie) bezwzględny zakaz używania tabulatorów
    * wcięcia w blokach kodu stosujemy 2 znaki, a nie 4 znaki; kod wówczas optycznie jest mniej rozwleczony, lepiej się go czyta
    * oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod którymi jest tylko jedna instrukcja.


  • Treść treścią, ale także trzeba dbać o formę prezentacji.

    Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli:
    * szerokość linii to 100 znaków, nie ma wyjątków
    - ciekawostka a propos 80 znaków i osób niedowidzących
    * (pamiętajcie, że zło czai się wszędzie) bezwzględny zakaz używania tabulatorów
    * wcięcia w blokach kodu stosujemy 2 znaki, a nie 4 znaki; kod wówczas optycznie jest mniej rozwleczony, lepiej się go czyta
    * oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod którymi jest tylko jedna instrukcja.


  • Pierwsza porada. Zacznijcie kodować defensywnie. Jasno zapisujcie warunki wejścia do metod. Co prawda moglibyście zapisać te rzeczy w JavaDocach, to jednak nie jest wystarczające, gdyż kompilator nie patrzy na JavaDoci i ich nie rozumie.
  • Jak w takim razie kodowanie defensywne może wyglądać? Tadaaa. W jasny i precyzyjny sposób zacząłem definiować wejście do metody. Można co prawda by wykorzystać metody assert, które istnieją w Javie - to jednak nie są one domyślnie włączone.

    Co uzyskujemy przez to?
    - bardziej czytelny kod
    - moj kod wowczas mniej sie wywala,
    - latwiej dostrzec przypadki brzegowe.
  • Ale czy da się to lepiej zapisać? Tak, w Guavie znajdziemy klasę Preconditions. Jest to zbiór metod statycznych, które można używać do zdefiniowania wejścia do metody. Dzięki temu otrzymujemy zachowanie fail-fast i wyjątek, który możemy otrzymać jest bardzo czytelny.

    Jaka jest różnica pomiędzy poprzednim zapisem a użyciem Preconditions? Żadna! Natomiast czytelność kodu została zwiększona.
  • Albo czy czasem nie macie dość pisania zbędnego kodu? Czy w waszych głowach nie zapala się światło ostrzegawcze, kiedy piszecie coś, co w waszym przeświadczeniu powinno być dużo prostsze?
  • Dla mnie takim zbędnym kodem podczas codziennej pracy to inicjalizacja kolekcji. Guava w interesujący sposób rozprawia się z tym problemem. Dostarcza wielu bardzo wartościowych metod.

    Fajne, no nie? Dzięki typom generycznym i poręcznym metodom wytwórczym (factory method) wygląda to już o niebo lepiej. Nie musimy pisać nudnego kodu, który Java powinna rozumieć od początku.

    Powyższe metody wytwórcze mają zostać wprowadzone w JDK 7 i będzie to świetne. Ale po co czekać na nie teraz?
  • Przejdźmy do konceptu niemodyfikowalnych obiektów.
    Uwaga: jeśli chciałbym, żebyście zapamiętali z tej prezentacji jedną rzecz to właśnie koncept niemodyfikowalnych obiektów.

    Ok, co to są niemodyfikowalne obiekty?
  • (1) Nie dostarczaj metod modyfikujących stan obiektu. Settery.

    (2) Oznacz wszystkie pola klasy jako final. To jasno i precyzyjnie określa twoje intencje. Java w czasie kompilacji jest w stanie to sprawdzić.
    W ten sposób nowo utworzony obiekt jest w pełni zainicjalizowany i nie potrzeba żadnego ekstra kodu do jego inicjalizacji. Przynajmniej tak powinno być.

    Obiekty niemodyfikowalne są proste, z natury bezpieczne wątkowo, nie wymagają żadnej synchronizacji i mogą być dowolnie współdzielone.

    Jest to bardzo ważna cecha. Ponieważ w komputerach mamy coraz więcej rdzeni, a więc jesteśmy w stanie rozproszyć obliczenia. Żeby to robić efektywnie, współdzielone obiekty nie powinny zmieniać swojego stanu, jako że problemy współbieżne będą krzyczeć na produkcji.

    --- Jedyną wadą takich obiektów jest to, że wymagają osobnego obiektu, kiedy jego stan się zmienia.
    -- kiedy jeszcze raz bedziesz chcial napisac metoda zaczynajaca sie na set* - zastanow sie
  • Wygląda kod znajomo? Taki kod często można spotkać podczas pisania testów, kiedy chcemy dostarczyć testowanej klasie jakieś dane.

    Lub kiedy chcemy stworzyć stały zbiór wartości. Zazwyczaj piszemy pole, które jest public static final. Nadajemy nazwę. Następnie wypełniamy zbiór elementami. Mamy 2 metody do dyspozycji: albo zawołać metodę statyczną albo zainicjalizować polę w bloku statycznym. Drugie rozwiązanie jest najbardziej popularne. Także tworzymy zbiór, wypełniamy go elementami, a następnie tworzymy z tego niezmienialny zbiór. Zaskakujące jest, jak często zapomina się o ostatniej linijce. Wówczas mamy zbiór, który można zmodyfikować w polu public static final.
  • Krótsze, ale używa aż czterech klas. Coś jest nie tak.
  • To co na prawdę wówczas chcesz to niemodyfikowalna kolekcja wypełniona danymi. I żeby to zgrabnie wyglądało.

    Teraz kod mówi dokładnie to, co mamy na myśli. + jest to dużo wydajne
  • To co na prawdę wówczas chcesz to niemodyfikowalna kolekcja wypełniona danymi. I żeby to zgrabnie wyglądało.

    Teraz kod mówi dokładnie to, co mamy na myśli. + jest to dużo wydajne
  • To co na prawdę wówczas chcesz to niemodyfikowalna kolekcja wypełniona danymi. I żeby to zgrabnie wyglądało.

    Teraz kod mówi dokładnie to, co mamy na myśli. + jest to dużo wydajne

  • Wygląda kod znajomo?

    Czy nigdy nie potrzebowałeś mapy, która może przechowywać wiele wartości dla jednego klucza? Czy za każdym razem piszesz taki kod?

    Kod dość często pisany przez programistów, kiedy ich zadaniem jest pogrupowanie elementów z wejścia.

  • Wygląda kod znajomo?

    Czy nigdy nie potrzebowałeś mapy, która może przechowywać wiele wartości dla jednego klucza? Czy za każdym razem piszesz taki kod?

    Kod dość często pisany przez programistów, kiedy ich zadaniem jest pogrupowanie elementów z wejścia.

  • Wygląda kod znajomo?

    Czy nigdy nie potrzebowałeś mapy, która może przechowywać wiele wartości dla jednego klucza? Czy za każdym razem piszesz taki kod?

    Kod dość często pisany przez programistów, kiedy ich zadaniem jest pogrupowanie elementów z wejścia.

  • Wygląda kod znajomo?

    Czy nigdy nie potrzebowałeś mapy, która może przechowywać wiele wartości dla jednego klucza? Czy za każdym razem piszesz taki kod?

    Kod dość często pisany przez programistów, kiedy ich zadaniem jest pogrupowanie elementów z wejścia.

  • Wygląda kod znajomo?

    Czy nigdy nie potrzebowałeś mapy, która może przechowywać wiele wartości dla jednego klucza? Czy za każdym razem piszesz taki kod?

    Kod dość często pisany przez programistów, kiedy ich zadaniem jest pogrupowanie elementów z wejścia.

  • Jest to przykład multimap w Google Collections, czyli takich map, gdzie dla danego klucza można trzymać wiele wartości. W przypadku ListMultimap, kolejność dodawanych wartości dla danego klucza zostanie zachowana.

    Zachęcam do zapoznania się się z com.google.common.collect, jako że czekają tam prawdziwe perełki.
  • Jest to przykład multimap w Google Collections, czyli takich map, gdzie dla danego klucza można trzymać wiele wartości. W przypadku ListMultimap, kolejność dodawanych wartości dla danego klucza zostanie zachowana.

    Zachęcam do zapoznania się się z com.google.common.collect, jako że czekają tam prawdziwe perełki.
  • Jest to przykład multimap w Google Collections, czyli takich map, gdzie dla danego klucza można trzymać wiele wartości. W przypadku ListMultimap, kolejność dodawanych wartości dla danego klucza zostanie zachowana.

    Zachęcam do zapoznania się się z com.google.common.collect, jako że czekają tam prawdziwe perełki.
  • Jest to przykład multimap w Google Collections, czyli takich map, gdzie dla danego klucza można trzymać wiele wartości. W przypadku ListMultimap, kolejność dodawanych wartości dla danego klucza zostanie zachowana.

    Zachęcam do zapoznania się się z com.google.common.collect, jako że czekają tam prawdziwe perełki.
  • Stosowanie płynnych interfejsów (tzw. fluent interface) to sposób implementacji API w językach obiektowych, których celem jest zwiększenie czytelności kodu. Chodzi o to, żeby osoba czytająca miała wrażenie, jakby czytała zdanie w języku naturalnym.

    Jedną z techniką uzyskania płynnego interfejsu jest method chaining, czyli łańcuszek metod.

    Zobaczmy to na przykładach z Google Guava.
  • Stosowanie płynnych interfejsów (tzw. fluent interface) to sposób implementacji API w językach obiektowych, których celem jest zwiększenie czytelności kodu. Chodzi o to, żeby osoba czytająca miała wrażenie, jakby czytała zdanie w języku naturalnym.

    Jedną z techniką uzyskania płynnego interfejsu jest method chaining, czyli łańcuszek metod.

    Zobaczmy to na przykładach z Google Guava.
  • Stosowanie płynnych interfejsów (tzw. fluent interface) to sposób implementacji API w językach obiektowych, których celem jest zwiększenie czytelności kodu. Chodzi o to, żeby osoba czytająca miała wrażenie, jakby czytała zdanie w języku naturalnym.

    Jedną z techniką uzyskania płynnego interfejsu jest method chaining, czyli łańcuszek metod.

    Zobaczmy to na przykładach z Google Guava.
  • Java nie jest językiem funkcyjnym. Można natomiast z funkcyjnością eksperymentować. Jest to bardzo udana zabawa zwłaszcza z kolekcjami.

    Java i programowanie funkcyjne to trudna miłość. Jednak poszukiwanie dostarcza dużo radości. Zobaczmy.












  • Funkcja to operacja, która transformuje jest obiekt w drugi. Na przykład wyobraźmy sobie funkcję, która transformuje łańcuch znaków do liczb, czyli dla łańcucha “22” zwracana jest liczba całkowita 22.
    Funkcja transformująca nie musi zwracać obiektu innego typu. Przykładem niech będzie funkcja konwertująca stopnie w farenheicie do stopni w celsiuszu.

    Żadnych, ale to żadnych efektów ubocznych.




  • Predykat to rodzaj funkcji, który dla wejścia zwraca prawdę lub fałsz. W JDK korzystamy z wyrażeń regularnych dość często. Wyobraźmy sobie predykat wykorzystujący wyrażenie regularne. Dla danego łańcucha znaków zwraca prawdę, jeśli wyrażenie regularne pokrywa łańcuch znaków.

    Tak samo jak w przypadku funkcji: żadnych, ale to żadnych efektów ubocznych.






















  • Podsumowując, pokazałem wam, w jaki sposób przekonywałem siebie, że w Javie można dostrzec ładny programowania. Rozpocząłem swoją przygodę poprawiając swój kod małymi krokami. Gdy następnie nabrałem rozpędu - zacząłem eksperymentować, do czego was bardzo zachęcam.

  • Transcript

    • 1. LEKCJA STYLU czy w Javie można jeszcze dostrzec piękno? Wiktor Gworek • Javarsovia 2010 • Google
    • 2. @wwiktorr ^wwiktorr wiktorgworek.com blog.mocna-kawa.com
    • 3. PIĘKNO KODU definicja dla Javy
    • 4. czytelność boilerplate łatwe testowanie PIĘKNO KODU definicja dla Javy statyczne narzędzia typowanie
    • 5. NARZĘDZIA • Google Guava • http://code.google.com/p/guava-libraries/ • Google Guice • http://code.google.com/p/google-guice/ • Mockito • http://code.google.com/p/mockito/
    • 6. Czytelność Funkcyjność
    • 7. POPRAWIANIE CZYTELNOŚCI http://www.flickr.com/photos/jleveque/2151484964
    • 8. “Jejku, ten kod wygląda, jakby go pisał sam Steven King. Horror, aż strach przejść na kolejną stronę.” – anonimowy programista
    • 9. if (GOOGLE) { CODE.STYLE(); }
    • 10. 100 znaków if (GOOGLE) { CODE.STYLE(); }
    • 11. 100 znaków if (GOOGLE) { t CODE.STYLE(); }
    • 12. 100 znaków if (GOOGLE) { t CODE.STYLE(); } 2 znaki
    • 13. 100 znaków if (GOOGLE) { t CODE.STYLE(); } 2 znaki
    • 14. KODOWANIE DEFENSYWNE http://www.flickr.com/photos/mosca27/166707333/
    • 15. KODOWANIE DEFENSYWNE public void analyze(String msg) { if (msg == null) { throw NullPointerException(); } if (msg.length() > 160) { throw IllegalArgumentException( “Tak długa wiadomość?”); } // analiza wiadomości }
    • 16. KODOWANIE DEFENSYWNE public void analyze(String msg) { Preconditions.checkNotNull(msg); Preconditions.checkArgument( msg.length() <= 160, “Tak długa wiadomość?”); // analiza wiadomości }
    • 17. ZBĘDNY KOD
    • 18. KOLEKCJE com.google.common.collect Map<String, List<User, Role>> map = new HashMap<String, List<User, Role>>;
    • 19. KOLEKCJE com.google.common.collect Map<String, List<User, Role>> map = new HashMap<String, List<User, Role>>; Map<String, List<User, Role>> m = Maps.newHashMap(); List<Long> l = Lists.newArrayListWithExpectedSize(3); Set<Pair<String, User>> set = Sets.newHashSet(); Set<String> set = Sets.newHashSet(“a”, “b”, “c”);
    • 20. NIEMODYFIKOWANE OBIEKTY
    • 21. NIEMODYFIKOWANE OBIEKTY public void setName(String newName); private final Address address;
    • 22. NIEMODYFIKOWANE OBIEKTY public void setName(String newName); private final Address address; // Wykorzystanie Protocol Buffers Post newPost = post.toBuilder() .setTitle(newTitle) .build();
    • 23. KOLEKCJE com.google.common.collect List<String> list = new ArrayList<String>(); list.add(“a”); list.add(“b”); list.add(“c”); public static final Set<Integer> LUCKY_NUMBERS; static { Set<Integer> set = new LinkedHashSet<Integer>; set.add(4); set.add(7); set.add(42); LUCKY_NUMBERS = Collections.unmodifiableSet(set); }
    • 24. KOLEKCJE com.google.common.collect public static final Set<Integer> LUCKY_NUMBERS = Collections.unmodifiableSet( new LinkedHashSet<Integer>( Arrays.asList(4, 7, 42)));
    • 25. KOLEKCJE com.google.common.collect
    • 26. KOLEKCJE com.google.common.collect List<String> list = ImmutableList.of(“a”, “b”, “c”);
    • 27. KOLEKCJE com.google.common.collect List<String> list = ImmutableList.of(“a”, “b”, “c”); static final Set<Integer> LUCKY_NUMBERS = ImmutableSet.of(4, 7, 42);
    • 28. KOLEKCJE com.google.common.collect List<String> list = ImmutableList.of(“a”, “b”, “c”); static final Set<Integer> LUCKY_NUMBERS = ImmutableSet.of(4, 7, 42); static final Map<String, String> FORBIDDEN = ImmutableMap.of(“key1”, “val1”, “key2”, “val2”);
    • 29. ZNOWU TO SAMO... http://www.flickr.com/photos/nifmus/2385966735/
    • 30. KOLEKCJE com.google.common.collect Map<String, List<String>> map = Maps.newHashMap(); for (Pair<String, String> pair : input) { if (map.containsKey(pair.fst)) { map.get(pair.fst).add(pair.snd); } else { map.put(pair.fst, Lists.newArrayList(pair.snd)); } } List<String> result = map.get(“Kasia”);
    • 31. KOLEKCJE com.google.common.collect Map<String, List<String>> map = Maps.newHashMap(); for (Pair<String, String> pair : input) { if (map.containsKey(pair.fst)) { map.get(pair.fst).add(pair.snd); } else { map.put(pair.fst, Lists.newArrayList(pair.snd)); } } List<String> result = map.get(“Kasia”);
    • 32. KOLEKCJE com.google.common.collect Map<String, List<String>> map = Maps.newHashMap(); for (Pair<String, String> pair : input) { if (map.containsKey(pair.fst)) { map.get(pair.fst).add(pair.snd); } else { map.put(pair.fst, Lists.newArrayList(pair.snd)); } } List<String> result = map.get(“Kasia”);
    • 33. KOLEKCJE com.google.common.collect Map<String, List<String>> map = Maps.newHashMap(); for (Pair<String, String> pair : input) { if (map.containsKey(pair.fst)) { map.get(pair.fst).add(pair.snd); } else { map.put(pair.fst, Lists.newArrayList(pair.snd)); } } List<String> result = map.get(“Kasia”);
    • 34. KOLEKCJE com.google.common.collect Map<String, List<String>> map = Maps.newHashMap(); for (Pair<String, String> pair : input) { if (map.containsKey(pair.fst)) { map.get(pair.fst).add(pair.snd); } else { map.put(pair.fst, Lists.newArrayList(pair.snd)); } } List<String> result = map.get(“Kasia”);
    • 35. KOLEKCJE com.google.common.collect Map<String, List<String>> map = Maps.newHashMap(); for (Pair<String, String> pair : input) { if (map.containsKey(pair.fst)) { map.get(pair.fst).add(pair.snd); } else { map.put(pair.fst, Lists.newArrayList(pair.snd)); } } List<String> result = map.get(“Kasia”);
    • 36. KOLEKCJE com.google.common.collect Multimap<String, String> multimap = ArrayListMultimap.create(); for (Pair<String, String> pair : input) { multimap.put(pair.fst, pair.snd); } List<String> result = multimap.get(“Kasia”);
    • 37. KOLEKCJE com.google.common.collect Multimap<String, String> multimap = ArrayListMultimap.create(); for (Pair<String, String> pair : input) { multimap.put(pair.fst, pair.snd); } List<String> result = multimap.get(“Kasia”);
    • 38. KOLEKCJE com.google.common.collect Multimap<String, String> multimap = ArrayListMultimap.create(); for (Pair<String, String> pair : input) { multimap.put(pair.fst, pair.snd); } List<String> result = multimap.get(“Kasia”);
    • 39. KOLEKCJE com.google.common.collect Multimap<String, String> multimap = ArrayListMultimap.create(); for (Pair<String, String> pair : input) { multimap.put(pair.fst, pair.snd); } List<String> result = multimap.get(“Kasia”);
    • 40. KOLEKCJE com.google.common.collect Multimap<String, String> multimap = ArrayListMultimap.create(); for (Pair<String, String> pair : input) { multimap.put(pair.fst, pair.snd); } List<String> result = multimap.get(“Kasia”);
    • 41. FLUENT INTERFACE com.google.common.base.Joiner
    • 42. FLUENT INTERFACE com.google.common.base.Joiner String s = Joiner.on(",").join(episodes); String s = Joiner.on(“|”).skipNulls().join(users);
    • 43. FLUENT INTERFACE com.google.common.base.Joiner String s = Joiner.on(",").join(episodes); String s = Joiner.on(“|”).skipNulls().join(users); StringBuffer sb = ...; Joiner.on(“|”) .useForNull("[user removed]") .appendTo(sb, users);
    • 44. FLUENT INTERFACE com.google.common.base.Joiner String s = Joiner.on(",").join(episodes); String s = Joiner.on(“|”).skipNulls().join(users); StringBuffer sb = ...; Joiner.on(“|”) .useForNull("[user removed]") .appendTo(sb, users); Joiner.on(“;”) .userForNull(“NODATA”) .withKeyValueSeparator(“:”) .join(ImmutableMap.of(“key”, “value”, ...));
    • 45. ZABAWA Z FUNKCYJNOŚCIĄ http://www.flickr.com/photos/infrarad/182786930
    • 46. WEJŚCIE: lista loginów w serwisie WYJŚCIE: posortowana lista użytkowników, którzy mają więcej niż 18 lat
    • 47. logins .map{ |login| User.select_by_login(login)} .find_all{ |user| user != nil && user.age > 18 } .sort_by{ |user| [user.surname, user.name] }
    • 48. logins .map{ |login| User.select_by_login(login)} .find_all{ |user| user != nil && user.age > 18 } .sort_by{ |user| [user.surname, user.name] }
    • 49. logins .map{ |login| User.select_by_login(login)} .find_all{ |user| user != nil && user.age > 18 } .sort_by{ |user| [user.surname, user.name] }
    • 50. logins .map{ |login| User.select_by_login(login)} .find_all{ |user| user != nil && user.age > 18 } .sort_by{ |user| [user.surname, user.name] }
    • 51. PIERWSZA PRÓBA List<String> logins = ...; List<User> users = new ArrayList(); for (String login : logins) { if (!Strings.isNullOrEmpty(login)) { User user = userDao.selectByLogin(login); if (user != null && user.getAge() >= 18) { users.add(user); } } } Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { int result = u1.getSurname().compareTo(u2.getSurname()); if (result != 0) { return result; } return u1.getName().compareTo(u2.getName()); }});
    • 52. PIERWSZA PRÓBA List<String> logins = ...; List<User> users = new ArrayList(); for (String login : logins) { if (!Strings.isNullOrEmpty(login)) { User user = userDao.selectByLogin(login); if (user != null && user.getAge() >= 18) { users.add(user); } } } Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { int result = u1.getSurname().compareTo(u2.getSurname()); if (result != 0) { return result; } return u1.getName().compareTo(u2.getName()); }});
    • 53. PIERWSZA PRÓBA List<String> logins = ...; List<User> users = new ArrayList(); for (String login : logins) { if (!Strings.isNullOrEmpty(login)) { User user = userDao.selectByLogin(login); if (user != null && user.getAge() >= 18) { users.add(user); } } } Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { int result = u1.getSurname().compareTo(u2.getSurname()); if (result != 0) { return result; } return u1.getName().compareTo(u2.getName()); }});
    • 54. PIERWSZA PRÓBA List<String> logins = ...; List<User> users = new ArrayList(); for (String login : logins) { if (!Strings.isNullOrEmpty(login)) { User user = userDao.selectByLogin(login); if (user != null && user.getAge() >= 18) { users.add(user); } } } Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { int result = u1.getSurname().compareTo(u2.getSurname()); if (result != 0) { return result; } return u1.getName().compareTo(u2.getName()); }});
    • 55. PIERWSZA PRÓBA List<String> logins = ...; List<User> users = new ArrayList(); for (String login : logins) { if (!Strings.isNullOrEmpty(login)) { User user = userDao.selectByLogin(login); if (user != null && user.getAge() >= 18) { users.add(user); } } } Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { int result = u1.getSurname().compareTo(u2.getSurname()); if (result != 0) { return result; } return u1.getName().compareTo(u2.getName()); }});
    • 56. PIERWSZA PRÓBA List<String> logins = ...; List<User> users = new ArrayList(); for (String login : logins) { if (!Strings.isNullOrEmpty(login)) { User user = userDao.selectByLogin(login); if (user != null && user.getAge() >= 18) { users.add(user); } } } Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { int result = u1.getSurname().compareTo(u2.getSurname()); if (result != 0) { return result; } return u1.getName().compareTo(u2.getName()); }});
    • 57. PIERWSZA PRÓBA List<String> logins = ...; List<User> users = new ArrayList(); for (String login : logins) { if (!Strings.isNullOrEmpty(login)) { User user = userDao.selectByLogin(login); if (user != null && user.getAge() >= 18) { users.add(user); } } } Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { int result = u1.getSurname().compareTo(u2.getSurname()); if (result != 0) { return result; } return u1.getName().compareTo(u2.getName()); }});
    • 58. PIERWSZA PRÓBA List<String> logins = ...; List<User> users = new ArrayList(); for (String login : logins) { if (!Strings.isNullOrEmpty(login)) { User user = userDao.selectByLogin(login); if (user != null && user.getAge() >= 18) { users.add(user); } } } Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { int result = u1.getSurname().compareTo(u2.getSurname()); if (result != 0) { return result; } return u1.getName().compareTo(u2.getName()); }});
    • 59. PIERWSZA PRÓBA List<String> logins = ...; List<User> users = new ArrayList(); for (String login : logins) { if (!Strings.isNullOrEmpty(login)) { User user = userDao.selectByLogin(login); if (user != null && user.getAge() >= 18) { users.add(user); } } } Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { int result = u1.getSurname().compareTo(u2.getSurname()); if (result != 0) { return result; } return u1.getName().compareTo(u2.getName()); }});
    • 60. FUNKCJE com.google.common.base.Function public interface Function<F, T> { T apply(@Nullable F from); }
    • 61. FUNKCJE com.google.common.base.Function static class FetchUsers implements Function<String, User> { private final UserDao userDao; public FetchUsers(UserDao userDao) { this.userDao = userDao; } @Override public User apply(String login) { if (Strings.isNullOrEmpty(login)) { return null; } return userDao.selectByLogin(login); } }
    • 62. FUNKCJE com.google.common.base.Function static class FetchUsers implements Function<String, User> { private final UserDao userDao; public FetchUsers(UserDao userDao) { this.userDao = userDao; } @Override public User apply(String login) { if (Strings.isNullOrEmpty(login)) { return null; } return userDao.selectByLogin(login); } }
    • 63. FUNKCJE com.google.common.base.Function static class FetchUsers implements Function<String, User> { private final UserDao userDao; public FetchUsers(UserDao userDao) { this.userDao = userDao; } @Override public User apply(String login) { if (Strings.isNullOrEmpty(login)) { return null; } return userDao.selectByLogin(login); } }
    • 64. FUNKCJE com.google.common.base.Function static class FetchUsers implements Function<String, User> { private final UserDao userDao; public FetchUsers(UserDao userDao) { this.userDao = userDao; } @Override public User apply(String login) { if (Strings.isNullOrEmpty(login)) { return null; } return userDao.selectByLogin(login); } }
    • 65. FUNKCJE com.google.common.base.Function static class FetchUsers implements Function<String, User> { private final UserDao userDao; public FetchUsers(UserDao userDao) { this.userDao = userDao; } @Override public User apply(String login) { if (Strings.isNullOrEmpty(login)) { return null; } return userDao.selectByLogin(login); } }
    • 66. PREDYKATY com.google.common.base.Predicate public interface Predicate<T> { boolean apply(@Nullable T input); }
    • 67. PREDYKATY com.google.common.base.Predicate static final Predicate<User> OVER_18 = new Predicate<User>() { @Override public boolean apply(User user) { return user.getAge() >= 18; } };
    • 68. PREDYKATY com.google.common.base.Predicate static final Predicate<User> OVER_18 = new Predicate<User>() { @Override public boolean apply(User user) { return user.getAge() >= 18; } };
    • 69. PREDYKATY com.google.common.base.Predicate static final Predicate<User> OVER_18 = new Predicate<User>() { @Override public boolean apply(User user) { return user.getAge() >= 18; } };
    • 70. PREDYKATY com.google.common.base.Predicate static final Predicate<User> OVER_18 = new Predicate<User>() { @Override public boolean apply(User user) { return user.getAge() >= 18; } };
    • 71. ŁADNY KOMPARATOR com.google.common.collect.ComparisonChain static final Comparator<User> NAME_ASC = new Comparator<User>() { @Override public int compare(User u1, User u2) { return ComparisonChain.start() .compare(u1.getSurname(), u2.getSurname()) .compare(u1.getName(), u2.getName()) .result(); } };
    • 72. ŁADNY KOMPARATOR com.google.common.collect.ComparisonChain static final Comparator<User> NAME_ASC = new Comparator<User>() { @Override public int compare(User u1, User u2) { return ComparisonChain.start() .compare(u1.getSurname(), u2.getSurname()) .compare(u1.getName(), u2.getName()) .result(); } };
    • 73. ŁADNY KOMPARATOR com.google.common.collect.ComparisonChain static final Comparator<User> NAME_ASC = new Comparator<User>() { @Override public int compare(User u1, User u2) { return ComparisonChain.start() .compare(u1.getSurname(), u2.getSurname()) .compare(u1.getName(), u2.getName()) .result(); } };
    • 74. ŁADNY KOMPARATOR com.google.common.collect.ComparisonChain static final Comparator<User> NAME_ASC = new Comparator<User>() { @Override public int compare(User u1, User u2) { return ComparisonChain.start() .compare(u1.getSurname(), u2.getSurname()) .compare(u1.getName(), u2.getName()) .result(); } };
    • 75. ŁADNY KOMPARATOR com.google.common.collect.ComparisonChain static final Comparator<User> NAME_ASC = new Comparator<User>() { @Override public int compare(User u1, User u2) { return ComparisonChain.start() .compare(u1.getSurname(), u2.getSurname()) .compare(u1.getName(), u2.getName()) .result(); } };
    • 76. ŁADNY KOMPARATOR com.google.common.collect.ComparisonChain static final Comparator<User> NAME_ASC = new Comparator<User>() { @Override public int compare(User u1, User u2) { return ComparisonChain.start() .compare(u1.getSurname(), u2.getSurname()) .compare(u1.getName(), u2.getName()) .result(); } };
    • 77. DRUGA PRÓBA com.google.common.collect.Iterables import static com.google.common.collect.Iterables.*; Iterable<User> users = transform(logins, new FetchUsers(userDao)); Iterable<User> notNullUsers = filter(users, Predicates.notNull()); Iterable<User> matureUsers = filter(notNullUsers, OVER_18); List<User> result = com.google.common.collect.Ordering .from(NAME_ASC) .reverse() .immutableSortedCopy(matureUsers);
    • 78. DRUGA PRÓBA com.google.common.collect.Iterables import static com.google.common.collect.Iterables.*; Iterable<User> users = transform(logins, new FetchUsers(userDao)); Iterable<User> notNullUsers = filter(users, Predicates.notNull()); Iterable<User> matureUsers = filter(notNullUsers, OVER_18); List<User> result = com.google.common.collect.Ordering .from(NAME_ASC) .reverse() .immutableSortedCopy(matureUsers);
    • 79. DRUGA PRÓBA com.google.common.collect.Iterables import static com.google.common.collect.Iterables.*; Iterable<User> users = transform(logins, new FetchUsers(userDao)); Iterable<User> notNullUsers = filter(users, Predicates.notNull()); Iterable<User> matureUsers = filter(notNullUsers, OVER_18); List<User> result = com.google.common.collect.Ordering .from(NAME_ASC) .reverse() .immutableSortedCopy(matureUsers);
    • 80. DRUGA PRÓBA com.google.common.collect.Iterables import static com.google.common.collect.Iterables.*; Iterable<User> users = transform(logins, new FetchUsers(userDao)); Iterable<User> notNullUsers = filter(users, Predicates.notNull()); Iterable<User> matureUsers = filter(notNullUsers, OVER_18); List<User> result = com.google.common.collect.Ordering .from(NAME_ASC) .reverse() .immutableSortedCopy(matureUsers);
    • 81. DRUGA PRÓBA com.google.common.collect.Iterables import static com.google.common.collect.Iterables.*; Iterable<User> users = transform(logins, new FetchUsers(userDao)); Iterable<User> notNullUsers = filter(users, Predicates.notNull()); Iterable<User> matureUsers = filter(notNullUsers, OVER_18); List<User> result = com.google.common.collect.Ordering .from(NAME_ASC) .reverse() .immutableSortedCopy(matureUsers);
    • 82. DRUGA PRÓBA com.google.common.collect.Iterables import static com.google.common.collect.Iterables.*; Iterable<User> users = transform(logins, new FetchUsers(userDao)); Iterable<User> notNullUsers = filter(users, Predicates.notNull()); Iterable<User> matureUsers = filter(notNullUsers, OVER_18); List<User> result = com.google.common.collect.Ordering .from(NAME_ASC) .reverse() .immutableSortedCopy(matureUsers);
    • 83. DRUGA PRÓBA com.google.common.collect.Iterables import static com.google.common.collect.Iterables.*; Iterable<User> users = transform(logins, new FetchUsers(userDao)); Iterable<User> notNullUsers = filter(users, Predicates.notNull()); Iterable<User> matureUsers = filter(notNullUsers, OVER_18); List<User> result = com.google.common.collect.Ordering .from(NAME_ASC) .reverse() .immutableSortedCopy(matureUsers);
    • 84. DRUGA PRÓBA com.google.common.collect.Iterables import static com.google.common.collect.Iterables.*; Iterable<User> users = transform(logins, new FetchUsers(userDao)); Iterable<User> notNullUsers = filter(users, Predicates.notNull()); Iterable<User> matureUsers = filter(notNullUsers, OVER_18); List<User> result = com.google.common.collect.Ordering .from(NAME_ASC) .reverse() .immutableSortedCopy(matureUsers);
    • 85. DRUGA PRÓBA com.google.common.collect.Iterables import static com.google.common.collect.Iterables.*; Iterable<User> users = transform(logins, new FetchUsers(userDao)); Iterable<User> notNullUsers = filter(users, Predicates.notNull()); Iterable<User> matureUsers = filter(notNullUsers, OVER_18); List<User> result = com.google.common.collect.Ordering .from(NAME_ASC) .reverse() .immutableSortedCopy(matureUsers);
    • 86. TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
    • 87. TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
    • 88. TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
    • 89. TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
    • 90. TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
    • 91. TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
    • 92. TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
    • 93. Czytelność Funkcyjność
    • 94. Pytania? Wiktor Gworek • Javarsovia 2010 • Google

    ×