Podczas pracy ze skomplikowanymi algorytmami w językach z obsługą funkcji zagnieżdżonych (takich jak Python i D) często piszę ogromne funkcje (ponieważ algorytm jest skomplikowany), ale łagodzę to, używając funkcji zagnieżdżonych do struktury skomplikowanego kodu. Czy ogromne (ponad 100 linii) funkcje są nadal uważane za złe, nawet jeśli mają wewnętrzną strukturę dzięki zastosowaniu funkcji zagnieżdżonych?
Edycja: Dla tych, którzy nie znają Python lub D, funkcje zagnieżdżone w tych językach umożliwiają również dostęp do zewnętrznego zakresu funkcji. W D ten dostęp umożliwia mutację zmiennych w zakresie zewnętrznym. W Pythonie pozwala tylko na czytanie. W D można jawnie wyłączyć dostęp do zakresu zewnętrznego w funkcji zagnieżdżonej, deklarując go static
.
Odpowiedzi:
Zawsze pamiętaj o regule, funkcja robi jedną rzecz i robi to dobrze! Jeśli możesz to zrobić, unikaj zagnieżdżonych funkcji.
Utrudnia to czytelność i testowanie.
źródło
Niektórzy twierdzą, że krótkie funkcje mogą być bardziej podatne na błędy niż długie .
Osobiście odkryłem, że dobrze skomentowany kod liniowy jest łatwiejszy do naśladowania (zwłaszcza gdy nie byłeś tym, który go pierwotnie napisał), niż gdy jest podzielony na wiele funkcji, które nigdy nie są używane gdzie indziej. Ale to naprawdę zależy od sytuacji.
Myślę, że głównym problemem jest to, że kiedy dzielisz blok kodu, zamieniasz jeden rodzaj złożoności na inny. Prawdopodobnie jest gdzieś pośrodku.
źródło
Idealnie byłoby, gdyby cała funkcja była widoczna bez konieczności przewijania. Czasami nie jest to możliwe. Ale jeśli uda ci się go rozbić na części, znacznie ułatwi to czytanie kodu.
Wiem, że jak tylko popycham Page Up / Down lub przechodzę do innej sekcji kodu, pamiętam tylko 7 +/- 2 rzeczy z poprzedniej strony. I niestety, niektóre z tych lokalizacji zostaną wykorzystane podczas czytania nowego kodu.
Zawsze lubię myśleć o mojej pamięci krótkotrwałej jak o rejestrach komputerowych (CISC, a nie RISC). Jeśli masz całą funkcję na tej samej stronie, możesz przejść do pamięci podręcznej, aby uzyskać wymagane informacje z innej sekcji programu. Jeśli cała funkcja nie mieści się na stronie, byłoby to równoznaczne z wypychaniem pamięci na dysk po każdej operacji.
źródło
Dlaczego warto korzystać z funkcji zagnieżdżonych zamiast zwykłych funkcji zewnętrznych?
Nawet jeśli funkcje zewnętrzne były kiedykolwiek używane tylko w jednej, dawniej dużej funkcji, nadal sprawia, że cały bałagan jest łatwiejszy do odczytania:
źródło
W tej chwili nie mam przed sobą książki (zacytować), ale według Code Complete „sweetspot” dla długości funkcji wynosił około 25-50 linii kodu według jego badań.
Są chwile, w których dobrze jest mieć długie funkcje:
Czasy, w których długie funkcje nie są w porządku:
Najważniejsze jest to, że łatwość konserwacji powinna być jednym z najwyższych priorytetów na liście. Jeśli inny programista nie może spojrzeć na twój kod i uzyskać „sedna” tego, co robi kod w czasie krótszym niż 5 sekund, Twój kod nie zapewnia wystarczającej liczby „metadanych”, aby powiedzieć, co robi. Inni deweloperzy powinni być w stanie powiedzieć, co robi Twoja klasa, patrząc na przeglądarkę obiektów w wybranym IDE zamiast czytać ponad 100 linii kodu.
Mniejsze funkcje mają następujące zalety:
I tak dalej.....
źródło
Odpowiedź brzmi: to zależy, jednak prawdopodobnie powinieneś zmienić to w klasę.
źródło
Nie lubię większości zagnieżdżonych funkcji. Jagnięta należą do tej kategorii, ale zwykle mnie nie oflagują, chyba że mają więcej niż 30-40 znaków.
Podstawowym powodem jest to, że staje się wysoce lokalnie gęstą funkcją z wewnętrzną rekurencją semantyczną, co oznacza , że trudno mi się owijać wokół mózgu, a po prostu łatwiej jest wypchnąć niektóre rzeczy do funkcji pomocniczej, która nie zaśmieca przestrzeni kodu .
Uważam, że funkcja powinna robić swoje. Robienie innych rzeczy jest tym, co robią inne funkcje. Jeśli więc masz 200-liniową funkcję Robi swoje rzeczy i wszystko płynie, to jest OK.
źródło
Czy jest to akceptowane? To naprawdę pytanie, na które tylko Ty możesz odpowiedzieć. Czy funkcja osiąga to, czego potrzebuje? Czy można to utrzymać? Czy jest to „akceptowalne” dla innych członków twojego zespołu? Jeśli tak, to właśnie to ma znaczenie.
Edycja: Nie widziałem rzeczy o zagnieżdżonych funkcjach. Osobiście nie używałbym ich. Zamiast tego użyłbym zwykłych funkcji.
źródło
Długa funkcja „linii prostej” może być prostym sposobem na określenie długiej sekwencji kroków, które zawsze występują w określonej sekwencji.
Jednak, jak wspomnieli inni, ta forma jest podatna na lokalne obszary złożoności, w których ogólny przepływ jest mniej widoczny. Umieszczenie tej lokalnej złożoności w funkcji zagnieżdżonej (tj. Zdefiniowanej gdzie indziej w funkcji długiej, być może na górze lub na dole) może przywrócić przejrzystość przepływu linii głównej.
Drugim ważnym zagadnieniem jest kontrolowanie zakresu zmiennych, które mają być używane tylko w lokalnym odcinku długiej funkcji. Wymagana jest czujność, aby uniknąć posiadania zmiennej, która została wprowadzona w jednej sekcji kodu nieświadomie przywołanej gdzie indziej (na przykład po cyklach edycji), ponieważ ten rodzaj błędu nie pojawi się jako błąd kompilacji lub środowiska wykonawczego.
W niektórych językach tego problemu można łatwo uniknąć: lokalny odcinek kodu można owinąć we własnym bloku, na przykład za pomocą „{...}”, w którym wszelkie nowo wprowadzone zmienne są widoczne tylko dla tego bloku. Niektóre języki, takie jak Python, nie mają tej funkcji, w którym to przypadku funkcje lokalne mogą być przydatne do wymuszenia regionów o mniejszym zasięgu.
źródło
Nie, funkcje wielostronicowe nie są pożądane i nie powinny przejść przeglądu kodu. Pisałem też długie funkcje, ale po przeczytaniu Refaktoryzacji Martina Fowlera przestałem. Długie funkcje są trudne do napisania poprawnie, trudne do zrozumienia i trudne do przetestowania. Nigdy nie widziałem funkcji nawet 50 linii, która nie byłaby łatwiejsza do zrozumienia i przetestowania, gdyby została podzielona na zestaw mniejszych funkcji. W funkcji wielostronicowej prawie na pewno istnieją całe klasy, które należy uwzględnić. Trudno jest być bardziej konkretnym. Może powinieneś opublikować jedną ze swoich długich funkcji w Code Review, a ktoś (może ja) pokaże ci, jak ją poprawić.
źródło
Gdy programuję w Pythonie, lubię cofać się po napisaniu funkcji i zadać sobie pytanie, czy jest ona zgodna z „Zen of Python” (wpisz „import this” w interpreterie Pythona):
Piękne jest lepsze niż brzydkie.
Jawne jest lepsze niż niejawne.
Prosty jest lepszy niż złożony.
Kompleks jest lepszy niż skomplikowany.
Mieszkanie jest lepsze niż zagnieżdżone.
Rzadki jest lepszy niż gęsty.
Liczy się czytelność.
Przypadki specjalne nie są wystarczająco wyjątkowe, aby złamać zasady.
Chociaż praktyczność przewyższa czystość.
Błędy nigdy nie powinny przejść bezgłośnie.
Chyba że wyraźnie uciszone.
W obliczu dwuznaczności odmów pokusy zgadywania.
Powinien być jeden - a najlepiej tylko jeden - oczywisty sposób na zrobienie tego.
Chociaż na początku taki sposób może nie być oczywisty, chyba że jesteś Holendrem.
Teraz jest lepiej niż nigdy.
Chociaż nigdy nie jest często lepsze niż właściweteraz.
Jeśli implementacja jest trudna do wyjaśnienia, to zły pomysł.
Jeśli implementacja jest łatwa do wyjaśnienia, może to być dobry pomysł.
Przestrzenie nazw to jeden świetny pomysł - zróbmy ich więcej!
źródło
Umieść je w osobnym module.
Zakładając, że twoje rozwiązanie nie jest bardziej rozdęte niż potrzeba, nie masz zbyt wielu opcji. Już podzieliłeś funkcje na różne podfunkcje, więc pytanie brzmi, gdzie powinieneś to umieścić:
Teraz zarówno druga, jak i trzecia alternatywa są w pewnym sensie zagnieżdżone, ale druga alternatywa nie wydaje się być zła. Jeśli nie wykluczysz drugiej alternatywy, nie widzę zbyt wiele powodów, aby wykluczyć trzecią.
źródło