Non-anemic entities

0

Generalnie jeżeli nie tylko usuwanie, ale wszystkie operacje dotyczące A dotyczą też B i C to bym połączył. Generalnie jak mysle o tym usuwaniu to jednak skłaniałbym się w kierunku jednego modułu i jednego agregatu, ale inna opcja to po prostu przy usunieciu A jest wysyłany event ADeleted i reszta nasłuchuje na te eventy. Jeżeli B i C będzie nasłuchiwac praktycznie na każdy event to imho wtedy powinien być jeden moduł

0

@hcubyc:

Encje z modułów B i C nie mogą żyć bez encji A. Przykładem niech będą moduły jak Samochód, Koła, Zawieszenie, Silnik. Każdy z tych modułów ma charakterystyczne dla siebie metody, ale te 3 ostatnie nie mogą być bez samochodu. Każdą encję z tych 3 ostatnich wyszukuję nie po jej własnym id tylko po id samochodu - one nie mają swojego niezależnego bytu w świecie.

Druga sprawa. AggrgatRoot jest identyfikowalny. Encja też. Czym one się różnią ?

0

Po stronie agregatu są reguły biznesowe. Czyli w twoim wypadku samochód jest agregatem, a zawieszenie, silnik i kola są encjami, sobótka o tym szerzej opowiadał w któryms ze swoich wykładów, w którym nie pamietam. No i to zależy od domeny, bo jeżeli bys miał domenę, gdzie samochodem jeździsz etc to wtedy to będzie właśnie agregat, gdyby chodziło np. o appke serwisowa (dobór cześci, diagnostyka etc) to już niekoniecznie

0

@hcubyc:
Zawieszenie, silnik, koła na pewno są encjami ? Nie żyją przecież własnym życiem w systemie - są zależne od auta. Z tego co czytałem encja jest niezależnym bytem.

I co do tematu - jednak potraktowałbyś to jako 1 moduł ?

0

Czy encja musi żyć własnym życiem? Wg książkowych definicji encja charakteryzuje się tym, że posiada tożsamość (jakiś ID, klucz złożony, naturalny, whatever) i posiada cykl życia oraz zachowania. Przykład samochodu jest troche z d**y, bo silnik mógłby być Value Objectem albo Encją - założmy konkretny silnik zamontowany w konkretnym samochodzie - ma swoje zachowania, z których korzysta agregat, do tego zestaw własnych cech (przebieg, jakieś serwisy pierdy) i pewnie ID, że to właśnie ten silnik został zamontowany w danym samochodzie - możesz wymienić silnik na taki sam model silnika, ale to nie bedzie ten sam silnik. Na innym przykładzie mozna to lepiej zrozumieć, generalnie jak chcesz zasięgnąc teorii to polecam olać evansa i poczytać vernona. Z drugiej strony w innym kontekście silnik mógłby być value objectem - tez ma zachowania, ale nie posiada tożsamości i składa się tylko z właściwości, czyli wtedy gdzieś masz przebieg silnika i jego 'zycie' po prostu potrzebujesz jakiś silnik o określonych parametrach i więcej cie nie obchodzi

0

Ja zaś chciałbym powrócić do poruszanej tutaj kwestii. Mamy wydzielone moduły np tak jak Jakub Nabrdalik pokazywał na prezentacji z wypożyczalnią filmów, moduł User miał powiązania z wieloma modułami. Tworząc encję JPA/obiekt domenowy z ograniczoną widocznością do pakietu nie ma wtedy możliwości nawiązać relacji np. z filmami (wypożyczone filmy przez użytkownika), zgłoszenia wysłane przez użytkownika, jakieś poczekalnie, coś co przynależy do użytkownika. W jaki sposób wtedy powiązać ze sobą te obiekty? Nie da rady wykorzystać do tego fasady, która tam jest zaprojektowana, bo ona nie pozwala na utworzenie relacji. Powinniśmy wtedy obiekt domenowy/encję JPA umieścić w shared kernel i zainteresowany moduł będzie mógł być z nią bezpośrednio powiązany?

0

@daw22:

A czemu nie miżesz do Filmu dać pola userId: Long? ?

0

@daw22 ja u siebie do wszystkich zależności takich jak mówisz używam po prostu dodatkowe pola (uuid czy cos). Problem jest tylko, żeby potem pamiętać, żeby wszystko pospinać przy jakichś akcjach oraz rosną dodatkowo zależności.

