• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Lekcja stylu
 

Lekcja stylu

on

  • 4,228 views

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.

Statistics

Views

Total Views
4,228
Views on SlideShare
1,292
Embed Views
2,936

Actions

Likes
1
Downloads
15
Comments
0

16 Embeds 2,936

http://blog.mocna-kawa.com 2711
http://pawelzubkiewicz.blogspot.com 105
http://flavors.me 69
http://feeds.feedburner.com 27
http://translate.googleusercontent.com 6
http://feeds2.feedburner.com 6
http://static.slidesharecdn.com 2
http://pawelzubkiewicz.blogspot.co.uk 2
http://pawelzubkiewicz.blogspot.no 1
http://web.archive.org 1
http://theoldreader.com 1
http://pawelzubkiewicz.blogspot.de 1
http://translate.yandex.net 1
http://pawelzubkiewicz.blogspot.se 1
http://www.newsblur.com 1
http://pawelzubkiewicz.blogspot.co.at 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

CC Attribution-ShareAlike LicenseCC Attribution-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Cze&#x15B;&#x107; wszystkim. Ciesz&#x119; si&#x119;, &#x17C;e jest was tutaj tak du&#x17C;o. Zastanawiam si&#x119;, czy przyszli&#x15B;cie na prezentacje zwabieni jej tytu&#x142;em, czy bardziej przyci&#x105;gn&#x105;&#x142; was fakt, &#x17C;e pracuj&#x119; dla firmy Google. <br /> Tadaaa. Witam na prezentacji Lekcja Stylu, czyli czy w Javie mo&#x17C;na jeszcze dostrzec pi&#x119;kno, czy da si&#x119; jeszcze &#x142;adnie i rado&#x15B;nie programowa&#x107;. <br />
  • Nazywam si&#x119; Wiktor Gworek. Tak wygl&#x105;da m&#xF3;j obecny avatar, gdyby&#x15B;cie mnie szukali. A znale&#x17A;&#x107; mo&#x17C;ecie mnie na Twitterze oraz na Blipie. Od czasu do czasu co&#x15B; ciekawego napisz&#x119; na swoim blogu. <br />
  • Pracuj&#x119; przy serwisie Blogger.com. Blogger jest najwi&#x119;ksz&#x105; platform&#x105; blogow&#x105; na &#x15B;wiecie, gdzie 275 tysi&#x119;cy s&#x142;&#xF3;w jest pisanych w ci&#x105;gu ka&#x17C;dej minuty. <br /> <br /> Jest to serwis w ca&#x142;o&#x15B;ci napisany w Javie. Od pierwszego dnia. <br /> <br /> Co wi&#x119;cej, w sierpniu sko&#x144;czy on 11 lat. By&#x142; on 7 lat temu przepisany na technologie Google&#x2019;owe. Mo&#x17C;ecie sobie wyobrazi&#x107;, &#x17C;e przez ten szmat czasu wiele, na prawd&#x119; wiele in&#x17C;ynier&#xF3;w pracowa&#x142;o przy Bloggerze. Potrzeba by&#x142;o w&#x142;o&#x17C;y&#x107; w niego bardzo du&#x17C;o wysi&#x142;ku, aby kolejni dochodz&#x105;cy do niego in&#x17C;ynierowie mogli efektywnie pracowa&#x107;. <br />
  • Pracuj&#x119; przy serwisie Blogger.com. Blogger jest najwi&#x119;ksz&#x105; platform&#x105; blogow&#x105; na &#x15B;wiecie, gdzie 275 tysi&#x119;cy s&#x142;&#xF3;w jest pisanych w ci&#x105;gu ka&#x17C;dej minuty. <br /> <br /> Jest to serwis w ca&#x142;o&#x15B;ci napisany w Javie. Od pierwszego dnia. <br /> <br /> Co wi&#x119;cej, w sierpniu sko&#x144;czy on 11 lat. By&#x142; on 7 lat temu przepisany na technologie Google&#x2019;owe. Mo&#x17C;ecie sobie wyobrazi&#x107;, &#x17C;e przez ten szmat czasu wiele, na prawd&#x119; wiele in&#x17C;ynier&#xF3;w pracowa&#x142;o przy Bloggerze. Potrzeba by&#x142;o w&#x142;o&#x17C;y&#x107; w niego bardzo du&#x17C;o wysi&#x142;ku, aby kolejni dochodz&#x105;cy do niego in&#x17C;ynierowie mogli efektywnie pracowa&#x107;. <br />
  • Do Bloggera przyszed&#x142;em p&#xF3;&#x142;tora roku, jako &#x15B;wie&#x17C;ak prosto ze studi&#xF3;w. My&#x15B;la&#x142;em, &#x17C;e potrafi&#x119; programowa&#x107;. Bardzo si&#x119; myli&#x142;em. <br /> Lekcja stylu, to moja historia, kt&#xF3;r&#x105; wam przedstawi&#x119;, jak poznawa&#x142;em Jav&#x119; i ma&#x142;ymi krokami dostrzega&#x142;em jej pi&#x119;kno. Chc&#x119;, &#x17C;eby ta prezentacja by&#x142;a dla was inspiracj&#x105;, &#x17C;eby pisa&#x107; &#x142;adniejszy kod, ale tak&#x17C;e &#x17C;eby to by&#x142;a dla was zach&#x119;ta, &#x17C;eby bawi&#x107; si&#x119; z kodem. <br /> <br /> 1) Pi&#x119;kny kod to taki, kt&#xF3;ry &#x142;atwo si&#x119; czyta. To taki kod, w kt&#xF3;rym brak jest szelmowskich sztuczek piekielnie zdolnego programisty. <br /> 2) pozbywanie si&#x119; nisko poziomowego zb&#x119;dnego kodu (tzw. boilerplate code). przyk&#x142;adem dla mnie jest JDBC, gdzie ilo&#x15B;&#x107; nadmiarowego kodu to oko&#x142;o 80%. Mimo to, je&#x15B;li chcemy skorzysta&#x107; z JDBC ten kod musimy napisa&#x107;. <br /> 3) to taki kod, kt&#xF3;ry mo&#x17C;na &#x142;atwo testowa&#x107;, gdzie wszystkie zale&#x17C;no&#x15B;ci obiektu s&#x105; jasno zdefiniowane -- tak aby mo&#x17C;na by&#x142;o wstrzykn&#x105;&#x107; do niego obiekty mockuj&#x105;ce sprawdzaj&#x105;ce poprawne zachowanie obiektu. <br /> 4) to taki kod, kt&#xF3;ry wykorzystuje typowanie statyczne, aby jak najwcze&#x15B;niej wykrywa&#x107; b&#x142;&#x119;dy w kodzie. Je&#x15B;li piszemy ju&#x17C; w Javie to wykorzystujmy moc, kt&#xF3;r&#x105; nam daje kompilator. <br /> 5) A tak&#x17C;e pi&#x119;kny kod mo&#x17C;na uzyskiwa&#x107; poprzez u&#x17C;ywanie odpowiednich narz&#x119;dzi, kt&#xF3;re spowoduj&#x105;, &#x17C;e pisanie kodu stanie si&#x119; &#x142;atwiejsze <br /> <br />
  • Narz&#x119;dzia, kt&#xF3;re stosuje ka&#x17C;dego dnia podczas mojej pracy to Guava (open-sourceowany wycinek wewn&#x119;trzych wsp&#xF3;lnych bibliotek Googleowych), Guice (aby nada&#x107; aplikacji architektoniczny porz&#x105;dek) oraz Mockito - do testowania. Czyli 2 biblioteki Google&#x2019;owe oraz jedna krakowska :). <br /> <br /> Wymienione tutaj biblioteki upraszczaj&#x105; tw&#xF3;j kod. Z nimi jest &#x142;atwiej pisa&#x107;, czyta&#x107; i utrzymywa&#x107; kod w projekcie. Chocia&#x17C; mogliby&#x15B;my przetrwa&#x107; bez nich i rzeczy, kt&#xF3;re one wprowadzaj&#x105;, to jednak zwi&#x119;ksz&#x105; one moj&#x105; produktywno&#x15B;&#x107; jako programisty. Redukuj&#x105; one spor&#x105; ilo&#x15B;&#x107; zb&#x119;dnego nisko poziomowego kodu, kt&#xF3;ry musia&#x142;bym napisa&#x107;. <br /> <br /> Zosta&#x142;a tutaj wymieniona biblioteka wspomagaj&#x105;ca mockowanie Mockito. Z dum&#x105; mog&#x119; powiedzie&#x107;, &#x17C;e w Bloggerze wi&#x119;kszo&#x15B;&#x107; test&#xF3;w jest oparta o Mockito. <br /> <br /> Na tej prezentacji skupi&#x119; si&#x119; na tej pierwszej - Guava. <br />
  • Prezentacj&#x119; podzieli&#x142;em na 2 cz&#x119;&#x15B;ci. <br /> - Na pocz&#x105;tku poka&#x17C;&#x119;, jak ma&#x142;ymi kroczkami b&#x119;dziemy modyfikowa&#x107; nasz kod, aby stawa&#x142; si&#x119; bardziej czytelny. <br /> - a nast&#x119;pnie zaprezentuj&#x119;, w jaki spos&#xF3;b mo&#x17C;na si&#x119; bawi&#x107; z Jav&#x105; na przyk&#x142;adzie programowania funkcyjnego. <br /> <br /> Do dzie&#x142;a. <br />
  • Zacznijmy od poprawiania kodu. Wyznaczmy sobie jaki&#x15B; cel, do kt&#xF3;rego b&#x119;dziemy d&#x105;&#x17C;y&#x107;. <br />
  • Oto nasz cel. Miejmy ten cytat w g&#x142;owie i zaczynajmy. <br />
  • Tre&#x15B;&#x107; tre&#x15B;ci&#x105;, ale tak&#x17C;e trzeba dba&#x107; o form&#x119; prezentacji. <br /> <br /> Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli: <br /> * szeroko&#x15B;&#x107; linii to 100 znak&#xF3;w, nie ma wyj&#x105;tk&#xF3;w <br /> - ciekawostka a propos 80 znak&#xF3;w i os&#xF3;b niedowidz&#x105;cych <br /> * (pami&#x119;tajcie, &#x17C;e z&#x142;o czai si&#x119; wsz&#x119;dzie) bezwzgl&#x119;dny zakaz u&#x17C;ywania tabulator&#xF3;w <br /> * wci&#x119;cia w blokach kodu stosujemy 2 znaki, a nie 4 znaki; kod w&#xF3;wczas optycznie jest mniej rozwleczony, lepiej si&#x119; go czyta <br /> * oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod kt&#xF3;rymi jest tylko jedna instrukcja. <br /> <br /> <br />
  • Tre&#x15B;&#x107; tre&#x15B;ci&#x105;, ale tak&#x17C;e trzeba dba&#x107; o form&#x119; prezentacji. <br /> <br /> Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli: <br /> * szeroko&#x15B;&#x107; linii to 100 znak&#xF3;w, nie ma wyj&#x105;tk&#xF3;w <br /> - ciekawostka a propos 80 znak&#xF3;w i os&#xF3;b niedowidz&#x105;cych <br /> * (pami&#x119;tajcie, &#x17C;e z&#x142;o czai si&#x119; wsz&#x119;dzie) bezwzgl&#x119;dny zakaz u&#x17C;ywania tabulator&#xF3;w <br /> * wci&#x119;cia w blokach kodu stosujemy 2 znaki, a nie 4 znaki; kod w&#xF3;wczas optycznie jest mniej rozwleczony, lepiej si&#x119; go czyta <br /> * oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod kt&#xF3;rymi jest tylko jedna instrukcja. <br /> <br /> <br />
  • Tre&#x15B;&#x107; tre&#x15B;ci&#x105;, ale tak&#x17C;e trzeba dba&#x107; o form&#x119; prezentacji. <br /> <br /> Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli: <br /> * szeroko&#x15B;&#x107; linii to 100 znak&#xF3;w, nie ma wyj&#x105;tk&#xF3;w <br /> - ciekawostka a propos 80 znak&#xF3;w i os&#xF3;b niedowidz&#x105;cych <br /> * (pami&#x119;tajcie, &#x17C;e z&#x142;o czai si&#x119; wsz&#x119;dzie) bezwzgl&#x119;dny zakaz u&#x17C;ywania tabulator&#xF3;w <br /> * wci&#x119;cia w blokach kodu stosujemy 2 znaki, a nie 4 znaki; kod w&#xF3;wczas optycznie jest mniej rozwleczony, lepiej si&#x119; go czyta <br /> * oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod kt&#xF3;rymi jest tylko jedna instrukcja. <br /> <br /> <br />
  • Tre&#x15B;&#x107; tre&#x15B;ci&#x105;, ale tak&#x17C;e trzeba dba&#x107; o form&#x119; prezentacji. <br /> <br /> Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli: <br /> * szeroko&#x15B;&#x107; linii to 100 znak&#xF3;w, nie ma wyj&#x105;tk&#xF3;w <br /> - ciekawostka a propos 80 znak&#xF3;w i os&#xF3;b niedowidz&#x105;cych <br /> * (pami&#x119;tajcie, &#x17C;e z&#x142;o czai si&#x119; wsz&#x119;dzie) bezwzgl&#x119;dny zakaz u&#x17C;ywania tabulator&#xF3;w <br /> * wci&#x119;cia w blokach kodu stosujemy 2 znaki, a nie 4 znaki; kod w&#xF3;wczas optycznie jest mniej rozwleczony, lepiej si&#x119; go czyta <br /> * oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod kt&#xF3;rymi jest tylko jedna instrukcja. <br /> <br /> <br />
  • Pierwsza porada. Zacznijcie kodowa&#x107; defensywnie. Jasno zapisujcie warunki wej&#x15B;cia do metod. Co prawda mogliby&#x15B;cie zapisa&#x107; te rzeczy w JavaDocach, to jednak nie jest wystarczaj&#x105;ce, gdy&#x17C; kompilator nie patrzy na JavaDoci i ich nie rozumie. <br />
  • Jak w takim razie kodowanie defensywne mo&#x17C;e wygl&#x105;da&#x107;? Tadaaa. W jasny i precyzyjny spos&#xF3;b zacz&#x105;&#x142;em definiowa&#x107; wej&#x15B;cie do metody. Mo&#x17C;na co prawda by wykorzysta&#x107; metody assert, kt&#xF3;re istniej&#x105; w Javie - to jednak nie s&#x105; one domy&#x15B;lnie w&#x142;&#x105;czone. <br /> <br /> Co uzyskujemy przez to? <br /> - bardziej czytelny kod <br /> - moj kod wowczas mniej sie wywala, <br /> - latwiej dostrzec przypadki brzegowe. <br />
  • Ale czy da si&#x119; to lepiej zapisa&#x107;? Tak, w Guavie znajdziemy klas&#x119; Preconditions. Jest to zbi&#xF3;r metod statycznych, kt&#xF3;re mo&#x17C;na u&#x17C;ywa&#x107; do zdefiniowania wej&#x15B;cia do metody. Dzi&#x119;ki temu otrzymujemy zachowanie fail-fast i wyj&#x105;tek, kt&#xF3;ry mo&#x17C;emy otrzyma&#x107; jest bardzo czytelny. <br /> <br /> Jaka jest r&#xF3;&#x17C;nica pomi&#x119;dzy poprzednim zapisem a u&#x17C;yciem Preconditions? &#x17B;adna! Natomiast czytelno&#x15B;&#x107; kodu zosta&#x142;a zwi&#x119;kszona. <br />
  • Albo czy czasem nie macie do&#x15B;&#x107; pisania zb&#x119;dnego kodu? Czy w waszych g&#x142;owach nie zapala si&#x119; &#x15B;wiat&#x142;o ostrzegawcze, kiedy piszecie co&#x15B;, co w waszym prze&#x15B;wiadczeniu powinno by&#x107; du&#x17C;o prostsze? <br />
  • Dla mnie takim zb&#x119;dnym kodem podczas codziennej pracy to inicjalizacja kolekcji. Guava w interesuj&#x105;cy spos&#xF3;b rozprawia si&#x119; z tym problemem. Dostarcza wielu bardzo warto&#x15B;ciowych metod. <br /> <br /> Fajne, no nie? Dzi&#x119;ki typom generycznym i por&#x119;cznym metodom wytw&#xF3;rczym (factory method) wygl&#x105;da to ju&#x17C; o niebo lepiej. Nie musimy pisa&#x107; nudnego kodu, kt&#xF3;ry Java powinna rozumie&#x107; od pocz&#x105;tku. <br /> <br /> Powy&#x17C;sze metody wytw&#xF3;rcze maj&#x105; zosta&#x107; wprowadzone w JDK 7 i b&#x119;dzie to &#x15B;wietne. Ale po co czeka&#x107; na nie teraz? <br />
  • Przejd&#x17A;my do konceptu niemodyfikowalnych obiekt&#xF3;w. <br /> Uwaga: je&#x15B;li chcia&#x142;bym, &#x17C;eby&#x15B;cie zapami&#x119;tali z tej prezentacji jedn&#x105; rzecz to w&#x142;a&#x15B;nie koncept niemodyfikowalnych obiekt&#xF3;w. <br /> <br /> Ok, co to s&#x105; niemodyfikowalne obiekty? <br />
  • (1) Nie dostarczaj metod modyfikuj&#x105;cych stan obiektu. Settery. <br /> <br /> (2) Oznacz wszystkie pola klasy jako final. To jasno i precyzyjnie okre&#x15B;la twoje intencje. Java w czasie kompilacji jest w stanie to sprawdzi&#x107;. <br /> W ten spos&#xF3;b nowo utworzony obiekt jest w pe&#x142;ni zainicjalizowany i nie potrzeba &#x17C;adnego ekstra kodu do jego inicjalizacji. Przynajmniej tak powinno by&#x107;. <br /> <br /> Obiekty niemodyfikowalne s&#x105; proste, z natury bezpieczne w&#x105;tkowo, nie wymagaj&#x105; &#x17C;adnej synchronizacji i mog&#x105; by&#x107; dowolnie wsp&#xF3;&#x142;dzielone. <br /> <br /> Jest to bardzo wa&#x17C;na cecha. Poniewa&#x17C; w komputerach mamy coraz wi&#x119;cej rdzeni, a wi&#x119;c jeste&#x15B;my w stanie rozproszy&#x107; obliczenia. &#x17B;eby to robi&#x107; efektywnie, wsp&#xF3;&#x142;dzielone obiekty nie powinny zmienia&#x107; swojego stanu, jako &#x17C;e problemy wsp&#xF3;&#x142;bie&#x17C;ne b&#x119;d&#x105; krzycze&#x107; na produkcji. <br /> <br /> --- Jedyn&#x105; wad&#x105; takich obiekt&#xF3;w jest to, &#x17C;e wymagaj&#x105; osobnego obiektu, kiedy jego stan si&#x119; zmienia. <br /> -- kiedy jeszcze raz bedziesz chcial napisac metoda zaczynajaca sie na set* - zastanow sie <br />
  • Wygl&#x105;da kod znajomo? Taki kod cz&#x119;sto mo&#x17C;na spotka&#x107; podczas pisania test&#xF3;w, kiedy chcemy dostarczy&#x107; testowanej klasie jakie&#x15B; dane. <br /> <br /> Lub kiedy chcemy stworzy&#x107; sta&#x142;y zbi&#xF3;r warto&#x15B;ci. Zazwyczaj piszemy pole, kt&#xF3;re jest public static final. Nadajemy nazw&#x119;. Nast&#x119;pnie wype&#x142;niamy zbi&#xF3;r elementami. Mamy 2 metody do dyspozycji: albo zawo&#x142;a&#x107; metod&#x119; statyczn&#x105; albo zainicjalizowa&#x107; pol&#x119; w bloku statycznym. Drugie rozwi&#x105;zanie jest najbardziej popularne. Tak&#x17C;e tworzymy zbi&#xF3;r, wype&#x142;niamy go elementami, a nast&#x119;pnie tworzymy z tego niezmienialny zbi&#xF3;r. Zaskakuj&#x105;ce jest, jak cz&#x119;sto zapomina si&#x119; o ostatniej linijce. W&#xF3;wczas mamy zbi&#xF3;r, kt&#xF3;ry mo&#x17C;na zmodyfikowa&#x107; w polu public static final. <br />
  • Kr&#xF3;tsze, ale u&#x17C;ywa a&#x17C; czterech klas. Co&#x15B; jest nie tak. <br />
  • To co na prawd&#x119; w&#xF3;wczas chcesz to niemodyfikowalna kolekcja wype&#x142;niona danymi. I &#x17C;eby to zgrabnie wygl&#x105;da&#x142;o. <br /> <br /> Teraz kod m&#xF3;wi dok&#x142;adnie to, co mamy na my&#x15B;li. + jest to du&#x17C;o wydajne <br />
  • To co na prawd&#x119; w&#xF3;wczas chcesz to niemodyfikowalna kolekcja wype&#x142;niona danymi. I &#x17C;eby to zgrabnie wygl&#x105;da&#x142;o. <br /> <br /> Teraz kod m&#xF3;wi dok&#x142;adnie to, co mamy na my&#x15B;li. + jest to du&#x17C;o wydajne <br />
  • To co na prawd&#x119; w&#xF3;wczas chcesz to niemodyfikowalna kolekcja wype&#x142;niona danymi. I &#x17C;eby to zgrabnie wygl&#x105;da&#x142;o. <br /> <br /> Teraz kod m&#xF3;wi dok&#x142;adnie to, co mamy na my&#x15B;li. + jest to du&#x17C;o wydajne <br />
  • <br />
  • Wygl&#x105;da kod znajomo? <br /> <br /> Czy nigdy nie potrzebowa&#x142;e&#x15B; mapy, kt&#xF3;ra mo&#x17C;e przechowywa&#x107; wiele warto&#x15B;ci dla jednego klucza? Czy za ka&#x17C;dym razem piszesz taki kod? <br /> <br /> Kod do&#x15B;&#x107; cz&#x119;sto pisany przez programist&#xF3;w, kiedy ich zadaniem jest pogrupowanie element&#xF3;w z wej&#x15B;cia. <br /> <br />
  • Wygl&#x105;da kod znajomo? <br /> <br /> Czy nigdy nie potrzebowa&#x142;e&#x15B; mapy, kt&#xF3;ra mo&#x17C;e przechowywa&#x107; wiele warto&#x15B;ci dla jednego klucza? Czy za ka&#x17C;dym razem piszesz taki kod? <br /> <br /> Kod do&#x15B;&#x107; cz&#x119;sto pisany przez programist&#xF3;w, kiedy ich zadaniem jest pogrupowanie element&#xF3;w z wej&#x15B;cia. <br /> <br />
  • Wygl&#x105;da kod znajomo? <br /> <br /> Czy nigdy nie potrzebowa&#x142;e&#x15B; mapy, kt&#xF3;ra mo&#x17C;e przechowywa&#x107; wiele warto&#x15B;ci dla jednego klucza? Czy za ka&#x17C;dym razem piszesz taki kod? <br /> <br /> Kod do&#x15B;&#x107; cz&#x119;sto pisany przez programist&#xF3;w, kiedy ich zadaniem jest pogrupowanie element&#xF3;w z wej&#x15B;cia. <br /> <br />
  • Wygl&#x105;da kod znajomo? <br /> <br /> Czy nigdy nie potrzebowa&#x142;e&#x15B; mapy, kt&#xF3;ra mo&#x17C;e przechowywa&#x107; wiele warto&#x15B;ci dla jednego klucza? Czy za ka&#x17C;dym razem piszesz taki kod? <br /> <br /> Kod do&#x15B;&#x107; cz&#x119;sto pisany przez programist&#xF3;w, kiedy ich zadaniem jest pogrupowanie element&#xF3;w z wej&#x15B;cia. <br /> <br />
  • Wygl&#x105;da kod znajomo? <br /> <br /> Czy nigdy nie potrzebowa&#x142;e&#x15B; mapy, kt&#xF3;ra mo&#x17C;e przechowywa&#x107; wiele warto&#x15B;ci dla jednego klucza? Czy za ka&#x17C;dym razem piszesz taki kod? <br /> <br /> Kod do&#x15B;&#x107; cz&#x119;sto pisany przez programist&#xF3;w, kiedy ich zadaniem jest pogrupowanie element&#xF3;w z wej&#x15B;cia. <br /> <br />
  • Jest to przyk&#x142;ad multimap w Google Collections, czyli takich map, gdzie dla danego klucza mo&#x17C;na trzyma&#x107; wiele warto&#x15B;ci. W przypadku ListMultimap, kolejno&#x15B;&#x107; dodawanych warto&#x15B;ci dla danego klucza zostanie zachowana. <br /> <br /> Zach&#x119;cam do zapoznania si&#x119; si&#x119; z com.google.common.collect, jako &#x17C;e czekaj&#x105; tam prawdziwe pere&#x142;ki. <br />
  • Jest to przyk&#x142;ad multimap w Google Collections, czyli takich map, gdzie dla danego klucza mo&#x17C;na trzyma&#x107; wiele warto&#x15B;ci. W przypadku ListMultimap, kolejno&#x15B;&#x107; dodawanych warto&#x15B;ci dla danego klucza zostanie zachowana. <br /> <br /> Zach&#x119;cam do zapoznania si&#x119; si&#x119; z com.google.common.collect, jako &#x17C;e czekaj&#x105; tam prawdziwe pere&#x142;ki. <br />
  • Jest to przyk&#x142;ad multimap w Google Collections, czyli takich map, gdzie dla danego klucza mo&#x17C;na trzyma&#x107; wiele warto&#x15B;ci. W przypadku ListMultimap, kolejno&#x15B;&#x107; dodawanych warto&#x15B;ci dla danego klucza zostanie zachowana. <br /> <br /> Zach&#x119;cam do zapoznania si&#x119; si&#x119; z com.google.common.collect, jako &#x17C;e czekaj&#x105; tam prawdziwe pere&#x142;ki. <br />
  • Jest to przyk&#x142;ad multimap w Google Collections, czyli takich map, gdzie dla danego klucza mo&#x17C;na trzyma&#x107; wiele warto&#x15B;ci. W przypadku ListMultimap, kolejno&#x15B;&#x107; dodawanych warto&#x15B;ci dla danego klucza zostanie zachowana. <br /> <br /> Zach&#x119;cam do zapoznania si&#x119; si&#x119; z com.google.common.collect, jako &#x17C;e czekaj&#x105; tam prawdziwe pere&#x142;ki. <br />
  • Stosowanie p&#x142;ynnych interfejs&#xF3;w (tzw. fluent interface) to spos&#xF3;b implementacji API w j&#x119;zykach obiektowych, kt&#xF3;rych celem jest zwi&#x119;kszenie czytelno&#x15B;ci kodu. Chodzi o to, &#x17C;eby osoba czytaj&#x105;ca mia&#x142;a wra&#x17C;enie, jakby czyta&#x142;a zdanie w j&#x119;zyku naturalnym. <br /> <br /> Jedn&#x105; z technik&#x105; uzyskania p&#x142;ynnego interfejsu jest method chaining, czyli &#x142;a&#x144;cuszek metod. <br /> <br /> Zobaczmy to na przyk&#x142;adach z Google Guava. <br />
  • Stosowanie p&#x142;ynnych interfejs&#xF3;w (tzw. fluent interface) to spos&#xF3;b implementacji API w j&#x119;zykach obiektowych, kt&#xF3;rych celem jest zwi&#x119;kszenie czytelno&#x15B;ci kodu. Chodzi o to, &#x17C;eby osoba czytaj&#x105;ca mia&#x142;a wra&#x17C;enie, jakby czyta&#x142;a zdanie w j&#x119;zyku naturalnym. <br /> <br /> Jedn&#x105; z technik&#x105; uzyskania p&#x142;ynnego interfejsu jest method chaining, czyli &#x142;a&#x144;cuszek metod. <br /> <br /> Zobaczmy to na przyk&#x142;adach z Google Guava. <br />
  • Stosowanie p&#x142;ynnych interfejs&#xF3;w (tzw. fluent interface) to spos&#xF3;b implementacji API w j&#x119;zykach obiektowych, kt&#xF3;rych celem jest zwi&#x119;kszenie czytelno&#x15B;ci kodu. Chodzi o to, &#x17C;eby osoba czytaj&#x105;ca mia&#x142;a wra&#x17C;enie, jakby czyta&#x142;a zdanie w j&#x119;zyku naturalnym. <br /> <br /> Jedn&#x105; z technik&#x105; uzyskania p&#x142;ynnego interfejsu jest method chaining, czyli &#x142;a&#x144;cuszek metod. <br /> <br /> Zobaczmy to na przyk&#x142;adach z Google Guava. <br />
  • Java nie jest j&#x119;zykiem funkcyjnym. Mo&#x17C;na natomiast z funkcyjno&#x15B;ci&#x105; eksperymentowa&#x107;. Jest to bardzo udana zabawa zw&#x142;aszcza z kolekcjami. <br /> <br /> Java i programowanie funkcyjne to trudna mi&#x142;o&#x15B;&#x107;. Jednak poszukiwanie dostarcza du&#x17C;o rado&#x15B;ci. Zobaczmy. <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • Funkcja to operacja, kt&#xF3;ra transformuje jest obiekt w drugi. Na przyk&#x142;ad wyobra&#x17A;my sobie funkcj&#x119;, kt&#xF3;ra transformuje &#x142;a&#x144;cuch znak&#xF3;w do liczb, czyli dla &#x142;a&#x144;cucha &#x201C;22&#x201D; zwracana jest liczba ca&#x142;kowita 22. <br /> Funkcja transformuj&#x105;ca nie musi zwraca&#x107; obiektu innego typu. Przyk&#x142;adem niech b&#x119;dzie funkcja konwertuj&#x105;ca stopnie w farenheicie do stopni w celsiuszu. <br /> <br /> &#x17B;adnych, ale to &#x17C;adnych efekt&#xF3;w ubocznych. <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • Predykat to rodzaj funkcji, kt&#xF3;ry dla wej&#x15B;cia zwraca prawd&#x119; lub fa&#x142;sz. W JDK korzystamy z wyra&#x17C;e&#x144; regularnych do&#x15B;&#x107; cz&#x119;sto. Wyobra&#x17A;my sobie predykat wykorzystuj&#x105;cy wyra&#x17C;enie regularne. Dla danego &#x142;a&#x144;cucha znak&#xF3;w zwraca prawd&#x119;, je&#x15B;li wyra&#x17C;enie regularne pokrywa &#x142;a&#x144;cuch znak&#xF3;w. <br /> <br /> Tak samo jak w przypadku funkcji: &#x17C;adnych, ale to &#x17C;adnych efekt&#xF3;w ubocznych. <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • Podsumowuj&#x105;c, pokaza&#x142;em wam, w jaki spos&#xF3;b przekonywa&#x142;em siebie, &#x17C;e w Javie mo&#x17C;na dostrzec &#x142;adny programowania. Rozpocz&#x105;&#x142;em swoj&#x105; przygod&#x119; poprawiaj&#x105;c sw&#xF3;j kod ma&#x142;ymi krokami. Gdy nast&#x119;pnie nabra&#x142;em rozp&#x119;du - zacz&#x105;&#x142;em eksperymentowa&#x107;, do czego was bardzo zach&#x119;cam. <br />
  • <br />

