Często pisałem tego rodzaju funkcje w obu formatach i zastanawiałem się, czy jeden format jest lepszy od drugiego i dlaczego.
public void SomeFunction(bool someCondition)
{
if (someCondition)
{
// Do Something
}
}
lub
public void SomeFunction(bool someCondition)
{
if (!someCondition)
return;
// Do Something
}
Zwykle koduję za pomocą pierwszego, ponieważ w ten sposób działa mój mózg podczas kodowania, chociaż myślę, że wolę drugi, ponieważ od razu zajmuje się obsługą błędów i łatwiej mi go czytać
Odpowiedzi:
Wolę drugi styl. Najpierw usuń niepoprawne przypadki, po prostu wychodząc lub podnosząc wyjątki, wstaw odpowiednią pustą linię, a następnie dodaj „rzeczywistą” treść metody. Łatwiej mi to czytać.
źródło
Zdecydowanie to drugie. Ten pierwszy nie wygląda teraz źle, ale kiedy otrzymujesz bardziej złożony kod, nie wyobrażam sobie, aby ktokolwiek pomyślałby tak:
jest bardziej czytelny niż
W pełni przyznaję, że nigdy nie zrozumiałem zalet pojedynczych punktów wyjścia.
źródło
return value;
pomaga!?! Następnie trzeba polować na pół tuzinavalue = ...
, z tą wadą, że nigdy nie masz pewności, że wartość nie zostanie zmieniona między tym zadaniem a ostatecznym zwrotem. Przynajmniej natychmiastowy powrót jest jasny, że nic już nie zmieni wyniku.To zależy - ogólnie rzecz biorąc, nie będę się starał przesuwać wielu kodów, aby wcześnie wyjść z funkcji - kompilator ogólnie się tym zajmie. To powiedziawszy jednak, jeśli są jakieś podstawowe parametry na górze, których potrzebuję i nie mogę kontynuować w inny sposób, wybuchnę wcześnie. Podobnie, jeśli warunek generuje gigantyczny
if
blok w działaniu, to również wcześniej go wyłamię.To powiedziawszy jednak, jeśli funkcja wymaga pewnych danych podczas jej wywoływania, zwykle rzucę wyjątek (patrz przykład), a nie tylko powracam.
źródło
Wolę wczesny powrót.
Jeśli masz jeden punkt wejścia i jeden punkt wyjścia, zawsze musisz śledzić cały kod w głowie aż do punktu wyjścia (nigdy nie wiesz, czy jakiś inny kod kodu robi coś innego, więc możesz muszę to wyśledzić, aż będą istnieć). Robisz to bez względu na to, która gałąź określa ostateczny wynik. To jest trudne do naśladowania.
Z jednym wpisem i wielokrotnością istnieje, wracasz, gdy masz wynik i nie zawracasz sobie głowy śledzeniem go do końca, aby zobaczyć, że nikt nie robi nic innego (ponieważ nie będzie nic innego, odkąd wróciłeś). To tak, jakby ciało metody podzieliło się na więcej kroków, które każdy krok z możliwością zwrócenia wyniku lub wypróbowania szczęścia w następnym kroku.
źródło
W programowaniu C, w którym trzeba ręcznie wyczyścić, wiele można powiedzieć o jednopunktowym zwrocie. Nawet jeśli nie ma teraz potrzeby, aby coś wyczyścić, ktoś może edytować twoją funkcję, przydzielić coś i musi to wyczyścić przed powrotem. Jeśli tak się stanie, będzie to koszmarna praca przeglądająca wszystkie zwroty.
W programowaniu w C ++ masz destruktory, a nawet teraz osłony wyjścia z zakresu. Wszystko to musi być tutaj, aby upewnić się, że kod jest wyjątkowo bezpieczny, więc kod jest dobrze chroniony przed wczesnym wyjściem, a zatem nie ma logicznego minusu i jest wyłącznie kwestią stylu.
Nie mam wystarczającej wiedzy na temat Javy, czy „w końcu” zostanie wywołany kod blokowy i czy finaliści mogą poradzić sobie z sytuacją konieczności zapewnienia, że coś się stanie.
C # Na pewno nie mogę odpowiedzieć.
Język D zapewnia odpowiednie wbudowane osłony wyjścia zakresu i dlatego jest dobrze przygotowany do wcześniejszego wyjścia, dlatego nie powinien przedstawiać innego problemu niż styl.
Funkcje nie powinny oczywiście być tak długie, a jeśli masz dużą instrukcję switch, twój kod jest prawdopodobnie również źle uwzględniony.
źródło
goto
i ewentualnie dwukropka. Przykład (formatowanie kodu niemożliwe w komentarzach):foo() { init(); if (bad) goto err; bar(); if (bad) goto err; baz(); return 0; err: cleanup(); return 1; }
Wczesne zwroty dla wygranej. Mogą wydawać się brzydkie, ale znacznie mniej brzydkie niż duże
if
opakowania, szczególnie jeśli istnieje wiele warunków do sprawdzenia.źródło
Używam obu.
Jeśli
DoSomething
jest 3-5 wierszy kodu, kod wygląda pięknie przy użyciu pierwszej metody formatowania.Ale jeśli ma o wiele więcej wierszy, wolę drugi format. Nie podoba mi się, gdy nawiasy otwierające i zamykające nie są na tym samym ekranie.
źródło
Klasycznym powodem pojedynczego wejścia-pojedynczego wyjścia jest to, że inaczej formalna semantyka stałaby się niewymownie brzydka inaczej (ten sam powód GOTO został uznany za szkodliwy).
Innymi słowy, łatwiej jest uzasadnić, kiedy oprogramowanie opuści procedurę, jeśli masz tylko 1 zwrot. Co jest również argumentem przeciwko wyjątkom.
Zazwyczaj minimalizuję podejście do wczesnego powrotu.
źródło
Osobiście wolę na początku sprawdzać warunki zaliczenia / niepowodzenia. To pozwala mi pogrupować większość najczęstszych awarii na górze funkcji z resztą logiki do naśladowania.
źródło
To zależy.
Wcześniejszy powrót, jeśli istnieje jakiś oczywisty stan ślepej uliczki, który należy natychmiast sprawdzić, co sprawiłoby, że uruchomienie pozostałej funkcji byłoby bezcelowe. *
Ustaw Retval + pojedynczy powrót, jeśli funkcja jest bardziej złożona i w przeciwnym razie może mieć wiele punktów wyjścia (problem z czytelnością).
* Może to często wskazywać na problem z projektem. Jeśli okaże się, że wiele metod wymaga sprawdzenia stanu zewnętrznego / parametrów przed uruchomieniem pozostałej części kodu, prawdopodobnie to powinno być zajęte przez program wywołujący.
źródło
Fred
okna jest jużFred
ustawiona, a ustawienie nazwy kontrolki na jej obecny stan wymusiłoby przerysowanie (co, choć potencjalnie przydatne, w niektórych przypadkach, być denerwujące w tym, który jest pod ręką), byłoby całkowicie rozsądne, aby metoda set-name wcześnie wychodziła, jeśli stare i nowe nazwy pasują do siebie.Użyj If
W książce Dona Knutha o GOTO czytałem, że podaje powód, dla którego zawsze najbardziej prawdopodobny warunek jest najważniejszy w stwierdzeniu if. Przy założeniu, że jest to nadal rozsądny pomysł (i nie tylko z uwagi na szybkość epoki). Powiedziałbym, że wczesne zwroty nie są dobrą praktyką programistyczną, szczególnie biorąc pod uwagę fakt, że częściej niż nie są używane do obsługi błędów, chyba że Twój kod jest bardziej podatny na awarię niż na :-)
Jeśli zastosujesz się do powyższej porady, musisz umieścić ten zwrot na dole funkcji, a wtedy równie dobrze możesz nie nazwać go return, po prostu ustaw kod błędu i zwróć dwa wiersze. W ten sposób osiągnięcie idealnego wyjścia 1 wejście 1.
Specyficzne dla Delphi ...
Myślę, że jest to dobra praktyka programistyczna dla programistów Delphi, chociaż nie mam żadnego dowodu. Przed D2009 nie mamy atomowego sposobu na zwrócenie wartości, mamy
exit;
iresult := foo;
moglibyśmy po prostu rzucić wyjątki.Gdybyś musiał zastąpić
dla
możesz mieć dość tego, że widzisz to u góry każdej z twoich funkcji i wolisz
i po prostu
exit
całkowicie unikajcie .źródło
if true then Exit(foo);
używam często technikę najpierw zainicjowaćresult
donil
lubFALSE
odpowiednio, a następnie sprawdzając wszystkie warunki błędach i tylkoExit;
jeśli jest spełniony. Przypadek sukcesuresult
jest następnie (zwykle) gdzieś na końcu metody.Zgadzam się z następującym oświadczeniem:
Zaczerpnięte z tego pytania w przepełnieniu stosu .
źródło
Korzystam z wczesnych zwrotów prawie wyłącznie w dzisiejszych czasach, do skrajności. Piszę to
tak jak
ale to naprawdę nie ma znaczenia. Jeśli masz więcej niż jeden lub dwa poziomy zagnieżdżania w swoich funkcjach, należy je wyeliminować.
źródło
Wolałbym pisać:
źródło
DoSomeFunctionIfSomeCondition
?Tak jak ty, zwykle piszę pierwszy, ale wolę ostatni. Jeśli mam dużo zagnieżdżonych czeków, zwykle refaktoryzuję się do drugiej metody.
Nie podoba mi się, jak obsługa błędów jest odsuwana od kontroli.
Wolę to:
źródło
Warunki na górze nazywane są „warunkami wstępnymi”. Stawiając
if(!precond) return;
, wizualnie wymieniasz wszystkie warunki wstępne.Użycie dużego bloku „jeśli-inaczej” może zwiększyć obciążenie wcięcia (zapomniałem cytatu o wcięciach 3-poziomowych).
źródło
Wolę zachować, jeśli stwierdzenia są małe.
Wybierając między:
i
Wybrałbym to, co opisałeś jako „wczesny powrót”.
Pamiętaj, że nie dbam o wczesne zwroty lub cokolwiek innego, po prostu bardzo lubię uprościć kod, skrócić treść instrukcji if itp.
Zagnieżdżone jeśli i dla i podczas gdy są okropne , unikaj ich za wszelką cenę.
źródło
Jak mówią inni, to zależy. W przypadku małych funkcji, które zwracają wartości, mogę kodować wcześniejsze zwroty. Ale w przypadku funkcji o dużych rozmiarach zawsze lubię mieć miejsce w kodzie, w którym wiem, że mogę umieścić coś, co zostanie wykonane przed jego zwróceniem.
źródło
Szybko ćwiczę na poziomie funkcji. Utrzymuje spójny i czysty kod (dla mnie i dla tych, z którymi pracowałem). Z tego powodu zawsze wracam wcześnie.
W przypadku niektórych często sprawdzanych warunków możesz zaimplementować aspekty tych kontroli, jeśli używasz AOP.
źródło