Statyczne kolekcje? Jak ogarnąć niewielkie struktory danych wykorzystywane w wielu miejscach aplikacji?

0

Programuję amatorsko, uczę się powoli w wolnych chwilach od nieco ponad 2 lat.
Mam mniej więcej ogarnięte kwestie czystości kodu, wzorców projektowych, ogarniam Spring Boota i główne elementy Springa. Ogarniam też podstawy Androida.

Coraz bardziej ciśnie mnie jednak brak wiedzy nad tym jak prawidłowo konstruować architekturę aplikacji. Niby tak by moduły było odpowiednio odseparowane od siebie i komunikujące się między sobą interfejsami. W prostych aplikacjach sieciowych Springa podział ten wychodzi niemal automatycznie, ale gdy logika biznesowa jest rozbudowana to w niej też czuję wewnętrzną potrzebę większego uporządkowania i nie bardzo wiem jak to robić. W książkach niewiele znalazłem na ten temat (może złe czytam), w przykładach, tutorialach zwykle wszystko jest zbyt proste by przedstawiać problemy architektury aplikacji. Niestety nie znam też nikogo kto mógłby mi od ręki pomóc (w efekcie czasem utykam na miesiąc nad czymś co potem wydaje mi się tak proste, że jestem pewien iż komuś innemu wyjaśniłbym to w 10minut).

Najczęściej jednak spotykam się z problemem w którym potrzebuję dostępu w wielu miejscach aplikacji do tych samych prostych struktur danych. Jeśli ich rozmiar to mniej niż 1MB to nie widzę sensu zaprzęgania do tego baz danych. Ciągłe przekazywanie referencji pomiędzy wielu klasami do tych samych kolekcji nie wydaje mi się eleganckim rozwiązaniem. Ale jaka jest alternatywa? Czy uzasadnione w takich przypadkach jest tworzenie dla takich małych struktur danych kolekcji w polach statycznych? Czytam, że w Androidzie wielu tak robi?
Jak powinno się prawidłowo korzystać z małych struktur danych w architekturze aplikacji?
Z góry dzięki za pomoc i sorry za długi opis.

1

No więc metoda powinna korzystać z argumentów i pól obiektu (napisałem klasy, ale to było wieloznaczne).
Unikaj static jak ognia.

Jeśli korzysta z jakiś statycznych elementów/ przekazywanych przez bazę / thread local itp... to katastrofa.
Zaskakujesz przyszłego czytającego kod. W szczególności w Springu czasem niektórzy stosują obiekty RequestScope, gdzie trzyma się dane kontekstowe ( i wstrzykuje ten kontekst gdzie popadnie) . To jedna z gorszych pułapek jaką można zostawić kolegom, który w przyszłości będą kod poprawiać.

0

No właśnie zdaje sobie sprawę, że statycznie przechowywane dane nie są dobrym rozwiązaniem, ale widziałem je w aplikacjach androidowych.

Czyli prawidłowo taki pakiet danych po prostu mozolnie przekazywać pomiędzy obiektami ? (standardowo jako argument, setery, getery itp)?
Ktoś mi kiedyś sugerował by takie pakiety danych podręcznych wydzielić do odrębnych klas. Ma to sens ?

2

Do osobnych klas. Dokładnie. Wtedy przestaje być to męczące. Tylko nie zrób sobie klasy - IHaveEverything.java

Argument. Setery i Getery - najlepiej jednak nie.
W szczególności:

calc.setParam1( 7);
calc.setParam2( 6);
calc.setOperation(OP.MULT);
calc.calculate();

jest gorsze od:

calc.calculate( 6,7, OP.MULT);

albo

new Calculator(6,7,OP.MULT).calculate();

Głowny problem z seterami jest taki, że ktoś może zapomnieć ustawić... a drugi to jak działają w środowisku wielowątkowym.

1

A bezpośredni dostęp do pól bez g/s jak działa w środowisku wielowątkowym? ^^

Jeżeli masz klasy które "coś robią" czyli DAO, controllery itp to najlepiej wstrzykiwac inne zależności przez konstruktor z użyciem kontenera, a pojemniki na obiekty czyli takie obiekty jak DTO czy encje mozna stosować z g/s i polecam Lomboka do tego

0

W środowisku wielowątkowym przekazuje się niemutowalne obiekty i wtedy jest git. (Stąd cała idea actor model).

0

Ale co jeśli chcesz przekazywać między soba mutowalne obiekty?
Załózmy masz aplikacje do otwarzania muzyki, masz konfiguracje do Lastfm. W jednym wątku obiekt z konfiguracją edytujesz(tzn. np. ustawiasz nowy login) a w 2 czytasz przy wysyłaniu danych RESTem -> jak byś to zrobił?
Akurat IMO gettery i settery są całkiem niezłe do takich obiektów mutowalnych, bo możes użyć https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html

0
  1. Poczytaj./ pooglądaj o Actorach. Aktor != wątek.

  2. A przykład dokładnie dobrze pasuje. (pomijając to nieszczęsne słowo wątek).
    generalnie mutujesz obiekt lokalnie w Actorze - a potem wysyłasz drugiemu wynik niemutowalny.

2a. Nawet jak nie mam actorów to używam wtedy AtomicReference albo volatile i też jest git - nie musze komplikować kodu przez ReentrantLock.
Zmiana jest atomowa i jasna.

3 .Co ciekawe w JavaScrypcie WebWorkery działają też na tej zasadzie jak actorzy. (A jak wiadomo w JS wszystko jest idealne :P).

0

Samo volatile nie zapewnia bezpieczeństwa, ale z tym AtomicReference to już nie głupi pomysł ;)

0

volatile na niemutowalnym obiekcie i AtomicReferencje są prawie równoważne. Prawie bo AtomicReference daje ci kilka dodatkowych metod. volatile problemu nie ma -chyba, że wiesz o czymś o czym ja nie wiem. (chodzi o jedno! volatile - gdzie jeden zapisuje reszta czyta ).

0

Dzięki za pomoc. Dowiedziałem się więcej niż liczyłem ;)
Chyba trafiłem na dobre forum ;)

0

Pytałem o statyczne kolekcje, ale tak czytając co piszecie. Myślę jak ma się to do zachęty do tworzenia statycznych metod factory z książki "Effective Java" ?
Zeresztą Java w swoich standardowych bibliotekach też ma sporo metod statycznych.

0

Statyczne utile nie są złe, o ile są bardzo prostymi narzędziowymi wrapperami które nie wymagają izolowania do testów. Jakiś StringUtil do cięcia stringa czy Collections.emptyList() są dobrymi przykładami. Ale jak chcesz pakować logikę biznesową w takiego utila to robi się problem, bo potem jak testować kod który korzysta z kupy tych utilsów? Mockować jest trudno (jak na własnym kodzie musisz używać powermocka to znaczy że jest źle...), a bez mockowania to najwyżej zrobisz test integracyjny połowy systemu za jednym razem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1