Wzorzec repozytorium. Kilka niepewności. Co zamiast

0

. A "programowaniem aspektowym" zapewne też nazywasz proxy nad Twoją klasą utworzone przez kontener IoC.

Tak spring tworzy proxy. Ale aspektowe jest przez to że celem klasy którą tworzenie nie jest zarządzanie transakcjami :
https://en.wikipedia.org/wiki/Aspect-oriented_programming

0
jarekr000000 napisał(a):

To nie robicie jak ludzie, ze jest po prostu jedna, dwie metody utilsowe, które jako parametr przyjmują funkcję do wykonania na DB (z argumentem w postaci sesji)?

Nie, bo ludzie tak nie robią. (Argumenty oparte na presupozycjach obalają się same.)

Jakby nie widzę zysku z tego. W kodzie swojego serwisu robię co potrzebuję na sesji i tyle, nie muszę niczego nikomu przekazywać. Lubię, jak jest prosto, te wszystkie "reużywalne" repozytoria i query objecty, szybko przestają być "reużywalne" i albo trzeba refaktoryzować, żeby było dobrze, albo dodawać ify, żeby było bardziej enterprise.

Nic nie trzeba rejestrować.

No ja też nie muszę, wszystko jest już zarejestrowane. (Taka zaleta posiadania konwencji zamiast konfigurowania IoC w XML.)

Żadnych aspektów/ procy cudów.

Z polimorfizmu jest taki cud jak z wizerunku Jezusa na toście.

Testowanie proste.

Wręcz banalne. Czy mock sesji, czy SQLite w pamięci, czy integracja - wszystko to jest proste.

scibi92 napisał(a):

Ale aspektowe jest przez to że celem klasy którą tworzenie nie jest zarządzanie transakcjami :

Nie no, masz rację... Ja po prostu nie lubię tego słowa, bo kojarzy mi się z powolnymi frameworkami, które robią cuda z wyjściowym kodem, żeby te swoje "aspekty" dodać.

0
somekind napisał(a):

Nic nie trzeba rejestrować.

No ja też nie muszę, wszystko jest już zarejestrowane. (Taka zaleta posiadania konwencji zamiast konfigurowania IoC w XML.)

Żadnych aspektów/ procy cudów.

Z polimorfizmu jest taki cud jak z wizerunku Jezusa na toście.

No bo jak masz po prostu prosty polimorfizm - to co się rejestruje? I po co ta konwencja?
Bo jeżeli masz coś działającego na "konwencji".. to chyba nie jest to prosty polimorfizm.

Może pokaż przykład.

0

Mniej więcej tak działają interceptory z IoC, że generują w locie proxy, które nadpisuje metody z klasy bazowej.
Rejestruje się klasy, żeby nie trzeba było ich tworzyć ręcznie tylko wyciągnąć sobie z kontenera.

0

No to jednak nie jest prosty polimorfizm. To samo w Javie jest w Spring/JavaEE. Zresztą też przez konwencję. Kiedyś wydawało mi się fajne.
Napisz mi ... a jak się ta transakcja jednak nie wystartuje (metody się nie nadpiszą) to gdzie stawiasz breakpointa, żeby się dowiedzieć dlaczego?

0

Jeśli metoda się nie nadpisze, to sprawdzę, czy jest wirtualna, czy klasa jest udekorowana atrybutem, i czy na pewno jest zarejestrowana w IoC. Ale to dość sztuczny przypadek - w sensie może się zdarzyć na początku projektu, kiedy jeszcze nie ma konfiguracji, ale nie nagle pewnego dnia. (No chyba, że ktoś nie oznaczy metody jako virtual itp., ale to są trywialne do naprawienia kwestie.)

0

Czyli całe piękno kontenerów.... To nie jest proste!

Wczoraj np. walczyłem po raz kolejny z Webspherem (javowy kontener JavaEE)- jeden z serwisów Rest nie startował transakcji w odpowiednim momencie i działał jakby nie był skonfigurowany annotacjami ( czyli dawniej XMLem obecnie wje...nym w kod).

