Czy metody C #, które mogą być statyczne, powinny być statyczne?
Rozmawialiśmy o tym dzisiaj i jestem na płocie. Wyobraź sobie, że masz długą metodę, w której refaktoryzujesz kilka wierszy. Nowa metoda prawdopodobnie pobiera kilka zmiennych lokalnych z metody nadrzędnej i zwraca wartość. Oznacza to, że może być statyczny.
Pytanie brzmi: czy powinno być statyczne? Nie jest statyczny z założenia ani z wyboru, po prostu z natury, ponieważ nie odwołuje się do żadnych wartości instancji.
Odpowiedzi:
To zależy. Naprawdę istnieją 2 rodzaje metod statycznych:
W małej lub średniej bazie kodu można naprawdę traktować obie metody zamiennie.
Jeśli masz metodę, która należy do pierwszej kategorii (może być statyczna) i musisz ją zmienić, aby uzyskać dostęp do stanu klasy, stosunkowo łatwo jest dowiedzieć się, czy można zmienić metodę statyczną w metodę instancji.
Jednak w dużej bazie kodu sama liczba witryn wywołujących może sprawić, że wyszukiwanie w celu sprawdzenia, czy możliwe jest przekonwertowanie metody statycznej na niestatyczną, jest zbyt kosztowne. Wiele razy ludzie zobaczą liczbę połączeń i powiedzą „ok ... lepiej nie zmieniać tej metody, ale zamiast tego utworzę nową, która robi to, czego potrzebuję”.
Może to spowodować:
Obie te rzeczy są złe.
Więc moja rada byłaby taka, że jeśli masz kod bazowy powyżej 200K LOC, uczyniłbym metody statycznymi tylko wtedy, gdy są one metodami statycznymi.
Refaktoryzacja z niestatycznej do statycznej jest stosunkowo łatwa (wystarczy dodać słowo kluczowe), więc jeśli chcesz później przekształcić zmienną can-be-static w rzeczywistą statyczną (gdy potrzebujesz jej funkcjonalności poza instancją), możesz. Jednak refaktoryzacja odwrotna polegająca na przekształceniu metody can-be-static w metodę instancji jest DUŻO droższa.
W przypadku dużych baz kodu lepiej jest popełniać błędy po stronie łatwości rozszerzenia niż po stronie czystości idealogicznej.
Tak więc w przypadku dużych projektów nie rób statycznych rzeczy, chyba że tego potrzebujesz. W przypadku małych projektów po prostu rób to, co lubisz najbardziej.
źródło
Chciałbym nie sprawiają, że publiczne statyczne członkiem tej klasy . Powodem jest to, że upublicznienie statycznego oznacza powiedzenie czegoś o typie klasy: nie tylko to, że „ten typ wie, jak zrobić to zachowanie”, ale także „to on jest odpowiedzialny za wykonanie tego zachowania”. A są szanse, że zachowanie nie ma już żadnego rzeczywistego związku z większym typem.
Nie oznacza to jednak, że w ogóle bym tego nie statował. Zadaj sobie pytanie: czy nowa metoda logicznie może być inna? Jeśli możesz na to odpowiedzieć „tak”, prawdopodobnie zechcesz uczynić go statycznym (i również go przesunąć). Nawet jeśli to nieprawda, nadal możesz to uczynić statycznym. Po prostu nie zaznaczaj tego
public
.Dla wygody możesz przynajmniej to oznaczyć
internal
. Zwykle pozwala to uniknąć konieczności przenoszenia metody, jeśli nie masz łatwego dostępu do bardziej odpowiedniego typu, ale nadal pozostawia ją dostępną w razie potrzeby w taki sposób, że nie będzie wyświetlana jako część publicznego interfejsu dla użytkowników Twojej klasy .źródło
Niekoniecznie.
Przeniesienie metod publicznych ze statycznej na niestatyczną jest przełomową zmianą i wymagałoby zmian dla wszystkich wywołań lub konsumentów. Jeśli metoda wydaje się być metodą instancji, ale nie wykorzystuje żadnych elementów instancji, sugerowałbym uczynienie jej metodą instancji jako miary przyszłości.
źródło
Tak. Powodem, dla którego „może być statyczny” jest to, że nie działa na stan obiektu, na którym jest wywoływana. Dlatego nie jest to metoda instancji, ale metoda klasowa. Jeśli może robić to, co musi, nigdy nie uzyskując dostępu do danych instancji, powinien być statyczny.
źródło
Tak, powinno. Istnieją różne metryki sprzężenia, które mierzą zależność twojej klasy od innych rzeczy, takich jak inne klasy, metody itp. Uczynienie metod statycznymi jest sposobem na utrzymanie niskiego stopnia sprzężenia, ponieważ możesz być pewien, że metoda statyczna nie odwołuje się do żadnych członków.
źródło
Myślę, że byłoby to trochę bardziej czytelne, gdybyś oznaczył to jako statyczne ... Wtedy ktoś, kto się pojawi, będzie wiedział, że nie odwołuje się do żadnych zmiennych instancji bez konieczności czytania całej funkcji ...
źródło
Osobiście jestem wielkim fanem bezpaństwowości. Czy Twoja metoda wymaga dostępu do stanu klasy? Jeśli odpowiedź brzmi nie (i prawdopodobnie nie, w przeciwnym razie nie rozważałbyś uczynienia tego metodą statyczną), to tak, idź do tego.
Brak dostępu do stanu to mniejszy ból głowy. Tak jak dobrym pomysłem jest ukrycie prywatnych członków, którzy nie są potrzebni innym klasom, tak samo dobrym pomysłem jest ukrycie stanu przed członkami, którzy tego nie potrzebują. Ograniczony dostęp może oznaczać mniej błędów. Ułatwia również tworzenie wątków, ponieważ znacznie łatwiej jest zachować bezpieczeństwo wątków statycznych elementów członkowskich. Istnieje również kwestia wydajności, ponieważ środowisko wykonawcze nie musi przekazywać odwołania do tego jako parametru dla metod statycznych.
Oczywiście wadą jest to, że jeśli kiedykolwiek okaże się, że Twoja poprzednio statyczna metoda będzie musiała uzyskać dostęp do stanu z jakiegoś powodu, musisz to zmienić. Teraz rozumiem, że może to stanowić problem dla publicznych interfejsów API, więc jeśli jest to metoda publiczna w klasie publicznej, być może powinieneś trochę pomyśleć o konsekwencjach tego. Mimo to nigdy nie spotkałem się z sytuacją w prawdziwym świecie, w której rzeczywiście spowodowałoby to problem, ale może po prostu mam szczęście.
Więc tak, zrób to, jak najbardziej.
źródło
Metody statyczne są szybsze niż metody niestatyczne, więc tak, powinny być statyczne, jeśli to możliwe i nie ma specjalnego powodu, aby pozostawić je niestatyczne .
źródło
Dziwię się, że tak niewielu wspomina tutaj o hermetyzacji. Metoda instancji automatycznie uzyska dostęp do wszystkich prywatnych pól (instancji), właściwości i metod. Oprócz wszystkich chronionych dziedziczonych z klas podstawowych.
Kiedy piszesz kod, powinieneś pisać go tak, aby ujawniać jak najmniej, a także aby mieć jak najmniejszy dostęp.
Więc tak, może być ważne, aby przyspieszyć kod, co mogłoby się zdarzyć, gdybyś uczynił swoje metody statycznymi, ale zwykle ważniejsze jest to, aby kod był tak samo niezdolny do tworzenia błędów, jak to tylko możliwe. Jednym ze sposobów na osiągnięcie tego jest zapewnienie, aby Twój kod miał jak najmniejszy dostęp do „prywatnych rzeczy”.
Na pierwszy rzut oka może się to wydawać nieistotne, ponieważ OP oczywiście mówi o refaktoryzacji, która nie może się nie udać w tym scenariuszu i stworzyć żadnych nowych błędów, jednak ten refaktoryzowany kod musi być utrzymywany w przyszłości i modyfikowany, co powoduje, że twój kod ma większy "atak surface ”w odniesieniu do nowych błędów, jeśli ma dostęp do prywatnych członków instancji. Generalnie myślę, że wniosek jest taki „tak, głównie twoje metody powinny być statyczne”, chyba że istnieją inne powody, dla których nie mają one statyczności. A to po prostu dlatego, że „lepsze wykorzystanie hermetyzacji i ukrywania danych oraz tworzenie„ bezpieczniejszego ”kodu”…
źródło
Robienie czegoś statycznego tylko dlatego, że możesz, nie jest dobrym pomysłem. Metody statyczne powinny być statyczne ze względu na swój projekt, a nie z przypadku.
Jak powiedział Michael, zmiana tego później spowoduje uszkodzenie kodu, który go używa.
Mając to na uwadze, wygląda na to, że tworzysz prywatną funkcję narzędzia dla klasy, która w rzeczywistości jest statyczna z założenia.
źródło
Jeśli udało Ci się zrefaktoryzować kilka wierszy, a wynikowa metoda mogłaby być statyczna, prawdopodobnie oznacza to, że wiersze, które wyciągnąłeś z tej metody, w ogóle nie należą do klasy zawierającej i powinieneś rozważyć przeniesienie ich do własną klasę.
źródło
Osobiście nie miałbym innego wyboru, jak tylko uczynić to statycznym. Resharper ostrzega w tym przypadku, a nasz premier ma zasadę „Żadnych ostrzeżeń od Resharper”.
źródło
To zależy, ale generalnie nie ustawiam tych metod jako statyczne. Kod ciągle się zmienia i być może kiedyś będę chciał uczynić tę funkcję wirtualną i zastąpić ją w podklasie. A może pewnego dnia będzie musiał odwołać się do zmiennych instancji. Wprowadzenie tych zmian będzie trudniejsze, jeśli trzeba będzie zmienić każdą witrynę wywołującą.
źródło
Sugeruję, aby najlepiej o tym pomyśleć: Jeśli potrzebujesz metody klasy, która musi być wywołana, gdy żadne instancje klasy nie są tworzone lub utrzymują jakiś stan globalny, statyczny jest dobrym pomysłem. Ale ogólnie sugeruję, abyś wolał, aby członkowie nie byli statyczni.
źródło
Powinieneś pomyśleć o swoich metodach i klasach:
Jeśli ostatnie dwa to „tak”, twoja metoda / klasa powinna być prawdopodobnie statyczna.
Najczęściej używanym przykładem jest prawdopodobnie
Math
klasa. Każdy główny język obiektowy ma to i wszystkie metody są statyczne. Ponieważ musisz mieć możliwość korzystania z nich w dowolnym miejscu i czasie, bez tworzenia instancji.Innym dobrym przykładem jest
Reverse()
metoda w C #.To jest metoda statyczna w
Array
klasie. Odwraca kolejność twojej tablicy.Kod:
Nawet nic nie zwraca, twoja tablica jest odwrócona, ponieważ wszystkie tablice są instancjami klasy Array.
źródło
Tak długo, jak ustawisz nową metodę jako private static, nie będzie to przełomowa zmiana. W rzeczywistości FxCop zawiera te wskazówki jako jedną ze swoich zasad ( http://msdn.microsoft.com/en-us/library/ms245046(VS.80).aspx ), z następującymi informacjami:
To powiedziawszy, pierwszy komentarz Davida Kean'a bardziej zwięźle podsumowuje obawy, mówiąc, że w rzeczywistości chodzi bardziej o bycie poprawnym niż o wzrost wydajności:
źródło
Zdecydowanie zmieniłbym wszystko, co mogę w statyczne z innego powodu:
Funkcje statyczne, gdy są JIT, są wywoływane bez parametru „this”. Oznacza to na przykład, że 3-parametrowa funkcja niestatyczna (metoda składowa) zostaje wypchnięta z 4 parametrami na stosie.
Ta sama funkcja skompilowana jako funkcja statyczna byłaby wywoływana z 3 parametrami. Może to zwolnić rejestry dla JIT i zaoszczędzić miejsce na stosie ...
źródło
Jestem w obozie „Tylko statyczne metody prywatne”. Utworzenie metody publicznej może wprowadzić sprzężenie, którego nie chcesz, i może zmniejszyć testowalność: nie możesz zablokować publicznej metody statycznej.
Jeśli chcesz przetestować jednostkowo metodę, która używa publicznej metody statycznej, w końcu testujesz również metodę statyczną, co może nie być tym, czego chcesz.
źródło
Z natury statyczne metody, które z jakiegoś powodu są niestatyczne, są po prostu irytujące. Dowcip:
Dzwonię do banku i pytam o saldo.
Proszą o numer mojego konta.
Słusznie. Metoda instancji.
Dzwonię do banku i pytam o adres pocztowy.
Proszą o numer mojego konta.
WTF? Niepowodzenie - powinno być metodą statyczną.
źródło
Patrzę na to ogólnie z funkcjonalnej perspektywy czystych funkcji. Czy musi to być metoda instancji? Jeśli nie, możesz skorzystać na zmuszeniu użytkownika do przekazania zmiennych i nie manipulowaniu stanem bieżącej instancji. (Cóż, nadal możesz zmieniać stan, ale chodzi o to, aby zgodnie z projektem tego nie robić). Generalnie projektuję metody instancji jako publiczne elementy członkowskie i staram się, aby prywatne elementy członkowskie były statyczne. Jeśli to konieczne (możesz później łatwiej wyodrębnić je do innych klas.
źródło
W takich przypadkach staram się przenosić metodę do biblioteki statycznej lub utils, więc nie mieszam pojęcia „obiektu” z pojęciem „klasy”
źródło