Zawsze słyszałem o funkcji pojedynczego punktu wyjścia jako o złym sposobie kodowania, ponieważ tracisz czytelność i wydajność. Nigdy nie słyszałem, żeby ktoś argumentował po drugiej stronie.
Myślałem, że ma to coś wspólnego z CS, ale to pytanie zostało odrzucone przy wymianie stosów teorii.
coding-style
hex bob-omb
źródło
źródło
Odpowiedzi:
Istnieją różne szkoły myślenia iw dużej mierze sprowadza się to do osobistych preferencji.
Jednym z nich jest to, że mniej zagmatwane jest, jeśli istnieje tylko jeden punkt wyjścia - masz jedną ścieżkę przez metodę i wiesz, gdzie szukać wyjścia. Z drugiej strony, jeśli używasz wcięć do reprezentowania zagnieżdżenia, twój kod zostanie masowo wcięty w prawo i bardzo trudno będzie śledzić wszystkie zagnieżdżone zakresy.
Innym jest to, że możesz sprawdzić warunki wstępne i wyjść wcześnie na początku metody, dzięki czemu wiesz w treści metody, że pewne warunki są prawdziwe, bez wcięcia całej metody o 5 mil w prawo. Zwykle minimalizuje to liczbę zakresów, o które musisz się martwić, co znacznie ułatwia śledzenie kodu.
Trzecią jest to, że możesz wyjść gdziekolwiek zechcesz. Kiedyś było to bardziej zagmatwane, ale teraz, gdy mamy edytory i kompilatory do kolorowania składni, które wykrywają nieosiągalny kod, jest o wiele łatwiejsze do zrobienia.
Jestem w środku obozu. Egzekwowanie pojedynczego punktu wyjścia jest bezcelowym lub wręcz przynoszącym efekt przeciwny do zamierzonego ograniczeniem IMHO, podczas gdy losowe wyjście z całej metody może czasami prowadzić do bałaganu i trudnej do przestrzegania logiki, w której trudno jest zobaczyć, czy dany fragment kodu będzie, czy nie będzie wykonany. Jednak „bramkowanie” metody umożliwia znaczne uproszczenie całości metody.
źródło
singe exit
paradygmacie głębokiego zagnieżdżenia można uniknąć za pomocągo to
stwierdzeń. Dodatkowo dostaje się możliwość wykonania postprocessingu pod lokalnąError
etykietą funkcji, co jest niemożliwe w przypadku wielureturn
s.Moje ogólne zalecenie jest takie, aby instrukcje return w praktyce znajdowały się albo przed pierwszym kodem, który ma jakiekolwiek skutki uboczne, albo po ostatnim kodzie, który ma jakiekolwiek skutki uboczne. Rozważałbym coś takiego:
jaśniejsze niż:
Jeśli jakiś warunek powinien uniemożliwić funkcji wykonanie czegokolwiek, wolę wcześniej wrócić z funkcji w miejscu powyżej punktu, w którym funkcja zrobiłaby cokolwiek. Jednak gdy funkcja podejmie działania ze skutkami ubocznymi, wolę powrócić od dołu, aby wyjaśnić, że wszystkie skutki uboczne muszą zostać rozwiązane.
źródło
ok
zmienną, wygląda dla mnie jako podejście z pojedynczym zwrotem. Ponadto blok if-else można po prostu przepisać na:return ok ? 0 : ERR_NOT_OK;
return
na początku znak przed całym kodem, który robi wszystko. Jeśli chodzi o używanie?:
operatora, zapisanie go w oddzielnych wierszach ułatwia w wielu IDE dołączenie punktu przerwania debugowania do scenariusza, w którym nie jest dobrze. Przy okazji, prawdziwym kluczem do „pojedynczego punktu wyjścia” jest zrozumienie, że liczy się to, że dla każdego konkretnego wywołania normalnej funkcji punktem wyjścia jest punkt bezpośrednio po wywołaniu . Obecnie programiści uważają to za coś oczywistego, ale nie zawsze tak było. W niektórych rzadkich przypadkach kod może wymagaćPojedynczy punkt wejścia i wyjścia był oryginalną koncepcją programowania strukturalnego w porównaniu z kodowaniem krok po kroku Spaghetti. Istnieje przekonanie, że wiele funkcji punktów wyjścia wymaga więcej kodu, ponieważ trzeba odpowiednio wyczyścić przestrzeń pamięci przydzieloną dla zmiennych. Rozważmy scenariusz, w którym funkcja przydziela zmienne (zasoby), a wczesne opuszczenie funkcji i bez odpowiedniego czyszczenia spowoduje wycieki zasobów. Ponadto skonstruowanie czyszczenia przed każdym wyjściem spowodowałoby utworzenie dużej ilości nadmiarowego kodu.
źródło
W większości przypadków sprowadza się to do potrzeb produktu. W „dawnych czasach” kod spaghetti z wieloma punktami powrotu powodował wycieki pamięci, ponieważ programiści preferujący tę metodę zazwyczaj nie usuwali dobrze. Pojawiły się również problemy z „utratą” przez niektóre kompilatory odniesienia do zmiennej zwracanej, gdy stos był zdejmowany podczas powrotu, w przypadku powrotu z zagnieżdżonego zakresu. Bardziej ogólny problem dotyczył kodu ponownego wejścia, który próbuje uzyskać stan wywołania funkcji dokładnie taki sam, jak stan jej powrotu. Mutatory oop naruszyły to i koncepcja została odłożona na półkę.
Istnieją produkty, w szczególności jądra, które wymagają szybkości zapewnianej przez wiele punktów wyjścia. Te środowiska mają zwykle własną pamięć i zarządzanie procesami, więc ryzyko wycieku jest zminimalizowane.
Osobiście lubię mieć pojedynczy punkt wyjścia, ponieważ często używam go do wstawiania punktu przerwania w instrukcji return i wykonywania kodu sprawdzającego, w jaki sposób kod określił to rozwiązanie. Mógłbym po prostu podejść do wejścia i przejść przez nie, co robię w przypadku rozwiązań szeroko zagnieżdżonych i rekurencyjnych. Jako recenzent kodu, wielokrotne zwroty w funkcji wymagają znacznie głębszej analizy - więc jeśli robisz to, aby przyspieszyć implementację, okradasz Petera, aby uratować Paula. Przegląd kodu będzie wymagał więcej czasu, unieważniając domniemanie skutecznej implementacji.
- 2 centy
Więcej informacji można znaleźć w tym dokumencie: NISTIR 5459
źródło
multiple returns in a function requires a much deeper analysis
tylko jeśli funkcja jest już ogromna (> 1 ekran), w przeciwnym razie ułatwia analizęMoim zdaniem rada wyjścia z funkcji (lub innej struktury kontrolnej) tylko w jednym miejscu jest często wyprzedana. Zwykle podaje się dwa powody, aby wyjść tylko w jednym punkcie:
Drugi powód jest subtelny i ma pewne zalety, zwłaszcza jeśli funkcja zwraca dużą strukturę danych. Jednak nie martwiłbym się tym zbytnio, poza ...
Jeśli jesteś studentem, chcesz zdobyć najwyższe oceny w swojej klasie. Rób to, co preferuje instruktor. Ze swojej perspektywy prawdopodobnie ma dobry powód; więc przynajmniej poznasz jego perspektywę. Ma to wartość samą w sobie.
Powodzenia.
źródło
Kiedyś byłem zwolennikiem stylu pojedynczego wyjścia. Moje rozumowanie pochodziło głównie z bólu ...
Pojedyncze wyjście jest łatwiejsze do debugowania.
Biorąc pod uwagę techniki i narzędzia, które mamy dzisiaj, jest to znacznie mniej rozsądne stanowisko, ponieważ testy jednostkowe i rejestrowanie mogą sprawić, że pojedyncze wyjście stanie się niepotrzebne. To powiedziawszy, kiedy trzeba obserwować wykonanie kodu w debugerze, znacznie trudniej było zrozumieć kod zawierający wiele punktów wyjścia i pracować z nim.
Stało się to szczególnie prawdziwe, gdy trzeba było wtrącać przypisania w celu zbadania stanu (zastąpione wyrażeniami obserwującymi w nowoczesnych debugerach). Zbyt łatwo było również zmienić przepływ sterowania w sposób, który ukrył problem lub całkowicie zepsuł wykonanie.
Metody z pojedynczym wyjściem były łatwiejsze do przejścia w debugerze i łatwiejsze do rozłączenia bez łamania logiki.
źródło
Odpowiedź jest bardzo zależna od kontekstu. Jeśli tworzysz GUI i masz funkcję, która inicjuje API i otwiera okna na początku twojego maina, będzie ona pełna wywołań, które mogą powodować błędy, z których każdy może spowodować zamknięcie instancji programu. Jeśli użyjesz zagnieżdżonych instrukcji JEŻELI i wprowadzisz wcięcie, kod może szybko zostać bardzo przekrzywiony w prawo. Zwracanie błędów na każdym etapie może być lepsze i bardziej czytelne, a jednocześnie łatwe do debugowania z kilkoma flagami w kodzie.
Jeśli jednak testujesz różne warunki i zwracasz różne wartości w zależności od wyników uzyskanych w metodzie, znacznie lepszą praktyką może być posiadanie jednego punktu wyjścia. Kiedyś pracowałem nad skryptami do przetwarzania obrazu w MATLAB-ie, które mogły być bardzo duże. Wiele punktów wyjścia może bardzo utrudnić śledzenie kodu. Instrukcje przełączania były znacznie bardziej odpowiednie.
Najlepiej uczyć się w trakcie. Jeśli piszesz kod do czegoś, spróbuj znaleźć kod innych osób i zobaczyć, jak go implementują. Zdecyduj, które bity Ci się podobają, a które nie.
źródło
Jeśli uważasz, że potrzebujesz wielu punktów wyjścia w funkcji, oznacza to, że funkcja jest za duża i robi za dużo.
Poleciłbym przeczytać rozdział o funkcjach w książce Roberta C. Martina Clean Code.
Zasadniczo powinieneś próbować pisać funkcje z maksymalnie 4 liniami kodu.
Kilka uwag z bloga Mike'a Longa :
źródło