0

@daw22: masz relację pomiędzy klientem, a filmem. @Aleksander Brzozowski ładnie nazwał to wypożyczeniem. Reprezentuje ono nie tylko relację, ale całe zdarzenie, które zachodzi w systemie.

0

Czyli tak jak radziliście wcześniej i po głębszym zastanowieniu ma to sens i rozbija powiązania modułów ze sobą. Dziękuję ;)

0

Nie mogę nadal dojść do tego dlaczego wszyscy znawcy DDD mówią, aby nie myśleć rzeczownikami tylko czasownikami. W sensie może i rozumiem powoli sens tego, ale nadal to jest dla mnie za mgłą.

Obejrzałem 4x ten film Sobótki:

i coś tam zrozumiałem, ale jest ciężko.

Czy chodzi generalnie o to, aby przestać myśleć w kontekście rzeczowników, czyli struktur danych na froncie ? Olać query ?

0

@hcubyc:

Bo ogólnie jestem na etapie projektowania architektury do gierki przeglądarkowej w styu Ogame. Use case'y mam już w miarę rozpisane. Przyszła pora na jakieś rozrysowanie modułów i ich relacji. Oczywiście moje pierwsze podejście do schematu to wydzielenie rzeczowników i tak też zrobiłem przez co pojawiło się moje pytanie wyżej o rozbijanie modułów. No bo tak: gracz posiada kilka baz militarnych, każda baza ma swoje budynki, surowce i stacjonującą flotą. Na 1 rzut oka wydaje się, że agregatem jest user z listą baz, każda z baz z listą budynków, surowcami i flotą. No, ale nie wydaje mi się, żeby to było dobre bo coś za duże jest :D. W następnym kroku jednak rozbiłem ten 1 wielki moduł na kilka mniejszych (per rzeczownik) .. ale to chyba nadal nie jest dobry pomysł, bo jak będę chciał wyciągnąć dane o całej bazie to odpytam moduł bazy, potem po id bazy odpytam surowce i jeszcze budynki i flotę - chyba już za dużo tych zależności i łatwiej wyciągnąć jeden agregat. Z drugiej jednak stron - to jest ta część 'query', prezentacyjna, mniej ważna - bez reguł biznesowych. Popisałem z J. Nabrdalikiem i zasugerował, że źle kombinuję myśląc rzeczownikami, żebym zrobił model c4, wypisał use casy i starał się je przejść za pomocą diagramów sekwencji - jeszcze nie do końca wiem jak to mnie naprowadzi na wydzielenie agregatów/modułów, ale spróbuję. Może tak naprawdę nie muszę mieć modułów jakie wydzieliłem do tej pory tylko zupełnie inne.

No mam ogólnie mind fucka, ale nie daje mi to spać po nocach :D

0

Generalnie za pierwszym razem nie zrobisz tego dobrze, nawet jak już będziesz miał w tym doświadczenie to i tak będziesz dalej popełniać błędy, choćby ze względu na nieznajomośc domeny. Jeżeli chodzi o agregaty to pamiętaj też żeby mieć 1 transakcję per agregat, tzn staraj się unikać takich sytacji gdzie żeby wykonać 1 akcję użytkownika musisz zapisać w jednej transkacji 3 różne agregaty. Generalnie myslenie czasownikami IMHO jest spoko, bo wtedy w miare bedziesz widzieć jakie są interakcje - jeżeli coś ze soba często gada/wymaga cyklicznej zależności to zazwyczaj jest to jedna i ta sama rzecz. Zastanawiam się właśnie czy baza by nie była agregatem z referencją do użytkownika jako ID. Pytanie czy budynki nie będą częścią bazy? I surowce osobno tez per użyktownik? Musiałbys więcej napisać to z pewnością ktoś pomoże, bo nie grałem nigdy w ogame. Czy baza produkuje i konsumuje surowce? Surowce są per baza czy per gracz? Jakie są podstawowe akcje? Bez tego cięzko doradzać

0

@hcubyc:
To jest tak, że każdy user po założeniu konta dostaje pierwszą swoją bazę (w dalszej części gry może utworzyć kolejne jak ogarnie potrzebne technologie ale to nieważne). Każda baza ma swoje budynki, które są jej częścią. Czyli załóżmy w swojej bazie nr 1 możesz mieć kopalnie złota poziom 5 i stocznie poziom 3 a w bazie 2 kopalnie złota poziom 7 i stocznie poziom 3. Surowce są per baza, a nie user, czyli jeśli chcesz mocno rozwijać jedną bazę to możesz sobie transportować surowce z innych baz do tej głównej.

