71 votes

Pourquoi les références circulaires sont-elles considérées comme nuisibles ?

Pourquoi est-ce une mauvaise conception qu'un objet fasse référence à un autre objet qui renvoie au premier ?

70voto

Stephen C Points 255558

Dépendances circulaires entre classes ne sont pas nécessairement nuisibles. En effet, dans certains cas, ils sont souhaitables. Par exemple, si votre application traite des animaux domestiques et de leurs propriétaires, vous vous attendez à ce que la classe Pet ait une méthode pour obtenir le propriétaire de l'animal, et que la classe Owner ait une méthode qui renvoie la liste des animaux. Bien sûr, cela peut rendre la gestion de la mémoire plus difficile (dans un langage non CG'ed). Mais si la circularité est inhérente au problème, alors essayer de s'en débarrasser va probablement conduire à d'autres problèmes.

D'autre part, les dépendances circulaires entre modules sont nuisibles. Elles sont généralement le signe d'une structure de modules mal pensée, et/ou d'un manque de respect de la modularisation originale. En général, un code de base avec des dépendances croisées incontrôlées sera plus difficile à comprendre et à maintenir qu'un code avec une structure de modules propre et en couches. Sans modules décents, il peut être beaucoup plus difficile de prévoir les effets d'un changement. Et cela rend la maintenance plus difficile, et conduit à la "dégradation du code" résultant de Parcheando mal conçus.

(De même, les outils de construction comme Maven ne gèrent pas les modules (artefacts) avec des dépendances circulaires).

6 votes

Peut-être que la table de relation SQL classique pourrait être utilisée pour supprimer la circularité de la dépendance entre l'animal et le propriétaire ? Un objet contenant des références aux relations entre le propriétaire et l'animal et supportant des méthodes d'ensemble pour retourner des tuples de sous-ensembles dans les deux sens (ainsi que des méthodes pour ajouter et supprimer ces relations). Dans ce schéma, les classes animal et propriétaire dépendent chacune de cette classe de relation. Cependant, elle ne doit pas nécessairement dépendre de l'une ou l'autre des classes qui l'utilisent.

8 votes

@Jim - Je ne dis pas que vous ne pouvez pas supprimer la dépendance circulaire entre les classes. Par exemple, vous pourriez le faire en déclarant (disons) getOwner() pour renvoyer un Object plutôt qu'un Owner . Mais, IMO, ce genre de chose est susceptible d'entraîner des problèmes pires que la dépendance circulaire que vous avez éliminée.

58voto

LBushkin Points 60611

