Le classi statiche vanno bene fintanto che vengono utilizzate nei posti giusti.
Vale a dire: metodi che sono metodi "foglia" (non modificano lo stato, semplicemente trasformano l'input in qualche modo). Buoni esempi di questo sono cose come Path.Combine. Questo genere di cose sono utili e rendono la sintassi più concisa.
I problemi che ho con la statica sono numerosi:
In primo luogo, se hai classi statiche, le dipendenze sono nascoste. Considera quanto segue:
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 }
}
Guardando TextureManager, non puoi dire quali passaggi di inizializzazione devono essere eseguiti guardando un costruttore. È necessario approfondire la classe per trovare le sue dipendenze e inizializzare le cose nell'ordine corretto. In questo caso, è necessario che ResourceLoader venga inizializzato prima di essere eseguito. Ora aumenta questo incubo di dipendenza e probabilmente puoi indovinare cosa succederà. Immagina di provare a mantenere il codice dove non esiste un ordine esplicito di inizializzazione. Confronta questo con l'inserimento di dipendenze con le istanze: in tal caso il codice non verrà nemmeno compilato se le dipendenze non vengono soddisfatte!
Inoltre, se usi le statistiche che modificano lo stato, è come un castello di carte. Non si sa mai chi ha accesso a cosa e il design tende ad assomigliare a un mostro di spaghetti.
Infine, e altrettanto importante, l'uso della statistica lega un programma a un'implementazione specifica. Il codice statico è l'antitesi della progettazione per la testabilità. Testare un codice pieno di statiche è un incubo. Una chiamata statica non può mai essere scambiata con una doppia di test (a meno che non si utilizzino framework di test progettati specificamente per simulare i tipi statici), quindi un sistema statico fa sì che tutto ciò che lo utilizza sia un test di integrazione istantaneo.
In breve, la statica va bene per alcune cose e per piccoli strumenti o codice usa e getta non ne scoraggerei l'uso. Tuttavia, oltre a ciò, sono un incubo sanguinario per la manutenibilità, il buon design e la facilità di test.
Ecco un buon articolo sui problemi: http://gamearchitect.net/2008/09/13/an-anatomy-of-despair-managers-and-contexts/