czwartek, 27 marca 2014

my struggle with code = matrix

W cyklu postów 'my struggle with code' postaram się opisywać problemy jakie napotkasz na co dzień podczas implementacji lub projektowania swoich systemów. Postaram się też podać gotową receptę na dany przypadek.
Dziś padło na marix variables. Termin ten związany jest często z implementacją REST API. Chcemy aby API restowe było 'piękne', czytelne czy funkcjonalne.

Tip : Zawsze dużo wysiłku wkładaj w projektowanie API. To trzon wszystkiego. Dobre API to 50% sukcesu.  


O co tu w ogóle chodzi?

chce tworzyć API na wzór  :
  //moremaps.com/map/color;lat=50;long=20;scale=32000
coś na kształt najlepszych obecnie API jak :

 LinkedIn API :
  /people:(id,first-name,last-name,industry)

FaceBook API :
  /slawomir.borowiec/friends?fields=id,name,picture
  /me?fields=hometown,address,birthday

Google API : 
 ?fields=title,media:group(media:thumbnail)

My API :
/category/{name}/desc='restAPI';location='warsaw'
/user/location/{district};ochota,praga,wola/{permission};business,user


W połączeniu ze wzorcem Tuple i  Dao możemy powiedzieć REST API jakie kolumny chcemy zwrócić, czy jakie parametry czy dane nas interesują.

Krótko - > Zajebiste...:)


Pomysł wydaje się prosty a rozwiązanie równie proste jak i oczywiste, ale jak zwykle napotkałem niespodziewane problemy.

W Spring 3.2.2 wszystko działa jak należy. Czyli przewidywalnie.

Ok. Teraz używam Spring 4.0.2 czyli największą stabilną i  aktualną wersją.
I mam problem. Matrix Variables nie działa jak potrzeba. Po prostu przestał parsować URL'a.
Dzieje się tak już od wersji 3.2.2 wzwyż . Np w wersji 3.2.3 już ten feature nie działa. Ok zaglądamy do dokumentacji.


Prototypując aplikacje używam Spring Boot'a. Dlaczego ? Bo tak trzeba:). Jest dużo prościej i zaoszczędza mi to w cholerę pracy. (O Spring Boot przeczytasz sobie tutaj)


Opierając się na Spring Boot odpalam swoje REST API. Druga sprawa nie chce używać wcale XML skoro specyfikacja JavaConfig ma już tyle lat i naprawdę teraz wydaje się być dojrzała.
Rozwiązanie zajęło mi trochę czasu - udało się w końcu :).
Poniżej jest recepta na pozbycie się gównianego xml i zastąpienie go odpowiednikiem w javie.

Tutaj znajdziesz kod z REST API + HATEOAS + NOSQL

poniedziałek, 24 marca 2014

Effective java programming in practice part 2

Guava została stworzona byś pisał mniej kodu.

Jednocześnie kod ten ma takie zalety jak zwiększona czytelność, czystość oraz wydaje się bardziej prosty.

Pozwala skupić się na problemach biznesowych zamiast tworzyć powtarzalne już struktury kodu jak : utils czy helper


Dla mnie Guava jest rozszerzeniem tez zawartych w książce Joshua Blocha pt
Effective java programming.

Dlaczego guava ?
 - static import
 - eliminacja boilderplate code
 - minimalizacja kodu
 - testy, jakość, pewność.
 - wydajność
 - niezmienność
 - kodowanie defensywne
 - wprowadzenie do kodowania funkcyjnego (Functional idioms)
   ( w java 8 -> java.util.function)

Recepty :

Unikaj jak tylko możesz tworzenia obiektu.

Zamiast używać konstruktora w celu tworzenia obiektu użyj statyczną metodę wytwórczą, która zwykle tego nie robi.

Tip : W przypadku Springa możesz użyć : FactoryBean


nigdy nie rób tak jak poniżej !:

Używaj typów prostych zamiast opakowanych typów prostych - wydajność !!

Tip : Rozważ użycie wzorca Flyweight

Tworzenie i zwracanie małych obiektów nie jest kosztowne.

Stosuj pule wątków : Executors (ściśle związane z kolejką zadań) - Wątek pobiera z kolejki zadanie wykonuje je i wracają z powrotem by poprać następne zadanie
Ponowne wykorzystanie tych samych wątków bez tworzenia nowych ,rozkłada koszty kreacji i niszczenia na wiele zadań. Zmniejsza opóźnienia wykonania zadania ponieważ wątek już jest w puli. Odpowiedni rozmiar puli zapewnia efektywne wykorzystanie zasób procesora przy jednoczesnym uniknięciu zajęcia całej dostępnej pamięci przez tworzone nieustanie wątki. (saturation)

