2012-08-04 2 views
10

J'ai remarqué que même en respectant le principe de responsabilité unique de l'OOD, parfois les classes grandissent encore. Parfois, l'accès direct aux variables membres dans les méthodes semble avoir un état global, et beaucoup de choses existent dans la portée actuelle. Juste en regardant la méthode qui fonctionne actuellement, il n'est plus possible de déterminer d'où viennent les variables inviduelles accessibles dans la portée actuelle. Lorsque je travaillais avec un ami ces derniers temps, je me suis rendu compte que j'écrivais beaucoup plus de code verbeux que lui, parce que je transmets toujours des variables membres en tant que paramètres dans chaque méthode.Accéder directement aux variables membres ou passer en paramètre?

Est-ce une mauvaise pratique?

edit: exemple:

class AddNumbers { 
public: 
    int a, b; 
    // ... 
    int addNumbers { 
     // I could have called this without arguments like this: 
     // return internalAlgorithmAddNumbers(); 
     // because the data needed to compute the result is in members. 
     return internalAlgorithmAddNumbers(a,b); 
    } 

private: 
    int internalAlgorithmAddNumbers(int sum1, int sum2) { return sum1+sum2; } 
}; 
+1

Si vos classes sont trop grandes, séparez-les. Si vous avez une variable membre, utilisez-la. Si vous n'utilisez pas de variables membres dans une méthode, il devrait probablement être 'static', mais faire beaucoup de choses semble étrange. – Flexo

+1

Excusez-moi, je semble avoir un léger problème avec votre anglais. Vous transmettez des variables membres en tant que paramètres? Variables membres publiques? Ou de nouvelles valeurs pour ces variables membres? Je suis un peu confus. – ATaylor

+0

Désolé que je n'étais pas clair sur ce point. Lors de l'implémentation d'un algorithme, je réitère généralement les paramètres qu'il prend dans la signature de la méthode, bien que les données dont l'algorithme a besoin puissent être extraites directement des variables membres. Supposons que vous avez une classe, qui ajoute deux nombres, et a les 2 nombres a et b comme variables membres. Alors au lieu d'avoir une méthode add privée avec des paramètres zéro, je définirais toujours une fonction en prenant 2 arguments int. Comme ça, je pourrais réutiliser l'algorithme plus tard en dehors d'une classe. – Tom

Répondre

5

Si une classe a des variables membres, les utiliser. Si vous voulez transmettre des paramètres explicitement, faites-en une fonction gratuite. Le fait de passer des variables membres non seulement rend le code plus bavard, mais aussi viole les attentes des gens et rend le code difficile à comprendre.

L'objectif entier d'une classe est de créer un ensemble de fonctions avec un état partagé implicitement passé. Si ce n'est pas ce que vous voulez faire, n'utilisez pas de classe.

2

Oui, certainement une mauvaise pratique. Passer une variable membre à une fonction membre n'a aucun sens, de mon point de vue. Il présente plusieurs inconvénients:

  1. lisibilité code Diminution
  2. coût en terme de performances pour copier le paramètre sur la pile

Finalement, la conversion de la méthode pour une fonction simple, peut avoir un sens. En effet, du point de vue des performances, l'appel à la fonction non-membre est en réalité plus rapide (il n'est pas nécessaire de déréférencer ce pointeur).

EDIT:

Répondez à vos commentaires. Si la fonction peut effectuer son travail uniquement en utilisant quelques paramètres passés explicitement, et n'a besoin d'aucun état interne, il n'y a probablement aucune raison de déclarer qu'elle a une fonction membre. Utilisez un simple appel de fonction de style C et transmettez-lui les paramètres.

+0

C'est exactement mon point dans la question. Parce que je pense que cela augmente réellement la lisibilité du code, aucun nom externe magique n'apparaît dans votre portée locale. Il y a longtemps, on m'a enseigné que les variables globales sont de très mauvais style, et l'accès à une variable membre a parfois l'impression d'utiliser des variables globales. Vous accédez à quelque chose qui n'est ni dans votre portée locale, ni transmis de l'extérieur en tant que paramètre. – Tom

+1

Les membres de classe @Tom ne sont pas globaux - ils sont délibérément explicitement locaux à l'instance de la classe avec laquelle vous travaillez. Votre classe est une encapsulation d'un petit état lié. Si ce n'est pas le cas, vous avez de plus gros problèmes de conception qui ne peuvent pas être réparés comme ça. Dans l'exemple que vous avez donné, je serais tenté de rendre vos instances immuables même. – Flexo

1

Je comprends le problème, ayant eu à maintenir de grandes classes dans le code que je n'ai pas d'origine auteur. En C++, nous avons le mot clé const pour aider identifier les méthodes qui ne changent pas l'état:

void methodA() const; 

L'utilisation de ce aide maintenabilité parce que nous pouvons voir si une méthode peut changer l'état d'un objet.

Dans d'autres langues qui n'ont pas ce concept, je préfère être clair quant à savoir si je change l'état de la variable d'instance soit par l'avoir transmise par référence ou le changement de retour

this->mMemberVariable = this->someMethod(); 

Plutôt que

void someMethod() 
{ 
    this->mMemberVariable = 1; // change object state but do so in non transparent way 
} 

J'ai trouvé au cours des années que cela rend plus facile de maintenir le code.

Questions connexes