Co się okazało - klasa implementująca nie deklarowała implementacji interfejsu bezpośrednio, tylko za pośrednictwem jakiejś klasy bazowej. Z punktu widzenia Javy to samo (jak dziedziczysz z klasy która implementuje interfejs to jest to przechodnie). Z punktu widzenia kontenera - pogubił się w skanowaniu klas i nie znalazł interfejsu (debil :-)) , a w nim były adnotacje konfigurujące. Kilka godzin w plecy, bo kto by na to wpadł.

Dlatego uważam , że dorośli programiści nie powinni się w to bawić. Jednak podejście z JOOQ - czyli ogólnie High order functions jest niezawodne. Żaden kontener się nie miesza i wszystko jest jasne w momencie kompilacji. Nie ma żadnych konwencji and konfiguracji.

W ogólności to takie rzeczy jak transakcje, security, monitoring itp. można by załatwiać przez Free Monad .. ale IMO w Javie nie może Free działać (mimo że jest taki projekt na githubie :-).

0
somekind napisał(a):

@scibi92: no ja nie mam Springa, więc po prostu rejestruję w kontenerze SessionFactory jako singletona, a Session per lifetime scope. Do tego mam zarejestrowany interceptor, który opakowuje wskazane (atrybutem) metody/klasy, i podczas ich wykonywania otwiera transakcje, wykonuje kod metody, potem zatwierdza transakcję (albo wycofuje jeśli poleciał wyjątek). Wewnątrz metody operuję po prostu na obiekcie session (Get/Load/Save/Delete/QueryOver), nie mam żadnych commitów, rollbacków, ani nawet try-catch.

@somekind: pokazałbyś jakiś przykład? Ponieważ jestem wspomnianym programistą który w każdej metodzie otwiera nową sesję ORMa i ma try-catch. Niemniej jednak nie płacą mi za linijki (ba, w ogóle nie płacą).

3
jarekr000000 napisał(a):

Czyli całe piękno kontenerów.... To nie jest proste!

Wczoraj np. walczyłem po raz kolejny z Webspherem (javowy kontener JavaEE)- jeden z serwisów Rest nie startował transakcji w odpowiednim momencie i działał jakby nie był skonfigurowany annotacjami ( czyli dawniej XMLem obecnie wje...nym w kod).

Co się okazało - klasa implementująca nie deklarowała implementacji interfejsu bezpośrednio, tylko za pośrednictwem jakiejś klasy bazowej. Z punktu widzenia Javy to samo (jak dziedziczysz z klasy która implementuje interfejs to jest to przechodnie). Z punktu widzenia kontenera - pogubił się w skanowaniu klas i nie znalazł interfejsu (debil :-)) , a w nim były adnotacje konfigurujące. Kilka godzin w plecy, bo kto by na to wpadł.

Ja nie mam Websphera, JavyEE ani upośledzonych kontenerów. Mam sprawdzone narzędzia, których używam w prosty sposób.

Dlatego uważam , że dorośli programiści nie powinni się w to bawić. Jednak podejście z JOOQ - czyli ogólnie High order functions jest niezawodne. Żaden kontener się nie miesza i wszystko jest jasne w momencie kompilacji. Nie ma żadnych konwencji and konfiguracji.

Nie mam JOOQ, ale też nie mam problemu ze swoim działającym rozwiązaniem. Nie mam copy-paste, w całym kodzie mam tylko jedno miejsce, w którym muszę podpiąć debugger, aby dowiedzieć się, czemu transakcja sie nie udała, a do tego ta sama transakcja jest użyta we wszystkich metodach używanych w danym UoW (co prawda nie przydaje się to często, ale skoro już mam to za darmo, to po co sobie upośledzać rozwiązanie).