Stosuj pule połączeń dla połączeń z bazą
Każde wytworzenie i nawiązanie połączenia jest drogie. Ale idąc w drugą stronę utrzymywanie puli połączeń również. Zawsze należy szukać równowagi.

Przypisuj wartość null do niepotrzebnych już referencji. (wycieki pamięci) Jeśli referencja do obiektu będzie nieświadomie przetrzymywana, nie tylko ten obiekt nie będzie podlegał odśmiecaniu ale również cały graf obiektów mu podległych.

Tip : Najlepszym sposobem na eliminowanie niepotrzebnych referencji jest powtórne ich wykorzystanie lub wyjście poza z ich zasięgu.
Programując pseudo-obiektowo jesteś narażony na powyższą sytuację.

Tip : Stosuj możliwe najmniejsze zakresy zmiennych oraz ich widoczność.

Tip : Buforowanie może powodować wycieki pamięci. Stosuj WeakHashMap , lub stosuj zmienną timeIdle do określenia świeżości danych w buforach.
 
Tip : Listenery i event'y mogą być źródłem wycieków pamięci. Należy pamiętać o wyrejestrowaniu usług.

Unikaj finalizatorów , bo :
 - są nieprzewidywalne
 - niebezpieczne
 - użycie ich zwykle jest błędem programisty
 - powodują spadek wydajności

Zamiast finalizatorów używaj metodę kończącą, zwalniającą dane zasoby.


Używaj konstrukcji try-finally a jeszcze lepiej try-with-resources

Medoty wspólne : 

toString() - kiedy tylko możesz dobrą praktyką jest przedefiniowanie metody toString tak aby nie zwracała funkcji skrótu która to de facto nic nam nie mówi.
Tip : Użyj guavy Objects.toStringHelper lub Lomboka @ToString

equals()

Kiedy nie musimy przesłonić metody equals : 
- kiedy obiekt ze swojej natury jest unikalny
- kiedy nie trzeba sprawdzać logicznej równoważności
- kiedy nadklasa posiada już przesłoniętą metodę equals i to jej działanie jest wystarczające w stosunku do naszych zamierzeń
- kiedy jest to klasa prywatna wewnątrz pakietu i metoda equals nie zostanie nigdy wywołana

Kiedy musimy koniecznie przesłonić metodę equals :
-  logiczna równoważność może różnić się od zwykłej identyczności w ramach obiektu javy

Przedefiniowanie metody equals musi zapewnić następujące warunki: 
 - zwrotność  if (x != null)  x.equals(x) == true
 - symetria  x.equals(y) == y.equals(x)
 - przechodność x.equals(y) == y.equals(z) == z.equals(x)
 - spójność  -  idempotentność  - wielokrotne wywołanie x.equals(y) zawsze zwraca ten sam wynik

Zasada tworzenia : 
 - sprawdź przez == czy argument jest referencją do tego samego obiektu
 - użyj instanceOf w celu sprawdzenia czy argument jest odpowiedniego typu
 - rzutuj argument na właściwy typ
 - dla kluczowych pól porównaj wartości z obiektem przekazanym jako argument
 - zawsze przedefiniuj metodę hashCode() , w przypadku przedefiniowania metody equals()

Tip : Użyj Lomboka lub guavy w celu stworzenia equals() lub hashCode() i zapomnij o powyższych zasadach.

Tip : od javy 1.7  użyj klasy narzędziowej Objects.


hashCode()

Bez prawidłowego działania hashCode zapomnij o prawidłowym działaniu kolekcji opartych o kod mieszający.

Warunki :
 - idempoteność
 - jeśli metoda equals() wykażę , że obiekty są jednakowe metoda hashCode() powinna zadziałać podobnie - identyczna funkcja skrótu.
 - nie jest wymagane aby dwa różne obiekty , według porównania equals zwracały różne wartości. (Jednak zwracanie różnych wartości znacznie poprawia wydajność operacji na tablicach mieszających)


Uwaga ! : zła implementacja metod hashCode i equals może nas bardzo dużo kosztować. Powstałe w ten sposób anomalie i błędy działania programu nie są trywialne i ciężkie go wyłapania. Zawsze poświęć trochę czasu nad zastanowieniem się czy dobrze zaprojektowałeś metodę equals w stosunku do jej kontraktu. Podobnie postępuj z metodą hashCode.

Programowanie defensywne :

Preconditions - check conditions you expect variables
W poprzednim poście zastosowaliśmy buildera aby wyeliminować problem licznych parametrów w konstruktorze. Dziś użyjemy mechanizmu guavy  Preconditions w celu walidacji parametrów podczas stosowania wzorca builder co jest dobrą praktyką.

Co zyskujemy ?
Ważne jest aby możliwie jak najszybciej wyrzucać błędy z funkcji czy funkcjonalności biznesowej tak aby wyrządzić możliwie mało szkód i a potem łatwo namierzyć problem.

kod znajdziesz tutaj

Wyjątki. 
Powstały do obsługi sytuacji wyjątkowych. Tworzenie, zgłaszanie i przechwytywanie wyjątków to operacje stosunkowo kosztowne. Słabo optymalizowane przez JVM
Umieszczenie kodu w bloku try-catch uniemożliwia niektóre optymalizacje.

Możemy przerwać (termination) jeśli błąd jest krytyczny, nie istnieje możliwość powrotu do miejsca w którym pojawił się wyjątek lub wznowić czyli próbować wywołać wadliwą metodę jeszcze raz (np OptimisticLockException)

Są w pełni funkcjonalnymi obiektami w których można definiować pola oraz metody. Ma to na celu pomóc programiście opisać lepiej kod przechwytujący wyjątek oraz zdarzenie które je spowodowało.

Tip : Stosuj centralizację obsługi wyjątków : AOP
AOP : ThrowsAdvice lub @AfterThrowing
(An after throwing advice is executed only when an exception is thrown by a join point. )

Jeśli je stosujemy dobrze to :
 - zwiększamy czytelność
 - ułatwiamy konserwacje oraz solidność
 - bulletproof programming





źródło : www.javamex.com 

Dzielimy na :
- weryfikowalne  (Checked exceptions) - muszą być jawnie obsłużone w metodach
- nieweryfikowalne (Runtime exceptions (unchecked exceptions)) - są instancją klasy Error i RuntimeException
Nie potrzebują jawnej obsługi. Rollbackują transakacje!! 
Wyjątki nieweryfikowalne nie powinny być przechwytywane.
 

- błędy (Errors)

Wyjątki nie mogą służyć do sterowania przepływem programu !!

Dobrze zaprojektowane API nie powinno wymuszać na klientach wykorzystywania wyjątków do sterowania przypływem.

Przychwytywanie wyjątków stosuj w przypadkach kiedy możemy przywrócić normalny stan programu.

Wszystkie zdefiniowane przez Ciebie wyjątki nieprzechwytywalne powinny dziedziczyć po RuntimeException

Wyjątki przechwytywalne stosuj wtedy kiedy można naprawić błąd, a nieprzechwytywalnych do obsługi błędów programowych.

Tip : Patrz rozdział wyżej programowanie defensywne a wykorzystanie wyjątków. 

Nigdy nie ignoruj wyjątku !!  - blok catch nigdy nie może być pusty.
Zaloguj zawsze wyjątek do odpowiedniego loggera (ERROR, FATAL , WARN)



Zawsze zawężaj wyjątki jak to tylko możliwe: Zamiast używać Throwable lub Exception używaj podklas odpowiednich do zaistniałej sytuacji


Nigdy nie łap Throwable. Ponieważ java Erros jest podklasą Throwable. Jeśli program wyrzuci Error to znaczy, że jest martwy.

Zawsze odpowiednio 'wrap' (opakowuj) wyjątek tak aby nie stracić stack trace.

Nigdy nie wyrzucaj wyjątku z sekcji finally !

Jeśli stosujesz metodę która może wyrzucić jakiś wyjątek, lepiej zastosować sekcje finally zamiast catch ponieważ w sekcji finally wykona się jeszcze kod np czyszczący zasoby.

Zawsze wyrzucaj wyjątki najszybciej jak to możliwe.
Tip : patrz wyżej guava Preconditions

Pamiętaj o czyszczeniu zasobów nawet jak zostanie wyrzucony jakiś wyjątek - zastosuj finally block.

Owijaj wyjątki w stosunku do potrzeby. Np NPE zwykle nie mówi nic. Czasem lepiej jest użyć np IllegalArgumentException , IllegalStateException etc


Tip : Zawsze staraj się dopasowywać wyjątki do sytuacji

Tip : Używaj walidatorów JSR 303

<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>


Staraj się nie rozprzestrzeniać takich samych bloków try-catch - Użyj klasy szablony klas lub metody templatowe.



Warte uwagi są również rozwiązania zaproponowane przez frameworki integracji w kwestii obsługi błędów
np definicja ponawiania wygląda w skrócie tak : (źródło camel in action)
 

Ale co w tym dobrego? To, że wszystko jest pięknie zamknięte w abstrakcjach i szablonach przez co nigdy nie ponawiamy kodu. A obsługę sytuacji wyjątkowych i związanych z tym ponowień coś na kształt kolejek JMS mamy out-of-the-box.





