J'ai récemment entrepris une refactorisation d'un projet de taille moyenne en Java pour revenir en arrière et ajouter des tests unitaires. Quand j'ai réalisé à quel point c'était pénible de se moquer des singletons et de la statique, j'ai finalement «compris» ce que j'avais lu à leur sujet tout ce temps. (Je fais partie de ces personnes qui ont besoin d'apprendre de leur expérience. Oh bien.)
Donc, maintenant que j'utilise Spring pour créer les objets et les câbler, je me débarrasse des static
mots clés à gauche et à droite. (Si je pouvais potentiellement m'en moquer, ce n'est pas vraiment statique dans le même sens que Math.abs (), n'est-ce pas?) Le fait est que j'avais pris l'habitude d'utiliser static
pour indiquer qu'une méthode ne reposait pas sur n'importe quel état d'objet. Par exemple:
//Before
import com.thirdparty.ThirdPartyLibrary.Thingy;
public class ThirdPartyLibraryWrapper {
public static Thingy newThingy(InputType input) {
new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
}
}
//called as...
ThirdPartyLibraryWrapper.newThingy(input);
//After
public class ThirdPartyFactory {
public Thingy newThingy(InputType input) {
new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
}
}
//called as...
thirdPartyFactoryInstance.newThingy(input);
Alors, c'est là que ça devient délicat. J'ai aimé l'ancienne façon parce que la lettre majuscule m'a dit que, tout comme Math.sin (x), ThirdPartyLibraryWrapper.newThingy (x) faisait la même chose de la même manière à chaque fois. Il n'y a aucun état d'objet pour changer la façon dont l'objet fait ce que je lui demande de faire. Voici quelques réponses possibles que j'envisage.
- Personne d'autre ne ressent cela, alors il y a quelque chose qui ne va pas chez moi. Peut-être que je n'ai pas vraiment intériorisé la façon OO de faire les choses! Peut-être que j'écris en Java mais que je pense en FORTRAN ou quelque chose comme ça. (Ce qui serait impressionnant puisque je n'ai jamais écrit FORTRAN.)
- J'utilise peut-être la statique comme une sorte de proxy pour l'immuabilité à des fins de raisonnement sur le code. Cela étant dit, quels indices devrais- je avoir dans mon code pour que quelqu'un vienne le maintenir afin de savoir ce qui est et ce qui ne l'est pas?
- Peut-être que cela devrait venir gratuitement si je choisis de bonnes métaphores d'objet? eg
thingyWrapper
ne sonne pas comme s'il avait un état indépendant de l'enveloppéThingy
qui peut lui-même être mutable. De même, unthingyFactory
son comme il devrait être immuable mais pourrait avoir différentes stratégies qui sont choisies parmi à la création.
À mon avis, ce que vous dites - toutes les fonctions statiques doivent être nullipotentes - est une bonne façon OO d'écrire du code dans la plupart des cas, mais je ne pense pas que lorsque vous regardez une fonction statique, vous devez automatiquement supposer qu'elle n'a pas d'effets secondaires . La situation peut être plus complexe; prenez par exemple la fonction
Class.forName(String)
qui semble être sans état mais elle charge en fait une classe dans la mémoire et finalement instancie les champs statiques / lance l'initialisation statique; c'est un exemple de fonction idempotente (les appels éventuels après le premier ne font aucune différence) mais ce n'est pas une fonction pure (on ne peut pas dire qu'elle n'a pas d'effets secondaires). C'est également un bon choix, mais il peut y avoir des cas où trois appels distincts à la même fonction donnent trois résultats différents; par exemple si vous appelezThread.currentThread()
dans une application multi-thread, il n'y a aucune garantie que vous recevrez le même thread à chaque fois.Une bonne solution est de documenter (Javadoc par exemple); aussi, du nom de la fonction et de ce qu'elle fait parfois, on peut déduire que la fonction statique est une fonction pure. Par exemple, il n'y a aucune raison pour que quelqu'un pense que
Assert.assertTrue(boolean)
JUnit changerait quelque part l'état. D'un autre côté, quand une fonction commeSystem.clearProperty(String)
est appelée, il est assez évident qu'il y aura des effets secondaires.la source
Vous pouvez les rendre statiques. FxCop dans le monde C # vous poussera à rendre les choses statiques qui ne font référence à aucune variable membre. C'est la bonne chose à faire (généralement).
Les déplacer tous vers des instances n'est peut-être pas la bonne approche. À la place, dissociez les dépendances des méthodes statiques des classes qui les utilisent. Vous pouvez tester les méthodes statiques isolément, puis remplacer la dépendance dans les consommateurs lorsqu'ils doivent être testés.
la source