Kolejne co mnie zastanawiało - jak ogarnąć system przyrostu surowców. Czyli załóżmy, że kliknąłeś na ulepszanie kopalni złota na poziom 10 i trwa to 5h. Wzięło Ci surowce i na froncie widzisz odliczanie tego czasu. No ale teraz tak - trzeba jakoś zaimplementować sposób naliczania tych surowców. Załóżmy, że na kopalnia na poziomie 9 wydobywała 10j. złota na sekunde, a na poziomie 10 wydobywa 12j / s. Na pewno nie chce mieć żadnego chodzącego joba, który będzie updatował surowce, bardziej preferuję sposób, że surowce będą się updatowały w przypadku odpytania o nie w jakiejkolwiek sytuacji - np. chcesz coś zbudować, musi iść odpytanie o ich stan, przy okazji jest naliczony ich nowy stan na podstawie poziomu jakiejś tam kopalni i czasie ostatniego ich updatu. Gorzej tylko w sytuacji, kiedy akurat jakaś kopalnia będzie w trakcie budowania. Bo jeśli w czasie, kiedy user nic nie zrobił zakończy się ulepszanie to przecież przy najbliższym odświeżaniu powinno naliczyć surowce z niższym wydobyciem do czasu ulepszenia i potem już z nowym wydobyciem - może muszę zapisywać jakieś akcje w bazie i sprawdzać stan.

0

Ciężki masz przypadek, bo gry rzadza sie troche innymi prawami, ja np jako gracz chciałbym widzieć jak mi złoto rośnie na koncie ;) nie wiem czy jeden mega wielki agregat/modul baza by nie był odpowiedni, bo wszystko musi być spójne - nie możesz utworzyc budynku, wysłać event, a baza sobie go skonsumuje i doda budynek po jakimś czasie, tak samo z surowcami - wiesz np. że w tej minucie powinieneś mieć złota na nowy budynek, a tu kleks bo się nie przeprocesowało ;) z drugiej strony duże agregaty to nie jest dobra praktyka, więc na twoim miejscu bym próbował zrobić pierwszą implementację, popatrzył potestował i najwyzej refaktorował dalej.

0

@hcubyc:

To jak Ci złoto rośnie mogę rozwiązać tym, że na front wyślę info o stanie + przyroście i już front będzie updatował wartość co 1s czy tam ile chce.

Kurde no też mi się wydaje, że baza tu jest 1 agregatem, bo chociażby patrząc na tą zasadę z transakcjami - jeśli wybuduję budynek i miałbym dwa agregaty - Budynki i Surowce to oba agregaty zapisuję w transakcji czyli źle ..

No i na budowanie mam taki pomysł, że po kliknięciu buduj jest taki flow:

  1. Sprawdzanie stanu surowców i tego czy już dany budynek nie jest budowany
  2. Odjęcie surowców, zmiana stanu budynku na "w budowie" i ustawienie czasu wybudowania na te załóżmy +5h od teraz.
  3. Przy odpytywaniu o surowce dla jakiejkolwiek potrzebującej tego operacji sprawdzę czy budynek odpowiedzialny za przyrost surowców ma ustawiony czas ukończenia budowy - jeśli tak i jest już po nim to odpowiednio przeliczę przyrost, podniosę level budynku, ustawię datę ukończenia budowy na null.

Chociaż jak tak o tym piszę to w sumie trochę słabo z tym ustawianiem nulla i robieniem budynków stanowych. Klaruję mi się tu encja "Modyfikacje", która by zawierała info o tym co jest budowane i kiedy jest plan ukończenia. Hmm to DDD to serio ciężki temat :D

0

