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.
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. 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());
}});
61. 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());
}});
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.
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;.
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.
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.
Jest to serwis w ca&#x142;o&#x15B;ci napisany w Javie. Od pierwszego dnia.
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;.
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.
Jest to serwis w ca&#x142;o&#x15B;ci napisany w Javie. Od pierwszego dnia.
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;.
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.
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.
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.
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;.
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.
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.
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
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 :).
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;.
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.
Na tej prezentacji skupi&#x119; si&#x119; na tej pierwszej - Guava.
Prezentacj&#x119; podzieli&#x142;em na 2 cz&#x119;&#x15B;ci.
- 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.
- 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.
Do dzie&#x142;a.
Zacznijmy od poprawiania kodu. Wyznaczmy sobie jaki&#x15B; cel, do kt&#xF3;rego b&#x119;dziemy d&#x105;&#x17C;y&#x107;.
Oto nasz cel. Miejmy ten cytat w g&#x142;owie i zaczynajmy.
Tre&#x15B;&#x107; tre&#x15B;ci&#x105;, ale tak&#x17C;e trzeba dba&#x107; o form&#x119; prezentacji.
Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli:
* szeroko&#x15B;&#x107; linii to 100 znak&#xF3;w, nie ma wyj&#x105;tk&#xF3;w
- ciekawostka a propos 80 znak&#xF3;w i os&#xF3;b niedowidz&#x105;cych
* (pami&#x119;tajcie, &#x17C;e z&#x142;o czai si&#x119; wsz&#x119;dzie) bezwzgl&#x119;dny zakaz u&#x17C;ywania tabulator&#xF3;w
* 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
* oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod kt&#xF3;rymi jest tylko jedna instrukcja.
Tre&#x15B;&#x107; tre&#x15B;ci&#x105;, ale tak&#x17C;e trzeba dba&#x107; o form&#x119; prezentacji.
Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli:
* szeroko&#x15B;&#x107; linii to 100 znak&#xF3;w, nie ma wyj&#x105;tk&#xF3;w
- ciekawostka a propos 80 znak&#xF3;w i os&#xF3;b niedowidz&#x105;cych
* (pami&#x119;tajcie, &#x17C;e z&#x142;o czai si&#x119; wsz&#x119;dzie) bezwzgl&#x119;dny zakaz u&#x17C;ywania tabulator&#xF3;w
* 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
* oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod kt&#xF3;rymi jest tylko jedna instrukcja.
Tre&#x15B;&#x107; tre&#x15B;ci&#x105;, ale tak&#x17C;e trzeba dba&#x107; o form&#x119; prezentacji.
Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli:
* szeroko&#x15B;&#x107; linii to 100 znak&#xF3;w, nie ma wyj&#x105;tk&#xF3;w
- ciekawostka a propos 80 znak&#xF3;w i os&#xF3;b niedowidz&#x105;cych
* (pami&#x119;tajcie, &#x17C;e z&#x142;o czai si&#x119; wsz&#x119;dzie) bezwzgl&#x119;dny zakaz u&#x17C;ywania tabulator&#xF3;w
* 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
* oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod kt&#xF3;rymi jest tylko jedna instrukcja.
Tre&#x15B;&#x107; tre&#x15B;ci&#x105;, ale tak&#x17C;e trzeba dba&#x107; o form&#x119; prezentacji.
Styl kodowania jest prawie zgodny z Sunowskim stylem kodowania w Javie. Czyli:
* szeroko&#x15B;&#x107; linii to 100 znak&#xF3;w, nie ma wyj&#x105;tk&#xF3;w
- ciekawostka a propos 80 znak&#xF3;w i os&#xF3;b niedowidz&#x105;cych
* (pami&#x119;tajcie, &#x17C;e z&#x142;o czai si&#x119; wsz&#x119;dzie) bezwzgl&#x119;dny zakaz u&#x17C;ywania tabulator&#xF3;w
* 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
* oraz zawsze nawiasujemy, nawet w przypadku instrukcji warunkowych, pod kt&#xF3;rymi jest tylko jedna instrukcja.
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.
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.
Co uzyskujemy przez to?
- bardziej czytelny kod
- moj kod wowczas mniej sie wywala,
- latwiej dostrzec przypadki brzegowe.
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.
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.
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?
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.
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.
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?
Przejd&#x17A;my do konceptu niemodyfikowalnych obiekt&#xF3;w.
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.
Ok, co to s&#x105; niemodyfikowalne obiekty?
(1) Nie dostarczaj metod modyfikuj&#x105;cych stan obiektu. Settery.
(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;.
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;.
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.
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.
--- Jedyn&#x105; wad&#x105; takich obiekt&#xF3;w jest to, &#x17C;e wymagaj&#x105; osobnego obiektu, kiedy jego stan si&#x119; zmienia.
-- kiedy jeszcze raz bedziesz chcial napisac metoda zaczynajaca sie na set* - zastanow sie
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.
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.
Kr&#xF3;tsze, ale u&#x17C;ywa a&#x17C; czterech klas. Co&#x15B; jest nie tak.
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.
Teraz kod m&#xF3;wi dok&#x142;adnie to, co mamy na my&#x15B;li. + jest to du&#x17C;o wydajne
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.
Teraz kod m&#xF3;wi dok&#x142;adnie to, co mamy na my&#x15B;li. + jest to du&#x17C;o wydajne
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.
Teraz kod m&#xF3;wi dok&#x142;adnie to, co mamy na my&#x15B;li. + jest to du&#x17C;o wydajne
Wygl&#x105;da kod znajomo?
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?
Kod do&#x15B;&#x107; cz&#x119;sto pisany przez programist&#xF3;w, kiedy ich zadaniem jest pogrupowanie element&#xF3;w z wej&#x15B;cia.
Wygl&#x105;da kod znajomo?
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?
Kod do&#x15B;&#x107; cz&#x119;sto pisany przez programist&#xF3;w, kiedy ich zadaniem jest pogrupowanie element&#xF3;w z wej&#x15B;cia.
Wygl&#x105;da kod znajomo?
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?
Kod do&#x15B;&#x107; cz&#x119;sto pisany przez programist&#xF3;w, kiedy ich zadaniem jest pogrupowanie element&#xF3;w z wej&#x15B;cia.
Wygl&#x105;da kod znajomo?
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?
Kod do&#x15B;&#x107; cz&#x119;sto pisany przez programist&#xF3;w, kiedy ich zadaniem jest pogrupowanie element&#xF3;w z wej&#x15B;cia.
Wygl&#x105;da kod znajomo?
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?
Kod do&#x15B;&#x107; cz&#x119;sto pisany przez programist&#xF3;w, kiedy ich zadaniem jest pogrupowanie element&#xF3;w z wej&#x15B;cia.
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.
Zach&#x119;cam do zapoznania si&#x119; si&#x119; z com.google.common.collect, jako &#x17C;e czekaj&#x105; tam prawdziwe pere&#x142;ki.
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.
Zach&#x119;cam do zapoznania si&#x119; si&#x119; z com.google.common.collect, jako &#x17C;e czekaj&#x105; tam prawdziwe pere&#x142;ki.
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.
Zach&#x119;cam do zapoznania si&#x119; si&#x119; z com.google.common.collect, jako &#x17C;e czekaj&#x105; tam prawdziwe pere&#x142;ki.
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.
Zach&#x119;cam do zapoznania si&#x119; si&#x119; z com.google.common.collect, jako &#x17C;e czekaj&#x105; tam prawdziwe pere&#x142;ki.
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.
Jedn&#x105; z technik&#x105; uzyskania p&#x142;ynnego interfejsu jest method chaining, czyli &#x142;a&#x144;cuszek metod.
Zobaczmy to na przyk&#x142;adach z Google Guava.
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.
Jedn&#x105; z technik&#x105; uzyskania p&#x142;ynnego interfejsu jest method chaining, czyli &#x142;a&#x144;cuszek metod.
Zobaczmy to na przyk&#x142;adach z Google Guava.
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.
Jedn&#x105; z technik&#x105; uzyskania p&#x142;ynnego interfejsu jest method chaining, czyli &#x142;a&#x144;cuszek metod.
Zobaczmy to na przyk&#x142;adach z Google Guava.
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.
Java i programowanie funkcyjne to trudna mi&#x142;o&#x15B;&#x107;. Jednak poszukiwanie dostarcza du&#x17C;o rado&#x15B;ci. Zobaczmy.
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.
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.
&#x17B;adnych, ale to &#x17C;adnych efekt&#xF3;w ubocznych.
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.
Tak samo jak w przypadku funkcji: &#x17C;adnych, ale to &#x17C;adnych efekt&#xF3;w ubocznych.
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.