Shalom
2017-10-10 22:42

Dzisiaj mały rant na "magię" a w sumie może bardziej na jakiś taki cargo cult i bezmyślne używanie rzeczy, ktorych się nie rozumie.

Jestem juz przyzwyczajony że co jakiś czas ktoś z temu prosi mnie o pomoc w zdebugowaniu jakiegoś problemu z serii przeciez to niemożliwe, java się zepsuła!!11.
Tak też było i dziś. Jedna osoba stawiała sobie środowisko do pracy nad jakimś nowym modułem i potrzebowała setup trochę mniej typowy niż u innych. Sam projekt generalnie jest upchany do granic możliwości rozwiązaniami z serii hype driven development i @jarekr000000 dostałby pewnie zawału ;) Niestety jest to jednocześnie tak zrobione, że rekord postawienia tego lokalnie u developera wynosi jakieś 2 dni... Sugerowałem nawet, żeby następnym razem ktos po prostu zrobił VMkę z gotowym środowiskiem, no ale nie mam "mocy sprawczej" więc bawią się dalej :D

Wracając do tematu, odbywała się dziś (tzn już pewnie od wczoraj jak nie dłużej) próba kolejnego setupu i pojawił się problem nie do przejścia -> w trakcie startu aplikacji leci wyjątek z JMSa że nie da się połącyć do jakiejśtam kolejki o podanym URLu. Niby nic wiekiego, niemniej to jest aplikacja z pluginami i nie do końca wiadomo kto i gdzie te JMSa próbuje postawić i skąd bierze adres. Adres pewnie z propertisów, ale tych jak sie dorzuci pluginy jest trochę, no ale nic, grepujemy sobie po nich i nie ma tego adresu który szukamy. Po drodze wyszło jeszcze trochę potencjalnych baboli w konfiguracji więc poprawiamy, no ale czas wrócić do tego JMSa. Pomyślałem nawet, że może gdzieś ktoś na lewo coś dorzuca do jara, więc rozpakowałem i sprawdziłem tam no i nadal nic.

Przy okazji miałem pokaz "permutation driven development", bo zanim zostałem wezwany do pomocy to już pewne desperackie próby zostały podjętę. Pliki properties były powrzucane w każde możliwe miejsce w strukturze projektu i musiałem poświęcić kilka minut na wyjaśnienie, że nie ma sensu, bo tylko te z src/main/resources będą brane pod uwagę. Musiałem też co jakiś czas stopować genialne pomysły z serii zmieńmy tutaj to property i przebudujmy projekt!, kiedy ewidentnie widać że nijak nie ma to związku z naszym problemem.

No więc czas jednak użyć debugera i zobaczyć co tam się generalnie dzieje. A tu niestety kłody pod nogi. Ten JMS to oczywiście startuje oczywiście z jakiegoś Springowego beana, na podstawie 7 krotnie powstrzykiwanych obiektów a na koniec wstrzykniętych properties. Istniała też szansa że może ta wartość jest gdzieś "w kodzie" ustawiana setterem - no to można by się breakować tam. A tu niestety Lombok :D Dobrze że IntelliJ dekompiluje klasy w locie i pozwala postawić breakpointy w tym zdekompilowanym bajtkodzie, który już ma te dodane lombokiem konstruktory i metody. Debuger potwierdza że faktycznie property jest ewidentnie z jakiegoś wstrzyknięcia, więc wskakujemy sobie w property resolver i patrzymy co za propertisy Spring sobie znalazł. Jest ich tam trochę, ale po chwili trafiamy na "winnego". Jest on o tyle dziwny, że to nie jest plik z classpath, tylko... URL! Moja pierwsza myśl jest taka, że ktoś sprytnie zrobił sobie property które przechowuje URLa do innych property i się to tak sprytnie rekurencyjnie ładuje. Powtarzamy więc sesje grepowania, szukając teraz już nie naszego JMSowego endpointa (tego który nie działał na samym początku), tylko szukając URLa do tych lewych propertisów i znów nic. Nauczony doświadczeniem sprawdziłem na wszelki wypadek czy springowy property resolver gdzieś tego nie widzi wśród załadowych propertisów, ale też nie!

Przyszło mi wtedy do głowy, że cudów tutaj nie ma, skoro nie ma tego w kodzie ani w properties ani w jarze, to jedyna możliwość, która pozostaje, to oczywiście parametry wywołania programu, które oczywiście też są automatycznie obsługiwane przez Spinga. Otwieram "run configuration" i widzę tam już znajomy URL do rypniętych properties... Myśle że moja mina to było klasyczne szok, niedowierzanie i tysiące pytań bez odpowiedzi. Pytam więc grzecznie WTF?! Jak się okazuje parametry zostały dodane zupełnie bezmyślnie bo tak było w developer's guidzie i bez jakiejś refleksji nad tym do czego one służą i czy nie należy ich jakoś zmodyfikować. Usuwamy parametr, wszystko startuje od kopa. Kurtyna.