Kiedyś używałem swoich wyjątków biznesowych, które dziedziczyły po Exception. To nie było dobre. Po pierwsze takie podejście łamie zasadę Open-Close po drugie narusza hermetyzacje programu. Jeden dodany wyjątek powoduje zmianę całego stosu API , między innymi poprzez potrzebę dodania klauzuli throws. Mało tego korzystanie z wyjątków weryfikowalnych nie powoduje wycofania transakcji, przez co musiałem odpowiednio niepotrzebnie dekorować @Transactional(rollbackFor=....).


Dziedziczenie po RuntimeException prawie zawsze jest lepszym pomysłem.

Korzystaj z udogodnień dostępnych już od javy 7 : 

- try-with-resources block - jako usprawnienie obsługi wyjątków w kodzie

- catching multiple exception types- jako usprawnienie sprawdzania typów wyjątków

Korzystaj z mechanizmu propagacji Exception w Guavie

Korzystaj z google catch-exception w celu testowania wyjątków (najlepsza praktyka testowania wyjątków w javie)
 

więcej o strategiach testowania znajdziesz w tym poście
 cdn

Date & Time java 8


W poprzednich wersjach javy Calendar i Date były klasami o których lepiej zapomnieć a najlepiej wcale ich nie używać aby nie narobić sobie niepotrzebnych kłopotów.

Ich wady to : 
- mutability (mutowalność)
- brak stref czasowych
- trudność w użyciu  (API)
- podatność na bugi
- słaba wydajność
- problem indeksowania od zera (miesiące)




Joda Time była receptą na problemy związane z obsługą czasu w javie.
Od Java 8 biblioteka Joda Time została wchłonięta przez korporację Oracle.

Zalety : 
- łatwość użycia (API)
- dokumentacja
- lepsza wydajność
- immutable
- strefy czasowe
- lepsza funkcjonalość

Terminy :
Strefa czasowa - identyfikuje dany obszar lub lokację w odniesieniu do czasu
UTC - Coordinated Universal Time
Offset - jest to różnica w godz i min pomiędzy czasem UTC a daną strefą czasową.

TIP : A co z JPA ?
Użyj mappera jak:
hibernate joda-time
lub
http://jadira.sourceforge.net/

Kod do posta znajdziecie tu

środa, 19 marca 2014

hello java 8

Wczoraj Oracle wypuścił pełną wersję javy 8.
Java rozwija się w takim kierunku aby sprostać dzisiejszym wyzwaniom jakim jest Big Data (przetwarzanie terabajtów danych) i efektywne wykorzystanie wielordzeniowych procesorów.
Pozwala na skuteczne pisanie złożonych algorytmów, wydajne przetwarzanie kolekcji w połączeniu ze skutecznym wykorzystaniem rdzeni procesora.
Pamiętacie join/fork z javy 7 ? :) Teraz zrobimy to prościej dzięki parallel stream.
A to tylko wierzchołek góry lodowej. Dzięki lambda zbliżamy się w kierunku języków funkcyjnych jak scala lub groovy (closures). Nasz kod teraz powinien być solidniejszy, pozbawiony zbędnych powtórzeń

Dobre wieści są takie, od grudnia 2013 Spring wspiera java 8 .
  W duchu lambda mamy:
  - JdbcTemplate - RowMapper
  - JmsTemplate - odświeżony na MessageCreator
  - TransactionTemplate - TransactionCallback

Features :
  - lambda expressions - umożliwia programowanie funkcyjne JSR-335
     (redukcja boilerplate code - metody anonimowe, reduce verbosity)
     (bazuje na invokeDynamic),
     (thread-safe)
      Podsumowując teraz możesz tworzyć kod bardziej abstrakcyjny, bardziej   czytelny oraz odporny na błędy, mniej podatny na mutowalność przez co  łatwiejszy do zrównoleglania.
      
  - stream - sekwencyjne oraz równoległe przetwarzanie danych
      (analogia do pipe w systemach linux, zyskujemy bardzo dużą elestyczność )
      (bazuje na join/fork)
  - compact profiles
  - prepare to Modularization
  - more and stronger algorithms
  - remove the permanent generation (nigdy już nie dostaniesz OutOfMemoryError : PermGen error)
  - Data & Time API -> joda (Wprowadza nową datę , czas i API )
    (Partial, duration, period, intervals, date ,time , instant , time-zone)
  - jdbc 4.2
  - bulk data operations for collections (filter/map/reduce)
    (bazuje na interfejsach : Function, Predicate, Consumer , Supplier , oraz Stream, Collector)
    (Przetwarza szeregowo i równolegle z wykorzystaniem wyrażenia Lambda)
    (Równoległość oparta jest na Fork-Join)
    (Lazy evaluation)
  - small VM (wsparcie dla urządzeń o małych zasobach pamięci - mobile device)
  - nashorn (natywny silnik js wbudowany w jre)
  - JavaFX 8

