Pytanie nie tylko w kontekście Pythona ale ogólnie programowania w jakimkolwiek języku, np. Go, C++, C#, Java.
Powiedzmy że mam taką strukturę
Kopiuj
class Interface:
def __init__(self, name):
self.name = name
self.profiles = {} # profiles interface belong to
class Profile:
def __init__(self, name):
self.name = name
self.interfaces = {} # interfaces belonging to profile
Czy takie dwukierunkowe relacje zaimplementowane bezpośrednio w klasach powinny być sygnałem ostrzegawczym? Jeżeli tak, czy zamiast tego dobrym pomysłem jest wydzielenie w takich sytuacjach osobnej klasy o nazwie np. NetworkMapping lub innej, która będzie jasno informowała o swoim przeznaczeniu:
Kopiuj
from bidict import bidict
class NetworkMapping:
def __init__(self):
self.map = bidict()
moim zdaniem, jeśli takie dwukierunkowe powiązania nie upraszczają znacząco programu, to lepiej ich unikać. mając dwukierunkowe powiązania można czasem zapomnieć o aktualizacji przeciwnego kierunku powiązania i wykryć to dużo później niż przy jednokierunkowych powiązaniach. gdybym miał już wybierać z powyższych, to pewnie wybrałbym rozwiązanie drugie, tzn. osobną klasę z powiązaniami (przy czym opieram się tu na domysłach, a gdybym znał więcej szczegółów to być może decyzja byłaby inna). mając powiązania w obie strony w jednej klasie od razu widać gdzie i jak trzeba aktualizować powiązania w obu kierunkach. nie wiem czy akurat bidict rozwiązuje sprawę, bo chyba to nie jest multimapa, tylko zwykła mapa, ale za to dwukierunkowa.
Samo w sobie niekoniecznie jest czymś złym, np.
Kopiuj
class Node {
List<Node> children;
Node parent;
...
}
...
...
To całkiem normalne w przypadku list i struktur drzewiastych że dzieci znają rodzica a rodzic zna dzieci, nie ma w tym nic złego ani nadzwyczajnego.
...
zależność między profile, a interface nie wygląda na strukturę drzewiastą, tylko na pełnoprawny graf z pętlami. to jedno, a drugie to jest to, że (wzbogacone lub nie) drzewo jest reprezentowane przez jeden typ lub zestaw ściśle powiązanych typów (a'la tree, node, leaf, etc). ścisła zależność między typami tree, node i leaf to sprawa naturalna i nieproblematyczna, ale jeśli wprowadzilibyśmy równie silne sprzężenie między typami profile i interface to już jest całkowicie inna sprawa. tworzenie grafu zależności chyba nie jest główną powinnością typów profile i interface.
podsumowując:
w zależności od sytuacji takie dwukierunkowe powiązania mogą mieć mocno odmienny rachunek zalet i wad, więc trzeba się wstrzymać od ogólnikowych zasad typu 'dwukierunkowe zależności są ogólnie dobre' (albo analogicznie 'kiepskie' zamiast 'dobre'), a zamiast tego podejść do sprawy indywidualnie (jak zwykle zresztą - jeśli znamy daną sprawę od podszewki to kierujmy się indywidualną znajomością sprawy, a nie ogólnymi regułami kciuka, które bazują na dużo mniejszym wycinku wiedzy).
p.s.
jeśli chodzi o pythona, to ten ma gc oparte o zliczanie wskaźników, więc do obsługi pętli w grafie obiektów musi stosować dodatkowe mechanizmy, a więc nie radzi sobie z nimi tak dobrze jak z resztą, tzn. nie odśmieca ich od razu. to jest oparte o mojej wiedzy o pythonie sprzed wielu lat, więc może się zmieniło, ale nie sądzę. tak czy siak, możliwe że nie jest to duży problem.