Start projektu. Clean Architecture

1

Wujek Bob (Boże, jaka ta nazwa jest okropna), mowi w CA, ze należy opóźniać decyzje co do wyboru frejmworku, bazy czy innych elementów technicznych.

Tzn Najpierw napisz biznes, później, odwróć zależności przez interfejsy, weź porty i adaptery i doczep sobie co chcesz. Takim sposobem będzie niezależna warstwa wewnętrzna.

Ja jako początkujący chciałem zapytać, czy spotkaliście się z takim podejściem?
Tzn. Dobór technicznych rzeczy był na samym końcu?
Po napisaniu bizensu?

7

Tak. Wg mnie to bardzo dobre podejście. To proste i logiczne. Najpierw planujemy co chcemy osiągnąć potem dobieramy narzędzia.
Co innego jak jesteś właścicielem 100 koparek... wtedy musisz planować projekt tak aby najlepiej wykorzystać te koparki.

10

Spotkałem się w ksiązkach i na konfach. W życiu standardowo, pierwsze co to ładujemy spring boota i naparzamy init.sqlki (:

1

U mnie było raz tak, ze prosty crud.
To senior mowi mikroserwisy bo to teraz ważne i modne.
Skończyło się niepotrzebnymi i złe zaprojektowanymi mikro, które trzeba było spinać organoleptycznie, bo logiki tam nie było. :/

6

Wujek Bob (Boże, jaka ta nazwa jest okropna), mowi w CA, ze należy opóźniać decyzje co do wyboru frejmworku, bazy czy innych elementów technicznych.

Nic dziwnego, skoro jest sygnatariuszem manifestu Agile, który mówi to samo w kilku punktach:

"Responding to change over following a plan"
"Welcome changing requirements, even late in
development."
"Simplicity--the art of maximizing the amount
of work not done--is essential.
The best architectures, requirements, and designs
emerge from self-organizing teams."

A zafiksowanie się na wstępie na konkretne frameworki, bazy itp. blokuje ci tę zwinność.

Po napisaniu bizensu?

Dlaczego "po"? O ile nie masz ścisłego waterfallu, to budowanie software'u to dość iteracyjny proces, a nie, że najpierw piszemy rzeczy A, potem już tylko rzeczy B, potem tylko C.

Ja to rozumiem tak, żeby nie fiksować się na to, żeby robić coś "we frameworku" i nie podporządkować projektu frameworkowi, tylko, żeby używać frameworków, baz itp. jako narzędzi pomocniczych, które można będzie potem wymienić w razie potrzeby.

2

Spotkałem się. Znane też pod nazwą architektury heksagonalnej lub portów i adapterów. Wykorzystuję w pracy w projektach, które mają skomplikowaną domenę biznesową. Takie podejście nie nadaje się zbyt dobrze dla projektów czysto technicznych typu CRUD lub przeczytaj excel i wrzuć na kolejkę.

5

Z reguły biznes sam nie wie czego chce, rozwija swoje pomysły w trakcie i jak najszybciej chce zobaczyć pierwszy działający prototyp, żeby się do niego odnieść, więc przeważnie się nie da napisać tego po kolei i równolegle rozwija się domenę oraz infrastrukturę. Faktem jest, że zasłonięcie owej domeny i jej logiki za zasłoną z interfejsów sprawia, że teoretycznie można łatwo wymienić jedną technologię na drugą (dajmy na to, persystencję, czyli np zastąpić jedną bazę inną), ale w praktyce okazuje się, że raz posadzone technologie ciężko potem wykorzenić, bo wymagałoby to czasu, który klient/biznes nie chce raczej poświęcać w pogoni za nowymi taskami, feature'ami i możliwościami. Jak zwykle więc teoretyczna doskonałość idealnej architektury musi walczyć o przeżycie i zasoby z wymaganiami i oczekiwaniami klienta, bo koniec końców to on za wszystko płaci i niewiele wie na temat tego, jak to wszystko wygląda w środku.

Z drugiej strony, w tradycyjnym monolicie możliwości wymiany technologii przeważnie nie ma wcale, bo jest nadto wbudowana w strukturę projektu, gdzie wszystko się łączy z wszystkim i próba ruszenia czegokolwiek powoduje, że wszystko się wali. Toteż taka architektura faktycznie ma sens w stosowaniu, wprowadzając pewną stabilną strukturę.

1
nie100sowny napisał(a):

Spotkałem się. Znane też pod nazwą architektury heksagonalnej lub portów i adapterów. Wykorzystuję w pracy w projektach, które mają skomplikowaną domenę biznesową. Takie podejście nie nadaje się zbyt dobrze dla projektów czysto technicznych typu CRUD lub przeczytaj excel i wrzuć na kolejkę.

No ale w crudzie nie masz za duzo logiki, stad możesz stworzyć moduł crudowy i w nim też robić DIP, dodając interfejsy i odwracając zależności, tak by moduł był niezależny.
A do logiki inny moduł i tam orkiestrować prace przez building blocksy.
To się nie gryzie ze sobą. Chyba, ze wiesz, ze nigdy już projekt nie wyjdzie poza cruda to faktycznie bezsensu.

5

Co do tematu - nie zdarzyło mi się żeby chociaż kilka technologii nie było znanych. Czasem są narzucone, czasem po postu zaproponowane. Natomiast zazwyczaj próbowałem prowadzić tak, aby ignorować fakt, że je znamy.
Może sobie troche dopowiadam, ale myśle, że Uncle Bobowi nie chodziło wprost o to aby ich nie znać, a raczej o to aby nie było przecieku do domeny oraz aby więcej uwagi poświęcić modelowaniu swojego serwisu i jego logiki biznesowej niż rozmowie o frameworkach i bazach danych.

9

Myśle że chodziło tutaj bardziej o tym, żeby skupić się na tym co a nie jak. Programiści lubią dyskusje w stylu sql vs nosql albo request-response vs reactive, w ogóle nie myśląc o potrzebach biznesowych, od których należy wyjść. Dobiera się technologię do problemu a nie odwrotnie. Jeśli jeszcze nie znacie wymagań co do systemu, a już postawiliście sobie Oracle i ładujecie jakiś web-framework do aplikacji, to coś jest nie tak, bo może aplikacja na być batchowa bez żadnego weba i może w ogóle nie ma potrzeby niczego zapisywać w zadnej bazie (albo to co zapisujecie bardziej pasuje do innego rozwiązania niż sql).

Jak wiecie już że potrzeba będzie weba, to wiadomo ze dodajecie zależność do jakiegoś rozwiązania które to umożliwi, ale można też spróbować zrobić to tak, żeby nie spinać z tym całego systemu. Jak dodajesz bazę to zrób jakiś ładny interfejs nad dostępem do niej, tak że w kodzie domenowym masz jakieś repository.persistData(x) i nie musisz wiedzieć jak działa to repository. Wiesz ze zapisuje jakoś dane i tyle. Dziś będziesz zmiał SQLRepository ale jutro uznacie ze to słabe i zrobicie CouchRepository, podmienicie jedną linijkę kodu gdzie to repository było tworzone i cała reszta kodu działa bez zmian. Co więcej chwilowo możesz w ogóle mieć InMemoryRepository a decyzję czy mieć tu SQLa czy cokolwiek innego możesz odroczyć w czasie, bo jest nieistotna w tej chwili.

4
DKN napisał(a):

Tzn. Dobór technicznych rzeczy był na samym końcu?
Po napisaniu bizensu?

Nie no, co Ty. Seniorzy nie daliby rady, to by wymagało braku wyciekającej abstrakcji, czyli w popularnych językach to trzeba by faktycznie OOP mieć.

Shalom napisał(a):

Jak wiecie już że potrzeba będzie weba, to wiadomo ze dodajecie zależność do jakiegoś rozwiązania które to umożliwi, ale można też spróbować zrobić to tak, żeby nie spinać z tym całego systemu. Jak dodajesz bazę to zrób jakiś ładny interfejs nad dostępem do niej, tak że w kodzie domenowym masz jakieś repository.persistData(x) i nie musisz wiedzieć jak działa to repository. Wiesz ze zapisuje jakoś dane i tyle. Dziś będziesz zmiał SQLRepository ale jutro uznacie ze to słabe i zrobicie CouchRepository, podmienicie jedną linijkę kodu gdzie to repository było tworzone i cała reszta kodu działa bez zmian. Co więcej chwilowo możesz w ogóle mieć InMemoryRepository a decyzję czy mieć tu SQLa czy cokolwiek innego możesz odroczyć w czasie, bo jest nieistotna w tej chwili.

Najważniejsze, to wstrzyknąć do domeny HttpContext, bo nigdy nie wiadomo, kiedy będzie trzeba sprawdzić jakiś accept header albo ciasteczko. ;)

