Podział projektu na pakiety - szybkie, proste pytanko.

Odpowiedz Nowy wątek
2019-08-12 16:31
0

Cześć.

Niedawno wyczytałem, że znacznie lepiej jest dzielić klasy na pakiety pod względem funkcjonalności, a nie warstw aplikacji. Wcześniej dzieliłem projekt po prostu na pakiety service, controller, config, model itd, a w dopiero w tych pakietach, rozdzielających projekt warstwowo, tworzyłem dokładniejszy podział.
Narzuca mi się do głowy kilka drobnych pytań doprecyzowujących mój tok myślenia:

  1. Czy obiekty encji powinienem trzymać jednak razem w jednym pakiecie?
  2. Czy warstwę kontrolerów też wrzucić do pakietu kontroler?
  3. Rozumiem, że podział na pakiety per funkcjonalność odbywa się głównie w warstwie serwisu, tj. miejscu, w którym realizowana jest logika biznesowa. Czy taki podział stosować w taki sposób, że w pakiecie znajdują się klasy odpowiedzialne za pewną funkcjonalność, obiekt domenowy, dto, jakaś fasada wystawiająca publiczny interfejs sklejony z tych klas itd? Co jednak, gdy kilka funkcjonalności wykorzystuje tą samą grupę obiektów? Jak zapobiec takiemu wymieszaniu wszystkiego? Boję się, że poprzez nieumiejętny podział zamienię siekierkę na kijek i wszystko mi się pomiesza.

Jak powinienem zrealizować taki podział?

Pozostało 580 znaków

2019-08-12 16:50
1

Wszystko zależy od architektury. Jeśli się nie mylę, opisujesz dość ciekawą ale starą już ;-) architekturę n-warstwową, gdzie dzieli się horyzontalnie i architekturę gdzie dzieli się pionowo (ehh, nazwa mi wypadła). Ten drugi podział na funkcjonalności można też w pewnym sensie obserwować w mikro serwisach, w końcu każdy ma tylko wycinek swojej funkcjonalności, a nie całą warstwę.

Więc przy feature slice'ach to nie powinineś trzymać wszystkic X razem, a jeśli masz monolit to trzymać w jednym feature folderze (albo pakiecie, projekcie, zależy jak to sobie wydzieliłeś i co ma sens) z podfolderami jeśli trzeba (jak masz 4 pliki w jednym folderze, np Controller, DTO, Serwis i model domenowy - encje, to jest ok, a jak będzie ich 100 to już słabo się robi i trzeba to jakoś ogarnąć).

Teraz odp na Twoje pytania:

  1. Nie *.
  2. Nie *.
  3. Tak *. A gdy masz wspólne części to może to wspólna funkcjonalność? A może zostało źle podzielone? A może tylko wydaje się wspólna ze względu na odczyt/prezentacje, a nie na to jak działa (patrz CQRS)? Ciężko powiedzieć coś innego niż - to zależy.
    I teraz gwiazdka na koniec - to zależy, czy technologia, framework to wspiera ładnie. Jeśli nie, to musisz iść na ustępstwa. Np da się trzymać widoki i kontrolery osobno w .Net Core i klasycznym, ale w starszych wersjach było z tym wcześniej ciężko, ale Nancy (taki framework) to ładnie wspierało od strzała). Czasem framework coś wymusza i trudno.

Pozostało 580 znaków

2019-08-12 17:00
0

Więc przy feature slice'ach to nie powinineś trzymać wszystkic X razem, a jeśli masz monolit to trzymać w jednym feature folderze (albo pakiecie, projekcie, zależy jak to sobie wydzieliłeś i co ma sens) z podfolderami jeśli trzeba (jak masz 4 pliki w jednym folderze, np Controller, DTO, Serwis i model domenowy - encje, to jest ok, a jak będzie ich 100 to już słabo się robi i trzeba to jakoś ogarnąć).

Tworzę monolit. Mikroserwisy to jeszcze nie mój level umiejętności, muszę się zabierać za wszystko po kolei, żeby się nie pogubić :)
Cały Twój post rozjaśnił moje wątpliwości, jednak intryguje mnie fragment, który pozwoliłem sobie zacytować.

