2009-04-29 3 views
3

Je suis intéressé à explorer l'idée que la relation entre les méthodes et les membres varialbes qu'ils utilisent peut donner un indice sur la façon dont la classe pourrait être divisée en plus petits morceaux. L'idée est qu'un groupe de variables sera étroitement lié à une responsabilité et devrait être contenu dans une classe selon la SRP.Est-ce que vous regardez les variables utilisées par une méthode avant de refactoriser une grande classe en plus petites?

Pour un exemple trivial, une classe telle que:

public class Rectangle { 
    private int width; 
    private int height; 
    private int red,green,blue; 
    public int area() { return width * height; } 
//just an example, didn't check the api. 
    public Color color() { return new Color (red, green, blue); } 
} 

Devrait être remaniée:

public class Rectangle { 
    private Dimension size; 
    private Color color; 
    ... 
} 

Parce que le bas de rupture serait:

Zone: largeur, hauteur Couleur: rouge, vert, bleu

Puisque ces variables sont nous ed dans la même méthode, ils sont clairement liés et pourraient être transformés en une classe à part. Je sais que cet exemple pourrait être trop trivial mais supporter avec moi et essayer et penser plus grand ici. Si d'autres méthodes utilisent également ces variables, elles sont très probablement également liées et peuvent également être déplacées dans la nouvelle classe.

Juste pour le plaisir que j'ai créé un peu plugin for Eclipse qui essaye de faire ceci. Il aura une décomposition sur méthodes-> variables, variables-> et essayera aussi de regrouper les méthodes après quelles variables elles utilisent directement ou indirectement.

Est-ce quelque chose que vous faites lors du codage, et est-ce vraiment utile?

+0

Alors, quelle est la question ici? – Lucero

+0

Vous voulez dire en fait des variables membres, pas des instances, n'est-ce pas? – kgiannakakis

+0

@Lucero - Il y a quelques questions. Ils peuvent être identifiés en étant suivis d'un point d'interrogation (?). – willcodejavaforfood

Répondre

0

On dirait que quelqu'un a lu le Law of Demeter et tente de le prendre à l'extrême. Je dois dire que je traite toujours les fanatiques du «découplage» avec une certaine méfiance, notamment parce que certains préconisent un «couplage nul» dans la conception, tout en ignorant le fait que sans aucun couplage, un système est inutile. Néanmoins, en réduisant les dépendances dans le code, il est plus facile à tester et plus résilient aux autres refactoring, et je trouve qu'il a tendance à conduire à un code plus simple et plus évident. Un équilibre sain est l'objectif à atteindre.

+0

Je pense que vous avez peut-être mal compris. C'est à propos de ce que les méthodes utilisant un ensemble similaire de variables appartiennent à la même classe. Permet également d'essayer et d'éviter de se concentrer dans les cas extrêmes. – willcodejavaforfood

2

Je ne peux pas dire que cela a déjà été quelque chose que j'ai pensé pendant le codage. Oui, cela pourrait entraîner une certaine amélioration, mais je pense que ce que vous pourriez faire en pratique, c'est créer un grand nombre de cours qui seraient encore plus difficiles à gérer. Cependant, il peut y avoir un certain mérite en tant que «odeur de code». Si vous voyez une classe avec des tonnes de variables membres, et la plupart ne sont utilisées que par une poignée de méthodes, c'est généralement un mauvais signe.

-1

Cela semble être une mauvaise idée dans l'ensemble. Tout d'abord, une classe représente une collection de données et/ou de méthodes associées. Il n'a pas du tout besoin d'avoir des méthodes pour être toujours une classe utile. Pour une bonne encapsulation, vous pourriez vouloir des getters et setters; ces méthodes par définition n'accèderont pas à plus d'une variable. Cela n'implique en rien que ces variables appartiennent ou non à la même classe. Enfin, une méthode appartient à la classe si elle fournit un moyen de manipuler la classe, de calculer quelques informations sur elle-même, de construire la classe, etc .; Il existe des raisons infinies pour qu'une méthode appartienne à une classe mais n'accède pas à la plupart des variables membres. Ensuite, il y a des méthodes statiques; devraient-ils par définition être dans d'autres classes?

Une classe doit être divisée si elle contient trop de concepts. Mais ces concepts ne correspondent qu'aux méthodes et aux variables. Le comptage des utilisations variables est un moyen infaillible de compliquer votre hiérarchie de classe sans bénéfice.

+0

Évidemment, les getters et les setters sont omis de cette analyse. Suivez le lien pour la documentation complète sur le plugin. – willcodejavaforfood

1

Je pense que chaque classe devrait être organisée par ce qu'elle fait, et non par les variables qu'elle utilisera. Je recommanderais de faire en sorte que chaque cours ait un seul but (principe de responsabilité unique). Au lieu de casser les choses en fonction de leur utilisation de variables, les classes séparées en fonction de leur responsabilité ou de leur but. À mon avis, écrire du code propre n'est pas seulement un bon aspect du code, mais aussi sa facilité de lecture. Le code doit être groupé logiquement et avoir un style cohérent. Gardez à l'esprit que certaines classes ne vont pas utiliser toutes les variables. En Java, vous avez des méthodes de mutateur et d'accesseur. Ces méthodes sont utilisées pour obtenir ou définir une seule variable.

Exemple:

public class Rectangle { 

    private int lenght = 0; 
    private int width = 0; 

    public Rectangle (int length, width) 
     { 
     this.length = length; 
     this.width = width; 
    } 

    public int getLength(int length) 
    { 
     return length; 
    } 

    public int getWidth(int width) 
    { 
     return wdith; 
    } 


    public void setLength(int length) 
    { 
     this.length = length; 
    } 

    public void setWidth(int width) 
    { 
     this.width = width; 
    } 
} 

Je ne cassera pas cette classe dans une classe RectangleLength et RectangleWidth. Ces méthodes servent une seule responsabilité et c'est de représenter un rectangle. Si cette classe contenait des fonctions mathématiques, vous pourriez vouloir la décomposer en classe RectangleGeometry.

+0

Cet exemple est simple à comprendre. Je pensais que ce serait évident qu'il serait utilisé pour des classes plus compliquées que les simples getters et setters :) – willcodejavaforfood

+0

Je pense que vous manquez le point. Si vous ne pouvez pas appliquer ce train de pensée à un exemple simple, comment pouvez-vous l'appliquer à un exemple plus compliqué? – sgmeyer

2

Je peux imaginer une situation où c'est une odeur de code raisonnable. Les simples setters/getters dans notre exemple ne sont pas trop persuasifs. Par exemple, refactoring fait qu'un objet plus complexe qui porte a et b autour de:

public class A { 
    private String a1; 
    public void aMeth() { 
    print(a1); 
    } 
} 
public class B { 
    private String b1; 
    public void bMeth() { 
    print(b1); 
    } 
} 

public class A { 
    private A a; 
    private B b; 
    ... insert infinite regress 
} 

Cependant, je peux voir cela comme un guide où vous avez des ensembles de variables empêtrés dans les grandes classes de monstres, où les groupements variables correspondent à la décomposition conceptuelle. Pensez-vous plus à quelque chose comme ça?

public class Rectangle { 
    private int width; 
    private int height; 
    private int red,green,blue; 
    public int area() { return width * height; } 
//just an example, didn't check the api. 
    public Color color() { return new Color (red, green, blue); } 
} 

Lorsque le rectangle doit avoir une dimension et une couleur. Il me semble que si vous pouvez clairement trouver des ensembles de variables privées qui s'emmêlent seulement les uns avec les autres, c'est une chose utile, tant que vous omettez les variables non enchevêtrées (ie Si vous pensez aux variables comme des sommets de graphes, je pense vous voudriez détecter les sous-graphes connectés mais omettez les sous-graphes de taille 1)

+0

Oui, c'est plus dans le sens de ce que je pensais qu'il serait utile. Le plugin crée un graphique et trouve les méthodes qui sont connectées via leurs variables. – willcodejavaforfood

1

J'ai fait ceci. Même créé un tableau, les méthodes de la première colonne, les variables d'instance en haut, avec un X pour indiquer qui utilise qui. Puis trier - sorte de heatmaps comme sont triés, mais plus à la légère, plus manuellement - pour voir quelles variables, et quelles méthodes, suivre ensemble. Cela fonctionne et c'est utile. Mais c'est au fond de mon sac de trucs; Je l'ai rarement utilisé. Je vais devoir vérifier votre plugin; si c'était moins de travail pour le faire, je pourrais le faire plus.

+0

Oui s'il vous plaît essayez le plugin et laissez-moi savoir ce que vous pensez – willcodejavaforfood

+0

Je ne pouvais pas le faire fonctionner. Installé dans mon dossier plugins, redémarré Eclipse, Windows-> Afficher les vues-> Autre ----> (Refactoring non trouvé). Je suis sur Windows, Eclipse 3.4.2, Build M20090211-1700. Il y a un message dans le journal des erreurs, trop long pour ici. écrivez-moi à mon nom de famille @ pobox.com pour le journal (je n'ai pas trouvé vos coordonnées). –

+0

Un an en retard avec ma réponse et je vous ai envoyé un courriel. C'est en fait la même construction que j'utilise. – willcodejavaforfood

1

C'est certainement une bonne approche de refactoring. Dans Working Effectively With Legacy Code, Michael Feathers décrit une technique pour cela dans une section intitulée Responsabilités Seeing:

Heuristique # 4 Rechercher des relations internes

Rechercher les relations entre les variables et les méthodes exemple. Certaines variables d'instance sont-elles utilisées par certaines méthodes et pas d'autres?

Il va ensuite décrire une méthode où vous dessinez un diagramme appelé esquisse de la fonction , qui est un graphique montrant les méthodes d'une classe et des appels de méthode internes. À partir du diagramme, vous pouvez facilement identifier visuellement des groupes d'appels de méthode interconnectés qui sont candidats à la refactorisation dans une nouvelle classe plus cohérente.

Il serait très cool que votre plugin Eclipse puisse générer rapidement un graphe comme décrit dans le livre - je pourrais le voir comme un outil de refactoring utile.

+0

Merci Ken. Cela semble vraiment intéressant même si ce n'est pas tout à fait ce que mon plugin s'est focalisé dessus c'est toujours le même principe. Sorte de. Je vais regarder en ajoutant que :) – willcodejavaforfood

+0

Les choses dans le livre ressemble exactement à ce que vous avez décrit. Le diagramme n'est pas seulement pour les méthodes, c'est aussi les méthodes et les variables d'instance. La visualisation est la clé IMO - malheureusement, il n'y a pas assez d'espace ici pour moi de décrire complètement ce qui est dans le livre. L'idée de base est que c'est juste un outil pour déterminer comment décomposer une grande classe - si vous pouvez automatiser le processus, ce serait beaucoup mieux. Si vous n'avez pas lu le livre, je vous recommande vivement de jeter un coup d'œil sur le livre - c'est le livre le meilleur et le plus pratique sur refactoring que j'ai vu. –

Questions connexes