1

@Shalom:

Jeśli jeszcze nie znacie wymagań co do systemu, a już postawiliście sobie Oracle i ładujecie jakiś web-framework do aplikacji, to coś jest nie tak, bo może aplikacja na być batchowa bez żadnego weba i może w ogóle nie ma potrzeby niczego zapisywać w zadnej bazie (albo to co zapisujecie bardziej pasuje do innego rozwiązania niż sql).

to jedna z tych historii która fajnie brzmi na forach, ale nigdy się nie przytrafiła nikomu?

nie musisz wiedzieć jak działa to repository. Wiesz ze zapisuje jakoś dane i tyle. Dziś będziesz zmiał SQLRepository ale jutro uznacie ze to słabe i zrobicie CouchRepository, podmienicie jedną linijkę kodu gdzie to repository było tworzone i cała reszta kodu działa bez zmian. Co więcej chwilowo możesz w ogóle mieć InMemoryRepository a decyzję czy mieć tu SQLa czy cokolwiek innego możesz odroczyć w czasie, bo jest nieistotna w tej chwili.

A gdyby tak zamiast robić się "niezależnym", to po prostu wybrać dobrze i użyć featuresów które dany engine udostępnia zamiast się ograniczać do jakiegoś wspólnego mianownika, lecz ubogiego?

