Jak żyć bez singeltona?

0

Witam.
Jak w dużych projektach dajecie rade nie popaść w paranoje?
Posiadam główną klasę a w niej dostęp do klasy jakże super nazwanej Database a w niej kolekcje z mongodb.
Następnie mam obiekt A w którym jest trzymany obiekt B w którym trzymany jest obiekt C.
I teraz chcąc mieć dostęp z klasy C -> Database muszę wykonać getB().getA(),getMain().getDatabase();
Wygląda to dziwnie ale co ja mogę zrobić?

2

poczytaj o regule TDA (Tell, don't ask)
nie powinieneś "pytać" o obiekt B, z niego o A, z niego o Main i z niego o Database, a raczej "powiedzieć" obiektowi B żeby coś zapisał, ten może to samo oddelegować do A itd. Generalnie nie powinno Cię interesować jak "B" to zrobi a implementacja może się łatwo zmienić w czasie.

Jeśli chcesz zrezygnować z singletonów to żeby nie popaść w paranoje musisz mieć jakiś mechanizm dependency injection... nie wyobrażam sobie zrezygnować ze staticów, singletonów, dependency injection i service locatora w tym samym czasie - potrzebujesz co najmniej jednego z tych mechanizmów i sugeruję postawić na DI

2

Jest coś takiego jak konstruktor. A jesli potrzebujesz wywołac getB() getC() itd to masz jakiś dziwny projekt, bo obiektów się używa do zrobienia rzeczy np. wczytaj dane z bazy danych, wyślij emaila, itp

1

Zgadzam się z poprzednikiem - problem polega na tym, że trzeba powiedzieć coś więcej o obiekcie C. Co to za gość?
Wtedy można powidzieć jakie jest rozwiązanie.
Sugerowane wcześniej DI jest często dobrym rozwiązaniem - z tym, że wbrew temu co większość javowców myśli, nie potrzeba do tego żadnych frameworków - wystarczą konstruktory.
(choć w kotlinie ładniej to troche wygląda).

2

I teraz chcąc mieć dostęp z klasy C -> Database muszę wykonać getB().getA(),getMain().getDatabase();

Albo przekazujesz do klasy C obiekt Database, jeśli koniecznie faktycznie go tam potrzebujesz (np. przez konstruktor), albo jw. delegujesz wywołania. Kod musi operować na odpowiednich poziomach abstrakcji. Na poziomie jakiejś biznesowej operacji często wcale nie chcesz wiedzieć ze tam pod spodem jest jakaś baza danych. Chcesz np. pobrać wszystkie raporty z ostatniego tygodnia. Skąd te raporty idą jest zupełnie nie istotne. Tak samo nie interesuje cię jak na podstawie tabel w bazie powstanie ta lista obiektów Raport. Ty chcesz operować jakims biznesowym repozytorium i zrobić List<Raport> raports = raportRepository.getLastWeekRaports();

0
MarekMareckiPL napisał(a):

Jak w dużych projektach dajecie rade nie popaść w paranoje?

Ja tam po prostu nie jestem fanatykiem kodowania, i jak widzę g*wno kod, to po prostu go ignoruję, robię swoje i idę dalej :D nie zamartwiam się tym - nie mam ambicji ratować świata

0

Dobra panowie wróciłem.
Mam stworzona jakąś tam główną klasę, w niej trzymam zmienną od konfiguracji, następnie mam moduł, który służy do ładowania/przetwarzania użytkowników, więc w tym module trzymam zmienne do klasy od wykonywania bazodanowych rzeczy, dodatkowo posiadam klasę do przetrzymywania załadowanych użytkowników.
Teraz skoro posiadam takie ułożenie i potrzebuje w prawie każdej klasie odnośnik do pobierania konfiguracji to dodać odnośnik w głównej klasie modułu i do niej za każdym razem gdy chce pobrać coś z configu się odnosić czy lepiej dodać odniesienie do tych wszystkich klas gdzie w wielu metodach potrzebuje użyć tej konfiguracji.

1
MarekMareckiPL napisał(a):

Teraz skoro posiadam takie ułożenie i potrzebuje w prawie każdej klasie odnośnik do pobierania konfiguracji to dodać odnośnik w głównej klasie modułu i do niej za każdym razem gdy chce pobrać coś z configu się odnosić czy lepiej dodać odniesienie do tych wszystkich klas gdzie w wielu metodach potrzebuje użyć tej konfiguracji.

Musisz sobie zadać jedno, ale to za to bardzo ważne pytanie: czy te klasy zależą od tej klasy czy od konfiguracji? A potem zacznij to robić.

W ogóle błąd już masz w pierwszym zdaniu - nie powinno istnieć coś takiego jak "główna klasa"

1
MarekMareckiPL napisał(a):

I teraz chcąc mieć dostęp z klasy C -> Database muszę wykonać getB().getA().getMain().getDatabase();

Takie coś to ma swoją nazwę: Train wreck
i nie powinno się pojawiać w kodzie.
Zauważ, że te wyrażenie powoduje, iż bieżąca klasa ma zależność do kolejnych klas użytych podczas kolejnych wywołań, co jest niepożądane.

Polecam przeczytać "Clean Code" Robert C Martin.

Zresztą sama metoda getDatabase jest dowodem na to, że masz architekturę postawioną bazo-centrycznie, co jest klasycznym błędem architektonicznym.
W centrum ma być coś, co obsługuję logikę biznesową, a baza danych ma być tylko pluginem do tej logiki.

0

Teraz skoro posiadam takie ułożenie i potrzebuje w prawie każdej klasie odnośnik do pobierania konfiguracji to dodać odnośnik w głównej klasie modułu i do niej za każdym razem gdy chce pobrać coś z configu się odnosić czy lepiej dodać odniesienie do tych wszystkich klas gdzie w wielu metodach potrzebuje użyć tej konfiguracji.

Ani jedno ani drugie. Tworząc te obiekty domenowe używasz danych z konfiguracji i tyle. Odnośnik do obiektu który trzyma konfiguracje to jest potrzebny tylko gdzieś gdzie tą konfiguracje zmieniasz, albo jak chcesz mieć dostęp do "aktualnej" konfiguracji która może się zmieniać. Jeśli twoja konfiguracja jest statyczna, ustalana przy starcie, to nigdzie jej nie potrzebujesz.

0

Dla przykładu:

  • moduł:
    • klasa bazodanowa
    • klasa trzymająca dane w pamięci(jeśli są potrzebne oczywiście)

Wtedy gdy np chce by załadowano jakieś dane to moduł powinien otrzymać dane od klasy bazodanowej i wrzucić je w klasę "trzymającą".
Dobrze mi zaświeciło?

1

A po co to trzymasz w pamięci? Chodzi o cache? Ja bym w tym przypadku zrobił repozytorium / klasę bazodanową i można to zwyczajnie opakować w dekorator keszujący który w miarę potrzeby zwróci obiekty albo z pamięci albo odwoła się do bazy
Jakiś przykład znaleziony na szybko w necie: http://www.beabetterdeveloper.com/2013/03/wanna-cache-decorate.html
Opakowaniem w cache może zająć się kontener DI, możesz też zrobić interceptor uaktywniany adnotacją i rozszerzyć tę logikę na inne obiekty.

Wszystko zależy od potrzeb. Najlepiej jakbyś dał kod całej aplikacji do review tutaj i na pewno posypie się tysiąc komentarzy jak to można zrobić na milion sposobów.

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