Podział projektu na pakiety - szybkie, proste pytanko.

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ł?

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.
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 :)

1

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:

2

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".

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.