Sam nie mogę się doczekać, aby napisać funkcję, gdy muszę zrobić coś więcej niż dwa razy. Ale jeśli chodzi o rzeczy, które pojawiają się tylko dwa razy, jest to nieco trudniejsze.
Dla kodu, który wymaga więcej niż dwóch linii, napiszę funkcję. Ale w obliczu takich rzeczy jak:
print "Hi, Tom"
print "Hi, Mary"
Waham się napisać:
def greeting(name):
print "Hi, " + name
greeting('Tom')
greeting('Mary')
Drugi wydaje się zbyt duży, prawda?
Ale co, jeśli mamy:
for name in vip_list:
print name
for name in guest_list:
print name
A oto alternatywa:
def print_name(name_list):
for name in name_list:
print name
print_name(vip_list)
print_name(guest_list)
Sprawy stają się trudne, nie? Trudno teraz zdecydować.
Co o tym sądzisz?
python
coding-style
Zen
źródło
źródło
always
inever
jak czerwone flagi. Istnieje coś, co nazywa się „kontekstem”, w którym regułyalways
inever
, nawet jeśli ogólnie są dobre, mogą nie być odpowiednie. Uważaj na twórców oprogramowania, którzy zajmują się absolutami. ;)from itertools import chain; for name in chain(vip_list, guest_list): print(name)
.Special cases aren't special enough to break the rules. Although practicality beats purity.
Odpowiedzi:
Chociaż jest to jeden z czynników decydujących o rozdzieleniu funkcji, liczba powtórzeń czegoś nie powinna być jedynym czynnikiem. Często sensowne jest utworzenie funkcji dla czegoś, co zostanie wykonane tylko raz . Zasadniczo chcesz podzielić funkcję, gdy:
Twoje przykłady nie spełniają tych kryteriów. Przechodzisz od jednej linijki do jednej linijki, a nazwy tak naprawdę nie kupują niczego pod względem przejrzystości. To powiedziawszy, proste funkcje są rzadkie poza samouczkami i zadaniami szkolnymi. Większość programistów ma tendencję do zbyt daleko idących błędów.
źródło
Tylko jeśli powielanie jest zamierzone, a nie przypadkowe .
Lub, mówiąc inaczej:
Tylko jeśli oczekujesz, że będą ewoluować w przyszłości.
Dlatego:
Czasami dwa kawałki kodu właśnie stało się stać to samo, mimo że nie mają nic wspólnego ze sobą. W takim przypadku musisz oprzeć się pragnieniu ich połączenia, ponieważ następnym razem, gdy ktoś przeprowadzi konserwację jednego z nich, osoba ta nie spodziewa się, że zmiany zostaną przeniesione do nieistniejącego wcześniej dzwoniącego, w wyniku czego funkcja ta może ulec awarii. Dlatego należy rozróżniać kod tylko wtedy, gdy ma to sens, a nie za każdym razem, gdy wydaje się zmniejszać rozmiar kodu.
Praktyczna zasada:
Jeśli kod zwraca tylko nowe dane i nie modyfikuje istniejących danych ani nie wywołuje innych skutków ubocznych, bardzo prawdopodobne jest, że będzie to bezpieczne jako osobna funkcja. (Nie wyobrażam sobie żadnego scenariusza, w którym spowodowałoby to awarię bez całkowitej zmiany zamierzonej semantyki funkcji, w którym to momencie nazwa funkcji lub sygnatura również powinna się zmienić, a ty i tak musisz zachować ostrożność. )
źródło
Nie, nie zawsze jest to najlepsza praktyka.
Wszystkie inne rzeczy, które są równe, liniowy kod wiersz po wierszu są łatwiejsze do odczytania niż przeskakiwanie wywołań funkcji. Nietrywialne wywołanie funkcji zawsze przyjmuje parametry, więc musisz to wszystko uporządkować i wykonać mentalne kontekstowe skoki od wywołania funkcji do wywołania funkcji. Zawsze faworyzuj lepszą przejrzystość kodu, chyba że masz dobry powód, aby być niejasnym (np. Uzyskać niezbędne ulepszenia wydajności).
Dlaczego zatem kod jest refaktoryzowany na osobne metody? Aby poprawić modułowość. Aby zebrać znaczącą funkcjonalność za poszczególną metodą i nadać jej sensowną nazwę. Jeśli tego nie osiągniesz, nie potrzebujesz tych osobnych metod.
źródło
Why take the performance hit of a function call when you don't get any significant benefit by doing so?
Jaka wydajność uderzyła? W ogólnym przypadku małe funkcje zostają wstawione, a narzut jest niewielki w przypadku dużych funkcji. CPython prawdopodobnie nie jest wbudowany, ale nikt nie używa go do wydajności. Ja teżline by line code...
trochę kwestionuję . Łatwiej jest, jeśli próbujesz symulować wykonanie w mózgu. Ale debugger wykona lepszą robotę, a próba udowodnienia czegoś o pętli poprzez wykonanie jej jest jak próba udowodnienia twierdzenia o liczbach całkowitych przez iterację po nich wszystkich.W twoim konkretnym przykładzie wykonanie funkcji może wydawać się przesadą; zamiast tego zadałbym pytanie: czy to możliwe, że to szczególne powitanie zmieni się w przyszłości? Jak to?
Funkcje nie służą jedynie do zawijania funkcjonalności i ułatwiają ponowne użycie, ale także do modyfikacji. Jeśli wymagania zmienią się, należy wkleić i wkleić ręcznie skopiowany kod, a przy pomocy funkcji kod należy zmodyfikować tylko raz.
Twój przykład skorzystałby na tym nie poprzez funkcję - ponieważ logika prawie nie istnieje - ale być może
GREET_OPENING
stała. Tę stałą można następnie załadować z pliku, aby program można łatwo dostosować na przykład do różnych języków. Zauważ, że jest to prymitywne rozwiązanie, bardziej złożony program prawdopodobnie potrzebowałby bardziej wyrafinowanego sposobu śledzenia i18n, ale znowu zależy to od wymagań, a nie pracy.W końcu chodzi o możliwe wymagania i planowanie z wyprzedzeniem, aby ułatwić sobie pracę w przyszłości.
źródło
Osobiście przyjąłem zasadę trzech - co uzasadnię, dzwoniąc do YAGNI . Jeśli muszę coś zrobić raz, napiszę ten kod, dwa razy mogę po prostu skopiować / wkleić (tak, przyznałem się do kopiowania / wklejania!), Ponieważ nie będę go więcej potrzebował, ale jeśli będę musiał zrobić to samo sprawa ponownie wtedy będę byłaby i wyodrębnić ten klocek do jego własnej metody, mam wykazać sobie, że będzie go trzeba ponownie.
Zgadzam się z tym, co powiedzieli Karl Bielefeldt i Robert Harvey, a moją interpretacją tego, co mówią, jest to, że nadrzędną zasadą jest czytelność. Jeśli dzięki temu mój kod będzie łatwiejszy do odczytania, rozważ utworzenie funkcji, pamiętaj o takich rzeczach, jak DRY i SLAP . Jeśli mogę uniknąć zmiany poziomu abstrakcji w mojej funkcji, to łatwiej mi sobie z tym poradzić, więc nie przeskakiwanie między funkcjami (jeśli nie rozumiem, co robi funkcja po prostu czytając jej nazwę), oznacza mniej przełączników w mojej procesy mentalne.
Podobnie nie konieczności przełączania kontekstu między funkcjami i kodu inline takich jak
print "Hi, Tom"
pracuje dla mnie, w tym przypadku może wyodrębnić funkcjęPrintNames()
IFF resztą mojej ogólnej funkcji były głównie wywołania funkcji.źródło
Rzadko jest to jednoznaczne, więc musisz zważyć opcje:
W C ++ zwykle stosuję zasadę trzech (tj. Za trzecim razem potrzebuję tego samego, przekształcam go w odpowiednio współdzielony kawałek), ale z doświadczeniem łatwiej jest dokonać tego wyboru na początku, ponieważ wiesz więcej o zakresie, oprogramowanie i domena, z którymi pracujesz.
Jednak w Pythonie ponowne użycie, a nie powtórzenie logiki jest dość lekkie. Bardziej niż w wielu innych językach (przynajmniej historycznie) IMO.
Rozważ więc ponowne użycie logiki lokalnie, na przykład poprzez utworzenie listy z lokalnych argumentów:
Możesz użyć krotki krotek i podzielić ją bezpośrednio na pętlę for, jeśli potrzebujesz kilku argumentów:
lub stwórz funkcję lokalną (może to twój drugi przykład), która sprawia, że ponowne użycie logiki jest jawne, ale także wyraźnie pokazuje, że print_name () nie jest używane poza funkcją:
Funkcje są preferowane, zwłaszcza gdy trzeba przerwać logikę na środku (tzn. Użyć return), ponieważ przerwa lub wyjątki mogą niepotrzebnie zagracać rzeczy.
Każda z nich jest lepsza niż powtarzanie tej samej logiki, IMO, a także mniej zaśmiecania niż deklarowanie funkcji globalnej / klasy, która jest używana tylko przez jednego rozmówcę (aczkolwiek dwa razy).
źródło
Wszystkie najlepsze praktyki mają szczególny powód, do którego możesz się odwołać, aby odpowiedzieć na takie pytanie. Zawsze należy unikać zmarszczek, gdy jedna potencjalna przyszła zmiana pociąga za sobą również zmiany innych składników.
W twoim przykładzie: jeśli zakładasz, że masz standardowe powitanie i chcesz upewnić się, że jest takie samo dla wszystkich ludzi, napisz
W przeciwnym razie musisz zwrócić uwagę i zmienić standardowe powitanie w dwóch miejscach, jeśli tak się stanie.
Jeśli jednak „Cześć” jest takie samo przez przypadek, a zmiana jednego z pozdrowieniami niekoniecznie powoduje zmiany w drugim, zachowaj je oddzielnie. Dlatego trzymaj je oddzielnie, jeśli istnieją logiczne powody, by sądzić, że bardziej prawdopodobna jest następująca zmiana:
W drugiej części, decyzja o tym, ile „spakować” w funkcje, prawdopodobnie zależy od dwóch czynników:
Idealnie, gdy nastąpi zmiana, pomyślisz „muszę zmienić większość następującego bloku”, a nie „muszę zmienić kod gdzieś wewnątrz dużego bloku”.
źródło
for name in "Tom", "Mary": std_greeting(name)
Najważniejszym aspektem nazwanych stałych i funkcji jest nie tyle to, że zmniejszają one ilość pisania, ale raczej „dołączają” różne miejsca, w których są używane. Jeśli chodzi o twój przykład, rozważ cztery scenariusze:
Konieczna jest zmiana obu powitań w ten sam sposób [np. Na
Bonjour, Tom
iBonjour, Mary
].Konieczna jest zmiana jednego powitania, ale pozostawienie takiego, jakie jest [np.
Hi, Tom
IGuten Tag, Mary
].Konieczna jest inna zmiana obu powitań [np.
Hello, Tom
IHowdy, Mary
].Żadne powitanie nigdy nie musi zostać zmienione.
Jeśli zmiana powitania nigdy nie będzie konieczna, tak naprawdę nie będzie miało znaczenia, które podejście zostanie zastosowane. Korzystanie z funkcji wspólnej spowoduje naturalny efekt, że zmiana powitania zmieni je w ten sam sposób. Gdyby wszystkie pozdrowienia zmieniły się w ten sam sposób, byłoby dobrze. Jeśli jednak nie powinni, powitanie każdej osoby będzie musiało zostać zakodowane lub określone osobno; każda praca, która sprawi, że będą korzystać ze wspólnej funkcji lub specyfikacji, będzie musiała zostać cofnięta (i lepiej byłoby, gdyby jej nie wykonano).
Oczywiście nie zawsze można przewidzieć przyszłość, ale jeśli ktoś ma powód, by sądzić, że bardziej prawdopodobne jest, że oba pozdrowienia będą musiały się zmienić razem, byłby to czynnik przemawiający za użyciem wspólnego kodu (lub nazwanej stałej) ; jeśli ktoś ma powód, by sądzić, że bardziej prawdopodobne jest, że jedno lub oba będą musiały zmienić, aby się różniły, byłby to czynnik przeciwko próbowaniu użycia wspólnego kodu.
źródło
Myślę, że powinieneś mieć powód, aby stworzyć procedurę. Istnieje wiele powodów, dla których należy utworzyć procedurę. Najważniejsze, które moim zdaniem są najważniejsze:
Abstrakcja
Procedurę można wykorzystać do wyodrębnienia ogólnego algorytmu ze szczegółów poszczególnych kroków algorytmu. Jeśli potrafię znaleźć odpowiednio spójną abstrakcję, pomaga mi to ustrukturyzować sposób myślenia o działaniu algorytmu. Na przykład mogę zaprojektować algorytm, który działa na listach bez konieczności rozważania reprezentacji listy.
Modułowość
Procedury mogą służyć do organizowania kodu w moduły. Moduły można często traktować osobno. Na przykład zbudowany i przetestowany osobno.
Dobrze zaprojektowany moduł zazwyczaj przechwytuje pewną spójną, znaczącą jednostkę funkcjonalności. Dlatego często mogą być własnością różnych zespołów, całkowicie zamienione na alternatywne lub ponownie wykorzystane w innym kontekście.
Nawigacja kodu
W dużych systemach znalezienie kodu związanego z określonym zachowaniem systemu może być trudne. Hierarchiczna organizacja kodu w bibliotekach, modułach i procedurach może pomóc w tym wyzwaniu. W szczególności, jeśli spróbujesz a) zorganizować funkcjonalność pod znaczącymi i przewidywalnymi nazwami b) umieść procedury związane z podobną funkcjonalnością blisko siebie.
Zaktualizuj spójność
W dużych systemach znalezienie kodu, który należy zmienić, aby uzyskać określoną zmianę zachowania, może być trudne. Użycie procedur do zorganizowania funkcjonalności programu może to ułatwić. W szczególności, jeśli każdy element funkcjonalności twojego programu pojawia się tylko raz i w spójnej grupie procedur, z mojego doświadczenia mniej prawdopodobne jest, że przegapisz miejsce, w którym powinieneś zaktualizować lub dokonać niespójnej aktualizacji.
Pamiętaj, że powinieneś organizować procedury w oparciu o funkcjonalność i abstrakty w programie. Nie opiera się na tym, czy w tej chwili dwa bity kodu są takie same.
Rekurencja
Korzystanie z rekurencji wymaga utworzenia procedur
Testowanie
Zazwyczaj można testować procedury niezależnie od siebie. Niezależne testowanie różnych części treści procedury jest trudniejsze, ponieważ zazwyczaj pierwszą część procedury należy wykonać przed drugą częścią. Ta obserwacja często ma również zastosowanie do innych podejść do określania / weryfikowania zachowania programów.
Wniosek
Wiele z tych punktów dotyczy zrozumiałości programu. Można powiedzieć, że procedury są sposobem na stworzenie nowego języka, specyficznego dla Twojej domeny, w którym można organizować, pisać i czytać o problemach i procesach w Twojej domenie.
źródło
Żaden z podanych przypadków nie wydaje się warty refaktoryzacji.
W obu przypadkach wykonujesz operację, która jest wyrażona jasno i zwięźle, i nie ma niebezpieczeństwa, że wprowadzona zostanie niespójna zmiana.
Zalecam, aby zawsze szukać sposobów izolowania kodu, w których:
Istnieje możliwe do zidentyfikowania, znaczące zadanie, które można oddzielić i
Zarówno
za. zadanie jest złożone do wyrażenia (biorąc pod uwagę dostępne funkcje) lub
b. zadanie jest wykonywane więcej niż raz i potrzebujesz sposobu, aby upewnić się, że jest zmieniany w ten sam sposób w obu miejscach,
Jeśli warunek 1 nie jest spełniony, nie znajdziesz odpowiedniego interfejsu dla kodu: jeśli spróbujesz go wymusić, skończysz z mnóstwem parametrów, wieloma rzeczami, które chcesz zwrócić, dużą ilością logiki kontekstowej i prawdopodobnie nie mogę znaleźć dobrego imienia. Spróbuj najpierw udokumentować interfejs, o którym myślisz, jest to dobry sposób na przetestowanie hipotezy, że jest to odpowiedni pakiet funkcjonalności i ma dodatkową zaletę, że podczas pisania kodu jest on już sprecyzowany i udokumentowany!
2a jest możliwe bez 2b: czasami wyjąłem kod, nawet gdy wiem, że zużywa się tylko raz, po prostu dlatego, że przeniesienie go w inne miejsce i zastąpienie go jedną linią oznacza, że kontekst, w którym jest wywoływany, jest nagle znacznie bardziej czytelny (szczególnie jeśli jest to prosta koncepcja, którą język utrudnia wdrożenie). Jest to również jasne podczas czytania wyodrębnionej funkcji, gdzie logika zaczyna się i kończy oraz co robi.
2b jest możliwe bez 2a: Sztuką jest wyczucie, jakie zmiany są bardziej prawdopodobne. Czy bardziej prawdopodobne jest, że zasady Twojej firmy zmienią się z powiedzenia „Cześć” wszędzie na „Cześć” przez cały czas lub że powitanie zmieni się na bardziej formalny ton, jeśli wysyłasz żądanie zapłaty lub przeprosiny za przerwę w świadczeniu usług? Czasami może to wynikać z tego, że korzystasz z biblioteki zewnętrznej, której nie jesteś pewien i chcesz móc szybko zamienić ją na inną: implementacja może się zmienić, nawet jeśli funkcjonalność się nie zmieni.
Najczęściej jednak będziesz mieć mieszankę 2a i 2b. Będziesz musiał użyć swojej oceny, biorąc pod uwagę wartość biznesową kodu, częstotliwość, z jakiej się korzysta, czy jest dobrze udokumentowany i zrozumiany, stan zestawu testów itp.
Jeśli zauważysz tę samą logikę, która została użyta więcej niż jeden raz, z pewnością powinieneś rozważyć możliwość refaktoryzacji. Jeśli zaczynasz nowe instrukcje bardziej niż
n
poziomy wcięcia w większości języków, jest to kolejny, nieco mniej znaczący wyzwalacz (wybierz wartość,n
którą czujesz się komfortowo dla danego języka: na przykład Python może wynosić 6).Tak długo, jak zastanawiasz się nad tymi rzeczami i eliminujesz duże potwory z kodem spaghetti, powinieneś czuć się dobrze - nie przejmuj się tak długo, jak drobnoziarniste musi być twoje refaktoryzowanie, że nie masz czasu dla takich rzeczy, jak przerabiane testy lub dokumentacja. Jeśli będzie trzeba, czas pokaże.
źródło
Ogólnie zgadzam się z Robertem Harveyem, ale chciałem dodać przypadek, aby podzielić funkcjonalność na funkcje. Aby poprawić czytelność. Rozważ przypadek:
Mimo że te wywołania funkcji nie są używane nigdzie indziej, istnieje znaczny wzrost czytelności, jeśli wszystkie 3 funkcje są znacznie długie i mają zagnieżdżone pętle itp.
źródło
Nie ma twardej i szybkiej reguły, którą należy zastosować, będzie ona zależeć od faktycznej funkcji, która zostanie użyta. W przypadku prostego drukowania nazw nie użyłbym funkcji, ale jeśli byłaby to suma matematyczna, byłaby to inna historia. Następnie utworzyłbyś funkcję, nawet jeśli zostanie wywołana tylko dwa razy, aby zapewnić, że suma matematyczna będzie zawsze taka sama, nawet jeśli zostanie zmieniona. W innym przykładzie, jeśli wykonujesz jakąkolwiek formę sprawdzania poprawności, użyłbyś funkcji, więc w twoim przykładzie, jeśli musisz sprawdzić, czy nazwa jest dłuższa niż 5 znaków, użyłbyś funkcji, aby upewnić się, że zawsze wykonywane są te same sprawdzenia.
Myślę więc, że odpowiedziałeś na swoje pytanie, kiedy powiedziałeś „W przypadku kodów, które wymagają więcej niż dwóch linii, będę musiał napisać func”. Zasadniczo używałbyś funkcji, ale musisz także użyć własnej logiki, aby ustalić, czy istnieje jakaś wartość dodana z używania funkcji.
źródło
Zacząłem wierzyć w coś o refaktoryzacji, o której tu nie wspominałem, wiem, że jest tu już wiele odpowiedzi, ale myślę, że to jest nowe.
Byłem bezwzględnym refaktorem i mocno wierzyłem w SUCHO, zanim jeszcze pojawiły się warunki. Głównie dlatego, że mam problemy z utrzymaniem dużej bazy kodu w mojej głowie, a częściowo dlatego, że lubię kodowanie DRY i nie lubię niczego w kodowaniu C&P, w rzeczywistości jest to dla mnie bolesne i strasznie wolne.
Chodzi o to, że naleganie na DRY dało mi dużo praktyki w niektórych technikach, z których rzadko widuję inne. Wiele osób twierdzi, że Java jest trudna lub niemożliwa do wykonania SUCHEGO, ale tak naprawdę po prostu nie próbują.
Jeden przykład dawno temu, który jest nieco podobny do twojego przykładu. Ludzie myślą, że tworzenie GUI w Javie jest trudne. Oczywiście jest tak, jeśli kodujesz w ten sposób:
Każdy, kto uważa, że to jest po prostu szalone, ma absolutną rację, ale to nie wina Javy - kodu nigdy nie należy tak pisać. Te wywołania metod są funkcjami przeznaczonymi do pakowania w inne systemy. Jeśli nie możesz znaleźć takiego systemu, zbuduj go!
Oczywiście nie możesz takiego kodu, więc musisz cofnąć się i spojrzeć na problem, co właściwie robi ten powtarzany kod? Określa niektóre ciągi znaków i ich związek (drzewo) i łączy liście tego drzewa z działaniami. Więc tak naprawdę chcesz powiedzieć:
Po zdefiniowaniu relacji w sposób zwięzły i opisowy piszesz metodę, jak sobie z tym poradzić - w tym przypadku iterujesz metody przekazanej klasy i budujesz drzewo, a następnie używasz go do budowania menu i Działania, a także (oczywiście) wyświetlają menu. Nie będziesz mieć powielania, a twoja metoda jest wielokrotnego użytku ... i prawdopodobnie łatwiejsza do napisania niż duża liczba menu, a jeśli naprawdę lubisz programować, masz o wiele więcej zabawy. To nie jest trudne - metoda, którą musisz napisać, to prawdopodobnie mniej linii niż ręczne tworzenie menu!
Chodzi o to, że aby dobrze to zrobić, trzeba dużo ćwiczyć. Musisz dobrze przeanalizować, jakie dokładnie informacje znajdują się w powtarzanych częściach, wyodrębnij te informacje i wymyśl, jak je dobrze wyrazić. Nauka używania narzędzi takich jak parsowanie ciągów i adnotacje bardzo pomaga. Bardzo ważna jest również wiedza na temat zgłaszania błędów i dokumentacji.
Otrzymujesz „darmową” praktykę, po prostu dobrze kodując - są duże szanse, że gdy będziesz w tym dobry, przekonasz się, że kodowanie czegoś SUCHEGO (w tym pisanie narzędzia wielokrotnego użytku) jest szybsze niż kopiowanie i wklejanie, a wszystkie błędy, powielone błędy i trudne zmiany, które powoduje ten rodzaj kodowania.
Nie sądzę, że byłbym w stanie czerpać przyjemność z mojej pracy, gdybym nie ćwiczył technik DRY i budowania narzędzi tak bardzo, jak tylko mogłem. Gdybym musiał wziąć obniżkę wynagrodzenia, aby nie musiałem kopiować i wklejać programowania, wziąłbym to.
Więc moje punkty to:
źródło
Ogólnie rzecz biorąc, dobrym pomysłem jest podzielenie czegoś na funkcję, która poprawia czytelność twojego kodu. Lub, jeśli często powtarzana część jest w jakiś sposób rdzeniem systemu. W powyższym przykładzie, jeśli trzeba przywitać użytkowników w zależności od ustawień regionalnych, warto mieć osobną funkcję powitania.
źródło
W następstwie komentarza @ DocBrown do @RobertHarvey na temat używania funkcji do tworzenia abstrakcji: jeśli nie możesz wymyślić odpowiednio pouczającej nazwy funkcji, która nie jest znacznie bardziej zwięzła ani bardziej przejrzysta niż kod za nią kryjący, nie pobiera się zbyt wiele . Bez jakiegokolwiek innego dobrego powodu, aby uczynić go funkcją, nie ma takiej potrzeby.
Ponadto nazwa funkcji rzadko przechwytuje pełną semantykę, więc może być konieczne sprawdzenie jej definicji, jeśli nie jest ona wystarczająco często znana. Zwłaszcza w języku innym niż funkcjonalny może być konieczne sprawdzenie, czy ma on skutki uboczne, jakie błędy mogą wystąpić i jak na nie reagować, złożoność czasu, czy przydziela i / lub zwalnia zasoby oraz czy jest wątkowo bezpieczny.
Oczywiście z definicji rozważamy tutaj tylko proste funkcje, ale dzieje się to w obie strony - w takich przypadkach wstawianie raczej nie zwiększy złożoności. Co więcej, czytelnik prawdopodobnie nie zda sobie sprawy, że jest to prosta funkcja, dopóki nie spojrzy. Nawet z IDE, które hiperłącza cię do definicji, wizualne przeskakiwanie jest przeszkodą w zrozumieniu.
Mówiąc ogólnie, rekurencyjnie dzieląc kod na więcej, mniejsze funkcje ostatecznie doprowadzą cię do punktu, w którym funkcje nie mają już niezależnego znaczenia, ponieważ ponieważ fragmenty kodu, z których są wykonane, stają się mniejsze, fragmenty te zyskują większe znaczenie z utworzonego kontekstu przez otaczający kod. Jako analogię, pomyśl o tym jak o zdjęciu: jeśli zbyt mocno powiększysz obraz, nie zobaczysz, na co patrzysz.
źródło
isWeekend
staje się oczywiste.