Na wstępie chciałbym powiedzieć, że będę wdzięczny za jakikolwiek odzew.
Planuję porzucić mój projekt który pisałem "jakiś czas", jednocześnie ucząc się Springa oraz testowania. Problem pojawił się w chwili, gdy zaczęło dochodzić do refactoringu oraz pisania testów, ponieważ nie skończyłem ani jednego z modułów, a miałem już ogólny zarys aplikacji (począwszy od logowania, przechodząc przez jakąś logikę czy jakieś walidacje pól). Zmienne, metody nazywałem niepoprawnie, ze strony gita - wszystko szło na jednym branchu i wiele więcej niepoprawnych rozwiązań. Toteż postanowiłem, poprosić Was o code-review (wytykanie błędów mile widziane), a jednocześnie mam kilka pytań:
1.Zmienne Sesyjne - jeżeli w aplikacji planujemy mieć system logowania (tak jak u mnie), to czy sposób z utworzeniem komponentu np SessionVariables o zasięgu @SessionScope i w każdym miejscu (panel użytkownika - UserService, dodawanie ofert kupna danej rzeczy np kryptowaluty jak na giełdzie https://www.binance.com/en/trade/ETH_BTC - CryptoCurrencyService) utworzyć obiekt tej klasy jako pole (wcześniej wspomnianego UserService czy CryptoCurrencyService) jest poprawny? Potem w sytuacji, gdybyśmy chcieli dodać ofertę wystarczyłoby:
sessionVariables.getLoggedUser().addOffer(offer);
Minusem czegoś takiego jest, mieszanie domeny Użytkownika z Kryptowalutą.
2. Mamy dwa serwisy: FooService i BooService. Co w sytuacji, gdy Foo i Boo są zupełnie innymi (tzn Foo i Boo są osobnymi agregatami [o ile dobrze zrozumiałem czym są agregaty]) klasami @Entity, więc w FooService powinno być np. FooRepository a w BooService - BooRepository. Chciałbym wykorzystać obiekt klasy Boo pobierając go z bazy danych w FooService? Czy utworzenie BooRepository w FooService jest błędem (ze względu na czystość kodu)? Jeżeli nie, to jak uzyskać komunikację serwisów? Jak sprawić, żeby FooService "poprosiło" BooService, żeby ten "poprosił" BooRepository żeby pobrał coś z bazy danych?
3. Jak testować, czy dwie zmienne double są sobie równe? Assert.assertEquals(double,double,epsilon) jest chyba przestarzałe, ale czy przy założeniu, że podczas testu np, pomimo tego, że te dwie zmienne są double są tak naprawdę całkowite (+- epsilon maszynowy) i wzięciu epsilon na tyle dużego, żeby wyeliminować błąd ale na tyle małego, żeby nie zakłamać wyniku (np 0.1) można używać assertEquals, czy jest jakaś alternatywa do tego?
4. Korzystam z thymeleafu, nie znam się na js a thymyleaf w zupełności mi wystarcza żeby sprawdzić ręcznie czy coś działa, jaki powinien być zwracany typ w kontrolerach? O ile wiem, że można zwrócić zwykłego Stringa, który przedstawia nazwę template'ki o tyle nie podoba mi się, że za każdym razem zwracam zwykłego Stringa.
5. Kontroler nie powinien mieć żadnej logiki. Czy takie coś w kontrolerze jest dopuszczalne, ze względu na czysty kod:
if(someCondition) return "u1";
else return "u2";
- Walidacja za pomocą setterów. Czy jest poprawna? Np w sytuacji gdy byśmy chcieli dopuścić, żeby imię użytkownika miało określony wzorzec. Jeżeli nie będzie - rzucenie wyjątkiem. Plus jest taki, że pozostali programiści nie muszą wiedzieć, czy jest jakaś dodatkowa klasa która pełni rolę walidatora (czy pośrednika), mamy walidację gdy w bazie danych będą złe dane (używając jakiegoś Hibernate czy SpringData). Minusem jest to, że rzucamy wyjątek (słyszałem, że rzucanie wyjątkiem w sytuacji gdy dana sytuacja może się bardzo często powtarzać nie jest czymś dobrym). Kolejnym ciekawym rozwiązaniem wydaje się zrobienie konstruktora klasy @Entity protected i utworzeniem jakiejś np. fabryki w tym samym pakiecie która by się komunikowała z resztą aplikacji. Plus zmiana:
Foo foo = new Foo(); //w konstruktorze jakieś zmienne
// na
Optional<Foo> foo = fooFactory.createFoo(); //w konstruktorze jakieś zmienne
O tyle fajne z Optionalem jest to, że nie rzucamy wyjątkiem.
7. Czy używając embeded database w testach, jak np H2, trzeba tworzyć plik konfiguracyjny? Czy wystarczy w pliku pom (jeżeli korzystam z mavena) główną bazę danych dać scope = runtime, a H2 scope = test? Sprawdzałem, wywalając konfigurację głównej bazy danych podczas testowania i tak - testowy kontekst aplikacji wstawał gdy główny nie mógł, więc chyba wystarczy.
8. Wiem, że powinienem usunąć konfigurację DB z application.properties i przerzucić to do zmiennych środowiskowych.
9. https://github.com/KamLar/market-simulator <-- Tak jak mówiłem, jeśli ktoś ma czas i mógłby spojrzeć i oprócz tego co napisałem wytknąć jeszcze jakieś błędy, ciekawe rozwiązania będę wdzięczny.