Przeczytałem cały temat i sobie go zapiasłem bo naprawdę dużo ciekawych info można tu znaleźć. Dzięki @Bambo że chce Ci się go też odświeżać po kilku miesiącach braku aktywności ;)
Przy okazji mam pytanie.
Obejrzałem film Jakuba Nabrdalika który tu linkowaliście. Generalnie super, mega chwalę i nawet mam trochę swoich kodów więc dla sportu zrobiłem refaktor żeby zobaczyć jak to się sprawdza i mam 2 wątpliwości:

  1. Przy niewielu klasach w pakiecie jest okej ale jeśli taki pakiet odzwierciedla jakąś domene a ta jest bardziej złożona to czy nie jest tak że w jednym pakiecie mamy naciapane kilkadziesiąt klas w których ciężko się połapać? Ja zrobiłem około 20 i już czuję że jest to mało intuicyjne.
  2. Weźmy przykład Jakuba z filmami i wypożyczaniem. Jeśli rozdzielimy te domeny do dwóch pakietów i encje zrobimy prywatne (z tego co zrozumiałem tylko fasady i dto ma public) to wówczas nie mamy jak powiązać ze sobą w bazie tabeli wypożyczenie z kluczem obcym na film. Jakub robi to na MongoDB ale załóżmy że mamy zwykłego SQLa. Jak w takim razie to powiązać? Można zrobić jakiś UUID filmu i w tabeli wypożyczenie trzymać go, natomiast nie mamy żadnej gwarancji że te dane są spójne (np. taki film zostanie usunięty). Jak to sensownie obsłużyć?

EDIT.
Naszło mnie na jeszcze trzecie pytanie:
3. Jaki sens ma używanie IoC razem z takim podejściem żeby wszystko było prywadne i wystawiać tylko fasadę? Wszelkie serwisy, komponenty itp jeśli będą zarządzane przez Springa to nawet jeśli będą package scope to i tak można to w dowolne miejsce wstrzyknąć. O ile jeszcze wyobrażam sobie żeby serwisy ręcznie tworzyć przez new i przekazać to do fasady przez konstruktor tak jak robi to Jakub, o tyle nie jest to już możliwe w przypadku np. springowych kontrolerów lub interfejsów repository od Spring Data JPA.

0

Ad.1 No cóż, wyjścia masz dwa: podzielić domenę albo zrezygnować z Javy na rzecz innego języka JVM(Scala etc.)
Ad.2 Zastanawiałem się jakiś czas temu nad tym problemem i ostatecznie zrezygnowaliśmy z relacji. Nie wydaje mi się, aby było inne wyjście niż umożliwienie dostępu między encjami. Niestety Hibernate, zreszta jak wiele innych frameworków i libek, nie był tworzony z myślą o package private

1

@eL:

To nie tak, że mi się chce go odświeżać :). Interesuję się dość mocno architekturą apek, DDD itd. Pracuję w banku, często gadam z analitykami i biznesem, wprowadzam building blocki z DDD, staram się unikać, a jak zastanę to refaktoryzować 8tysięczniki. Po prostu przy moich kolejnych priv projektach chcę pisać coraz lepiej, stosować nowe technologie i ogólnie rozwijać się, a że większość moich zagwostek tyczy się architektury to wolę nie zakładać kolejnych tematów tylko korzystam z tego :D

Sam osobiście porzuciłem springa mvc, javę i hibernata. Czas na kotlina, jakiś funkcyjny serwer (pewnie spring reaktywny) i jooq.

0

@hcubyc: :DD Mam nadzieję, że nie przeszkadza Ci, że od czasu do czasu Cię tu popinguję.

Mam dla Ciebie kolejny case:

Jak testujesz metodę fasady, która coś zapisuje, ale nigdzie w systemie nie masz potrzeby wyciągania zapisanej encji po id ? Robienie metody loadById() dla fasady tylko na potrzeby testów jest imho głupie.

Rozwiązanie, które obgadałem z kumplem w robocie to wstrzyknięcie do fasady InMemoryRepository dopiero w testach, aby mieć do tego referencje i dorobienie do tej InMemory implementacji metod na potrzeby testów - sprawdzających po id itd. Wiem, że to takie trochę wyciąganie bebechów na stół i grzebanie tam gdzie się nie powinno, ale chyba z dwojga złego lepsze to niż sztuczne dorabianie metod do fasady ?

0

