Powiązania pomiędzy modułami

AN
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 989
0

Jak zrobić żeby moduły nie były zbyt powiązane ze sobą np. w takim przypadku:

moduł Track
moduł Playlist

Playlista zawiera Track itd.

Mamy funkcję w module Track do pobierania Tracku ale potrzebujemy na tym etapie danych z Playlisty (np. czy track znajduje się w danej Playliscie, jej nazwę itd).
Przekazanie danych w funkcji (jako argumenty) odpada bo skoro Playlista jest typowana to chcielibyśmy to wykorzystać. A chcielibyśmy też uniknąć importowania Playlist na Track...

I jak tu żyć

opiszon
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 832
3

Dlaczego track potrzebuje danych z playlisty?

Dane nt playlisty czytasz z playlisty, dane nt track czytasz z track.

Przecież 1 track może należeć do N playlist.

AN
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 989
0

@opiszon no po prostu wymaganie biznesowe żeby np. do metadanych dodać dane z playlist

KR
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 55
1

Przekazanie danych w funkcji (jako argumenty) odpada bo skoro Playlista jest typowana to chcielibyśmy to wykorzystać. A chcielibyśmy też uniknąć importowania Playlist na Track...

Wprowadź strukturę danych TrackOutsideInfo, którą uzupełnisz danymi z Playlisty i zaimportujesz w obu klasach.

AN
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 989
0

@Krzemień O i takie podejście mi się podoba. W taki sposób w przyszłości mogę skasować moduł Playlist a moduł Track nadal pozostanie bez zmian i żadnych importów z Playlist.

Te moduły to tylko przykłady, chodzi mi o ogólne podejście i takie miałoby sens imo

A co jeśli chciałbym zrobić coś dla każdego Tracku jeśli coś w Playliście się zmieni? Do głowy przychodzi mi np. wysłanie sygnału to teortycznie też nie będzie powiązania

lion137
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5023
0

Jeśli te moduły są powiązane i tak, to może zrób je częścią jednej logiki - jakiegoś interfejsu, klasy?

AN
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 989
0

@lion137 tzn chodzi Ci o połączenie tego w jeden moduł? To jest tylko przykład ale bardzo często jednak logika biznesowa się przenika, rzadko jest tak, że jest sobie odrębny moduł nie powiązany z niczym

Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10227
2
anonimowy napisał(a):

Jak zrobić żeby moduły nie były zbyt powiązane ze sobą np. w takim przypadku:

moduł Track
moduł Playlist

Playlista zawiera Track itd.

Mamy funkcję w module Track do pobierania Tracku ale potrzebujemy na tym etapie danych z Playlisty (np. czy track znajduje się w danej Playliscie, jej nazwę itd).
Przekazanie danych w funkcji (jako argumenty) odpada bo skoro Playlista jest typowana to chcielibyśmy to wykorzystać. A chcielibyśmy też uniknąć importowania Playlist na Track...

Na pierwszy rzut oka to wygląda jak jeden moduł, ja bym go raczej nie rozdzielał. Wygląda że playlista nie ma sensu bez track. Jesteś pewien że Track i Playlist to są moduły? Może łatwiej byłoby o nich myśleć jak o terminach biznesowych? 🤔

No ale jeśli koniecznie chcesz je rozdzielić, to należy położyć pomiędzy nimi jakąś warstwę - np. to co proponuje @Krzemień, z przekazywaną dodatkowa strukturą. Tylko pytanie co w zasadzie chcesz osiągnąć tym rozdzieleniem? Chcesz używać tracków bez playlisty? Playlisty bez tracków (to chyba nie ma sensu)? Chcesz móc podmienić implementacje Tracków lub playlisty na inne? Bo jesli chcesz wprowadzić rozdzielenie modułów tylko po to żeby było albo "że tak trzeba", to raczej ja bym poczekał z tym.

AN
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 989
1

@Riddle dzięki, na Ciebie czekałem (serio :P)

Ogólnie chodzi o to, że Playlist czy Track to rozbudowane rzeczy w gruncie rzeczy. Są w pewien sposób ze sobą powiązane ale czy muszą?

Playlista ma mały sens bez Track - tu się zgadzam - większość, rzeczy w Playlist jest oparte na Track - z tym, że Track mógłby istnieć bez Playlist więc dlaczego z poziomu Track wiązać go z Playlist?

Tracki mają wiele różnych implementacji i działają bez Playlist, Playlista to tylko takie "rozszerzenie" funkcjonalności aplikacji. Po części zgadzam się, że chcę to zrobić "bo tak trzeba" ale też z tego względu, że mam złe doświadczenie z bardzo rozrośniętymi modułami i szukam sposobu na pogrupowanie tego

HS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 83
0

@anonimowy zrob totalny decouple modulow, a komunikacje miedzy modulami zepnij event'ami na jakims service/app event bus'ie.

Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10227
1
anonimowy napisał(a):

@Riddle dzięki, na Ciebie czekałem (serio :P)

Ogólnie chodzi o to, że Playlist czy Track to rozbudowane rzeczy w gruncie rzeczy. Są w pewien sposób ze sobą powiązane ale czy muszą?

Playlista ma mały sens bez Track - tu się zgadzam - większość, rzeczy w Playlist jest oparte na Track - z tym, że Track mógłby istnieć bez Playlist więc dlaczego z poziomu Track wiązać go z Playlist?

Tracki mają wiele różnych implementacji i działają bez Playlist, Playlista to tylko takie "rozszerzenie" funkcjonalności aplikacji. Po części zgadzam się, że chcę to zrobić "bo tak trzeba" ale też z tego względu, że mam złe doświadczenie z bardzo rozrośniętymi modułami i szukam sposobu na pogrupowanie tego

Rozumiem. Czyli track może być bez playlisty, ale może też ją mieć; chcemy uniezależnić track od playlisty, ale track chce mieć takie informacje jak czy nazwa playlisty w której się znajduje.

(np. czy track znajduje się w danej Playliscie, jej nazwę itd).

Ja w takim wypadku poleciłbym Ci wymyślenie nowego słowa, nowego konceptu które mogłoby być między playlistą a trackiem. Dobrze byłoby wymylić jakieś słowo/koncept żeby to określić. To może być nazwa w stylu: catalog, playlistItem, collection, tracklist, lineup, album, etc. Wtedy byłaby relacja:

Kopiuj
track -> PlaylistItem <- playlist

Taki PlaylistItem mógłby wyglądać np. tak: interface PlaylistItem { bool hasPlaylist; ?string playlistName; ?string playlistAuthor; string[] otherPlaylistsWithTrack }. Track mógłby zależeć od PlaylistItem - z niego brałby info w jakiej playliście jest i jak się nazywa ta playlista; a playlista dostarczałaby info o sobie i swojej nazwie do playlistItem. W wypadku tracku który nie jest w playlisćie, track mógłby dostać PlaylistItem który ma hasPlaylist=false a pozostałe atrybuty np. null albo pusty.

Oczywiście pola możesz zaprojektować do woli. W skrócie - wszystkie dane które mają "przejść" między playlistą a trackiem, wsadź do tego obiektu.

Tak na prawdę nie ma złotego środka na ten problem - wymaga to po prostu zaprojektowania relacji między elementami które masz 😊

HS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 83
1

@Riddle w EU lekarstwem na nadmiar regulacji jest jeszcze wiecej regulacji.
W zasadzie okreslanie czegokolwiek modulem, co nie jest w pelni izolowane od reszty kodu jest bledem.
Ty proponujesz rozwiazanie ktore dodaje tylko dodatkowa abstrakcje, ktora trywialny problem de facto jeszcze bardziej komplikuje.

Ludziska wykorzystuja eventy na potege wewnatrz spojnego funkcjonalnie kodu (ktory ich nie potrzebuje) zwlaszcza i to nagminnie w symfony, a o przypadku tak oczywistym jak separowane moduly i komunikacja miedzy nimi (dla ktorych eventy sa wrecz stworzone) nawet nikt nie pomysli.

loza_prowizoryczna
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1628
0
hyper-stack napisał(a):

@Riddle w EU lekarstwem na nadmiar regulacji jest jeszcze wiecej regulacji.
W zasadzie okreslanie czegokolwiek modulem, co nie jest w pelni izolowane od reszty kodu jest bledem.

W kontekście Pythona modułem jest wszystko co jest napisane w innym języku niż Python (bo musi działać wydajnie) i posiada eksporty dla Pythona. I wtedy to ma sens.

Wszystko inne co ma w nazwie moduł i jest pisane w tym samym języku powstało jak odpowiedź na odwieczny problem monolitu - skoro wszystko jest w tym samym języku ale mamy wiele zespołów to jak poradzić sobie z problemami konfliktu nazw/symboli/whatever?

Przykład analogiczny - skoro monorepo pozwala na łatwe współdzielenie kodu to dlaczego git się słabo sprawdza w tym modelu (i dlaczego git-submodules posysają po całości). Ten sam problem w innym opakowaniu.

HS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 83
0
loza_prowizoryczna napisał(a):

W kontekście Pythona modułem jest wszystko co jest napisane w innym języku niż Python (bo musi działać wydajnie) i posiada eksporty dla Pythona. I wtedy to ma sens.

W kontekscie izolacji, o ktorej pisalem, zalozenie jak najbardziej sluszne, natomiast patrzac na to bardziej ogolnie cos takiego jest po prostu osobny serwisem.