Lekcja stylu Lekcja stylu Presentation Transcript

  • LEKCJA STYLU czy w Javie można jeszcze dostrzec piękno? Wiktor Gworek • Javarsovia 2010 • Google
  • @wwiktorr ^wwiktorr wiktorgworek.com blog.mocna-kawa.com
  • PIĘKNO KODU definicja dla Javy
  • czytelność boilerplate łatwe testowanie PIĘKNO KODU definicja dla Javy statyczne narzędzia typowanie
  • 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/
  • Czytelność Funkcyjność
  • POPRAWIANIE CZYTELNOŚCI http://www.flickr.com/photos/jleveque/2151484964
  • “Jejku, ten kod wygląda, jakby go pisał sam Steven King. Horror, aż strach przejść na kolejną stronę.” – anonimowy programista
  • if (GOOGLE) { CODE.STYLE(); }
  • 100 znaków if (GOOGLE) { CODE.STYLE(); }
  • 100 znaków if (GOOGLE) { t CODE.STYLE(); }
  • 100 znaków if (GOOGLE) { t CODE.STYLE(); } 2 znaki
  • 100 znaków if (GOOGLE) { t CODE.STYLE(); } 2 znaki
  • KODOWANIE DEFENSYWNE http://www.flickr.com/photos/mosca27/166707333/
  • 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 }
  • KODOWANIE DEFENSYWNE public void analyze(String msg) { Preconditions.checkNotNull(msg); Preconditions.checkArgument( msg.length() <= 160, “Tak długa wiadomość?”); // analiza wiadomości }
  • ZBĘDNY KOD
  • KOLEKCJE com.google.common.collect Map<String, List<User, Role>> map = new HashMap<String, List<User, Role>>;
  • 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”);
  • NIEMODYFIKOWANE OBIEKTY
  • NIEMODYFIKOWANE OBIEKTY public void setName(String newName); private final Address address;
  • NIEMODYFIKOWANE OBIEKTY public void setName(String newName); private final Address address; // Wykorzystanie Protocol Buffers Post newPost = post.toBuilder() .setTitle(newTitle) .build();
  • 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); }
  • KOLEKCJE com.google.common.collect public static final Set<Integer> LUCKY_NUMBERS = Collections.unmodifiableSet( new LinkedHashSet<Integer>( Arrays.asList(4, 7, 42)));
  • KOLEKCJE com.google.common.collect
  • KOLEKCJE com.google.common.collect List<String> list = ImmutableList.of(“a”, “b”, “c”);
  • KOLEKCJE com.google.common.collect List<String> list = ImmutableList.of(“a”, “b”, “c”); static final Set<Integer> LUCKY_NUMBERS = ImmutableSet.of(4, 7, 42);
  • 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”);
  • ZNOWU TO SAMO... http://www.flickr.com/photos/nifmus/2385966735/
  • 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”);
  • 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”);
  • 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”);
  • 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”);
  • 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”);
  • 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”);
  • 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”);
  • 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”);
  • 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”);
  • 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”);
  • 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”);
  • FLUENT INTERFACE com.google.common.base.Joiner
  • FLUENT INTERFACE com.google.common.base.Joiner String s = Joiner.on(",").join(episodes); String s = Joiner.on(“|”).skipNulls().join(users);
  • 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);
  • 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”, ...));
  • ZABAWA Z FUNKCYJNOŚCIĄ http://www.flickr.com/photos/infrarad/182786930
  • WEJŚCIE: lista loginów w serwisie WYJŚCIE: posortowana lista użytkowników, którzy mają więcej niż 18 lat
  • logins .map{ |login| User.select_by_login(login)} .find_all{ |user| user != nil && user.age > 18 } .sort_by{ |user| [user.surname, user.name] }
  • logins .map{ |login| User.select_by_login(login)} .find_all{ |user| user != nil && user.age > 18 } .sort_by{ |user| [user.surname, user.name] }
  • logins .map{ |login| User.select_by_login(login)} .find_all{ |user| user != nil && user.age > 18 } .sort_by{ |user| [user.surname, user.name] }
  • logins .map{ |login| User.select_by_login(login)} .find_all{ |user| user != nil && user.age > 18 } .sort_by{ |user| [user.surname, user.name] }
  • 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()); }});
  • 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()); }});
  • 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()); }});
  • 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()); }});
  • 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()); }});
  • 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()); }});
  • 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()); }});
  • 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()); }});
  • 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()); }});
  • FUNKCJE com.google.common.base.Function public interface Function<F, T> { T apply(@Nullable F from); }
  • 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); } }
  • 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); } }
  • 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); } }
  • 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); } }
  • 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); } }
  • PREDYKATY com.google.common.base.Predicate public interface Predicate<T> { boolean apply(@Nullable T input); }
  • 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; } };
  • 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; } };
  • 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; } };
  • 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; } };
  • Ł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(); } };
  • Ł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(); } };
  • Ł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(); } };
  • Ł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(); } };
  • Ł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(); } };
  • Ł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(); } };
  • 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);
  • 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);
  • 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);
  • 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);
  • 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);
  • 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);
  • 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);
  • 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);
  • 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);
  • TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
  • TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
  • TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
  • TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
  • TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
  • TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
  • TRZECIA PRÓBA ImmutableList<User> result = FluentIterable .with(logins) .transform(new FetchUsers(userDao)) .filter(Predicates.notNull()) .filter(OVER_18) .sort(NAME_DESC) .immutableCopy();
  • Czytelność Funkcyjność
  • Pytania? Wiktor Gworek • Javarsovia 2010 • Google