Nie ma problemu ;)
Ja generalnie stosuje takie właśnie podejście - czyli do fasady leci interfejs i fasada na nim operuje, a w testach stawiam inMemory implementację i operuje na klasie konkretnej czyli inMemory i tam własnie dorabiam sobie metody do sprawdzenia. W testach z infrą jest łatwiej, bo zawsze możesz zapytac baze czy posiada taki obiekt. Staram się tego unikać tak jak tylko mogę i testować zachowanie, więc zazwyczaj jeżeli coś zapisujesz w bazie to potem chcesz na tym wykonać jakąś operację, wiec można dać jeden test, gdzie np. tworzysz nowe konto użytkownika, a nastepnie użytkownik moze się zalogować - przykład trochę z d**y, ale jeżeli masz wymaganie biznesowe żeby coś włożyć do bazy/stworzyć to zazwyczaj coś dalej się z tym dzieje, a takie przykłady gdzie faktycznie tylko coś wkładasz i nic dalej z tym nie robisz to zazwyczaj jakieś raporty/dane techniczne, więc wtedy nie mam oporów sprawdzać na implementacji inMemory czy się zapisało. Inny sposób jeżeli wolisz to można też sprawdzić to na mocku - czyli sprawdzasz czy do repo faktycznie poszedł strzał żeby coś zapisać i jeżeli tak to zakładasz, że implementacja to ogarnie.

0

Jakub w jednym ze swoich talkow mówi ze mock i referencja do Repository to złe rozwiązania bo grzebie się wewnątrz zamiast testować zachowania. Generalnie metody save, update po wykonaniu operacji bazodanowej zwracają zmienione Entity i to w sumie łatwo przetestować. Gorzej jak chcesz coś usunąć to wówczas nic nie zwracasz natomiast twój case jest trochę dziwny bo skoro coś zapisujesz w bazie to przecież gdzieś to musisz wyciągać?? Nawet raporty czy dane techniczne o których pisze @hcubyc jeśli są zapisywane to znaczy ze są na tyle istotne żeby je potem jakoś przetworzyć wiec trochę nie wyobrażam sobie przypadku kiedy coś się zapisuje i dalej nic się nie dzieje z tym.

0

Tak to prawda, ale od każdej zasady są wyjątki i nie ma w tym nic złego. Generalna zasada jest taka, by nie grzebać w bebechach tylko testować zachowanie, ale zdarzają sie takie przypadki i wtedy jeżeli takie grzebanie jest usprawiedliwione to jest OK. Przykład - robie jakąś migrację danych i tylko do tego celu wrzucam sobie to w kod domenowy, bo de facto akcja dzieje się w domenie, dodatkowo zrzucam sobie dane do bazy, tylko po to żeby mieć informację co się zmieniło w danej encji gdyby się coś zgubiło lub biznes o to zapytał, ale to nie są eventy domenowe i te informacje są w razie gdyby coś się złego stało. Wtedy nie wyciągam tych danych ani na nich nie operuję, bo nie ma takiego biznesowego przypadku, ale chce mieć potwierdzone w teście, że dane się zapisały. No i wtedy w teście moge skorzystać z mocka lub referencji do repo/storage inMemory. Tak, normalnie dane są wersjonowane, ale powiedzmy, że klient chce coś skopiowac z jednej 'przestrzeni' do drugiej, wtedy zapisuje sobie co się skopiowało gdzie - raczej się ta informacja nie przyda, bo klient ma skopiowane dane i generalnie nie trudno mu samemu to wyciągnąc, ale wole mieć to pod ręką

0

Odp na szybko: nigdy nie wyciągam tego po id. Jedynie mam query, które zwraca określoną ilośc rekordów z db z tabeli tej encji i mają być one randomowe. Czyli save dodaje do puli, a potem mogę to wylosować. W pełni odpiszę jtr rano :)

0

Można też utworzyć metodę package private w fasadzie do wyciągnięcia potrzebnych danych.

0

Hej, naszło mnie ostatnio pewne przemyślenia trochę związane z tematem.
Mam projekt który jest odpowiedzialny za cały backend aplikacji. Korzystam tam z Mongo i restowego API (+ fasady do komunikacji pomiędzy modułami).
Chciałem spróbować podejścia bez żadnych relacji więc tak jak tu wczześniej pisaliśmy zapisuje samo ID rekordu z innej tabeli na który wskazuje. Np. Artykuł ma kilka właściwości + pole creatorId. Mam też drugi odseparowany całkowicie web front który komunikuje się po reście. Nie wiem czy takie rozwiązanie ma sens ale pomyślałem sobie że jak będę chciał odciąć front bo technologie mi się tam nie sprawdziły to wystarczy podmienić serwis (choć z doświadczenia wiem że podejście "może kiedyś będzie potrzebne" nigdy się nie spradza i nigdy nie jest potrzebne :) )

