Często spotykam się z tym problemem. Na przykład obecnie piszę funkcję odczytu i funkcję zapisu, a oni oboje sprawdzają, czy buf
jest wskaźnikiem NULL i czy mode
zmienna mieści się w określonych granicach.
To jest duplikacja kodu. Można to rozwiązać, przenosząc go do własnej funkcji. Ale powinienem? Będzie to dość anemiczna funkcja (niewiele robi), raczej zlokalizowana (więc nie ma ogólnego zastosowania) i sama nie wytrzymuje dobrze (nie może zrozumieć, do czego jest potrzebna, chyba że zobaczysz, gdzie ona jest) używany). Inną opcją jest użycie makra, ale chcę porozmawiać o funkcjach w tym poście.
Więc czy powinieneś użyć funkcji do czegoś takiego? Jakie są zalety i wady?
coding-style
EpsilonVector
źródło
źródło
Odpowiedzi:
To świetne wykorzystanie funkcji.
Dobre. Funkcje powinny robić tylko jedną rzecz.
W języku OO ustaw go jako prywatny.
Jeśli obsługuje więcej niż jedną skrzynkę, jest to cel ogólny. Co więcej, uogólnienie to nie jedyne użycie funkcji. Są one rzeczywiście po to, aby (1) oszczędzić ci pisania tego samego kodu więcej niż raz, ale także (2), aby podzielić kod na mniejsze części, aby był bardziej czytelny. W tym przypadku osiąga zarówno (1), jak i (2). Jednak nawet jeśli twoja funkcja była wywoływana tylko z jednego miejsca, może to nadal pomóc w (2).
Wymyśl dla niej dobre imię, a samo w sobie będzie dobrze. „ValidateFileParameters” lub coś takiego. Teraz dobrze sobie radzi.
źródło
To całkowicie powinno być funkcją.
Znacznie bardziej czytelny i łatwiejszy w utrzymaniu (jeśli logika sprawdzania kiedykolwiek się zmienia, zmieniasz ją tylko w jednym miejscu).
Poza tym takie rzeczy łatwo się wprowadzają, więc nawet nie musisz się martwić o koszty ogólne wywołania funkcji.
Pozwól, że zadam ci lepsze pytanie. Jak nie jest to dobra praktyka?
Robić co należy. :)
źródło
return buffer != null;
, myślę, że szkodzi to czytelności.isBufferValid
jest zdecydowanie bardziej czytelny (w mojej książce) niżbuffer != null
, ponieważ bardziej jasno przekazuje cel. I znowu, nie wspominając o tym, chroni cię również przed powielaniem. Czego więcej potrzebujesz?IMO, fragmenty kodu warto przenieść do własnych funkcji, ilekroć sprawia to, że kod jest bardziej czytelny , niezależnie od tego, czy funkcja będzie bardzo krótka, czy będzie używana tylko raz.
Są oczywiście granice podyktowane zdrowym rozsądkiem. Na przykład nie chcesz mieć
WriteToConsole(text)
metody z ciałem po prostuConsole.WriteLine(text)
. Ale błędem w kwestii czytelności jest dobra praktyka.źródło
Zasadniczo dobrym pomysłem jest używanie funkcji do usuwania duplikacji w kodzie.
Jednak może to być brane zbyt daleko. To jest wyrok sądu.
Aby wziąć przykład z zerowego sprawdzania bufora, prawdopodobnie powiedziałbym, że poniższy kod jest wystarczająco jasny i nie powinien być wyodrębniany do oddzielnej funkcji, nawet jeśli ten sam wzorzec jest używany w kilku miejscach.
Jeśli podasz komunikat o błędzie jako parametr do ogólnej funkcji sprawdzania wartości NULL, a także weźmiesz pod uwagę kod wymagany do zdefiniowania funkcji, oznacza to, że nie jest to oszczędność netto LOC, aby zastąpić ją:
Ponadto konieczność zanurzenia się w funkcji, aby zobaczyć, co robi podczas debugowania, oznacza, że wywołanie funkcji jest mniej „przezroczyste” dla użytkownika, a zatem może być uważane za mniej czytelne / łatwe do utrzymania.
źródło
Centralizacja kodu jest zwykle zawsze dobrym pomysłem. Musimy ponownie wykorzystać kod w jak największym stopniu.
Należy jednak pamiętać, jak to zrobić. Na przykład, jeśli masz kod, który wykonuje compute_prime_number () lub check_if_packet_is_bad (), to dobrze. Są szanse, że algorytm samej funkcjonalności ewoluuje, co przyniesie korzyści.
Jednak żaden fragment kodu, który powtarza się jako proza, nie kwalifikuje się do natychmiastowego scentralizowania. To jest złe. Możesz ukryć dowolne wiersze kodu wewnątrz funkcji, aby ukryć kod, z czasem, gdy zacznie korzystać z wielu części aplikacji, wszystkie muszą pozostać kompatybilne z potrzebami wszystkich wywoływanych funkcji.
Oto kilka pytań, które powinieneś zadać przed zadaniem
Czy funkcja, którą tworzysz, ma swoje nieodłączne znaczenie, czy może to tylko wiązka linii?
Który inny kontekst będzie wymagał użycia tych samych funkcji? Czy jest prawdopodobne, że przed użyciem tego może być konieczne uogólnienie interfejsu API?
Jakich oczekiwań będą dotyczyły (różne części) aplikacje, gdy wprowadzisz wyjątki?
Jakie są scenariusze, aby zobaczyć, że funkcje będą ewoluować?
Powinieneś również sprawdzić, czy istnieją już takie rzeczy. Widziałem tak wielu ludzi, którzy zawsze starają się redefiniować swoje makra MIN, MAX zamiast szukać tego, co już istnieje.
Zasadniczo pytanie brzmi: „Czy ta nowa funkcja naprawdę zasługuje na ponowne użycie, czy to tylko kopia-wklej ?” Jeśli jest pierwszy, dobrze jest iść.
źródło
Należy unikać powielania kodu. Za każdym razem, gdy się tego spodziewasz, powinieneś unikać duplikacji kodu. Jeśli nie spodziewałeś się tego, zastosuj zasadę 3: refaktoryzuj, zanim ten sam fragment kodu zostanie zduplikowany 3 razy, zanotuj dziwactwo, gdy zostanie zduplikowane 2 razy.
Co to jest duplikat kodu?
Rozważ przykład poniżej:
staje się
Poprawiłeś enkapsulację (teraz możesz zmienić warunki, aby być administratorem w sposób transparentny) i semantykę kodu. Jeśli błąd zostanie wykryty w sposób, w jaki sprawdzasz, że użytkownik jest administratorem, nie musisz rzucać całą bazą kodu i naprawiać wszędzie (z ryzykiem zapomnienia o jednym i uzyskania luki w zabezpieczeniach aplikacji).
źródło
DRY polega na uproszczeniu manipulacji kodem. Właśnie poruszyłeś kwestię dotyczącą tej zasady: nie chodzi o zminimalizowanie liczby tokenów w kodzie, ale o tworzenie pojedynczych punktów modyfikacji dla semantycznie równoważnego kodu . Wygląda na to, że twoje czeki zawsze mają ten sam semantyczny, więc powinny zostać włączone do funkcji na wypadek, gdybyś musiał je zmodyfikować.
źródło
Jeśli widzisz, że jest powielony, powinieneś znaleźć sposób na jego scentralizowanie.
Funkcje są dobrym sposobem (może nie najlepszym, ale to zależy od języka). Nawet jeśli funkcja jest anemiczna, jak mówisz, nie oznacza to, że pozostanie taka.
Co jeśli musisz sprawdzić coś jeszcze?
Czy znajdziesz wszystkie miejsca, w których musisz dodać dodatkową kontrolę lub po prostu zmienić funkcję?
źródło
Prawie zawsze dobrze jest spełnić następujące warunki:
W większym zakresie należy dokładnie wyważyć powielanie z kompromisami zależności. Przykłady technik ograniczających zakres: ukrywanie się w sekcjach prywatnych lub modułach bez ujawniania ich publicznie.
źródło