0

A gdyby tak zamiast robić się "niezależnym", to po prostu wybrać dobrze i użyć featuresów które dany engine udostępnia zamiast się ograniczać do jakiegoś wspólnego mianownika, lecz ubogiego?

80% wymagań nie jest znana w chwili rozpoczęcia projektu ;) Waterfall i liczenie na to, że przewidzisz wszystko i zaprojektujesz "zawczasu" to marzenie ściętej głowy.
I nie chodzi o żaden ubogi wspólny mianownik tylko o domenowy adapter nad warstwą persystencji (:P) Tak że twoje domain w ogóle nie zależy od jakiegokolwiek "cudzego" kodu, tylko od twoich własnych interfejsów i klas. Dzięki temu żadna zewnętrzna zmiana nie rusza ci domeny, a co najwyżej wymaga zmian w odpowiednim adapterze.

1

80% wymagań nie jest znana w chwili rozpoczęcia projektu ;) Waterfall i liczenie na to, że przewidzisz wszystko i zaprojektujesz "zawczasu" to marzenie ściętej głowy.

To jedno @Shalom, ale ważne jest też że te aplikacje które nie są CRUDami na githuba juniorów na ogół troche sobie pożyją, technologie się zmieniają. Np. jak sobie @WeiXiao wyobrażasz migracją na mikroserwisy i nagle się okazuje że obiekty domenowe ktore były zależne od bazy danych przychodzą/są wysylane z kolejki albo resta?

0

@Shalom:

80% wymagań nie jest znana w chwili rozpoczęcia projektu

nie przesadzajmy, zresztą nawet jeśli, to te wymagania rzadko kiedy są aż tak znaczne, że musisz przejść z sql na nosql, a jak już jakiś taki feature się trafi, to możesz sobie postawić obok.

jak sobie @WeiXiao wyobrażasz migracją na mikroserwisy i nagle się okazuje że obiekty domenowe ktore były zależne od bazy danych przychodzą/są wysylane z kolejki albo resta?

Migracja na MS to nigdy nie jest prosta sprawa i są większe problemy niż bazka

Pokaż mi przykład obiektu domenowego który jest zależny od bazy danych z którym się spotkałeś w rzeczywistości

2

Pokaż mi przykład obiektu domenowego który jest zależny od bazy danych z którym się spotkałeś w rzeczywistości

Nie widziałeś nigdy projektu gdzie ktoś @Entity z JPA używał jako obiektów domenowych? ;) To mało chyba jeszcze widziałeś :) ~10 lat temu to był industry standard prawie że.

0

@Shalom: nie

1

Pokaż mi przykład obiektu domenowego który jest zależny od bazy danych z którym się spotkałeś w rzeczywistości

Oranie encjami z ORMów w warstwie logiki jest dosyć popularne.

1

@WeiXiao:

to jedna z tych historii która fajnie brzmi na forach, ale nigdy się nie przytrafiła nikomu?

E bez przesady. Tak samo kiedyś ludzie z niedowierzaniem reagowali jak się mówiło, że się testy pisze.

Jestem dość cięty na architektów, oracle, bazy danych, kopro frameworki, kafki, szyny i mikroserwisy, nosqle i inne. Musi być bardzo konkretna potrzeba, żebym na tego typu syf się zgodził.