Kontener IoC mam i tak, bo jestem zbyt leniwy, żeby go nie mieć, więc dodanie do niego paru dodatkowych ficzerów to dla mnie żaden wysiłek, a zyski są ogromne.
Moja "magia" działa. Setki linii kodu nawalone przez proceduralnych programistów, którzy chcą mieć wszystko jawnie napisane bez żadnej delegacji ani generycznych rozwiązań, zazwyczaj generują sporo błędów.

0

No ale dlaczego zamiast jakimś kontenerem i magią nie zrobić tego prosto?

//przykład uproszczony w składni javowej
TxManager{
  public <T> T  doInTx( Function1<DBSession, RESULT> dbCommand ) {
        DBSession session = openSession();
        try {
              session.beginTransaction();
              dbCommand.apply(session);
              session.getTransaction().commit();
        }
        catch (...) {
             session.getTransaction().rollback();
        }
    } 

}

i wtedy gdzie chcesz to siejesz:

TxManager.doInTx ( sess-> {
 sess.query("BL BLA JAKIS SQL");
... itd
}
1

@jarekr000000: bo jestem leniwy i nie chcę pisać w setkach miejsc TxManager.doInTx. W projekcie bez kontenera (albo z upośledzonym kontenerem, którego nie da się łatwo i stabilnie rozszerzać), to bym takiego helpera użył. Ale jak kontener mam, to korzystam z jego możliwości.

0

(to odnosi się do usuniętego postu @scibi92)

Co jest skomplikowanego w wywołaniu funkcji... kiedy cały kod twojego systemu jest podany explicit?
Naprawdę runtime magia na threadlocalach, proxy i nadpisywaniu bajtkodu jest prostsza? No bez żartów...

0

poza tym tak jest o wiele łatwiej. Jak będziesz łatwo współdzieli transakcje między obiektami biznesowymi itd?

EDIT:
A jak będziesz przenosić transakcje między obiektami logiki biznesowej

1

Nie jest trudne tylko czasochłonne. 10 linijek konfigurujących IoC to mniej roboty niż kilkaset wywołań new.

No i new działa tylko jeśli piszesz końcową aplikacje, jeśli piszesz frameworki to podejście nie zadziała.

0

Taki kod burzy podział na obiektyki odpowiedzialne za logikę i ORM

0

@somekind: a tak jeszcze wracając do tematu tego nieszczęsnego repozytorium. Załóżmy, że mam to repo zgodne z DDD, czyli jest to kolekcja obiektów domenowych. wykorzystywana podczas wykonywania jakiś operacji biznesowych.

Teraz potrzebuję wypluć na front jakieś dane ze stronicowaniem. Ponieważ samo ograniczanie wyników zapytania odbywa się w klasie, która zajmuje się tym stronicowaniem, to mam takie wyjścia:
a) Wrzucić wszystko do repozytorium, zamiast kolekcji/pojedynczego obiektu domenowego zwrócić paginator i mieć w dupie
b) Wrzucić wszystko do kontrolera i też mieć w dupie
c) Zwrócić z repozytorium zapytanie i utworzyć paginator w kontrolerze (albo nie z repozytorium tylko utworzyć jakiś QueryObject czy coś)
d) Utworzyć coś (co może ma jakąś nazwę, BlaBlaProvider?), co zwróci gotowy paginator (tak jak punkt a), tylko że nie robimy tego w repo).

Osobiście d) mi się najbardziej podoba. Czy taki obiekt, który zwraca dane tylko używane w widoku ma jakąś swoją nazwę (poza QueryCommand i QueryCommandHandler z CQRS).

0

Ja również wybieram opcję d. CQRS bym tu nie mieszał, bo to może działać bez tego podejścia.
Czy to ma jakąś inną nazwę? Pewnie nie, bo nazwy wymyśla enterprise, a to jest zbyt mądre i rozsądne, żeby było enterprise. :P

0

Ale dlaczego ty chcesz zwracać "paginator" który jest częścią Prezentacji albo Web z jakiegoś provaidera?.

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