Dzięki zastosowaniu Javy 8 zwiększymy skalowalność oraz wydajność naszych aplikacji:
  - ForkJoin : 
      - inna polityka cache
      - szybszy obsługa małych i krótko żyjących tasków
      - łatwiejsza impl dzięki Streams
     - Atomics (Typy Atomowe)
        - szybsze wstawianie , wyjmowanie i inkrementacja
     - Nowe biblioteki 
           - operacje takie jak count , sum etc teraz bazują na wielu wątkach w celach poprawienia wydajności
      - Szybsza kompilacja
      - szybszy start aplikacji
      - PermGen  = (OutOfMemoryError  brak)
      - Metaspace  (-XX:MaxMetaspaceSize={size})
      - InvokeDynamic  - całkowicie przepisany (JSR 292) lepsza stabilność , wydajność i utrzymywanie
 

Wparcie dla IDE :
- eclipse kepler  : link











- sts 3.4.0 nie udało mi się użyć lambdy tak aby kompilator IDE się nie czepiał
- sts 3.5.0 m2 - podobna sytuacja
- netbeans 8.0 działa bez zarzutu
- idea też ma pełne wsparcie 


Opis nowej funkcjonalności w następnych postach

czwartek, 6 marca 2014

Effective java programming in practice part 1


Effective java  jest podstawową książką adresowaną dla każdego członka javowej społeczności.

Dzięki niej zrozumiesz jak pisać lepszy kod, łatwiejszy w utrzymaniu, bardziej odporny na błędy.
Poza tym przybliży Ci mechanizmy GUAVY, pozostawiając Twój kod w lepszej kondycji i pomoże ominąć pułapki jakie czekają na Ciebie podczas implementacji systemów napisanych w javie. Ten post stanowi zbiór dobrych praktyk służących do wytwarzania oraz budowy obiektów w sposób wydaje mi się najbardziej efektywny.





Zacznijmy w końcu więcej kodować.
Kiedy zaczynamy coś wytwarzać jest dobrze i wygodnie posiadać jakieś fundamenty, a najlepiej solidne. Często taką podwaliną jest baza danych. W środowiskach programistycznych od kilku dobrych już lat traktuje się bazę jako coś co ma zapewnić trwałość.
Co to oznacza ? - tylko tyle, że jak pierdolnie prąd czy zdarzy się cokolwiek innego nasze dane nie znikną.
Zostaną i będą bezpieczne. Oczywiście to nadal jest "fikcja", ponieważ aby zapewnić bezpieczeństwo tych danych i mieć 100% pewności, że faktycznie nasze dane pozostaną w takim stanie jak oczekiwalibyśmy będzie nas to sporo kosztowało.
Musimy przyjąć odpowiednią politykę bezpieczeństwa jak: regularne backupy (przyrostowy, różnicowy czy pełny), użycie streamera, użycie macierzy RAID, cloud, centra danych itd. Generalnie działania zapewniające bezpieczeństwo czy wysoką dostępność dla naszych danych wiążą się z zastosowanie redundancji maszyn czy innych zasobów co implikuje zwiększeniem kosztów:)

Ale ok my zajmiemy się dzisiaj bardziej przyziemnymi sprawami jak kodowanie.
Dla mnie jako programisty obiektowego nie istnieje baza danych. Tak naprawdę powinno się tak programować jakby jej w ogóle nie było.
I tak mamy Hibernate, TopLinka, EclipseLinka, iBATISa oraz inne twory.
W groovy dostaniemy GROM, w scali jest np  Slick, SORM czy inne.

Fajnie podchodzić do tego jak do programowania na kolekcjach. Baza jest gdzieś tam w tle. Jeśli chcesz zostawić sobie większą elastyczność na przyszłość np zmienić providera persystencji postaw JPA API.

Jest też druga strona medalu. Zapytania bazodanowe (natywne), optymalizację struktur danych, indeksację, normalizację warto znać. Bez tego Twój ORM i tak może zacząć kuleć, nawet jak cache'ujesz już dane. Jeśli nie ma podziału na bazodanowców i programistów będziesz musiał zmierzyć się wcześniej czy później z tymi problemami. Należy też pamiętać, że ORM się nie nadaje do wszystkich zastosować. Masowe przetwarzanie danych na operacjach typu delete, insert czy update mogę poważnie zaboleć jak wszystko opierasz na ORM lub spowodować OutOfMemoryException.
ORM jest świetny ale narzut na cache i mechanizmy sprawdzające świeżość danych "Dirty pattern" zrobią swoje. Niektóre specyficzne zapytania dla konkretnych baz danych mogą nie zadziałać jak powinny we współpracy z dedykowanym  dialektem lub zadziałać po prostu źle. Wtedy będziemy musieli zrobić coś natywnie - takie życie:)

Mój osobisty wybór to Hibernate  poprzez JPA 2.1 a do tego koniecznie Spring Data.
Spring Data to jest coś co też wypada znać. Kiedyś bawiłem się w swoje rozwiązania generycznego DAO potem powstało coś na kształt wczesnej wersji Spring Data JPA, oczywiście dużo gorsze rozwiązanie ale co było w tym najlepsze? - Specifications, który jest sercem JPA API.
Wkrótce okazało się, że to mój największy osobisty sukces w programowaniu, bo twórcy JPA API wykorzystali taki same podejście i niemal identyczny interfejs toPredicate() jak ja w swoim dawnym rozwiązaniu generycznej wyszukiwarki.

Wyszukiwarka ta miała dużo niedociągnięć i niedoróbek ale potrafiła poprzez poprawne użycie adnotacji na modelu przekazywanym do kontrolera wyszukiwać, sortować, grupować i stronicować dane bez użycia SQL'a czy HSQL. W przypadku kiedy poziom czy stopień skompilowania faktycznie nie pozwalał użyć standardowych moich adnotacji trzeba było wywołać metodę  toPredicate() opartą na Criteria API.

TIP : Spring Data - możesz używać dao w rozszerzonej formie CRUD'a bez potrzeby pisania implementacji kodu. Co więcej jeśli będzie potrzeba użyć innej nie relacyjnej bazy danych, otrzymasz ogromną pomoc i zrobić dużo rzeczy w dziecinnie łatwy sposób :) Redukcja kodu w obu przypadkach jest ogromna.

W założeniu Spring Data wykorzystujesz generalnie interfejsy a zapominasz o implementacji. Czasem jednak bez implementacji kawałka kodu nie może się obejść..

Spring Data JPA = wszystkie bazy relacyjne
Spring Data Neo4j, MongoDB etc - bazy nosql

Projekt umożliwia dostęp do operacji CRUD poprzez swoje interfejsy :


- Saves the given entity.

- Returns the entity identified by the given id.

- Returns all entities.

- Returns the number of entities.

- Deletes the given entity.

- Indicates whether an entity with the given id exists.
Głupio było by robić to samemu skoro Spring podaje Ci to na tacy.

TIP : Spring REST DATA - udostępnia interfejs CRUD przez REST
(możesz teraz wykonywać operacje na modelu domenowym poprzez REST)

TIP : Zawsze kastomizuj swoje repozytorium.

TIP : Repository populators - zasil bazę danymi formatu JSON czy XML (oxm)

Dokładny opis i konfigurację projektów Spring Data i Spring Data Rest znajdziesz tutaj

W effective java jest następujący rozdział:

 Tworzenie i usuwanie obiektów (Creating and Destroying Objects)

Tworzenie statycznych metod factory zamiast konstruktorów
(Consider static factory methods instead of constructors)

Najczęściej znaną techniką na udostępnienie egzemplarza danej klasy jest utworzenie publicznego konstruktora. Metoda ta sprawdza się doskonale kiedy konstruktor zawiera max do dwóch parametrów.
Inna metodą stworzenia obiektu jest wykorzystanie statycznej metody factory występująca też pod inną nazwą jak Creation Method.

Ważne jest też to aby nie mylić tych metod ze wzorcem Factory Method, ponieważ zadaniem tego wzorca jest generowanie obiektów różnych klas w oparciu o polimorfizm. Fabryka ta jako wzorzec nie może być metodą statyczną, a implementacje muszą znajdować się w co najmniej dwóch klasach.


Bardzo dobrym przykładem takiego zachowania jest : klasa Boolean
Zalety (wykorzystania creation method):

możliwość posiadania wymownej nazwy w stosunku do standardowych konstruktorów. Takie podejście sprawia, że powstały kod jest łatwiejszy do analizy.

-  nie musimy tworzyć nowego obiektu podczas ich wywołania. Dzięki czemu możemy tworzyć klasy niezmienne, korzystające z wstępnie tworzonych obiektów lub tak zarządzające procesem tworzenia, aby uniknąć duplikacji tworzenia obiektów.

- możliwość zwracania typu, który jest podtypem zdefiniowanego, zwracanego typu

- ograniczenie objętości tworzonych instancji typów parametryzowanych.

