Ilekroć napotykam, że piszę tę samą logikę więcej niż raz, zwykle umieszczam ją w funkcji, więc w mojej aplikacji jest tylko jedno miejsce, w którym muszę ją zachować. Efektem ubocznym jest to, że czasami mam jedną lub dwie funkcje liniowe, takie jak:
function conditionMet(){
return x == condition;
}
LUB
function runCallback(callback){
if($.isFunction(callback))
callback();
}
Czy to leniwa czy zła praktyka? Pytam tylko dlatego, że skutkuje to większą liczbą wywołań funkcji dla bardzo małych elementów logiki.
programming-practices
coding-standards
Mark Brown
źródło
źródło
Assert.AreEqual<int>(expected, actual, message, arg1, arg2, arg3, ...);
. Drugi jest w porządku, jak jest. Potencjalnie dołączę opcjonalną flagę bool, która decyduje, czy zgłosić wyjątek / etc. w przypadku, gdy oddzwonienie nie jest funkcją.def yes(): return 'yes'
Odpowiedzi:
Hehe, oh Panie Brown, gdybym tylko mógł przekonać wszystkich programistów, których spotykam, do utrzymania ich tak małych funkcji, uwierzcie mi, świat oprogramowania byłby lepszym miejscem!
1) Czytelność kodu zwiększa się dziesięciokrotnie.
2) Tak łatwe do zrozumienia procesu kodu ze względu na czytelność.
3) OSUSZANIE - nie powtarzaj się - dostosowujesz się do tego bardzo dobrze!
4) Testowalne. Małe funkcje są milion razy łatwiejsze do przetestowania niż te 200 metod liniowych, które widzimy zdecydowanie za często.
Aha i nie martw się o „przeskakiwanie funkcji” pod względem wydajności. Kompilacje „Release” i optymalizacje kompilatora dbają o to bardzo dobrze, a wydajność wynosi 99% czasu w innym miejscu w projektowaniu systemów.
Czy to jest leniwe? - Bardzo odwrotnie!
Czy to zła praktyka? - Absolutnie nie. Lepiej wyciągnąć ten sposób tworzenia metod niż smoły smoliste lub „Boskie Przedmioty”, które są zbyt powszechne.
Kontynuujcie dobra prace, mój kolego rzemieślniku;)
źródło
Powiedziałbym, że refaktoryzowana metoda jest zbyt krótka, jeśli:
Dawny:
lub...
Dawny:
Może to być prawidłowy wzorzec, ale w tym przykładzie po prostu wstawiłbym metodę configureDialog (), chyba że zamierzałem go zastąpić lub użyć tego kodu w innym miejscu.
źródło
Czy funkcja może być za krótka? Ogólnie nie.
W rzeczywistości jedyny sposób, aby zapewnić, że:
Utrzymuje twoje funkcje tak małe jak to możliwe. Lub innymi słowy, wyodrębnij funkcje ze swoich funkcji, dopóki nie będziesz mógł już wyodrębnić. Nazywam to „Wyciągaj, aż upadniesz”.
Aby to wyjaśnić: funkcja to zakres z fragmentami funkcji komunikującymi się za pomocą zmiennych. Klasa jest także zakresem z dużą ilością funkcji komunikujących się za pomocą zmiennych. Tak więc długą funkcję można zawsze zastąpić jedną lub większą liczbą klas za pomocą małej metody.
Ponadto funkcja, która jest wystarczająco duża, aby umożliwić wyodrębnienie z niej innej funkcji, z definicji robi więcej niż jedną rzecz . Jeśli więc możesz wyodrębnić funkcję z innej, powinieneś ją wyodrębnić.
Niektórzy martwią się, że doprowadzi to do rozprzestrzeniania się funkcji. Mają rację. To będzie. To właściwie dobra rzecz. To dobrze, ponieważ funkcje mają nazwy. Jeśli ostrożnie wybierasz dobre imiona, funkcje te działają jak posty, które kierują innymi osobami przez Twój kod. Rzeczywiście, dobrze nazwane funkcje wewnątrz dobrze nazwanych klas wewnątrz dobrze nazwanych przestrzeni nazw są jednym z najlepszych sposobów, aby upewnić się, że czytelnicy NIE zgubią się.
Jest o wiele więcej na ten temat w odcinku III Czystego kodu na cleancoders.com
źródło
Wow, większość z tych odpowiedzi wcale nie jest bardzo pomocna.
Nie należy pisać funkcji, których tożsamość jest jej definicją . Oznacza to, że jeśli nazwa funkcji to po prostu blok kodu funkcji napisany w języku angielskim, nie zapisuj jej jako funkcji.
Rozważ swoją funkcję
conditionMet
i tę inną funkcjęaddOne
(wybacz mi mój zardzewiały JavaScript):conditionMet
jest właściwą definicją pojęciową;addOne
jest tautologią .conditionMet
jest dobre, ponieważ nie wiesz, co się z tymconditionMet
wiąże, mówiąc „warunek spełniony”, ale możesz zrozumieć, dlaczegoaddOne
to głupie, jeśli przeczytasz to po angielsku:Z miłości do wszystkiego, co może być jeszcze święte, proszę, nie pisz funkcji tautologicznych!
(I z tego samego powodu nie pisz komentarzy dla każdego wiersza kodu !)
źródło
function nametoolong() { return name.size > 15; }
lubfunction successorIndex(x) { return x + 1; }
Tak. Problem z twoimi funkcjami jest taki, że ich nazwa jest zła.Powiedziałbym, że jeśli uważasz, że zamiar jakiegoś kodu można poprawić poprzez dodanie komentarza, to zamiast dodawać ten komentarz, wypakuj kod do własnej metody. Bez względu na to, jak mały był kod.
Na przykład, jeśli twój kod miałby wyglądać tak:
zamiast tego wyglądać tak:
z
Innymi słowy, nie chodzi o długość metody, ale o kod samodokumentujący.
źródło
if x == PIXEL_ON
. Używanie stałej może być tak samo opisowe jak użycie metody i jest trochę krótsze.Myślę, że właśnie to chcesz zrobić. W tej chwili ta funkcja może składać się tylko z jednej lub dwóch linii, ale z czasem może rosnąć. Również posiadanie większej liczby wywołań funkcji pozwala odczytać wywołania funkcji i zrozumieć, co się tam dzieje. To sprawia, że twój kod jest bardzo SUCHY (Don't Repeat Yourself), co jest znacznie łatwiejsze w utrzymaniu.
źródło
conditionMet
jest zbyt ogólną nazwą i nie przyjmuje argumentów, więc testuje jakiś stan? (x == xWarunek) występuje w większości języków i sytuacji tak wyrazistych jak „xWarunek”.Zgadzam się ze wszystkimi pozostałymi postami, które widziałem. To jest dobry styl.
Narzut związany z tak małą metodą może być zerowy, ponieważ optymalizator może zoptymalizować połączenie i wstawić kod. Prosty kod taki jak ten pozwala optymalizatorowi wykonać najlepszą pracę.
Kod powinien być napisany dla jasności i prostoty. Staram się ograniczyć metodę do jednej z dwóch ról: podejmowanie decyzji; lub wykonując pracę. Może to generować metody jednowierszowe. Im lepiej to robię, tym lepiej znajduję mój kod.
Taki kod ma zwykle wysoką spójność i niskie sprzężenie, co jest dobrą praktyką kodowania.
EDYCJA: Uwaga na temat nazw metod. Użyj nazwy metody, która wskazuje, która metoda nie działa. Uważam, że verb_noun (_modifier) to dobry schemat nazewnictwa. Daje to nazwy takie jak Find_Customer_ByName zamiast Select_Customer_Using_NameIdx. Drugi przypadek może stać się niepoprawny po zmodyfikowaniu metody. W pierwszym przypadku możesz zamienić całą implementację bazy danych klienta.
źródło
Refaktoryzacja jednego wiersza kodu w funkcję wydaje się nadmierna. Mogą występować wyjątkowe przypadki, takie jak ver loooooong / comples wierszy lub wypraw, ale nie zrobiłbym tego, chyba że wiem, że funkcja będzie rosła w przyszłości.
i twój pierwszy przykład wskazuje na użycie globals (które mogą, ale nie muszą mówić o innych problemach w kodzie), przebuduję go jeszcze bardziej i uczynię te dwie zmienne jako parametry:
conditionMet
Przykład może być przydatne, jeśli stan jest długi i powtarzalny, takich jak:źródło
conditionMet
funkcja jest tylko pełnym==
operatorem. To prawdopodobnie nie jest przydatne.conditionMet (x, relation condition) {
tutaj, gdzie przekazujesz x, „==” i relację. Następnie nie musisz powtarzać kodu dla „<”, „>”, „<=”, „! =” Itd. Z drugiej strony - większość języków ma wbudowane te konstrukcje, ponieważ robią to operatory (warunek x ==). Funkcje instrukcji atomowych to o krok za daleko.Rozważ to:
Prosta funkcja wykrywania kolizji:
Jeśli cały czas pisałeś ten „prosty” jeden linijka w swoim kodzie, możesz w końcu popełnić błąd. Poza tym pisanie tego w kółko byłoby bardzo torturujące.
źródło
#define
;)Nie, a to rzadko stanowi problem. Teraz, jeśli ktoś uważa, że żadna funkcja nie powinna być dłuższa niż jeden wiersz kodu (choćby to mogło być tak proste), byłby to problem i pod pewnymi względami leniwy, ponieważ nie myśli o tym, co jest właściwe.
źródło
function isAdult () = { age >= 18; }
ale na pewno nieisAtLeast18
.Powiedziałbym, że są za krótkie, ale to moja subiektywna opinia.
Dlatego:
Długie funkcje są złe, ale funkcje krótsze niż 3 linie i wykonujące tylko jedną rzecz są równie złe IMHO.
Powiedziałbym więc, że napisz tylko małą funkcję, jeśli:
Założę się, że następny programista (starszy) będzie miał lepsze rzeczy do roboty niż zapamiętanie wszystkich funkcji SetXToOne. Więc wkrótce zmienią się w ciężar własny.
źródło
Nie podoba mi się przykład nie. 1, ponieważ i-ta nazwa ogólna.
conditionMet
nie wydaje się ogólny, więc oznacza konkretny warunek? LubićTo by było w porządku. To jest różnica semantyczna
nie byłoby dla mnie w porządku.
Może jest często używany i może podlegać późniejszym zmianom:
też jest w porządku. Używając go wiele razy, wystarczy zmienić jedno miejsce, jeśli to konieczne - być może bitej śmietany stanie się jutro.
nie jest atomowy i powinien dać ci dobrą okazję do przetestowania.
Jeśli potrzebujesz przekazać funkcję, oczywiście, przekaż co chcesz i napisz funkcje, które wyglądają inaczej.
Ale ogólnie widzę znacznie więcej funkcji, które są zbyt długie, niż funkcje, które są zbyt krótkie.
Ostatnie słowo: niektóre funkcje wyglądają tylko odpowiednio, ponieważ są napisane zbyt szczegółowe:
Jeśli widzisz, że to to samo co
nie będziesz mieć problemu z
zamiast
źródło
Nie ma takiego kodu jak żaden kod!
Uprość to i nie komplikuj.
Nie jest leniwy, wykonuje swoją pracę!
źródło
Tak, dobrze jest mieć funkcję krótkiego kodu. W przypadku metod takich jak „getters”, „setters”, „accesors” jest bardzo powszechny, jak wspomniano w poprzednich odpowiedziach.
Czasami te krótkie funkcje „akcesorów” są wirtualne, ponieważ po zastąpieniu w podklasach funkcje będą miały więcej kodu.
Jeśli chcesz, żebyś nie działał tak krótko, no cóż, w wielu funkcjach, niezależnie od tego, czy są globalne czy metody, zwykle używam zmiennej „wynik” (styl pascal) zamiast bezpośredniego powrotu, co jest bardzo pomocne podczas korzystania z debuggera.
źródło
Zbyt krótki nigdy nie stanowi problemu. Oto kilka przyczyn krótkich funkcji:
Wielokrotnego użytku
Np. Jeśli masz funkcję, taką jak metoda set, możesz ją potwierdzić, aby upewnić się, że parametry są prawidłowe. Sprawdzanie to należy wykonywać wszędzie, gdzie ustawiona jest zmienna.
Konserwowalność
Możesz użyć oświadczenia, które Twoim zdaniem w przyszłości może się zmienić. Na przykład teraz wyświetlasz symbol w kolumnie, ale później może on zmienić się w coś innego (lub nawet sygnał dźwiękowy).
Jednolitość
Używasz np. Wzoru elewacji i jedyne, co robi funkcja, to dokładne przekazywanie funkcji do innej bez zmiany argumentów.
źródło
Gdy nadasz sekcji kodu nazwę, jest ona zasadniczo przeznaczona do nadania jej nazwy . Może to wynikać z kilku powodów, ale najważniejsze jest, aby nadać mu sensowną nazwę, która dodaje do twojego programu. Nazwy takie jak „addOneToCounter” nic by nie dodały, ale
conditionMet()
by to zrobiły .Jeśli potrzebujesz reguły, aby dowiedzieć się, czy fragment jest za krótki, czy za długi, zastanów się, ile czasu zajmuje znalezienie sensownej nazwy fragmentu. Jeśli nie możesz w rozsądnym czasie, fragment kodu nie ma odpowiedniego rozmiaru.
źródło
Nie, ale może być zbyt zwięzłe.
Pamiętaj: kod jest zapisywany raz, ale czytany wiele razy.
Nie pisz kodu dla kompilatora. Napisz to dla przyszłych programistów, którzy będą musieli utrzymywać Twój kod.
źródło
Tak, kochanie, funkcja może być coraz mniejsza, a to, czy jest dobre czy złe, zależy od używanego języka / frameworka.
Moim zdaniem pracuję głównie nad technologiami Front End, małe funkcje są przeważnie używane jako funkcje pomocnicze, które z pewnością będziesz ich używać podczas pracy z małymi filtrami i przy użyciu tej samej logiki w całej aplikacji. Jeśli twoja aplikacja ma zbyt dużo wspólnej logiki, będzie mnóstwo małych funkcji.
Ale w aplikacji, w której nie masz wspólnej logiki, nie będziesz musiał tworzyć małych funkcji, ale możesz podzielić kod na segmenty, w których zarządzanie i zrozumienie staje się łatwe.
Ogólnie rzecz biorąc, rozbicie ogromnego kodu na małą funkcję to bardzo dobre podejście. W nowoczesnych ramach i językach będziesz musiał to zrobić np
jest anonimową funkcją w JavaScript 2017 i maszynopisie ES 2017
w powyższym kodzie widać 3 deklarację funkcji i 2 wywołania funkcji, jest to proste zgłoszenie serwisowe w Angular 4 z maszynowym skryptem. Możesz myśleć o tym jak o swoich wymaganiach
Powyżej są 3 anonimowe funkcje w języku clojure
Powyższa jest deklaracją funkcjonalną w zamknięciu
Więc tak, FUNKCJE mogą być mniejsze, ale czy są dobre czy złe, jeśli masz takie funkcje jak:
Cóż, nie jest to dobrą praktyką, ale co zrobić, jeśli używasz tej funkcji w znaczniku HTML, tak jak robimy to w Angular Framework, jeśli nie było obsługi Increment lub Decrement w Angularowych szablonach HTML, to byłoby to rozwiązanie dla mnie.
Weźmy inny przykład
Powyższy przykład jest koniecznością podczas gry, gdy tablice wewnątrz kątowych szablonów HTML. Czasami będziesz musiał stworzyć małe funkcje
źródło
Nie zgadzam się z prawie odpowiedzią udzieloną w tym czasie.
Niedawno znalazłem kolegę, który pisze wszystkich członków klas w następujący sposób:
Może to być dobry kod w sporadycznych przypadkach, ale na pewno nie, jeśli zdefiniujesz wiele klas mających wiele właściwości. Nie chcę przez to powiedzieć, że metody takie jak powyższe nie będą pisane. Ale jeśli skończysz pisać większość kodu jako „opakowanie” prawdziwej logiki, coś jest nie tak.
Prawdopodobnie programista nie rozumie ogólnej logiki, obawia się przyszłych zmian i refaktoryzacji kodu.
Definicja interfejsu wynika z rzeczywistej potrzeby; w rzeczy samej, jeśli musisz ustawić i uzyskać prostą właściwość (bez dużej logiki, co czyni członka krótszym), będzie to możliwe. Ale jeśli prawdziwą potrzebę można przeanalizować w inny sposób, dlaczego nie zdefiniować bardziej intuicyjnego interfejsu?
Aby naprawdę odpowiedzieć na pytanie, oczywiście, że nie, a powód jest bardzo oczywisty: należy określić metodę / właściwość / whatelse dla tego, czego potrzebuje. Nawet pusta funkcja wirtualna ma powód, aby istnieć.
źródło