#dailywtf #magic #ihavenoideawhatimdoing #java

jarekr000000

Tutaj w sumie nie było zrypki typowo Springowej... może poza tym, że lata pracy w tym powodują, że nie masz już zaufania do niczego i szukasz w każdym kącie zamiast iść drogą naprawdę prostej eliminacji :-) Cargo cult i copy paste z guide :-) -> jakże to klasyczne. Dla pełni szczęścia powinieneś jeszcze usłyszeć - "nie usuwaj tego, bo z tym zawsze działało".

jarekr000000

A co do zawału, to chyba nie wiesz w jakich kupach się grzebałem (zresztą, nadal się grzebie - jest podejrzenie, że to nawet lubię). 2 dni na postawienie środowiska nie robi żadnego wrażenia. W poprzedniej firmie było 2-3 i na koniec było środowisko, kóre czasem, bywa że działało. Podobno w ogóle byłem pierwszy któremu udało się na jednym kompie odpalić wszystkie serwery... wcześniej ludzie dzielili sie praca w zależności co komu udało się odpalić.... . Po roku zjechaliśmy z czasem stawiania do mniej więcej godziny (ale dużo osób nad tym pracowało).

scibi92

Dla mnie trochę słaby jest pod tym względem Spring Boot. O ile "zwykły" Spring polegał na tym że się dużo konfiguruje samemu i tak trzeba się troche rozpisać to jak się wie z czego się korzysta i to się miarę rozumie (dynamic proxy, etc) to generalnie działa, a jak ostatnio uruchamiełem Spring Boota z magiczną autokonfiguracją to mialem różne głupie blędy przez które wiecej straciłem czasu niż jakbym sam konfigurował...

Shalom

@scibi92: z drugiej strony jak chcesz zrobić rapid application development jakiegoś prostego CRUDa to dodajesz kilka modułów do poma i "samo się robi" ;) Tylko że trzeba nadal rozumieć co i dlaczego się dzieje.

scibi92

No tak, ale trzeba się przyzwyczaić ;) Jak już się napisze taką aplikacje to wtedy człowiek wie gdzie się magia może wywalić ;)

Desu

@jarekr000000: "wcześniej ludzie dzielili sie praca w zależności co komu udało się odpalić" wtf :D Wiele jeszcze przede mną...

jarekr000000

@Desu - to było żalosne, a nie śmieszne. Żeby było ciekawiej deploy i testy automatyczne aplikacji były całkiem dobrze zautomatyzowane - dostawienie kolejnych serwerów (nowe nody w klastrze ) robiło się "jednym palcem". Tylko środowisko developerskie to był dramat.

jarekr000000

@Shalom: @scibi92 co do magii to problem polega na tym - w ile miejsc musisz zajrzeć jeśli coś nie działa. Normalnie masz funkcję, jest input - output. Jak jest inny to masz parę linijek i problem jest "osaczony". Aspekty, kontenery itp. powdują, że gdzieś tam dopisany przez kolegę aspekt, może Ci zrypać kod w zupełnie innym module i nawet nie zobaczysz związku. Btw. nie wiem o co wam chodzi ze SpringBootem - jak już mam springa, wolę w tej wersji - przynajmniej odpada problem classloaderów (nie do końca, bo tomcatowe są, ale nadal to lepiej niż z warem).

Shalom

@jarekr000000: Mnie tam bardziej denerwują te wszystkie "kody generowane w locie/w trakcie kompilacji" czyli rzeczy w stylu Lombok czy Spring Data. Bo wszystko spoko, kodu mniej i w ogóle, ale tylko do czasu kiedy chciałbyś coś debugować i nagle nie ma gdzie postawic breakpointa. Pisałem jakiś czas temu jak skądś przychodziły nam dziwne zmiany w bazie danych i pierwsza myśl to dać breakpointy w repozytorium i zobaczyć skąd idą wywołania, a tu niestety nic z tego bo w kodzie mamy tylko interfejs do któego Spring Data generuje implementacje automatycznie ;)
Ja do Boota nic nie mam, o ile wszyscy rozumieją jak on działa i co robi.

jarekr000000

@Shalom - z punktu widzenia "dogenerowania" kodu SpringBoot ma coś więcej niż w zwykłym Springu można? Jeśli tak to kompletnie mi umknęło - dla mnie to zawsze (Auto)Config+ Start z main jeno.

karolinaa

że rekord postawienia tego lokalnie u developera wynosi jakieś 2 dni... to długo? ja stawiałam kiedyś tydzień środowisko , bo dostępy były h**** do nexusa i co chwila coś nie działało

karolinaa

czytam dalszą część opowieści Musiałem też co jakiś czas stopować genialne pomysły z serii zmieńmy tutaj to property i przebudujmy projekt!, kiedy ewidentnie widać że nijak nie ma to związku z naszym problemem.. czy tam są studenci czy jak? jak NASA albo ESA może taki poziom reprezentować!