Jak rozpoznać takie metody albo jaką konwencję nazewniczą stosować :

valueOf - zwraca obiekt , który ma tę samą wartość co parametr

of - bardziej zwięzła alternatywa powyższego przykładu

getInstance - zwraca obiekt opisany przez parametr. Charakterystyczne podejście dla wzorca Singleton. Często stosowana konwencja przez dostawcę usług.

newInstance - podobna do powyższego, lecz gwarantuje za każdym razem inną instancję obiektu.

getType , newType - podobna do getInstance ale używana gdy metoda factory znajduje się w osobnej klasie.

Lombok pomoże stworzyć Ci metody na kształt Creation Method.
@RequiredArgsConstructor = creation method

Ok , ok ale co ze Springiem ?
W przypadku wykorzystania Java Config (to podejście bardzo polecam) problemu w ogóle nie ma. Używany swoich implementacji beanów poprzez użycie @Bean.
Dlaczego mamy stosować ten cały xml skoro piszemy w javie ?
Dlaczego mam pisać cały czas web.xml skoro kilka lat temu już dostępny jest standard servlet 3.0. (no chyba, że używam starego serwera aplikacyjnego czy też starego kontenera serwletów)

 Wady :
 - klasy nie posiadające publicznego lub zabezpieczonego konstruktora nie mogą być dziedziczone.

Problem : liczne parametry w konstruktorze.

Rozwiazanie 1 (właściwe):
 
Zastosowanie budowniczego do obsługi wielu parametrów konstruktora.
Metody factory oraz konstruktory mają jedne wspólne ograniczenie - słabo obsługują dużą liczbę parametrów.

Jak stworzyć swój własny builder : 
   - konstruktor powinien być prywatny co oznacza, że klient nie może bezpośrednio stworzyć obiektu klasy
   - klasa powinna być niezmienna
  - udostępnić statyczną metodę do budowy buildera np newInstance()
  - udostępnić metodę build() - która służy do budowy obiektu

TIP : Zawsze użyj buildera gdy projektujesz klasę, której liczba argumentów konstruktora czy statycznej metody factory przekraczała by liczbę kilku parametrów.

Generalnie wzorzec builder służy do uproszczenia tworzenie struktury obiektów,
ukrywając przez klientem prawdziwy proces budowy oraz jego implementacje.

Rozwiązanie 2:
Wzorzec konstruktora teleskopowego działa, ale dla klienta, który na wpisać ponad trzy, cztery i więcej parametrów. Ale jest to koszmar oraz zwiększa ryzyko popełnienia błędu.

Tip : Zobacz i zrozum jak działa HandlerMethodArgumentResolver + Pageable
(super fajne rozwiązanie zastosowane w Springu, pozwalające ograniczyć ilość przekazywanych argumentów. Możesz pisać swoje spersonalizowane rozwiązania. Opis zastosowania i przykład znajdziesz w tym poście)


Problem : liczne konstruktory 

Rozwiązanie: Zastąp konstruktory statycznymi metodami factory, których nazwy niosą informację o ich przeznaczeniu. Drugą zaletą tego rozwiązania jest brak ograniczeń konstruktora czyli możliwość definiowania dwóch różnych konstruktorów o takich samych typach i ilości argumentów.
Trzecią zaletą jest szybsza eliminacja niewykorzystywanego, martwego kodu z systemu.

Mechnika rozwiązania:
Zaczynamy od zdefiniowania konstruktora zbierającego (należy skorzystać z przekształcenia 'chain constructors'). Następnie konstruktory teleskopowe zamieniamy na creation methods (można wykorzystać przekształcenie inline method). Na koniec dostajemy jeden konstruktor o zakresie public i zbiór metod statycznych pomagających wytwarzać potrzebne typy obiektów.

Jeśli potrzebujesz stworzyć singleton pamiętaj aby użyć konstruktora prywatnego w celu uniemożliwienia stworzenie egzemplarza obiektu przez klienta. Obiekt pobieraj metodą getInstance().
Publiczne pola statyczne zawsze oznacz jako final. Aby umożliwić serializację klasy singleton nie wystarczy jedynie dodać interfejs Serializable. Musimy nadpisać jeszcze metodę readResolve. Jeśli tego nie uczynimy każda serializacja i deserializacja obiektu spowoduje utworzenie nowego egzemplarza klasy. Nie będzie więc już ona dłużej singletonem.

TIP : Najbardziej odpowiednim i jedynym właściwym rodzajem singletonu w javie  jest enum!!!

Jeśli budujesz klasy narzędziowe nie powinny one mieć możliwości tworzenia swojej własnej instancji. Należy zawsze zadeklarować konstruktor prywatny jako konstruktor domyślny.