loza_prowizoryczna napisał(a)

Wszystko inne co ma w nazwie moduł i jest pisane w tym samym języku powstało jak odpowiedź na odwieczny problem monolitu - skoro wszystko jest w tym samym języku ale mamy wiele zespołów to jak poradzić sobie z problemami konfliktu nazw/symboli/whatever?

Mozliwe ze w python'ie stanowi to jakies wyzwanie, natomiast w przypadku php (w ktorym ja przede wszystkim kodze) nie stanowi to w sumie zadnego problemu. Przykladowa struktura projektu monolitu:

Kopiuj
my-app
  *src
    *Controller
      - MyController.php 
- server.php

Hula sobie na trywialnym namespace'ie:

Kopiuj
"App\\": "src"

Przeksztalcenie tego w modularny monolit wyglada tak:

Kopiuj
my-app
  *src
    *Controller
      - MyController
  *Modul1
    *src
      *Controller
        - Controller1.php
  *Modul2
    *src
      *Controller
        - Controller2.php 
- server.php

Na rownie banalnych namespace'ach:

Kopiuj
"App\\": "src"
"Module1\\": "Module1/src"
"Module2\\": "Module1/src"

W razie koniecznosci calkowitej izolacji, jednego lub wszystkich modulow (powod dowolny), moduly na zasadzie cut & paste moga stac sie:

  • albo rozwijanymi w osobnych repozytoriach bibiliotekami ladowanymi composer'em do glownego projektu ktory de facto staje sie wylacznie rama
  • albo rozwijanymi w osobnych repozytoriach servisami
loza_prowizoryczna napisał(a)

Przykład analogiczny - skoro monorepo pozwala na łatwe współdzielenie kodu to dlaczego git się słabo sprawdza w tym modelu (i dlaczego git-submodules posysają po całości). Ten sam problem w innym opakowaniu.

W tej kwestii, dla przypadku php wypowiedzialem sie powyzej i jak widzisz nie mieszamy w to git-submodules.

Na koniec dodam tylko, ze od juz od jakiegos czasu, moj zespol pracuje w ten sposob i wyglada to tak ze w przypadku jesli modul jest po prostu dopinany do ramy jako biblioteka:

  • deployment ogranicza sie wylacznie do modulow, bez masakry mielenia calej kobylastej aplikacji/platformy przy kazdym release'ie
  • spinanie modulu z aplikacja (wlasciwie jej rama) ogranicza sie do jednego polecenia update wersji modulu composer update
  • pracuje sie wygodnie na hermetycznych zakresach kodu, bo kazdy modul/paczka to osobna biblioteka w swoim wlasnym repozytorium
  • a zlecajac komukolwiek z zewnatrz jakas robote nie jestes zmuszony dawac dostepow do calego kodu aplikacji/platformy
loza_prowizoryczna
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1628
0
hyper-stack napisał(a):

W kontekscie izolacji, o ktorej pisalem, zalozenie jak najbardziej sluszne, natomiast patrzac na to bardziej ogolnie cos takiego jest po prostu osobny serwisem.

To nie ma znaczenia czy moduł nazwiesz serwisem, usługą czy procesem. Wszystko to pochodna tego że większość projektów ma flow Ulissesa Joyce'a a ty zachowujesz się jak krytyk literacki i dopatrujesz się powiązań znaczeniowych w obrębie rozdziałów.

Mozliwe ze w python'ie stanowi to jakies wyzwanie, natomiast w przypadku php (w ktorym ja przede wszystkim kodze) nie stanowi to w sumie zadnego problemu. Przykladowa struktura projektu monolitu:
(...)
W razie koniecznosci calkowitej izolacji, jednego lub wszystkich modulow (powod dowolny), moduly na zasadzie cut & paste moga stac sie:

  • albo rozwijanymi w osobnych repozytoriach bibiliotekami ladowanymi composer'em do glownego projektu ktory de facto staje sie wylacznie rama
  • albo rozwijanymi w osobnych repozytoriach servisami

Dobra, dobra, nie czarujmy się - wszystko sprowadza się do tego czy potrzebujesz w pliku import czy też nie. Resztę wydelegujesz na jakiś menedżer pakietów w którym bezpiecznie będzie można robić burdel (bo wszystkie menedżery do tego tak naprawdę służą).

