Quand utiliser une variable d'instance d'objet par rapport à la transmission d'un argument à la méthode

93

Comment décidez-vous entre passer des arguments à une méthode et simplement les déclarer en tant que variables d'instance d'objet visibles par toutes les méthodes de l'objet?

Je préfère garder les variables d'instance dans une liste à la fin de la classe, mais cette liste s'allonge à mesure que mon programme se développe. Je pense que si une variable est transmise assez souvent, elle devrait simplement être visible par toutes les méthodes qui en ont besoin, mais je me demande alors "si tout est public, il ne sera pas nécessaire de passer quoi que ce soit!"

Ziggy
la source
1
Si vous avez des exemples spécifiques, vous pourriez obtenir des réponses plus directement utiles
brabster

Réponses:

55

Puisque vous faites référence aux variables d'instance, je suppose que vous travaillez dans un langage orienté objet. Dans une certaine mesure, quand utiliser des variables d'instance, comment définir leur portée et quand utiliser des variables locales est subjectif, mais il existe quelques règles empiriques que vous pouvez suivre chaque fois que vous créez vos classes.

  • Les variables d'instance sont généralement considérées comme des attributs d'une classe. Considérez-les comme des adjectifs de l'objet qui sera créé à partir de votre classe. Si vos données d'instance peuvent être utilisées pour aider à décrire l'objet, alors il est probablement prudent de parier que c'est un bon choix pour les données d'instance.

  • Les variables locales sont utilisées dans le cadre des méthodes pour les aider à terminer leur travail. Habituellement, une méthode doit avoir pour but d'obtenir des données, de renvoyer certaines données et / ou de traiter / d'exécuter un algorithme sur certaines données. Parfois, il est utile de penser aux variables locales comme des moyens d'aider une méthode à avancer du début à la fin.

  • La portée de la variable d'instance n'est pas seulement pour la sécurité, mais également pour l'encapsulation. Ne partez pas du principe que «l'objectif devrait être de garder toutes les variables privées». En cas d'héritage, rendre les variables protégées est généralement une bonne alternative. Plutôt que de marquer toutes les données d'instance comme publiques, vous créez des getters / setters pour ceux qui doivent être accédés au monde extérieur. Ne les rendez pas tous disponibles - uniquement ceux dont vous avez besoin. Cela se produira tout au long du cycle de vie du développement - c'est difficile à deviner dès le départ.

Lorsqu'il s'agit de transmettre des données à une classe, il est difficile de dire que ce que vous faites est une bonne pratique sans voir du code. Parfois, opérer directement sur les données de l'instance est très bien; d'autres fois, ce n'est pas le cas. À mon avis, c'est quelque chose qui vient avec l'expérience - vous développerez une certaine intuition au fur et à mesure que vos capacités de réflexion orientée objet s'amélioreront.

À M
la source
Ma réponse serait d'ajouter cette réponse à la réponse H-Man2 (à vie). Il doit s'agir d'un attribut membre si et seulement s'il s'agit d'un état persistant de l'objet. Autrement dit, la valeur a du sens en elle-même en dehors de la portée de la pile de méthodes actuelle.
David Rodríguez - dribeas
Ma réaction instinctive est d'être d'accord avec David et H-MAn2. Cependant, je lis le "code propre" de Robert c Martin et au chapitre 3, il refactorise le code pour déplacer quelque chose d'un paramètre de méthode vers une variable membre, car avoir beaucoup de paramètres est mauvais. Dans l'ensemble, je suppose que si votre classe n'a qu'une seule responsabilité, la durée de vie de l'objet est la même que la durée de vie de ce calcul, alors peut-être que la réponse réelle est que si vous devez poser cette question, votre classe est trop grande?
Andy
@ DavidRodríguez-dribeas qu'entendez-vous par pile de méthodes?
commitandroider
@committedandroider: si la valeur survit à l'appel de fonction actuel
David Rodríguez - dribeas
46

Cela dépend principalement de la durée de vie des données que vous stockez dans la variable. Si les données ne sont utilisées que lors d'un calcul, transmettez-les en paramètre. Si les données sont liées à la durée de vie de l'objet, utilisez une variable d'instance.

Lorsque votre liste de variables devient trop longue, c'est peut-être un bon point de penser à refactoriser certaines parties de la classe dans une nouvelle classe.

H-Man2
la source
21

À mon avis, les variables d'instance ne sont nécessaires que lorsque les données seront utilisées à travers les appels.

Voici un exemple:

myCircle = myDrawing.drawCircle(center, radius);

Maintenant, imaginons que la classe myDrawing utilise 15 fonctions d'assistance pour créer l'objet myCircle et chacune de ces fonctions aura besoin du centre et du rayon. Ils ne doivent toujours pas être définis comme variables d'instance de la classe myDrawing. Parce qu'ils ne seront plus jamais nécessaires.

D'autre part, la classe myCircle devra stocker à la fois le centre et le rayon en tant que variables d'instance.

myCircle.move(newCenter);
myCircle.resize(newRadius);

Pour que l'objet myCircle sache quel est son rayon et son centre lorsque ces nouveaux appels sont effectués, ils doivent être stockés en tant que variables d'instance, et pas seulement transmis aux fonctions qui en ont besoin.

Donc, fondamentalement, les variables d'instance sont un moyen de sauvegarder "l'état" d'un objet. Si une variable n'est pas nécessaire pour connaître l'état d'un objet, alors ce ne devrait pas être une variable d'instance.

Et comme pour tout rendre public. Cela pourrait vous faciliter la vie sur le moment. Mais il reviendra vous hanter. Ne vous en faites pas.

ng.mangine
la source
Vous pouvez simplement définir move pour utiliser les paramètres (oldCenter, newCenter).
obesechicken13
4

A MON HUMBLE AVIS:

Si la variable fait partie de l'état de l'instance, alors il doit s'agir d'une variable d'instance - classinstance HAS-A instancevariable.

Si je me retrouvais à passer quelque chose à plusieurs reprises dans les méthodes d'une instance, ou si je découvrais que j'avais un grand nombre de variables d'instance, j'essaierais probablement de regarder ma conception au cas où j'aurais manqué quelque chose ou fait une mauvaise abstraction quelque part.

J'espère que ça aide

brabster
la source
3

Bien sûr, il est facile de conserver une grande liste de variables publiques dans la classe. Mais même intuitivement, vous pouvez dire que ce n'est pas la voie à suivre.

Définissez chaque variable juste avant de l'utiliser. Si une variable prend en charge la fonction d'une méthode spécifique, utilisez-la uniquement dans le cadre de la méthode.

Pensez également à la sécurité, une variable de classe publique est sensible aux modifications indésirables du code «extérieur». Votre objectif principal devrait être de garder toutes les variables privées, et toute variable qui ne l'est pas devrait avoir une très bonne raison de l'être.

À propos du passage des paramètres tout au long de la pile, cela peut devenir très rapide. Une règle de base est de garder vos signatures de méthode propres et élégantes. Si vous voyez de nombreuses méthodes utilisant les mêmes données, décidez si c'est suffisamment important pour être un membre de classe, et si ce n'est pas le cas, refactorisez votre code pour qu'il ait plus de sens.

Cela revient au bon sens. Pensez exactement où et pourquoi vous déclarez chaque nouvelle variable, quelle doit être sa fonction, et à partir de là, décidez dans quelle portée elle doit vivre.

Yuval Adam
la source
Vous voulez souvent que les méthodes soient publiques afin de pouvoir les tester unitaire.
obesechicken13