Obiekty niezmienne to obiekty których stan po utworzeniu nie może ulec zmianie.

    Zalety :
     -  thread-safe - współdzielenie obiektów - problemy związane z wątkowością
     -  łatwe do stworzenia, przetestowania i użycia
     -  nie potrzebują konstruktora kopiującego
     -  nie potrzebują  implementacji metody clone     
     -  doskonale pasują się na klucze w kontenerach opartych na hashCode
     -  pozwala na bezpieczne przekazywanie argumentów ( przykład : String)
     -  lepiej zarządzana przez jvm i gc
  Jak stworzyć klasę finalną :
     - klasa nie może pozwalać na dziedziczenie czyli musi być finalna
     - wszystkie pola powinny być finalne
     - wszystkie pola powinny być prywatne
     - klasa nie powinna wystawiać setterów



TIP : Obiekt niezmienny to Twój przyjaciel - wykorzystaj go

 W powyższym przykładzie użyłem również biblioteki Lombok do stworzenia klasy niezmiennej. Wszystkie pola mam finalne i tworzone przez konstruktor
za pomocą adnotacji @RequiredArgsConstructor = creation method. Wszystkie zmienne mogę jedynie pobierać  a dostaje to dzięki właściwości @Getter. Dodałem jeszcze generowanie funkcji equals i hashCode wykorzystując @EqualsAndHashCode oraz @ToString aby nadpisać standardowy toString(). Co też jest dobrą praktyką.

Piszą w groovy tworzymy podobne struktury. Właśnie tak poprzez początkowe doświadczenia w Groovy jakieś dwa lata temu znalazłem bibliotekę Lombok.
Oba podejścia są bardzo fajne gdyż redukujemy niepotrzebne settery i gettery, które są w standardzie Java Bean i tak czy inaczej pisząc w javie musimy je w ten czy inny sposób zaimplementować.

Tip : @Cannonical@ToString , @EqualsAndHashCode i @TupleConstructor a to jest w prostej linii odpowiednikiem @Data w lomboku.

Co zaoferuje nam Guava ? - Object common methods
czyli :
  equals i hashCode :
Z wykorzystaniem guavy:

Z wykorzystaniem Lomboka:  
ale zaraz zaraz equals i hashCode z guavy ?....:)  - jeśli używasz  java 7 już to masz  - zgadza się :) Warto jednak mieć świadomość skąd to przyszło do javy 7.

Guava daje mam jeszcze :

 - toStringHelper

 - compare/compareTo

- comparisonChain

- kolekcje niezmienne, operacje  na kolekcjach i Stringach i wiele innych features, które Guavy opiszę  już w następnym poście.

Czego się dziś nauczyłeś ? - Sam odpowiedz sobie na to pytanie. Kilka lat temu pisałem system, który integrował się z innymi systemami za pomocą plików. Wszystko mogło wydawać się na pierwszy rzut oka ok. Najnowszy wtedy dostępny spring, hibernate oraz pozostałe biblioteki. Działały profile stworzone w mavenie. Podział na moduły i pakiety też wydawał się być ok i taki był.
Dlaczego więc z perspektywy czasu ten projekt uważam na jeden z najbardziej spieprzonych w moim życiu ? Bo był ciężki w utrzymaniu. Miał masę kodu, którego trzy lata potem już wyeliminowałem stosując wczesną wersję Lomboka i Guavę. Nie znałem wtedy jeszcze Camela. Cały kod związany z obsługą plików spoczywał na moich barkach, to samo ze scheduling'iem. Dalej doszła do tego konwersja formatów, obsługa błędów itd. Sporo rzeczy było poprawnie zrobione  dzięki zastosowaniu AOP. Ale problem utrzymania i czystości kodu pozostał. Jak jakiś czas temu włączyłem sonara i przeprowadziłem analizę kodu i ....to co pokazał ....porażka.
Dzięki zastosowaniu features z Guavy i Lomboka w kilka godz tak dla treningu poprawiałem statystyki w znaczący sposób. Ilość kodu zmniejszyła się o 34% .
Gdybym zastosował jeszcze wzorce EIP oparte na Apache Camel myślę, że zmniejszyłbym ilość kodu o następne 30-40%. A utrzymanie, elastyczność i inne metryki projektu na pewno znacznie by wzrosły.

Na koniec chce dodać, że jeśli używasz Spring, ORM  czy innego zrębu oprogramowania nie zwalnia Cię to z posiadania elementarnej wiedzy jak tworzyć i projektować obiekty.

Otwórz się na nowe języki oparte na JVM : Groovy i Scale wiele rzeczy można zrobić tam prościej.

Kod basic_entity znajdziecie tutaj.

dalej