Zastanawiam się ostatnio w którym miejscu scalać te dane. Początkowo miałem plan żeby robić to na backendzie, tzn wyciągam artykuł, przepuszczam to przez jakąś metodę i dostaje na wyjściu jakiś SuperArtykuł z powiązanymi wszystkimi polami. Wydawało mi się to sensowne bo przynajmniej front nie będzie musiał robić dodatkowych requestów aby dociągnąć dane (a tych mogłoby trochę być, np. lista 20 artykułów na stronie i do każdego trzeba dociągnąć autorów, kategorie itd itd).
Później jednak zacząłem się zastanawiać czy to na pewno jest okej bo mam wrażenie że mój backend uzależniam od frontu. Wiem że na froncie zamiast id twórcy chcę wyświetlić imię i nazwisko więc wypluwam mu tak przygotowany obiekt. Gdybym jednak chciał to podpiąć pod jakąś apkę mobilną gdzie na ekranie jest znacznie mniej miejsca to wówczas chciałbym zamiast imienia i nazwiska wyświetlić powiedzmy awatar osoby. No i tu się robi problem...
Jakieś propozycje rozwiązania tego w sensowny sposób?

2

mam wrażenie że mój backend uzależniam od frontu. - a od czego ma backend zależeć? Od widzimisie sprzątaczki? Czy wyobraźni architektów ? (i będą wszędzie CRUDy, bo dalej ta wyobraźnia nie sięga...)

Generalnie to nie ma nic złego, że backend robi to co potrzebne jest do frontu :-)

Rozwiązań jest mnóstwo w generalnie najpowszechniejsze to warstwy:

W backendzie robsz się jakąś warstwę frontend-logic (presentation -tier), gdzie dokładnie umieszczasz takie specjalizowane serwisy.
Swój core backend (backend-backend :-), business logic ) pozostawiasz dość czystym i niezaleznym od wpływów frontu.
Frontentd-Backend (presentation) może mieć nawet własną perzystencje (user settings), cache na zagregowane dane itp. Może być nawet zrobiony w stylu CQRS. Gdzie zapisy lecą do core backendu, a presentation odpowiada za różne widoki, uzupełniane asynchronicznie na podstawie eventów z tego core.
I co więcej możesz mieć kilka instancji frontend-backendów (nieczęsto się tak robi, raczej wypadki przy pracy związane z migracjami na nowe technologie).

Inne rozwiązanie (częsciowo ortogonalne) to np. GraphQL, co w przypadku Mongo może mieć sens, ale zobacz, u mnie w jednej firmie byli tym zachwyceni (nie wiem czemu), sam się nie bawiłem.

0
jarekr000000 napisał(a):

mam wrażenie że mój backend uzależniam od frontu. - a od czego ma backend zależeć? Od widzimisie sprzątaczki? Czy wyobraźni architektów ? (i będą wszędzie CRUDy, bo dalej ta wyobraźnia nie sięga...)

Generalnie to nie ma nic złego, że backend robi to co potrzebne jest do frontu :-)

Miałem bardziej na myśli to że uzależniam sobie cały backend od jednego frontu który jest webem ale oczywiście rozumiem Twoją wypowiedź z podziałem chociażby na warstwy i dziękuję bardzo za pomoc ;)

Ps. Lubię Twoje odpowiedzi na 4p. Są takie ironiczne. Śmieszek z Ciebie choć na żywo taki niepozorny ;>

0

W sumie można by wyrzucić literkę Q z CQRS do frontendu, tylko backend musiałby mieć możliwość uwierzytelnienia klienta do danych o które prosi, no i analizy zapytania pod kątem kosztu wykonania

0

@jarekr000000:

Ja to ogólnie chciałbym trafić do apki w Javie/Kotlinie, która nie jest CRUDem. No chyba, że ten CRUD to buzzword. No bo co .. czy jeśli wystawiam resta, ale tak naprawdę między wyciągnięciem z DB, a wypluciem na front mam jakieś jeszcze pobieranie danych z innych mikroserwisów, liczenie czegoś, transformowanie tych danych to nadal to jest CRUD ? Wiadomo, że ciekawsze jest np. pisanie sterowania robotem w C na mikrokontrolery, ale ciężko mi sobie wyobrazić w Javowym świecie coś innego niż REST :(

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