Klasy statyczne są w porządku, o ile są używane we właściwych miejscach.
Mianowicie: Metody, które są metodami typu „liść” (nie modyfikują stanu, a jedynie w jakiś sposób przekształcają dane wejściowe). Dobrym tego przykładem są takie rzeczy jak Path.Combine. Tego typu rzeczy są przydatne i tworzą bardziej prostą składnię.
Te problemy mam z statyki są liczne:
Po pierwsze, jeśli masz klasy statyczne, zależności są ukryte. Rozważ następujące:
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 }
}
Patrząc na TextureManager, nie możesz powiedzieć, jakie kroki inicjalizacji należy wykonać, patrząc na konstruktora. Musisz zagłębić się w klasę, aby znaleźć jej zależności i zainicjować rzeczy we właściwej kolejności. W takim przypadku wymaga zainicjowania ResourceLoader przed uruchomieniem. Teraz zwiększ skalę tego koszmaru zależności i prawdopodobnie możesz zgadnąć, co się stanie. Wyobraź sobie, że próbujesz zachować kod, w którym nie ma wyraźnej kolejności inicjalizacji. Porównaj to z iniekcją zależności z instancjami - w takim przypadku kod nie zostanie nawet skompilowany, jeśli zależności nie zostaną spełnione!
Co więcej, jeśli używasz statystyk, które modyfikują stan, jest to jak domek z kart. Nigdy nie wiadomo, kto ma do czego dostęp, a projekt przypomina potwora spaghetti.
Wreszcie, co równie ważne, używanie statyki wiąże program z konkretną implementacją. Kod statyczny jest przeciwieństwem projektowania pod kątem testowalności. Testowanie kodu, który jest pełen elementów statycznych, to koszmar. Wywołanie statyczne nigdy nie może zostać zamienione na podwójne testowe (chyba że używasz struktur testowych specjalnie zaprojektowanych do wyszydzania statycznych typów), więc system statyczny powoduje, że wszystko, co go używa, jest natychmiastowym testem integracji.
Krótko mówiąc, statystyka jest dobra do niektórych rzeczy, a do małych narzędzi lub kodu jednorazowego użytku nie zniechęcałbym ich do używania. Jednak poza tym są krwawym koszmarem ze względu na łatwość konserwacji, dobry projekt i łatwość testowania.
Oto dobry artykuł na temat problemów: http://gamearchitect.net/2008/09/13/an-anatomy-of-despair-managers-and-contexts/