Z tego powodu dość często zamiast planowanego mikroserwisu robiłem... command line tool. Raz nawet w bashu :-). Akurat miałem klienta, którego infrastruktura (a nawet bardziej ludzie) lepiej radziła sobie z takimi toolami (bo było pocobolowa) niż z serwisami http.
Kilka razy całkiem wywracałem oryginalny koncept. Co prawda, bywało, że miałem korpo architektów i np. musiałem pisać w springu. Nauczyłem się pozorować pisanie w springu :-) Tzw. programowanie ze springiem w dupie. Zawsze to postęp, bo potem jedna godzina nieuwagi architektów i spring znika z projektu.

Oczywiście sam mam swoje własne zboczenia. Jeszcze klient nie powie czego chce, a ja już wiem, że zmiennych to w moim kodzie nie będzie :-) ale to chyba inny poziom. Poza tym, jak mam zespół, np. javowców nieprzystosowanych do fp to idę na tony kompromisów.

Przy okazji.:Niedawno kolega się ze mnie śmiał, bo przy okazji migracji systemów jednej firmy z Oracle na PotgreSQL okazało się, że jeden z moich projeków używa bazy danych. Dawno, ktoś tak nie był tak mną zawiedziony. Musiałem, się grubo tłumaczyć, że ja w tym Oracle, żadnych istotnych danych nie trzymałem :-)).
(zrzucałem tam log biznesowy, żeby ludzie od rozliczania klientów mogli sobie łatwo zrobić statystyki - grzebalcy SQL).

0
Shalom napisał(a):

Nie widziałeś nigdy projektu gdzie ktoś @Entity z JPA używał jako obiektów domenowych? ;) To mało chyba jeszcze widziałeś :) ~10 lat temu to był industry standard prawie że.

Czegoś nie łapie. W .NETowym klonie Hibernate'a podobno da się zmapowac złożony obiekt domenowy niezależny od jakiejkolwiek infrastruktury na bazę danych (@somekind) Nie macie tam jakichś klas konfiguracyjnych, tylko wszystko musi być przez adnotacje? Klon prześcignął oryginał? :D

4
Shalom napisał(a):

80% wymagań nie jest znana w chwili rozpoczęcia projektu ;) Waterfall i liczenie na to, że przewidzisz wszystko i zaprojektujesz "zawczasu" to marzenie ściętej głowy.

No, ale skoro nie znasz 80% wymagań, to niczego nie zaprojektujesz dobrze, a więc i tego adaptera także. Z adapterami jest ten problem, że z definicji wycinają część ficzerów tego, co siedzi pod spodem, i to jak sądzę @WeiXiao określił jako "ubogi wspólny mianownik" (swoją drogą szybko lecą z materiałem w tym pszeczkolu, skoro mieli już ułamki zwykłe).

I nie chodzi o żaden ubogi wspólny mianownik tylko o domenowy adapter nad warstwą persystencji (:P) Tak że twoje domain w ogóle nie zależy od jakiegokolwiek "cudzego" kodu, tylko od twoich własnych interfejsów i klas. Dzięki temu żadna zewnętrzna zmiana nie rusza ci domeny, a co najwyżej wymaga zmian w odpowiednim adapterze.

No to warto zrobić, jeśli w ogóle jest jakaś domena, walidacja biznesowa, maszyny stanów, publikowanie zdarzeń i w ogóle cokolwiek jest.
Jeśli logika polega na tym, że dane z requestu mamy wzbogacić o aktualną datę, wysłać do jakiegoś innego API, i zapisać sobie gdzieś, aby w razie restartu móc wysłać ponownie, to robienie tego w clean architecture z czterema identycznymi DTO w różnych warstwach wygląda jakby komuś płacili od linijki. (I to niezbyt dużo.) W moim odczuciu to już ani trochę nie jest clean.

Aleksander32 napisał(a):

To jedno @Shalom, ale ważne jest też że te aplikacje które nie są CRUDami na githuba juniorów na ogół troche sobie pożyją, technologie się zmieniają. Np. jak sobie @WeiXiao  wyobrażasz migracją na mikroserwisy i nagle się okazuje że obiekty domenowe ktore były zależne od bazy danych przychodzą/są wysylane z kolejki albo resta?

W dzisiejszym świecie mikroserwisów, to nawet jeśli w 1 na 10 przypadków okaże się, że pierwotne założenie było zbyt uproszczone, to można taki mikroserwis zastąpić nową wersją z odpowiednio lepszą architekturą i wzbogaconą logiką. I tak zyskamy na czasie nie przesadzając w pozostałych 9 przypadkach.
No, a jeśli faktycznie mamy mikroserwisy, a nie "robimy mikroserwisy, bo to teraz modne", to prawdopodobnie od razu da się stwierdzić, czy będzie w nim siedziała zaawansowana logika, czy np. tylko CRUD.

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