Załóżmy, że mam klasę ComputerRental, przechowującą w sobie obiekt Computer, Person (osoba, która np. wypożyczy sprzęt), ComputerModel, zawierający w sobie jeszcze ComputerProducer itd. Robi się tych obiektów dużo i o ile intuicyjnie przychodzi mi do głowy pomysł podziału tej całej struktury na pakiety, gdzie każdy realizowałby chociażby CRUDowe operacje (dodanie nowego producenta do bazy, usunięcie producenta, dodanie modelu komputera, modyfikacja parametrów modelu itd.), to w celu zaimplementowania funkcjonalności wypożyczenia, gdzie jako tako wszystkie te obiekty będą obecne robi mi się lekki miszmasz.

Chyba, że planuję to w trochę zły sposób. Może powinienem z tych pakietów powiązanych z pakietami powiązanych z ComputerModel, ComputerProducer udostępniać DTO i w pakiecie powiązanym z wypożyczeniami mapować to DTO na zagnieżdżony obiekt ComputerModel w klasie ComputerRental w pakiecie obejmującym funkcjonalność wypożyczenia? Trochę to zagmatwanie opisałem, więc wybacz :)

Pozostało 580 znaków

2019-08-12 17:22
0

Jak myślisz CRUDem - to myślisz źle ;-) Nie powinieneś iść tak mocno w dół z rozmiarem. Za bardzo to rozdrabniasz.

Funkcjonalność to całość, np wypożyczenie komputera. I nie dzielisz tego na techniczne "zapisz zmiany w X, zapisz zmiany w Y" bo faktycznie to tylko mentliku można dostać od tego. To jest jeden cały pakiet.
Inna funkcjonalność, którą może i można zrealizować CRUDem, jeśli nie ma dodatkowych warunków to może być faktycznie to co napisałeś "dodanie nowego producenta do bazy, usunięcie producenta" i kolejna "dodanie modelu komputera, modyfikacja parametrów modelu itd". Albo nawet możesz wziąć na klatę że to tylko CRUD i nawet nie dzielić na osobne pakiety dopóki to tylko CRUD.

Dodam kilka materiałów na ten temat, wyszukanych na szybko:



edytowany 1x, ostatnio: AreQrm, 2019-08-12 17:25

Pozostało 580 znaków

2019-08-12 17:39
1

Tylko że jeśli ktoś robi vertical slice na poziomie pakietów a nie jakichś modułów mavena czy czegoś w tym stylu, to nagle ma cały projekt "spaczony" frameworkiem i nie da się łatwo wyciągnąć np. "samej domeny".


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...
Myślałem, że pakietowanie to kwestia niezależna od frameworka :) - Charles_Ray 2019-08-13 10:24
Ale masz jara który zawiera wszystko w takim układzie. - Shalom 2019-08-13 11:02
Dopóki i tak wszystko wdrażam razem, nie widzę uzysku z N jarów. Widzę za to robienie sobie pod górkę, jeśli chodzi o współdzielone klasy - i tak powstanie moduł „commons” ;) - Charles_Ray 2019-08-13 12:23
@Charles_Ray: podam przykład, wdrażaliśmy pewną aplikację Androidową z rozbudowaną komunikacją sieciową. Komunikacja sieciowa potrzebowała zależności na przykład informacji o urządzeniu, bazy danych itp. Nagle dostaliśmy wymaganie by puścić komunikację sieciową na Jenkinsie bez dostępu do Androida. Dzięki podziałowi na moduły i osobnym jarom dodaliśmy tylko implementacje Runtime bazy danych, jakiegoś fikcyjnego providera danych o urządzeniach i mogliśmy napisać sobie zupełnie dodatkowy mini projekt korzystający z tej samej współdzielonej biblioteki sieciowej. - viader 2019-08-13 12:41
Projekt ten tak naprawdę miał wykrywać anomalie i awarie w komunikacji sieciowej dla produkcyjnej apki mobilinej i przy niepowodzeniu testu o odpowiednio wysokim priorytecie wysyłać informacje SMS'em do wsparcia technicznego. Dodatkowo praktycznie za friko mieliśmy testy regresji komunikacji sieciowej co update produkcyjnej aplikacji. - viader 2019-08-13 12:44
Z kolejnych korzyści - Gradle super optymalizuje czas kompilacji dla dużych projektów jeśli masz podział na moduły. Od strony clean codu moduły zapewniają najczęściej lepszą enkapsulację rzeczy i nazewnictwo dzięki czemu naprawdę jest sporo korzyści. - viader 2019-08-13 12:51

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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