Les références circulaires ne sont pas toujours nuisibles - il existe des cas d'utilisation où ils peuvent être très utiles. Les listes à double lien, les modèles de graphes et les grammaires de langage informatique viennent à l'esprit. Cependant, d'une manière générale, il existe plusieurs raisons pour lesquelles vous souhaitez éviter les références circulaires entre les objets.

  1. Cohérence des données et des graphiques. La mise à jour des objets avec des références circulaires peut créer des difficultés pour garantir qu'à tout moment les relations entre les objets sont valides. Ce type de problème se pose souvent dans les implémentations de modélisation objet-relationnel, où il n'est pas rare de trouver des références circulaires bidirectionnelles entre les entités.

  2. Assurer des opérations atomiques. S'assurer que les modifications apportées aux deux objets d'une référence circulaire sont atomiques peut s'avérer compliqué, en particulier lorsque plusieurs threads sont impliqués. Assurer la cohérence d'un graphe d'objets accessible à partir de plusieurs threads nécessite des structures de synchronisation et des opérations de verrouillage spéciales pour garantir qu'aucun thread ne voit un ensemble incomplet de modifications.

  3. Les défis de la séparation physique. Si deux classes différentes A et B se réfèrent l'une à l'autre de manière circulaire, il peut devenir difficile de séparer ces classes en assemblages indépendants. Il est certainement possible de créer un troisième assemblage avec des interfaces IA et IB que A et B implémentent, permettant à chacun de référencer l'autre à travers ces interfaces. Il est également possible d'utiliser des références faiblement typées (par exemple, objet) comme moyen de rompre la dépendance circulaire, mais alors l'accès aux méthodes et aux propriétés d'un tel objet ne pourrait pas être facilement accessible - ce qui peut aller à l'encontre de l'objectif d'avoir une référence.

  4. Appliquer les références circulaires immuables. Des langages comme C# et VB fournissent des mots-clés permettant de rendre les références d'un objet immuables (en lecture seule). Les références immuables permettent à un programme de s'assurer qu'une référence renvoie au même objet pendant toute la durée de vie de l'objet. Malheureusement, il n'est pas facile d'utiliser le mécanisme d'immuabilité imposé par le compilateur pour garantir que les références circulaires ne peuvent pas être modifiées. Cela ne peut se faire que si un objet instancie l'autre (voir l'exemple C# ci-dessous).

    class A
    {
        private readonly B m_B;
        public A( B other )  { m_B = other; }
    }
    
    class B 
    { 
        private readonly A m_A; 
        public A() { m_A = new A( this ); }
    }
  5. Lisibilité et maintenabilité du programme. Les références circulaires sont par nature fragiles et faciles à briser. Cela vient en partie du fait qu'il est plus difficile de lire et de comprendre un code qui inclut des références circulaires qu'un code qui les évite. S'assurer que votre code est facile à comprendre et à maintenir contribue à éviter les bogues et permet d'apporter des modifications plus facilement et en toute sécurité. Les objets avec des références circulaires sont plus difficiles à tester à l'unité car ils ne peuvent pas être testés de manière isolée les uns des autres.

  6. Gestion de la durée de vie des objets. Si le ramasseur de déchets de .NET est capable d'identifier et de traiter les références circulaires (et de se débarrasser correctement de ces objets), ce n'est pas le cas de tous les langages/environnements. Dans les environnements qui utilisent le comptage des références pour leur système de ramassage des déchets (par exemple VB6, Objective-C, certaines bibliothèques C++), il est possible que les références circulaires entraînent des fuites de mémoire. Étant donné que chaque objet s'accroche à l'autre, leur nombre de références n'atteindra jamais zéro et ne sera donc jamais candidat à la collecte et au nettoyage.

8voto

duffymo Points 188155

Parce que maintenant, ils sont vraiment un seul et même objet. Vous ne pouvez plus tester l'un ou l'autre isolément.

Si vous en modifiez un, il est probable que vous affectez également son compagnon.

0 votes

Et s'ils implémentent la même interface ?

0 votes

@Pierreten : Même dans ce cas, c'est une mauvaise idée pour la même raison.

3 votes

@RCIX - soyez prudent. Vous venez d'exclure les graphes, certains arbres et les listes doublement liées.

7voto

Paul Points 3876

De Wikipedia :

Les dépendances circulaires peuvent causer de nombreux effets indésirables dans les logiciels. Le plus problématique du point de vue d'un logiciel logiciel, c'est le couplage étroit des couplage étroit des modules mutuellement modules mutuellement dépendants, qui réduit ou rend impossible la réutilisation séparée d'un module unique.

Les dépendances circulaires peuvent provoquer une effet domino lorsqu'une petite changement local dans un module se propage dans d'autres modules et a des effets globaux non indésirables (erreurs de programme, de compilation de compilation). Les dépendances circulaires peuvent également entraîner des récursions infinies ou d'autres échecs inattendus.

Les dépendances circulaires peuvent également causer fuites de mémoire en empêchant certaines automatiques très primitifs (ceux qui très primitifs (ceux qui utilisent le référence) de désallouer les objets inutilisés inutilisés.

1 votes

Il s'agit davantage de références d'assemblage que de références d'objet.

2 votes

Comme c'est merveilleusement "méta". Cette page SO a une référence circulaire avec Wikipedia. Cette réponse cite Wikipedia, et la page Wikipedia renvoie ici : fr.wikipedia.org/wiki/Dépendance_circulaire (voir "liens externes" sur cette page wiki)

5voto

Chuck Conway Points 10293

Lequel sera construit en premier ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X