W programowaniu obiektowym oczywiście nie ma dokładnej reguły dotyczącej maksymalnej długości metody, ale nadal uważałem, że te dwa cytaty są ze sobą sprzeczne, więc chciałbym usłyszeć, co myślisz.
W czystym kodzie: Podręcznik zwinnego wytwarzania oprogramowania Robert Martin mówi:
Pierwszą zasadą funkcji jest to, że powinny być małe. Drugą zasadą funkcji jest to, że powinny one być mniejsze. Funkcje nie powinny mieć długości 100 linii. Funkcje rzadko powinny mieć długość 20 linii.
i podaje przykład z kodu Java, który widzi od Kent Beck:
Każda funkcja w jego programie miała tylko dwie, trzy lub cztery linie. Każda z nich była oczywista. Każdy opowiedział historię. I każdy prowadził cię do następnego w przekonującej kolejności. Tak krótkie powinny być twoje funkcje!
Brzmi świetnie, ale z drugiej strony w Code Complete Steve McConnell mówi coś zupełnie innego:
Należy pozwolić, aby rutyna rozwijała się w sposób organiczny do 100-200 linii, dekady dowodów wskazują, że procedury o takiej długości nie są bardziej podatne na błędy niż krótsze.
I podaje odniesienie do badania, które mówi, że rutyny 65 lub dłuższe są tańsze w opracowaniu.
Więc chociaż istnieją rozbieżne opinie na ten temat, czy istnieje dla Ciebie funkcjonalna najlepsza praktyka?
źródło
switch
Oświadczenie z 100case
warunkach jest bardziej utrzymaniu niż 10 poziomówif
wypowiedzi zagnieżdżone wewnątrz siebie.Odpowiedzi:
Funkcje powinny zwykle być krótkie, od 5 do 15 wierszy jest moją osobistą „praktyczną zasadą” przy kodowaniu w Javie lub C #. Jest to dobry rozmiar z kilku powodów:
Ale nie sądzę, aby pomocne było ustalenie bezwzględnej reguły, ponieważ zawsze będą istniały ważne wyjątki / powody do odstąpienia od reguły:
Zasadniczo używaj zdrowego rozsądku , trzymaj się małych rozmiarów funkcji w większości przypadków, ale nie bądź dogmatyczny, jeśli masz naprawdę dobry powód, aby wykonać niezwykle dużą funkcję.
źródło
Chociaż zgadzam się z komentarzami innych, którzy mówili, że nie ma twardych zasad dotyczących właściwego numeru LOC, założę się, że jeśli spojrzymy wstecz na projekty, które oglądaliśmy w przeszłości i zidentyfikujemy każdą funkcję powyżej, powiedzmy 150 linii kodu, ja ' zgaduję, że dojdziemy do konsensusu, że 9 na 10 z tych funkcji łamie SRP (a także bardzo prawdopodobne OCP), ma zbyt wiele zmiennych lokalnych, zbyt duży przepływ sterowania i jest ogólnie trudny do odczytania i utrzymania.
Więc chociaż LOC może nie być bezpośrednim wskaźnikiem złego kodu, z pewnością jest przyzwoitym pośrednim wskaźnikiem, że pewna funkcja może być napisana lepiej.
W moim zespole znalazłem się na czele i z jakiegokolwiek powodu ludzie wydają się mnie słuchać. Na ogół zdecydowałem się powiedzieć zespołowi, że chociaż nie ma absolutnego limitu, każda funkcja więcej niż 50 wierszy kodu powinna co najmniej podnieść czerwoną flagę podczas przeglądania kodu, abyśmy mogli na niego spojrzeć i ponownie go ocenić dla złożoności i naruszeń SRP / OCP. Po tym drugim spojrzeniu możemy to zostawić w spokoju lub możemy to zmienić, ale przynajmniej każe to ludziom myśleć o tych rzeczach.
źródło
Włączyłem się w projekt, który nie dbał o wytyczne dotyczące kodowania. Kiedy patrzę na kod, czasami znajduję klasy zawierające więcej niż 6000 linii kodu i mniej niż 10 metod. Jest to scenariusz grozy, w którym musisz naprawić błędy.
Ogólna zasada, jak duża powinna być metoda, nie zawsze jest tak dobra. Podoba mi się reguła Roberta C. Martina (wujek Bob): „Metody powinny być małe, mniejsze niż małe”. Cały czas staram się korzystać z tej reguły. Staram się, aby moje metody były proste i małe, wyjaśniając, że moja metoda robi tylko jedną rzecz i nic więcej.
źródło
Nie chodzi o liczbę linii, chodzi o SRP. Zgodnie z tą zasadą, twoja metoda powinna robić jedną i tylko jedną rzecz.
Jeśli twoja metoda robi to ORAZ to ORAZ to => prawdopodobnie robi to zbyt wiele. Spróbuj spojrzeć na tę metodę i przeanalizować: „tutaj otrzymuję te dane, sortuję je i otrzymuję potrzebne elementy” oraz „tutaj przetwarzam te elementy” i „tutaj w końcu łączę je, aby uzyskać wynik”. Te „bloki” należy przefaktoryzować na inne metody.
Jeśli po prostu zastosujesz się do SRP, większość twojej metody będzie niewielka iz wyraźną intencją.
Nieprawidłowe jest stwierdzenie „ta metoda ma> 20 wierszy, więc jest błędna”. Może to wskazywać, że coś może być nie tak z tą metodą, nie więcej.
Być może masz metodę przełączania 400 linii w metodzie (często dzieje się to w telekomunikacji), i nadal jest to pojedyncza odpowiedzialność i jest całkowicie OK.
źródło
Zależy to , poważnie, naprawdę nie ma solidnej odpowiedzi na to pytanie, ponieważ język, w którym pracujesz, ma znaczenie, od pięciu do piętnastu wierszy wymienionych w tej odpowiedzi może działać dla C # lub Java, ale w innych językach nie daje dużo pracy z. Podobnie, w zależności od domeny, w której pracujesz, możesz znaleźć wartości ustawień kodu w dużej strukturze danych. W przypadku niektórych struktur danych możesz mieć dziesiątki elementów, które musisz ustawić, czy powinieneś rozdzielić elementy na osobne funkcje tylko dlatego, że twoja funkcja działa długo?
Jak zauważyli inni, najlepszą regułą jest to, że funkcja powinna być pojedynczą logiczną jednostką, która obsługuje jedno zadanie. Jeśli spróbujesz wymusić drakońskie reguły, które mówią, że funkcje nie mogą być dłuższe niż n wierszy, a wartość ta będzie zbyt mała, twój kod będzie trudniejszy do odczytania, gdy programiści będą próbowali użyć wymyślnych sztuczek, aby obejść regułę. Podobnie, jeśli ustawisz go zbyt wysoko, nie będzie problemu i może prowadzić do złego kodu, choć lenistwo. Najlepiej jest po prostu przeprowadzić przegląd kodu, aby upewnić się, że funkcje obsługują jedno zadanie, i zostaw to.
źródło
Myślę, że jednym z problemów jest to, że długość funkcji nie mówi nic o jej złożoności. LOC (linie kodu) to zły instrument do mierzenia czegokolwiek.
Metoda nie powinna być zbyt skomplikowana, ale istnieją scenariusze, w których można łatwo utrzymać długą metodę. Zauważ, że poniższy przykład nie mówi, że nie można go podzielić na metody, tylko że metody nie zmieniają łatwości konserwacji.
na przykład moduł obsługi danych przychodzących może mieć dużą instrukcję przełączania, a następnie prosty kod dla każdej sprawy. Mam taki kod - zarządzanie przychodzącymi danymi z kanału. 70 (!) Kodowanych numerycznie programów obsługi. Teraz powiedzą „użyj stałych” - tak, z wyjątkiem tego, że API ich nie udostępnia i lubię być blisko „źródła”. Metody? Jasne - niestety wszystkie one zajmują się danymi z tych samych 2 ogromnych struktur. Nie ma korzyści z ich rozdzielenia, z wyjątkiem może posiadania większej liczby metod (czytelności). Kod z natury nie jest złożony - jeden przełącznik, w zależności od pola. Następnie każda sprawa ma blok, który analizuje x elementów danych i publikuje je. Bez koszmaru konserwacji. Jest jeden powtarzający się „warunek, który określa, czy pole ma dane (pField = pFields [x], jeśli pField-> IsSet () {blabla}) - to samo w zasadzie dla każdego pola.
Zamień to na znacznie mniejszą procedurę zawierającą zagnieżdżoną pętlę i wiele prawdziwych instrukcji przełączających, a ogromna metoda może być łatwiejsza w utrzymaniu niż jedna mniejsza.
Przykro nam, LOC nie jest dobrym pomiarem na początek. Jeśli już, to należy użyć punktów złożoności / decyzji.
źródło
Wrzucę jeszcze jeden cytat.
Jest bardzo nieprawdopodobne, że funkcje, które rosną do 100-200, postępują zgodnie z tą zasadą
źródło
Jestem w tej szalonej rakiecie, tak czy inaczej, od 1970 roku.
Przez cały ten czas, z dwoma wyjątkami, do których dojdę za chwilę, NIGDY nie widziałem dobrze zaprojektowanej „procedury” (metoda, procedura, funkcja, podprogram, cokolwiek), POTRZEBUJĄCEJ być więcej niż jedną wydrukowaną stroną ( około 60 linii). Zdecydowana większość z nich była dość krótka, rzędu 10-20 linii.
Widziałem jednak DUŻO kodu „strumienia świadomości”, napisanego przez ludzi, którzy najwyraźniej nigdy nie słyszeli o modularyzacji.
Te dwa wyjątki były bardzo szczególnymi przypadkami. Jeden z nich to tak naprawdę klasa wyjątków, które zbijam w całość: duże automaty o stanie skończonym, zaimplementowane jako duże brzydkie instrukcje przełączników, zwykle dlatego, że nie ma prostszego sposobu ich implementacji. Te rzeczy zwykle pojawiają się w automatycznych urządzeniach testowych, analizując dzienniki danych z testowanego urządzenia.
Drugim była procedura torped fotonów z gry STARTRK Matuszek-Reynolds-McGehearty-Cohen, napisana w CDC 6600 FORTRAN IV. Musiał przeanalizować linię poleceń, a następnie zasymulować lot każdej torpedy, z zaburzeniami, sprawdzić interakcję między torpedą a każdym rodzajem rzeczy, w które mogła trafić, i, nawiasem mówiąc, zasymulować rekurencję, aby uzyskać łączność 8-kierunkową na łańcuchach nowe od torpedowania gwiazdy znajdującej się obok innych gwiazd.
źródło
Jeśli znajdę długą metodę - mógłbym się założyć, że ta metoda nie jest odpowiednio testowana jednostkowo lub przez większość czasu wcale jej nie testuje. Jeśli zaczniesz robić TDD, nigdy nie zbudujesz 100-liniowych metod z 25 różnymi obowiązkami i 5 zagnieżdżonymi pętlami. Testy zobowiązują cię do ciągłego refaktoryzowania bałaganu i pisania czystego kodu wuja Boba.
źródło
Nie ma bezwzględnych reguł dotyczących długości metody, ale przydatne były następujące reguły:
źródło
Czy autorzy rozumieją to samo przez „funkcję” i „rutynę”? Zazwyczaj, gdy mówię „funkcja”, mam na myśli podprogram / operację, która zwraca wartość i „procedurę” dla takiej, która tego nie robi (a której wywołanie staje się pojedynczą instrukcją). Nie jest to powszechne rozróżnienie w SE w świecie rzeczywistym, ale widziałem to w tekstach użytkowników.
Tak czy inaczej, nie ma na to właściwej odpowiedzi. Preferencje dla jednego lub drugiego (jeśli w ogóle są preferencje) to coś, czego spodziewałbym się bardzo różnić między językami, projektami i organizacjami; tak jak w przypadku wszystkich konwencji kodu.
Dodam tylko, że całe twierdzenie, że „długie operacje nie są bardziej podatne na błędy niż krótkie operacje”, nie jest ściśle prawdziwe. Oprócz faktu, że większa liczba kodów równa się większej potencjalnej przestrzeni błędów, oczywiste jest, że podzielenie kodu na segmenty sprawi, że błędy będą łatwiejsze do uniknięcia i łatwiejsze do zlokalizowania. W przeciwnym razie nie byłoby powodu, aby w ogóle rozbijać kod na części, z wyjątkiem powtórzeń. Być może jest to jednak prawdą tylko wtedy, gdy wspomniane segmenty są wystarczająco dobrze udokumentowane, aby można było określić wyniki wywołania operacji bez czytania lub śledzenia rzeczywistego kodu (projekt na podstawie umowy oparty na specyfikacjach, a nie konkretnej zależności między obszarami kodu).
Ponadto, jeśli chcesz, aby dłuższe operacje działały dobrze, możesz zastosować bardziej surowe konwencje kodu w celu ich obsługi. Rzutowanie instrukcji return w środku operacji może być odpowiednie dla krótkiej operacji, ale w dłuższych operacjach może to stworzyć dużą sekcję kodu, która jest warunkowa, ale oczywiście nie zależy od szybkiego odczytu (tylko na przykład).
Sądzę więc, że to, który styl jest mniej prawdopodobnym koszmarem wypełnionym błędami, będzie w dużej mierze zależeć od konwencji, których przestrzegasz w pozostałej części kodu. :)
źródło
IMHO, nie powinieneś używać paska przewijania, aby odczytać swoją funkcję. Gdy tylko będziesz musiał przesunąć pasek przewijania, potrzeba więcej czasu, aby zrozumieć, jak działa ta funkcja.
W związku z tym zależy to od zwykłego środowiska programistycznego pracy zespołu (rozdzielczość ekranu, edytor, rozmiar czcionki itp.). W latach 80. było to 25 linii i 80 kolumn. Teraz w moim edytorze wyświetlam prawie 50 wierszy. Liczba wyświetlanych kolumn nie zmieniła się, ponieważ podzieliłem ekran na dwie części, aby wyświetlać dwa pliki naraz.
W skrócie, zależy to od konfiguracji twoich współpracowników.
źródło
Myślę, że odpowiedź TomTom była zbliżona do tego, jak się z tym czuję.
Coraz bardziej odczuwam złożoność cykliczną niż linie.
Zwykle dążę do uzyskania nie więcej niż jednej struktury kontrolnej na metodę, z wyjątkiem wielu pętli potrzebnych do obsługi tablicy wielowymiarowej.
Czasami umieszczam jednowierszowe ifs w przypadkach przełączania, ponieważ z jakiegoś powodu są to przypadki, w których podział przeszkadza, a nie pomaga.
Zauważ, że nie liczę logiki wartownika przed tym limitem.
źródło
W OOP wszystkie rzeczy są przedmiotem i są te funkcje:
Kiedy przestrzegasz tych reguł, twoje metody są zwykle małe, ale nie istnieją żadne reguły dla małych lub bardzo małych (np. 2-3 wiersze) reguł. Zaletą małej metody (małej jednostki, np. Metody lub funkcji) są:
źródło