Champs vs arguments de méthode [fermé]


9

Je viens de commencer à écrire une nouvelle classe et j'ai pensé que j'ajoutais beaucoup d'arguments de méthode qui ne sont pas strictement nécessaires. Ceci suit une habitude pour éviter d'avoir un état dans les classes qui est spécifique à un appel de méthode, plutôt que d'être une configuration générale ou des dépendances de la classe.

Cela signifie qu'un grand nombre de méthodes qui ne peuvent avoir aucun argument se retrouvent avec un, deux ou trois.

J'aimerais avoir votre avis sur ce que vous pensez de ce compromis et comment vous décidez de l'approche à adopter dans quelle situation?

Étant donné que le code est souvent plus facile à comprendre que l'anglais lors de la description du code, j'ai créé un petit résumé qui contient les deux variantes: https://gist.github.com/JeroenDeDauw/6525656


Les arguments qui sont utilisés uniquement en tant que variable locale (non globale pour la durée de vie de l'objet) ne devraient être dans la portée que si cela a du sens ... Je trouve cela très irritant lorsque les développeurs stockent l'état non-instance comme état d'instance parce que c'est pratique ... Juste mon avis cependant. Il est difficile de voir comment le flux d'exécution est réellement.
Max

L'utilisation de paramètres et le fait de laisser la classe prendre soin de savoir si elle doit ou non changer d'état lors de l'exécution d'une méthode, est parfaitement lié au principe «ne demande pas» . Gardez à l'esprit que Tell ne demande pas ne signifie pas que vous ne pouvez pas interroger un objet sur son état ( prise flagrante )
Marjan Venema

Réponses:


2

Étant donné que la seule méthode visible de l'extérieur de votre exemple est updateTable, je pense qu'il est bon d'utiliser des champs au lieu de paramètres de méthode.

Si cela fait partie d'une classe plus générique (par exemple TableTools), je déplacerais les méthodes d'assistance qui ont besoin de l'état dans une classe interne cachée.

Exemple de pseudo-code:

class TableTools {
    ...
    public void updateTable(currentTable, newTable) {
        TableUpdater u = new TableUpdater(schemaModifier, currentTable, newTable);
        u.removeRemovedFields();
        u.addAddedFields();
     }

     private class TableUpdater { ... }
}

De cette façon, vous évitez les champs qui sont utilisés par une seule méthode publique. En outre, le code est thread-safe dans le sens où chaque appel à updateTable utilise sa propre copie de TableUpdater et, par conséquent, des variables d'instance de TableUpdater.


7

L'utilisation de champs permet de rendre disponible le multithreading pour les méthodes qui utilisent ces champs.

L'utilisation de champs comme celui-ci n'est que légèrement meilleure que l'utilisation des globaux du point de vue de la réutilisabilité et de la maintenabilité, le point clé ici est que les configurations complexes ont besoin d'une documentation minutieuse et à jour sur les méthodes qui utilisent et / ou clobber quels champs; quelque chose que vous n'avez pas besoin de faire lorsque vous utilisez des arguments.


Le multithreading n'est pas pertinent pour mon cas d'utilisation, comme c'est le cas en PHP. Je suis d'accord que cette approche est mauvaise si la façon dont les champs sont utilisés n'est pas anodine. Dans ce cas, ils ne sont écrits (et toujours écrits) qu'à partir de la seule méthode publique. Je ne prévois pas que cela cause des problèmes. Quant à des domaines comme celui-ci qui ne sont que légèrement meilleurs que les mondiaux, je ne sais pas trop ce que vous voulez dire. Peux-tu élaborer?
Jeroen De Dauw

7

Dans les mots du profane:

  • les méthodes doivent avoir le moins d'arguments possible (Martin's Clean Code)
  • l'une des caractéristiques des objets est qu'ils peuvent (et devraient) avoir un état
  • les méthodes non statiques qui n'opèrent pas sur l'état de l'objet, c'est-à-dire qui reçoivent tout comme paramètres, ne sont pas cohérentes
  • les méthodes non cohésives pourraient aussi bien être rendues statiques et regroupées dans une classe d'utilité

Encore une fois, à mon humble avis, les méthodes non cohésives appartiennent à une classe d'utilité et non à une classe avec un nom de domaine.


1

N'utilisez pas de champs dans le cas actuel! Deux "fils" utilisant l'objet en même temps vont sérieusement se confondre. Ils ne doivent pas non plus être de vrais threads séparés (d'où les guillemets). Si vous configurez l'objet pour une table, puis appelez une méthode qui l'utilise pour une autre table, puis essayez d'utiliser la configuration d'origine, vous avez un problème. Restez avec les paramètres pour le moment.

Ce que vous voulez faire ici, c'est créer une nouvelle classe de mise à jour qui est utilisée dans un seul cas. La classe d'origine pourrait avoir une méthode pour créer une instance chaque fois que nécessaire. La nouvelle classe aurait des champs. Vous avez le meilleur des deux mondes. Parfois, il est plus simple de s'en tenir aux paramètres, mais dans votre exemple, vous arrivez déjà là où une classe séparée serait mieux.


0

Je pense que le choix devrait être en fonction de la situation réelle, comme vous le voyez. Si un élément appartient à une instance, il doit être considéré comme son champ. Si l'élément est externe à l'instance, il doit être passé en tant que paramètre de méthode.

Nous devons être guidés dans ce cas non pas par l'efficacité (la différence est insignifiante de toute façon), ou (Dieu sauve!) La facilité de frappe, mais par la compréhensibilité et le caractère naturel du code.


0

À mon avis, si vous écrivez du code qui fait quelque chose, il devrait prendre des paramètres qui définissent les choses à faire et son nom devrait définir autant que possible ce qu'il lui fait.

Si vous écrivez du code qui regroupe une action à effectuer sur quelque chose, vous devez envelopper les choses sur lesquelles elle doit être effectuée dans un objet et les transmettre à votre chose qui fait quelque chose .

Cette action devient alors une sorte de méta-description des appels aux méthodes de la première que vous pouvez ensuite peut-être effectuer à une date ultérieure en la mettant en file d'attente ou même décider de ne pas le faire du tout pour une raison quelconque.

Votre question se traduit donc par une action ou une fonction ? Une action peut être reportée ou annulée et doit donc résumer ce sur quoi elle agit. Une fonction se produit immédiatement, il n'est donc pas nécessaire de conserver ses paramètres.

Vous pouvez annuler et action mais pas une fonction .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.