Kiedyś uwielbiałem klasy użytkowe wypełnione metodami statycznymi. Dokonali wielkiej konsolidacji metod pomocniczych, które w przeciwnym razie powodowałyby piekło redundancji i konserwacji. Są bardzo łatwe w użyciu, bez tworzenia instancji, bez utylizacji, po prostu odpal i zapomnij. Myślę, że to była moja pierwsza nieświadoma próba stworzenia architektury zorientowanej na usługi - wiele usług bezstanowych, które po prostu wykonały swoją pracę i nic więcej. Jednak wraz z rozwojem systemu pojawią się smoki.
Polimorfizm
Powiedzmy, że mamy metodę UtilityClass.SomeMethod, która radośnie brzęczy. Nagle musimy nieco zmienić funkcjonalność. Większość funkcji jest taka sama, ale mimo to musimy zmienić kilka części. Gdyby nie była to metoda statyczna, moglibyśmy stworzyć klasę pochodną i zmienić zawartość metody w razie potrzeby. Ponieważ jest to metoda statyczna, nie możemy. Jasne, jeśli musimy tylko dodać funkcjonalność przed lub po starej metodzie, możemy utworzyć nową klasę i wywołać w niej starą - ale to po prostu obrzydliwe.
Problemy z interfejsem
Metod statycznych nie można definiować za pośrednictwem interfejsów z powodów logicznych. A ponieważ nie możemy przesłonić metod statycznych, klasy statyczne są bezużyteczne, gdy musimy je przekazać przez ich interfejs. To sprawia, że nie możemy używać klas statycznych jako części wzorca strategii. Możemy załatać niektóre problemy, przekazując delegatów zamiast interfejsów .
Testowanie
Zasadniczo idzie to w parze z problemami interfejsu opisanymi powyżej. Ponieważ nasza zdolność do wymiany implementacji jest bardzo ograniczona, będziemy mieć również problem z zastąpieniem kodu produkcyjnego kodem testowym. Ponownie możemy je zawinąć, ale będzie to wymagało zmiany dużych części naszego kodu, aby móc akceptować opakowania zamiast rzeczywistych obiektów.
Wspiera obiekty blob
Ponieważ metody statyczne są zwykle używane jako metody użytkowe, a metody narzędziowe zwykle mają różne cele, szybko skończymy z dużą klasą wypełnioną niespójną funkcjonalnością - najlepiej, aby każda klasa miała jeden cel w systemie . Wolałbym mieć pięć razy więcej klas, o ile ich cele są dobrze określone.
Pełzanie parametrów
Po pierwsze, ta mała urocza i niewinna metoda statyczna może przyjmować jeden parametr. Wraz ze wzrostem funkcjonalności dodawanych jest kilka nowych parametrów. Wkrótce dodawane są kolejne parametry, które są opcjonalne, więc tworzymy przeciążenia metody (lub po prostu dodajemy wartości domyślne w językach, które je obsługują). Wkrótce mamy metodę, która przyjmuje 10 parametrów. Tylko pierwsze trzy są naprawdę wymagane, parametry 4-7 są opcjonalne. Ale jeśli określono parametr 6, wymagane jest również wypełnienie 7-9 ... Gdybyśmy utworzyli klasę, której jedynym celem jest zrobienie tego, co zrobiła ta metoda statyczna, moglibyśmy rozwiązać ten problem, przyjmując wymagane parametry w konstruktor i zezwalając użytkownikowi na ustawianie wartości opcjonalnych za pomocą właściwości lub metod w celu ustawienia wielu współzależnych wartości w tym samym czasie. Ponadto, jeśli metoda urosła do takiego stopnia złożoności,
Wymaganie od konsumentów tworzenia instancji klas bez powodu
Jednym z najczęstszych argumentów jest to, po co żądać, aby konsumenci naszej klasy utworzyli instancję wywołującą tę pojedynczą metodę, nie mając później pożytku z instancji? Tworzenie instancji klasy jest bardzo tanią operacją w większości języków, więc szybkość nie jest problemem. Dodanie dodatkowej linii kodu do konsumenta to niski koszt położenia podwalin pod znacznie łatwiejsze w utrzymaniu rozwiązanie w przyszłości. I wreszcie, jeśli chcesz uniknąć tworzenia instancji, po prostu utwórz pojedynczą otokę swojej klasy, która umożliwia łatwe ponowne użycie - chociaż wymaga to, aby Twoja klasa była bezstanowa. Jeśli nie jest bezstanowy, nadal możesz tworzyć statyczne metody opakowujące, które obsługują wszystko, a jednocześnie zapewniają wszystkie korzyści na dłuższą metę. Wreszcie,
Tylko Sith postępuje absolutnie.
Oczywiście są wyjątki od mojej niechęci do metod statycznych. Prawdziwe klasy użytkowe, które nie stwarzają żadnego ryzyka rozdęcia, są doskonałymi przypadkami dla metod statycznych - na przykład System.Convert. Jeśli twój projekt jest jednorazowy i nie ma wymagań dotyczących przyszłej konserwacji, ogólna architektura naprawdę nie jest bardzo ważna - statyczna lub niestatyczna nie ma tak naprawdę znaczenia - jednak szybkość rozwoju ma znaczenie.
Normy, normy, standardy!
Korzystanie z metod instancji nie ogranicza możliwości używania metod statycznych i na odwrót. O ile istnieje uzasadnienie za różnicowaniem i jest ustandaryzowane. Nie ma nic gorszego niż przeglądanie warstwy biznesowej obejmującej różne metody implementacji.