Comment résoudre les dépendances de packages circulaires

11

Je refactorise une grande base de code où la plupart des classes sont situées dans un seul paquet. Pour une meilleure modularité, je crée des sous-packages pour chaque fonctionnalité.

Je me souviens avoir appris quelque part qu'un graphique de dépendance de package ne devrait pas avoir de boucles, mais je ne sais pas comment résoudre le problème suivant: Figureest dans le package figure, Layoutest dans le package layout, Layoutnécessite la figure pour effectuer la mise en page, donc le package layoutdépend du package figure. Mais d'un autre côté, un Figurepeut contenir d'autres Figures à l'intérieur, ayant le sien Layout, ce qui rend le paquet figuredépendant du paquet layout.

J'ai pensé à quelques solutions, comme créer une Containerinterface qui Figureimplémente et la mettre dans le Layoutpackage. Est-ce une bonne solution? D'autres possibilités?

Merci

vainolo
la source
Ce sont des modules (par exemple différents Jars) qui ne peuvent pas avoir de dépendances circulaires. Les packages PEUVENT et ont souvent des dépendances circulaires, tant qu'ils appartiennent au même module.
lorus
@lorus Ce n'est donc pas un problème de conception?
vainolo
2
Non, ça ne l'est pas. Les packages ne sont normalement que des espaces de noms. Cela ne peut changer que lorsqu'ils sont utilisés pour autre chose, par exemple pour changer la visibilité de leur contenu dans l'environnement OSGi. Ne vous embêtez pas autrement.
lorus
1
Notez que de nombreuses autorités condamnent les dépendances cycliques, et parfois avec raison, mais avant de procéder à une refonte aveugle, vous devez vous assurer que l'une de ces raisons s'applique réellement à vous. Si la structure du package ne vous pose aucun problème et que vous ne pouvez pas, en toute conscience, comprendre pourquoi cela changerait à l'avenir, ne changez rien de si fondamental juste pour satisfaire des valeurs architecturales abstraites.
Kilian Foth

Réponses:

9

Vous devriez penser à l' inversion du contrôle

Vous définissez essentiellement une interface pour votre Layoutqui est située quelque part près de votre classe Layout dans un propre package afin que vous ayez un package d'implémentation et un package d'interface publique - par exemple, l'appelez Layoutable(je ne sais pas si c'est le bon anglais). Maintenant - Layout n'implémentera pas cette interface mais la Figureclasse. De même, vous créez une interface pour Figure, Drawablepar exemple.

Donc

my.public.package.Layoutable
my.implementation.package.Layout
my.public.package.Drawable
my.implementation.package.Figure

Maintenant - Figure implémente Layoutable et peut donc être utilisé par Layout et (je ne suis pas encore sûr si c'est ce que vous vouliez) - Layout implémente Drawable et peut être dessiné dans une figure. Le fait est que la classe qui expose un service le rend disponible par une interface (ici: Layout et Layoutable) - la classe qui veut utiliser ce service doit implémenter l'interface.

Vous auriez alors quelque chose comme un objet créateur qui lie les deux ensemble. Ainsi, le créateur aurait une dépendance Layoutaussi bien que envers Figure, mais lui Layout- Figuremême serait indépendant.

Voilà l'idée approximative.

Une excellente source de solutions à ces problèmes est le livre Java Application Architecture de Kirk Knoernschild.

michael_s
la source
N'est-ce pas la même que l' Containerinterface comme suggéré dans la question?
vaughandroid
Oui - et non - je ne les mettrais pas tous les deux dans le même paquet que je l'ai dit. Et il n'y avait pas beaucoup de théorie derrière. Et dans ce cas, il ne suffit pas de le faire d'un côté, vous devrez le faire des deux côtés. Bien?
michael_s
Oups, j'ai manqué le bit dans la question d'origine sur le fait d' Containeraller dans le même paquet que Layout. Cela ne fonctionnerait pas, alors que votre solution fonctionnerait.
vaughandroid
ah - ok - il me semblait avoir raté la partie avec le conteneur quand je piratais - j'aurais dû le nommer conteneur;)
michael_s
0

Je ne suis pas trop clair sur ce qu'est un Figure, mais peut-être devrait-il être dans le même paquet que Layout?

Votre Containersolution d'interface proposée ne fonctionnerait pas - à moins que vous ne mettiez l' Containerinterface dans un troisième package, vous auriez toujours une dépendance circulaire entre les deux packages. Voir la réponse de michael_s pour quelque chose qui fonctionnerait.

Une autre chose, comme d'autres l'ont mentionné - ce ne sera probablement jamais un problème. Vous allez seulement à rencontrer des problèmes à l' avenir si Figureet Layoutveulent être séparés des modules . Vous pouvez gérer cela si et quand cela devient nécessaire, mais étant donné que les deux classes semblent assez étroitement liées, cela semble hautement improbable.

vaughandroid
la source