Zwykle deklaruję jako statyczne wszystkie metody w klasie, gdy ta klasa nie wymaga śledzenia stanów wewnętrznych. Na przykład, jeśli muszę przekształcić A w B i nie polegać na jakimś wewnętrznym stanie C, który może się różnić, tworzę transformację statyczną. Jeśli istnieje stan wewnętrzny C, który chcę mieć możliwość dostosowania, dodaję konstruktora do ustawienia C i nie używam transformacji statycznej.
Czytałem różne zalecenia (w tym dotyczące StackOverflow), aby NIE nadużywać metod statycznych, ale nadal nie rozumiem, co jest nie tak z powyższą zasadą.
Czy to rozsądne podejście, czy nie?
Obiekt bez żadnego stanu wewnętrznego jest rzeczą podejrzaną.
Zwykle obiekty hermetyzują stan i zachowanie. Obiekt, który tylko hermetyzuje zachowanie, jest dziwny. Czasami jest to przykład wagi lekkiej lub muszej .
Innym razem jest to projekt proceduralny wykonany w języku obiektowym.
źródło
To naprawdę tylko kontynuacja wspaniałej odpowiedzi Johna Millikina.
Chociaż może być bezpieczne uczynienie metod bezstanowych (które są w zasadzie funkcjami) statycznymi, czasami może to prowadzić do sprzężenia, które jest trudne do zmodyfikowania. Rozważ, że masz metodę statyczną jako taką:
Które nazywasz jako:
Co jest dobre, dobre i bardzo wygodne, dopóki nie natrafisz na przypadek, w którym musisz zmodyfikować zachowanie metody statycznej i stwierdzisz, że jesteś ściśle związany
StaticClassVersionOne
. Możliwe, że możesz zmodyfikować kod i byłoby dobrze, ale gdyby istniały inne wywołania zależne od starego zachowania, będą musiały zostać uwzględnione w treści metody. W niektórych przypadkach ciało metody może stać się dość brzydkie lub nie do utrzymania, jeśli spróbuje zrównoważyć wszystkie te zachowania. Jeśli podzielisz metody, być może będziesz musiał zmodyfikować kod w kilku miejscach, aby to uwzględnić, lub wykonać wywołania nowych klas.Ale zastanów się, czy stworzyłeś interfejs, aby udostępnić metodę i przekazałeś ją wywołującym, teraz, gdy zachowanie musi się zmienić, można utworzyć nową klasę do implementacji interfejsu, który jest czystszy, łatwiejszy do przetestowania i łatwiejszy w utrzymaniu, i to zamiast tego jest przekazywane dzwoniącym. W tym scenariuszu klasy wywołujące nie muszą być zmieniane ani nawet ponownie kompilowane, a zmiany są lokalizowane.
Może to być sytuacja prawdopodobna lub nie, ale myślę, że warto się nad tym zastanowić.
źródło
Inną opcją jest dodanie ich jako metod niestatycznych do obiektu źródłowego:
tj. zmiana:
w
jednak w wielu sytuacjach nie jest to możliwe (np. zwykłe generowanie kodu klasy z XSD / WSDL / itp.) lub spowoduje to, że klasa będzie bardzo długa, a metody transformacji mogą często być prawdziwym problemem dla złożonych obiektów i po prostu ich potrzebujesz we własnej, oddzielnej klasie. Więc tak, mam statyczne metody w klasach narzędzi.
źródło
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:
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/
źródło
Powodem ostrzeżenia przed metodami statycznymi jest to, że ich używanie powoduje utratę jednej z zalet obiektów. Obiekty są przeznaczone do enkapsulacji danych. Zapobiega to występowaniu nieoczekiwanych skutków ubocznych, co pozwala uniknąć błędów. Metody statyczne nie mają hermetyzowanych danych *, więc nie przynoszą tej korzyści.
To powiedziawszy, jeśli nie korzystasz z danych wewnętrznych, są one w porządku i nieco szybsze do wykonania. Upewnij się jednak, że nie dotykasz w nich danych globalnych.
źródło
Wydaje się, że to rozsądne podejście. Powodem, dla którego nie chcesz używać zbyt wielu statycznych klas / metod, jest to, że w końcu odchodzisz od programowania obiektowego i zaczynasz zajmować się programowaniem strukturalnym.
W przypadku, gdy po prostu przekształcasz A w B, powiedz, że wszystko, co robimy, to przekształcanie tekstu, z którego pochodzi
Wtedy metoda statyczna miałaby sens.
Jeśli jednak często wywołujesz te statyczne metody na obiekcie i zwykle jest to unikalne dla wielu wywołań (np. Sposób ich użycia zależy od danych wejściowych) lub jest to część nieodłącznego zachowania obiektu, bądź mądry, aby uczynić go częścią przedmiotu i utrzymywać go w stanie. Jednym ze sposobów byłoby zaimplementowanie go jako interfejsu.
Edycja: dobrym przykładem doskonałego wykorzystania metod statycznych są metody pomocnicze HTML w Asp.Net MVC lub Ruby. Tworzą elementy html, które nie są powiązane z zachowaniem obiektu i dlatego są statyczne.
Edycja 2: Zmieniłem programowanie funkcjonalne na programowanie strukturalne (z jakiegoś powodu byłem zdezorientowany), rekwizyty Torstenowi za wskazanie tego.
źródło
Niedawno zrefaktorowałem aplikację, aby usunąć / zmodyfikować niektóre klasy, które zostały pierwotnie zaimplementowane jako klasy statyczne. Z biegiem czasu te klasy zdobyły tak wiele, a ludzie po prostu oznaczali nowe funkcje jako statyczne, ponieważ nigdy nie było żadnej instancji.
Tak więc moja odpowiedź brzmi, że klasy statyczne nie są z natury złe, ale może być łatwiej zacząć tworzyć instancje teraz, a potem trzeba będzie je później refaktoryzować.
źródło
Uznałbym to za zapach designu. Jeśli używasz głównie metod statycznych, prawdopodobnie nie masz zbyt dobrego projektu obiektowego. Niekoniecznie jest to złe, ale tak jak w przypadku wszystkich zapachów, zatrzymałbym się i ponownie ocenił. Sugeruje, że możesz być w stanie stworzyć lepszy projekt OO lub że może powinieneś pójść w innym kierunku i całkowicie uniknąć tego problemu.
źródło
Kiedyś przechodziłem między klasami za pomocą kilku statycznych metod i singletona. Oba rozwiązują problem, ale singleton można znacznie łatwiej zastąpić więcej niż jednym. (Programiści zawsze wydają się być tak pewni, że będzie tylko 1 coś, a myliłem się wystarczająco dużo razy, aby całkowicie porzucić metody statyczne, z wyjątkiem niektórych bardzo ograniczonych przypadków).
W każdym razie singleton daje możliwość późniejszego przekazania czegoś do fabryki, aby uzyskać inną instancję, a to zmienia zachowanie całego programu bez refaktoryzacji. Zmiana globalnej klasy metod statycznych na coś z innymi danymi „bazowymi” lub nieco innym zachowaniem (klasa potomna) jest głównym problemem.
Metody statyczne nie mają podobnej przewagi.
Więc tak, są złe.
źródło
Dopóki nie wchodzi w grę stan wewnętrzny, to jest w porządku. Należy zauważyć, że zwykle metody statyczne powinny być bezpieczne dla wątków, więc jeśli używasz pomocniczych struktur danych, używaj ich w sposób bezpieczny dla wątków.
źródło
Jeśli wiesz, że nigdy nie będziesz musiał używać wewnętrznego stanu C, to jest w porządku. Gdyby to jednak kiedykolwiek się zmieniło w przyszłości, należałoby uczynić metodę niestatyczną. Jeśli na początku nie jest statyczny, możesz po prostu zignorować stan wewnętrzny, jeśli go nie potrzebujesz.
źródło
Jeśli jest to metoda narzędziowa, dobrze jest uczynić ją statyczną. Guawa i Apache Commons są zbudowane na tej zasadzie.
Moja opinia na ten temat jest czysto pragmatyczna. Jeśli jest to kod Twojej aplikacji, metody statyczne generalnie nie są najlepszym rozwiązaniem. Metody statyczne mają poważne ograniczenia w testowaniu jednostkowym - nie można ich łatwo wyszydzić: nie można wstrzyknąć fałszywej funkcjonalności statycznej do innego testu. Zwykle nie można również wstrzyknąć funkcjonalności do metody statycznej.
Tak więc w mojej logice aplikacji zwykle mam małe statyczne wywołania metod podobnych do narzędzi. To znaczy
jedną z korzyści jest to, że nie testuję takich metod :-)
źródło
Cóż, oczywiście nie ma srebrnej kuli. Klasy statyczne są odpowiednie dla małych narzędzi / pomocników. Ale używanie statycznych metod do programowania logiki biznesowej jest z pewnością złe. Rozważmy następujący kod
Widzisz statyczne wywołanie metody
ItemsProcessor.SplitItem(newItem);
It pachnie przyczynąBusinessService
izolując go odItemsProcessor
(większość narzędzi testowych nie mockuje klas statycznych) i uniemożliwia testowanie jednostkowe. Brak testów jednostkowych == niska jakośćźródło
Metody statyczne są ogólnie złym wyborem nawet w przypadku kodu bezstanowego. Zamiast tego utwórz klasę pojedynczą z tymi metodami, która jest tworzona raz i wstrzykiwana do tych klas, które chcą używać tych metod. Takie zajęcia są łatwiejsze do wyśmiewania i testowania. Są znacznie bardziej zorientowane obiektowo. W razie potrzeby możesz owinąć je proxy. Statyka znacznie utrudnia OO i nie widzę powodu, aby ich używać w prawie wszystkich przypadkach. Nie w 100%, ale prawie wszystkie.
źródło