Package scope i architektura aplikacji - jak do tego podejść?

0

Co sądzicie o używaniu domyślnego modyfikatora dostępu (package sope) zamiast public? Ostatnio oglądałem prezentację Jakuba Nabrdalika, w której pokazywał zalety takiego podejścia. Głównie chodzi o to, że dzięki temu można enkapsulować klasy w obrębie jednego pakietu, który tylko wystawia jakieś publiczne api (fasadę) zamiast wszystkich klas, method itd. Brzmi rozsądnie tylko, że pojawią się takie problemy jak np. to, że w jednym pakiecie musi znajdować się dość sporo klas np. encje, value objecty, serwisy domenowe, interfejsy i ich implementacje, (np. repozytoria przez co warsta domeny miesza się z infrastrukturą), security itd. a same fasady wydają się mieć tendencje do puchnięcia, co wydaje mi się, że widać też u autora prezentacji, który ma fasadę, przyjmującą wiele innych klas i na ich podstawie wystawia publiczne api, które zajmuje się bardzo różnymi rzeczami i nie wiem czy czasem nie łamie to SOLIDu, bo potem takiej fasady z różnymi methodami musi używać jakiś np. ReadController, który będzie miał też dostęp nie tylko do methody read, ale też do update czy co gorsza delete, co nie jest zbyt bezpieczne. No i niewszystkie języki wspierają package scope, np. chyba Kotlin i C# tego nie mają, ale głowy sobie nie dam uciąć.
Prezentacja Nabrdalika:

2
  1. package scope w javie jest zrypany i średnio użyteczny. Nie ma hierarchi - więc ani klas z modyfikatorem package nie widać w nadrzędnym pokiecie, ani w podpakietach. Scala ma taki uzyteczny package private.
  2. Kotlin ma internal i jest to taki public w ramach modułu. Trzeba się nauczyć rozdzielać projekt na wiele modułów - moduł == grupa pakietów i wtedy ten internal działa całkiem fajnie.
  3. jeżeli robisz tylko obiekty immutable, to dużo więcej rzeczy można spokojnie zostawić jako public - bo szkodliwość społeczna public zmniejsza się znacznie.
  4. fasady to normalna rzecz, jakbyś nie miał fasady to byś miał publiczne serwisy i też byś mógł wziąć sobie serwis odpowiedzialny za delete.
  5. Najbardziej zbliżone do sensownego rozwiązania w javie jest JPMS (java modules). W ramach modułu robimy sobie public, a potem deklarujemy co wystawiamy na zewnątrz w exportach. Przypomina to podejście kotlinowe. Nie stosowałem tego w praktyce.
1

Czasem używam, ale opieranie całej architektury większej aplikacji o package-private moduły raczej nie działa. Trochę bardziej rozbudowany moduł i robi się porównywalny śmietnik co dzielenie klas na horyzontalne warstwy (controller-service-repository-entity-exception itd.).
Moduły z Javy nie pomagają, bo są bardzo upierdliwe w użytkowaniu, a przynajmniej takie wrażenie odniosłem jak się z nimi trochę pobawiłem.

Pozostaje trzymanie się jakiś arbitralnych zasad układania kodu w pakietach i pilnowania tego na code review. Albo przejście na kotlina i używanie internal.

0

Jak potrzebuje enkapsulacje i ograniczanie scope to robie kolejny maven/gradle module i daje go jako zależność tylko tam gdzie jest potrzebny. W cudowanie z pakietami nie wierze.

0
Sampeteq napisał(a):

No i niewszystkie języki wspierają package scope, np. chyba Kotlin i C# tego nie mają, ale głowy sobie nie dam uciąć.

W C# nie ma package scope, bo nie ma czegoś takiego jak package. Dlatego też nie trzeba tak dzielnie walczyć ze wszystkimi problemami, które aberracja pakietowa stwarza.
Są projekty, każdy projekt wystawia swoje API przez publiczne klasy, resztę klas wypada zrobić internal. Projekt to zazwyczaj jedna warstwa systemu (ale też nie ma problemu z dzieleniem w pionie, jeśli zachodzi taka potrzeba, tu nie ma żadnych dziwacznych ograniczeń) albo jedna uruchamialna aplikacja.

0

Myślę, że warto tego używać od razu widać gdzie jest api i jakie klasy zostały przez autora "wystawione" do używania przez programistę.
Natomiast tak, że mamy encje,repozyoria,serwis,dto i cokolwiek jeszcze w jednym pakiecie to ja bym tak nie robił moim zdaniem to nie działa.

które zajmuje się bardzo różnymi rzeczami

Ale sama fasada tylko deleguje więc de facto nie łamie SRP.

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