karolinaa

Dobrze że IntelliJ dekompiluje klasy w locie i pozwala postawić breakpointy w tym zdekompilowanym bajtkodzie, który już ma te dodane lombokiem konstruktory i metody. dobrze wiedzieć

jarekr000000

@karolinaa: to jest jedno ze zdziwień, które odkrywa się jak się przestaje być juniorem. W bankach, medycynie, telekomunikacji, lotnictwie... pracują programiści tacy jak my. Trochę strach, co nie?

lukas_gab

Hmmm, a nie lepiej zrobić skrypt co stawia środowisko? Jak już nie skrypt, to może chociaż Vagranta? Przecież to jawne palenie godzin, no ale może o to chodzi w korpo ;)

karolinaa

Jak się okazuje parametry zostały dodane zupełnie bezmyślnie bo tak było w developer's guidzie i bez jakiejś refleksji nad tym do czego one służą i czy nie należy ich jakoś zmodyfikować. Usuwamy parametr, wszystko startuje od kopa. Kurtyna. no wydaje mi się, że 99% osób zrobiło by tak samo. jak aplikacje się uruchamia inaczej niż przysłowowie gradle bootRun i wymaga guida na confluence to chyba normalne, że człowiek zakłada, że guide jest napisany poprawnie i można mu ufać. co to za guide, który wprowadza w błąd.
na moje to nie wina tego gościa, że bezmyślnie to dodał tylko skopanego sposobu uruchamiania, ale o tym wspomniałeś już na początku

jarekr000000

@lukas_gab: w wielu korpo jest ten problem, że wywalczenie Vagranta czy czegokolwiek na komputerze developerskim zajmuje 18 miesięcy.

Shalom

@jarekr000000: Nie, nie ma tam nic więcej poza tym co da się zrobić "normalnie".
@karolinaa: Nie wiem czy długo, ale w moich projektach (tzn tych za które jestem odpowiedzialny) robi sie git clone + mvn install i wszystko działa. Co do studentów to tych jest oczywiście sporo, u mnie w sekcji 3/15 a w wakacje jeszcze więcej.
Trochę sie nie zgodzę że to wina guida. Bo nawet jak jest guide to należy go czytać ze zrozumieniem a nie kopiować z niego losowe snippety. Jak guide mówi że masz gdzieś ustawić adres do bazy danych a ty zostawisz default to możesz być tylko sobie winna ;)
@lukas_gab: tożto wspomniałem we wpisie, że sugerowałem już żeby tak zrobili, zeby następna osoba przygotowała jakieś wirtualne środowisko skoro tak ciężko to idzie, ale grochem o ścianę.

karolinaa

wgle sposób uruchamiania aplikacji / środowiska to dosyć ważna rzecz. bo przychodzi taka nowa osoba do projektu i traci tydzień na uruchomienie aplikacji na jakieś dziwne rzeczy to aż sie odechciewa. dla odmiany gdy jest proste git clone, mvn install, gradle bootRun i docker-compose up i wszystko trwa mniej niż godzinę to aż wow i chce sie pracować. ale to chyba rzadkość jest

jarekr000000

@karolinaa: albo jeszcze gorzej, zrobisz jakiś mały eksperyment i Ci się środowisko rozlatuje. Jak nie masz szybkiego odtworzenia, to tracisz czasem dni na przywrócenie do życia.... zamiast 10 minut na kill, erase and install again. To dopiero niszczy. Nie mówiąc o tym, że ludzie przestają chcieć eksperymentować...

lukas_gab

Guide i wszelakie dokumentacja mają taki problem, że jak się napiszą, to potem już nikt tego nie utrzymuje. Jednak to powinien być jakiś skrypt, albo konfiguracja na vagrancie i jakiś Jenkins powinien z tego stawiać co noc srodowisko i testować. Jak się nie uda postawić srodowiska to powinno to byc traktowane, jak wysypanie testów i skrypt stawiający do poprawki. No, ale przyznam - denerwujące, i współczuję. Sam już wiele razy stawiałem takie złożone środowiska devowe, ale to jeszcze z jakimiś serwerami w c++ i delphi, część nowego stufu, komunikacja via tcp, http - jednym słowem nic przyjemnego.

Koziołek

@karolinaa: właśnie pracuję nad taką standaryzacją w nowej firmie. Docelowo ma to wyglądać tak, że bazę danych wraz z JMSem odpalamy w kontenerach, a główna apka chodzi na hoście. Rzecz w tym, że nikt nie wiem jak prawidłowo skonfigurować apkę. Nawet najdłużej pracujący w projekcie nie wiedzą jak to zrobić...

vpiotr

@Shalom: witaj w swiecie korpo-flag. Ja takie bzdety robie na codzien.