Strona główna > Java > O testowaniu

O testowaniu

Ostatnio doświadczyłem jak pożytecznym narzędziem potrafią być testy. Chodzi o przypadek, w którym pomagają one skrócić czas, jaki jest pomiędzy zrodzenia się pomysłu, a wdrożeniem go i sprawdzenia czy jest dobry.

Warunki początkowe
Użycie JPA doprowadziło do pewnego problemu natury wydajnościowej (o szczegółach technicznych na końcu). No i aby temu zaradzić bawiłem się sprawdzając różne pomysły.
Proces przebiegał mniej wiece w ten sposób: wprowadzenie zmian w kodzie, wdrożenie aplikacji na serwer, sprawdzenie rozwiązania. Sprawdzenie polegało na: zaimportowaniu pliku poprzez klienta na serwer i sprawienie, aby dane z pliku, po uprzedniej obróbce, zostały zapisane do bazy. Problem dotyczył tego, że dla wyjątkowo dużych plików cały proces wczytywania do bazy potrafił trwać dobre ponad pół godziny😀. I to stanowiło przedmiotem moich dociekań, aby skrócić ten czas.

Początkowe próby
Okazało się nawet, że ten wyjątkowo długi proces potrafi się nie kończy. Zdarzało się że po około godzinie dostawałem wyjątek o braku pamięci.
Proce dochodzenia do rozwiązania był uciążliwy. Problematyczne nie było nawet to, że dość długo trwa wdrożenie pomysłu (około 5 minut i wymagało to kilka czynności do wykonania). Najbardziej deprymujące (czasochłonne) było już samo przerabianie pliku przez aplikacje.

Dlaczego testy wcześniej się nie pojawił?
Mogłem skrócić ten proces, poprze próbę zamknięcia całej sytuacji w standardowej strukturze testu (tu junit). W innych projektach zdarzało mi się już wykorzystywać podejście z lokalnym EntityManager_em. Polegało to na powołaniu do życia obiektów tylko określonych klas, a nie całej aplikacji (tu jest zgrabne pokazanie tej idei). Jednak w tym projekcie, z uwagi na dziwne zależności, nie jest to takie czyste – nie jest łatwe uczynienie testu przejrzystym i powtarzalnym.
To znaczy ja u siebie to uruchomię, ale na innej maszynie nie musi być to takie proste. Test w takiej formie nie mógłby być w przyszłości powtarzalną weryfikacją jakości kodu.
Tak więc to, że wprowadzenie tego nie było takie proste, powodowało to, że ociągałem się z użyciem testu w takiej formie. Jednak z czasem wyczerpałem wszystkie pomysły i nie miałem koncepcji jak ruszyć mój problem dalej. Postanowiłem wtedy wprowadzić chociaż test w tak ograniczonej formie. Nie miałem nic lepszego do zaproponowania🙂. No i po jakimś czasie byłem w stanie symulować tą samą sytuacje za pomocą testów. Czas wdrożenia zmiany skrócił się do paru sekund – ale i tak musiałem czekać pół godziny lub lepiej na wynik testu.

Sprzężenie zwrotne
Jednak wcześniejsze próby manualnego sprawdzania nie poszły na marne, miałem wtedy parę koncepcji. Wiedziałem też kiedy nie warto czekać, gdy widać że nie dział i test można przerwać (kolejny plus – byłem bardziej skłonny porzucić test, skoro wiedziałem że wdrożenie innego rozwiązania kosztuje mnie tak mało czasu). Mając już skrócony cykl wdrażania nowych zmian, mogłem testować różne dziwne rozwiązania, którym nie byłem skłonny wcześniej dać szansy. Dzięki temu wpadłem na właściwą drogę do obejścia problemu. Rozwiązaniem była kombinacja kilku pomysłów, które rozpatrywałem już wcześniej😉.

Wnioski
Przed wprowadzeniem testów zajmowałem się problemem około dwóch dnia, po wprowadzeniu testów wpadłem na właściwe rozwiązanie w pół dnia. Nie znaczy to, że tylko dzięki okresowi z testem udało mi się to zdziałać, wcześniej zdobyłem masę wiedzy, która w ostateczności okazała się użyteczna. Jednak skrócenie okres otrzymania zwrotnej odpowiedzi (czy dane podejście jest dobre czy nie) dało mi okazje przeszukanie o wiele większej populacji potencjalnych rozwiązań. Z wcześniejszym podejściem potrzebowałbym o wiele więcej czasu i samozaparcia aby się nie rozpraszać.
I na koniec wyznacznik sukcesu – proces, który trwał ponad godzinę i kończył się wyjątkiem, teraz wykonuje się poprawnie w 5 minut🙂, a więc prawie tyle, jeśli nie mniej, ile zajmowało mi wdrożenie zmian na samym początku.

Uwagi techniczne
Do zapisu dużej kolekcji przy użyciu JPA (tutaj potrafiło to być nawet do 20 tysięcy rekordów w jednej transakcji) pomocne było:

  • podział zapisu na paczki. Oparłem się na rozwiązaniu przedstawionym tutaj. Chociaż w moim przypadku nie potrzebne okazało się użycie parametru hibernate.jdbc.batch_size, wystarczyło użycie samego flush i clear.
  • zmniejszenie częstości zapytań o kolejny numer z sekwencji. W @SequenceGenerator zmiany w ustawieniu allocationSize. Tutaj sekwencja na bazie była zwiększana co 50, tak więc co tyle razy z JPA było pytanie o kolejną wartość, a potem przez 50 kolejnych zapisów wartość była zwiększana w javie.
  1. Brak komentarzy.
  1. No trackbacks yet.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d bloggers like this: