Comment le fait d'avoir trop de variables d'instance conduit-il à du code en double?

19

Selon Refactoring to Patterns :

Lorsqu'une classe essaie d'en faire trop, elle apparaît souvent comme trop de variables d'instance. Lorsqu'une classe a trop de variables d'instance, le code dupliqué ne peut pas être loin derrière.

Comment le fait d'avoir trop de variables d'instance conduit-il à du code en double?

q126y
la source
2
Autrement dit: les nvariables booléennes, par exemple, créent un espace d'état interne de 2^n. Plus souvent qu'autrement, votre objet n'a pas autant d' états observables , mais parce que vous avez regroupé tout cet état en un seul objet, en interne, vous devez toujours les gérer tous.
biziclop

Réponses:

23

Le fait d'avoir trop de variables d'instance n'est pas directement lié au code en double, ou vice versa. Cette affirmation, dans cette généralité, est fausse. On peut jeter deux classes distinctes sans code en double dans une seule classe - ce qui produit une nouvelle classe avec des responsabilités non séparées et trop de variables d'instance, mais toujours pas de code en double.

Mais lorsque vous trouvez une classe avec trop de responsabilités dans le code hérité du monde réel, les chances sont élevées que le programmeur qui l'a écrit ne se soucie pas du code propre ou des principes SOLIDES (du moins, pas au moment où il a écrit ce code), donc son il est peu probable que vous y trouviez d'autres odeurs de code comme du code en double.

Par exemple, l'anti-modèle "réutilisation copier-coller" est souvent appliqué en copiant une ancienne méthode et en y apportant quelques légères modifications, sans refactorisation appropriée. Parfois, pour que cela fonctionne, il faut dupliquer une variable membre et modifier aussi légèrement cette variable. Cela pourrait entraîner une classe avec trop de variables d'instance (plus précis: trop de variables d'instance très similaires). Dans une telle situation, les variables d'instance similaires peuvent être un indicateur de code répété ailleurs dans la classe. Cependant, comme vous l'avez noté, il s'agit d'un exemple artificiel et je n'en conclurais pas une règle générale.

Doc Brown
la source
11

Trop de variables d'instance signifie trop d'état. Trop d'état conduit à un code dupliqué qui n'est que légèrement différent pour chacun des états.

C'est une classe concrète unique classique qui fait trop de choses qui devraient être des sous-classes ou des compositions.

Trouvez quelques classes qui ont trop de variables d'instance, vous verrez qu'elles maintiennent beaucoup trop d'état et ont beaucoup de chemins de code dupliqués qui ne sont que légèrement spécialisés pour chaque cas, mais si compliqués qu'ils ne peuvent pas être séparés en méthodes réutilisables. C'est également l'une des sources side effectsles plus importantes.

Il y a au moins une exception à cela qui ne tombe pas dans cette catégorie et est un moyen facile de remédier à cela. Immutableles objets n'ont pas ce problème, car ils sont un état fixe, il n'y a aucune chance de gestion d'état alambiquée ou d'effets secondaires.


la source
7

La déclaration que vous citez doit être vue dans un contexte spécifique.

D'après mon expérience, je ne peux pas confirmer que "de nombreuses variables d'instance indiquent en général du code dupliqué". Notez également que cela appartient au "code odeurs" et qu'il y aurait des odeurs contradictoires. Jetez un œil ici:

http://c2.com/cgi/wiki?CodeSmell

De manière amusante, vous constaterez que «trop de variables d'instance» est aussi bonne qu'une odeur de code que «trop peu de variables d'instance».

Mais il y a des problèmes avec les variables d'instance, que ce soit trop peu ou trop:

  1. Chaque variable d'instance peut signifier une sorte de statut de l'objet. Stati a toujours besoin d'un traitement soigneux. Vous devez vous assurer que vous avez couvert toutes les combinaisons possibles de stati afin d'éviter un comportement inattendu. Vous devez toujours clairement maintenant: quel est le statut de mon objet en ce moment? Sous cet angle, de nombreuses variables d'instance peuvent indiquer que la classe est devenue impossible à maintenir. Cela peut également indiquer qu'une classe fait trop de travaux, car elle a besoin de tant de stati.

  2. Chaque variable d'instance vous oblige à surveiller, quelles méthodes modifient la variable de quelle manière. Du coup, tu ne connais plus tous les cuisiniers qui cuisinent. L'un d'eux, programmé avec fatigue tard le soir, gâtera votre soupe. Encore une fois: trop de ces variables conduiront à un code difficile à pénétrer.

  3. L'autre côté: trop peu de variables d'instance peuvent faire en sorte que de nombreuses méthodes doivent gérer leurs informations avec trop de travail et avec trop de paramètres. Vous le ressentez si vous donnez à plusieurs de vos méthodes un certain paramètre égal, et toutes les méthodes font quelque chose de très similaire avec ce paramètre. Dans cette situation, votre code commencera à gonfler. Vous finirez par faire défiler de nombreux écrans de haut en bas afin de rassembler des choses simples. Ici, une refactorisation peut aider: introduisez une variable d'instance et une entrée claire pour celle-ci. Ensuite, libérez toutes les méthodes.

  4. Dernier point mais non le moindre: si de nombreuses variables d'instance d'une classe ont chacune leur setter et leur getter, cela peut indiquer que d'autres classes n'utilisent pas cette première classe de la bonne façon. Il y a une discussion sur " Pourquoi les getters et les setters sont mauvais ". L'idée en bref est que si une classe en Rectanglepropose getX(), et que des dizaines d'autres classes l'utilisent rectangle.getX(), alors vous écrivez du code qui n'est pas robuste contre «l'effet d'entraînement» (dans quelle mesure un changement de code influence-t-il un autre code). Demandez simplement ce qui se passe si vous changez le type de inten double? Selon cette discussion, bon nombre des rectangle.getX()appels devraient en fait mieux être des appels commerectanlge.calculateThisThingForMe(). Ainsi, très indirectement, du code dupliqué pourrait émerger de nombreuses variables d'instance, car de nombreuses classes utilisent de nombreux getters et setters faisant des choses très similaires, c'est-à-dire des choses copiées, qui devraient mieux être déplacées à l'intérieur de la classe.

Beaucoup ou quelques variables d'instance restent un compromis permanent, modifiant les deux sens pendant la croissance du logiciel.

peter_the_oak
la source
La citation R-to-P est trop générale, c'est pourquoi j'aime cette réponse. Ma conclusion est la suivante: si nous exposons suffisamment de propriétés, un client peut et veut les prendre et écrire sa propre version d'une fonctionnalité donnée - # 4 ci-dessus. Le problème peut aller aussi loin que la composition de l'objet - voir # 2: Je le vois trop souvent dans notre code. (a) "pourquoi n'ont-ils pas utilisé la classe <différemment> (pour corriger une partie de cet état non organisé)? ou (b) "Pourquoi n'ont-ils pas fait un nouveau cours? Je ne peux pas tout suivre." Et bien sûr, nous avons plusieurs classes dupliquant en interne des fonctionnalités faute d'une classe cohérente.
radarbob
6

En termes simples: mauvaise séparation des préoccupations au sein du code, conduit à un code qui n'est pas modulaire, conduit à une mauvaise réutilisation, conduit à du code dupliqué.

Si vous n'essayez jamais de répéter la fonctionnalité, vous n'obtiendrez pas de code dupliqué et de nombreuses variables d'instance ne seront pas un problème.

Si vous essayez de répéter des fonctionnalités, le code monolithique, qui n'est pas modulaire, ne peut pas être réutilisé. Il en fait trop et ne peut faire que ce qu'il fait. Pour faire quelque chose de similaire, mais pas pareil, il est "plus facile" de couper et coller, plutôt que de briser le code monolithique. Les programmeurs d'expérience savent que le code dupliqué est le chemin de l'enfer.

Ainsi, bien que de nombreuses variables d'instance en elles-mêmes ne soient pas la cause première du problème, c'est une forte "odeur" que le problème vient.

Le langage "ne peut pas être loin derrière" est plus faible que de dire "doit sûrement suivre", donc l'auteur ne prétend pas que cela doit arriver mais finira par arriver; si vous devez réutiliser des fonctionnalités mais ne le pouvez pas car le code n'est pas modulaire.

simbo1905
la source