Czasami natrafiam na kod podobny do poniższego przykładu (to, co dokładnie robi ta funkcja, jest poza zakresem tego pytania):
function doSomething(value) {
if (check1(value)) {
return -1;
}
else if (check2(value)) {
return value;
}
else {
return false;
}
}
Jak widać, if
, else if
i else
oświadczenia są używane w połączeniu z return
oświadczeniem. Dla zwykłego obserwatora wydaje się to dość intuicyjne, ale myślę, że bardziej eleganckie (z perspektywy programisty) byłoby upuszczenie else
-s i uproszczenie kodu w następujący sposób:
function doSomething(value) {
if (check1(value)) {
return -1;
}
if (check2(value)) {
return value;
}
return false;
}
Ma to sens, ponieważ wszystko, co następuje po return
instrukcji (w tym samym zakresie), nigdy nie zostanie wykonane, dzięki czemu powyższy kod będzie semantycznie równy pierwszemu przykładowi.
Który z powyższych elementów bardziej odpowiada dobrym praktykom kodowania? Czy są jakieś wady obu metod w zakresie czytelności kodu?
Edycja: W tym pytaniu podano jako odniesienie duplikat . Uważam, że moje pytanie dotyczy innego tematu, ponieważ nie pytam o unikanie duplikatów stwierdzeń przedstawionych w drugim pytaniu. Oba pytania mają na celu ograniczenie liczby powtórzeń, choć w nieco inny sposób.
źródło
else
Jest mniejszym problemem, większym problemem jest oczywiście jesteś powrocie dwa typy danych z jednej funkcji, która sprawia, że API funkcji nieprzewidywalne.-1
jest liczbą,false
jest wartością logiczną ivalue
nie jest tu podana, więc może to być dowolny typ obiektu.value
to rzeczywiście liczba całkowita. Jeśli może to być cokolwiek, to jest jeszcze gorzej.Odpowiedzi:
Podoba mi się ten bez
else
i oto dlaczego:Ponieważ zrobienie tego nie zepsuło niczego, czego nie powinno było.
Nienawiść współzależności we wszystkich jej formach (w tym nazywanie funkcji
check2()
). Izoluj wszystko, co można odizolować. Czasami potrzebujesz,else
ale nie widzę tego tutaj.źródło
if
bloku,} //else
aby wyjaśnić podczas czytania kodu, że jedynym zamierzonym wykonaniem poif
bloku kodu jest, jeśli warunek wif
instrukcji jest fałszywy. Bez czegoś takiego, szczególnie jeśli kod wif
bloku staje się bardziej złożony, może nie być jasne dla tego, kto utrzymuje kod, że intencją było, aby nigdy nie przekroczyćif
bloku, gdyif
warunek jest spełniony.if
aby wyjaśnić, że ta sekcja kodu została wykonana i struktura jest zakończona. Aby to zrobić, robię to, czego tu nie zrobiłem (ponieważ nie chciałem odwracać uwagi od głównego punktu PO, wprowadzając inne zmiany). Robię najprostszą rzecz, jaką potrafię, a wszystko to bez rozpraszania uwagi. Dodaję pusty wiersz.Myślę, że to zależy od semantyki kodu. Jeśli twoje trzy przypadki są od siebie zależne, wyraźnie to zaznacz. Zwiększa to czytelność kodu i ułatwia zrozumienie dla każdego innego. Przykład:
Tutaj wyraźnie zależysz od wartości
x
we wszystkich trzech przypadkach. Jeśli pominąłbyś ostatnielse
, byłoby to mniej jasne.Jeśli twoje sprawy nie są bezpośrednio od siebie zależne, pomiń to:
Trudno to pokazać w prostym przykładzie bez kontekstu, ale mam nadzieję, że rozumiesz.
źródło
Wolę drugą opcję (oddzielny
ifs
bezelse if
i na początkureturn
) ale to jest tak długo, jak bloki kodu są krótkie .Jeśli bloki kodu są długie, lepiej użyć
else if
, ponieważ w przeciwnym razie nie miałbyś jasnego zrozumienia kilku punktów wyjścia, które ma kod.Na przykład:
W takim przypadku lepiej jest użyć
else if
, przechowywać kod powrotu w zmiennej i mieć tylko jedno zdanie zwrotne na końcu.Ale ponieważ należy dążyć do tego, aby funkcje były krótkie, powiedziałbym, aby były krótkie i wychodziły wcześniej niż w pierwszym fragmencie kodu.
źródło
return
mieści się w 3 liniach,if
więc nie różni się tak bardzo, jakelse if
nawet po 200 liniach kodu. Pojedynczy styl powrót przedstawisz tutaj tradycja C i innych języków, które nie zgłasza błędów z wyjątkami. Chodziło o stworzenie jednego miejsca do czyszczenia zasobów. Języki wyjątków używają do tegofinally
bloku. Podejrzewam, że tworzy to również miejsce do umieszczenia punktu przerwania, jeśli twój debugger nie pozwoli ci umieścić go w funkcjach zamykających nawias klamrowy.retVal
. Jeśli możesz bezpiecznie wyjść z funkcji, zrób to natychmiast, bez przypisywania bezpiecznej wartości, która ma być zwrócona do zmiennej pojedynczego wyjścia z funkcji. Kiedy używasz pojedynczego punktu powrotu w naprawdę długiej funkcji, generalnie nie ufam innym programistom i ostatecznie przeglądam resztę funkcji również pod kątem innych modyfikacji wartości zwracanej. Szybka porażka i wczesny powrót to między innymi dwie zasady, według których żyję.Używam obu w różnych okolicznościach. Podczas sprawdzania poprawności pomijam pozostałe. W przepływie kontrolnym używam innego.
vs
Pierwszy przypadek brzmi bardziej tak, jakbyś najpierw sprawdzał wszystkie wymagania wstępne, usuwając je z drogi, a następnie przechodząc do właściwego kodu, który chcesz uruchomić. W związku z tym soczysty kod, który naprawdę chcesz uruchomić, należy bezpośrednio do zakresu funkcji; na tym właśnie polega ta funkcja.
Drugi przypadek brzmi bardziej tak, jakby obie ścieżki były poprawnymi kodami do uruchomienia, które są tak samo istotne dla funkcji, jak inne na podstawie pewnych warunków. Jako takie należą one do siebie w podobnych poziomach zakresu.
źródło
Jedyną sytuacją, jaką kiedykolwiek widziałem, to naprawdę ważne, jest taki kod:
Jest tu oczywiście coś nie tak. Problem polega na tym, że nie jest jasne, czy
return
należy je dodać, czyArrays.asList
usunąć. Nie można tego naprawić bez głębszej kontroli powiązanych metod. Możesz uniknąć tej dwuznaczności, zawsze stosując w pełni wyczerpujące bloki if-else. To:nie będzie się kompilował (w językach sprawdzanych statycznie), chyba że w pierwszej kolejności dodasz wyraźny zwrot
if
.Niektóre języki nie pozwalają nawet na pierwszy styl. Staram się używać go tylko w ściśle imperatywnym kontekście lub jako warunek wstępny w długich metodach:
źródło
Trzy wyjścia z takiej funkcji są bardzo mylące, jeśli próbujesz postępować zgodnie z kodem i źle postępować.
Jeśli masz pojedynczy punkt wyjścia dla tej funkcji, pozostałe są wymagane.
W rzeczywistości idziemy jeszcze dalej.
Wystarczająco słuszne, możesz argumentować za jednym wczesnym zwrotem przy sprawdzaniu poprawności danych wejściowych. Po prostu unikaj zawijania całej masy, jeśli logika w if.
źródło
Wolę pominąć zbędną instrukcję else. Ilekroć to widzę (podczas przeglądania kodu lub refaktoryzacji), zastanawiam się, czy autor zrozumiał przepływ sterowania i czy w kodzie może być błąd.
Jeśli autor uważa, że instrukcja else jest konieczna, a tym samym nie rozumie konsekwencji instrukcji return dla przepływu kontrolnego, to z pewnością taki brak zrozumienia jest głównym źródłem błędów, w tej funkcji i ogólnie.
źródło