Dans quelle mesure suivez-vous strictement la règle du «cycle sans dépendance» (NDepend)

10

Un peu de contexte: En tant que chef d'équipe, j'utilise NDepend environ une fois par semaine pour vérifier la qualité de notre code. En particulier, la couverture de test, les lignes de code et les métriques de complexité cyclomatique sont inestimables pour moi. Mais en ce qui concerne les cycles de mise à niveau et de dépendance, je suis un peu ... très inquiet. Patrick Smacchia a un joli billet de blog qui décrit l'objectif de la mise à niveau.

Pour être clair: sous "cycle de dépendance", je comprends une référence circulaire entre deux espaces de noms.

Actuellement, je travaille sur une infrastructure graphique basée sur Windows CE pour les instruments intégrés - pensez à la plate-forme graphique Android mais pour les instruments très bas de gamme. Le framework est un assemblage unique avec environ 50 000 lignes de code (tests exclus). Le cadre est divisé en espaces de noms suivants:

  • Sous-système principal de navigation et de menu
  • Sous-système d'écran (Présentateurs / Vues / ...)
  • Contrôles / couche de widgets

Aujourd'hui, j'ai passé la demi-journée à essayer d'amener le code aux niveaux appropriés [grâce à Resharper, aucun problème en général] mais dans tous les cas, il existe des cycles de dépendance.

Ma question est donc la suivante: dans quelle mesure respectez-vous strictement la règle du «pas de cycle de dépendance»? La mise à niveau est-elle vraiment si importante?

ollifant
la source
2
Si "pas de cycle de dépendance" signifie pas de références circulaires, alors - pas d'excuses. Ce sont du mal pur.
Arnis Lapsa
@ollifant: définissez exactement ce que vous voulez dire lorsque vous écrivez "Pas de cycle de dépendance". Entre couches ou entre classes au sein d'une couche?
Doc Brown

Réponses:

9

J'ai récemment écrit 2 livres blancs, publiés sur Simple-Talk sur le thème de l'architecture du code .NET (le premier livre concerne les assemblages .NET, le deuxième sur les espaces de noms et la mise à niveau):

Partitionnement de votre base de code via des assemblys .NET et des projets Visual Studio

Définition de composants .NET avec des espaces de noms

La mise à niveau est-elle vraiment si importante?

Oui, ça l'est!

Citation du 2ème livre blanc:

Si le graphique des dépendances entre les composants contient un cycle, les composants impliqués dans le cycle ne peuvent pas être développés et testés indépendamment. De ce fait, le cycle des composants représente un super-composant, avec une entropie plus élevée que la somme des entropies de ses composants contenus.

(...)

Tant que la contrainte des composants acycliques est continuellement respectée, la base de code reste hautement apprenable et maintenable.

  • Dans l'architecture traditionnelle des bâtiments, la force de gravité exerce une pression sur les artefacts de faible niveau. Cela les rend plus stables: «stables» dans le sens où ils sont difficiles à déplacer.
  • En architecture logicielle, le respect de l'idée de composant acyclique a mis la pression sur les composants de bas niveau. Cela les rend plus stables, dans le sens où il est douloureux de les refaçonner. Les abstractions empiriques sont moins souvent sujettes au refactoring que les implémentations. c'est, pour cette raison, une bonne idée que les composants de bas niveau contiennent principalement des abstractions (interfaces et énumérations) pour éviter une refactorisation douloureuse.
Patrick Smacchia - NDepend dev
la source
6

Je n'autorise jamais les dépendances circulaires entre les classes ou les espaces de noms. En C #, Java et C ++, vous pouvez toujours rompre une dépendance de classe circulaire en introduisant une interface.

Le codage test-first rend difficile l'introduction de dépendances circulaires.

Kevin Cline
la source
4

C'est toujours un métier: vous devez comprendre le coût des dépendances pour comprendre pourquoi les dépendances doivent être évitées. De la même manière, si vous comprenez le coût d'une dépendance, vous pouvez mieux décider si cela vaut la peine dans votre cas spécifique.

Par exemple, dans les jeux vidéo sur console, nous comptons souvent sur des dépendances qui nécessitent des relations étroites d'informations, principalement pour des raisons de performances. C'est très bien dans la mesure où nous ne devons pas être aussi flexibles qu'un outil d'édition par exemple.

Si vous comprenez les contraintes dans lesquelles votre logiciel doit s'exécuter (qu'il s'agisse de matériel, de système d'exploitation ou simplement de conception (comme "l'interface utilisateur la plus simple que nous pouvons")), il devrait être facile de choisir de comprendre quelles dépendances ne doivent pas être faites et lesquelles sont D'accord.

Mais si vous n'avez pas de raison valable et claire, évitez toute dépendance possible. Le code dépendant est l'enfer de la session de débogage.

Klaim
la source
2

Chaque fois que ce sujet est discuté, les participants perdent généralement de vue la distinction entre les cycles de construction et d'exécution. Le premier est ce que John Lakos a qualifié de «conception physique», tandis que le second est fondamentalement sans rapport avec la discussion (ne vous laissez pas accrocher aux cycles d'exécution, tels que ceux créés par les rappels).

Cela dit, John Lakos était très strict quant à l'élimination de tous les cycles (au moment de la construction). Bob Martin, cependant, a adopté l'attitude selon laquelle seuls les cycles entre les fichiers binaires (par exemple, DLL, exécutables) étaient importants et devaient être évités; il pensait que les cycles entre les classes dans un binaire n'étaient pas terriblement importants.

Personnellement, je partage l'avis de Bob Martin à ce sujet. Cependant, je fais toujours attention aux cycles entre les classes car l'absence de tels cycles rend le code plus facile à lire et à apprendre pour les autres.

Il convient de noter, cependant, que tout code que vous créez avec Visual Studio n'est pas capable d'avoir des dépendances circulaires entre les binaires (qu'il s'agisse de code natif ou géré). Ainsi, le problème le plus grave avec les cycles a été résolu pour vous. :)

Brent Arias
la source
0

Presque totalement, car les cycles de dépendance de type build sont gênants dans Haskell, et impossibles dans Agda et Coq, et ce sont les langages que j'utilise généralement.

Robin Green
la source