Les classes statiques conviennent tant qu'elles sont utilisées aux bons endroits.
À savoir: les méthodes qui sont des méthodes «feuille» (elles ne modifient pas l'état, elles transforment simplement l'entrée en quelque sorte). De bons exemples de ceci sont des choses comme Path.Combine. Ces sortes de choses sont utiles et créent une syntaxe terser.
Les problèmes que j'ai avec la statique sont nombreux:
Premièrement, si vous avez des classes statiques, les dépendances sont masquées. Considérer ce qui suit:
public static class ResourceLoader
{
public static void Init(string _rootPath) { ... etc. }
public static void GetResource(string _resourceName) { ... etc. }
public static void Quit() { ... etc. }
}
public static class TextureManager
{
private static Dictionary<string, Texture> m_textures;
public static Init(IEnumerable<GraphicsFormat> _formats)
{
m_textures = new Dictionary<string, Texture>();
foreach(var graphicsFormat in _formats)
{
// do something to create loading classes for all
// supported formats or some other contrived example!
}
}
public static Texture GetTexture(string _path)
{
if(m_textures.ContainsKey(_path))
return m_textures[_path];
// How do we know that ResourceLoader is valid at this point?
var texture = ResourceLoader.LoadResource(_path);
m_textures.Add(_path, texture);
return texture;
}
public static Quit() { ... cleanup code }
}
En regardant TextureManager, vous ne pouvez pas dire quelles étapes d'initialisation doivent être effectuées en regardant un constructeur. Vous devez fouiller dans la classe pour trouver ses dépendances et initialiser les choses dans le bon ordre. Dans ce cas, il faut que ResourceLoader soit initialisé avant de s'exécuter. Maintenant, augmentez ce cauchemar de dépendance et vous pouvez probablement deviner ce qui va se passer. Imaginez essayer de maintenir du code là où il n'y a pas d'ordre explicite d'initialisation. Comparez cela avec l'injection de dépendances avec des instances - dans ce cas, le code ne sera même pas compilé si les dépendances ne sont pas remplies!
De plus, si vous utilisez des statiques qui modifient l'état, c'est comme un château de cartes. Vous ne savez jamais qui a accès à quoi, et le design a tendance à ressembler à un monstre spaghetti.
Enfin, et tout aussi important, l'utilisation de la statique lie un programme à une implémentation spécifique. Le code statique est l'antithèse de la conception pour la testabilité. Tester un code criblé de statique est un cauchemar. Un appel statique ne peut jamais être échangé contre un double de test (sauf si vous utilisez des frameworks de test spécialement conçus pour simuler des types statiques), donc un système statique fait de tout ce qui l'utilise un test d'intégration instantané.
En bref, la statique convient à certaines choses et pour les petits outils ou le code jetable, je ne découragerais pas leur utilisation. Cependant, au-delà de cela, ils sont un cauchemar sanglant pour la maintenabilité, la bonne conception et la facilité des tests.
Voici un bon article sur les problèmes: http://gamearchitect.net/2008/09/13/an-anatomy-of-despair-managers-and-contexts/