Na koniec dodam tylko, ze od juz od jakiegos czasu, moj zespol pracuje w ten sposob i wyglada to tak ze w przypadku jesli modul jest po prostu dopinany do ramy jako biblioteka:

  • deployment ogranicza sie wylacznie do modulow, bez masakry mielenia calej kobylastej aplikacji/platformy przy kazdym release'ie
  • spinanie modulu z aplikacja (wlasciwie jej rama) ogranicza sie do jednego polecenia update wersji modulu composer update
  • pracuje sie wygodnie na hermetycznych zakresach kodu, bo kazdy modul/paczka to osobna biblioteka w swoim wlasnym repozytorium
  • a zlecajac komukolwiek z zewnatrz jakas robote nie jestes zmuszony dawac dostepow do calego kodu aplikacji/platformy

Jak widzisz to co robisz to tylko delegacja burdelu wyżej.

HS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 83
0
loza_prowizoryczna napisał(a):

To nie ma znaczenia czy moduł nazwiesz serwisem, usługą czy procesem. Wszystko to pochodna tego że większość projektów ma flow Ulissesa Joyce'a a ty zachowujesz się jak krytyk literacki i dopatrujesz się powiązań znaczeniowych w obrębie rozdziałów.

O czym ty czlowieku "do mnie rozmawiasz"?

loza_prowizoryczna napisał(a):

Dobra, dobra, nie czarujmy się - wszystko sprowadza się do tego czy potrzebujesz w pliku import czy też nie. Resztę wydelegujesz na jakiś menedżer pakietów w którym bezpiecznie będzie można robić burdel (bo wszystkie menedżery do tego tak naprawdę służą).

loza_prowizoryczna napisał(a):

Jak widzisz to co robisz to tylko delegacja burdelu wyżej.

Moge ci tylko wspolczuc przezytych traum i zyczyc szybkiego powrotu do zdrowia.

loza_prowizoryczna
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1628
1
hyper-stack napisał(a):

O czym ty czlowieku "do mnie rozmawiasz"?

O tym że idea modularyzacji i izolacji to koncept fajny na papierze ale w dużych projektach jego całość sprowadza się do tego że zamiast zastanawiać się jak prefiksować nazwy funkcji i struktur wszystko sprowadza się do tego że srasz importami w nagłówkach i aliasujesz skonfliktowane przestrzenie nazw licząc na to że kompilator/interpreter/vm domyśli się reszty.

A powiązania między modułami najlepiej śledzić w dojrzałych menedżerach pakietów np. npm gdzie już chyba stosują heurystyki oparte o AI żeby wykryć cykle w grafie powiązań i rozwiązać ten bigos.

Moge ci tylko wspolczuc przezytych traum i zyczyc szybkiego powrotu do zdrowia.

Ty nie współczuj tylko przyjrzyj się współczesnym menedżerom pakietów bo to one dostarczają rozwiązań na problem wspomniany w tytule wątku.

YA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2384
1

Moje 0.02 PLN.

Staram się myśleć w terminach: komponent, interfejs komponentu, dane wymieniane przez interfejs. Są to terminy które sprawdzają się dobrze zarówno na poziomie kodu jak i architektury, nie są przywiązane do metodyki wytwórczej czy technologii.

Po co wywołujemy jakiś komponent? Zapewne, żeby zrealizować przypadek użycia. Niektóry z nich mogą być proste, inne wymagają nieco więcej pracy i wywołania kilku komponentów, pożenienia rezultatów. Jak to się ma do Track i Playlisty? Ano tak, że można przypadek użycia można zaimplementować jako osobną klasę/funkcję/serwis/etc. która będzie miała uchwyty (referencja do obiektu, czy port do komunikacji z komponentem) do Track i Playlisty i logikę zaszytą wewnątrz, np. klasa/funkcja AktualizujMetadane(modTrack, modPlaylist) ).

Wracając do pytania, Jak zrobić, żeby moduły nie były ze sobą powiązane? Dla każdego modułu zdefiniować interfejs(y) modułu, dane wejściowe interfejsu i dane wyjściowe. Co zrobić w przypadku Track i Playlisty? Nie mam pojęcia, nie wiem jaki problem rozwiązują :-)

HS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 83
0
loza_prowizoryczna napisał(a):

O tym że idea modularyzacji i izolacji to koncept fajny na papierze ale w dużych projektach jego całość sprowadza się do tego że zamiast zastanawiać się jak prefiksować nazwy funkcji i struktur wszystko sprowadza się do tego że srasz importami w nagłówkach i aliasujesz skonfliktowane przestrzenie nazw licząc na to że kompilator/interpreter/vm domyśli się reszty.

Dobrze, to inaczej, co ty czlowieku p...olisz? W czym ty kodzisz? W Basic'u na ZX-Spectrum?

loza_prowizoryczna
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1628
0
hyper-stack napisał(a):

Dobrze, to inaczej, co ty czlowieku p...olisz? W czym ty kodzisz? W Basic'u na ZX-Spectrum?

Basic C64. I jak kodziłem to pamiętam głównie komendę run.

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.