Podczas niedawnego przeglądu kodu poproszono mnie o umieszczenie default
skrzynek we wszystkich plikach wszędzie tam, gdzie switch
używany jest blok, nawet jeśli nie ma nic do zrobienia default
. Oznacza to, że muszę włożyć default
sprawę i nic w niej nie pisać.
Czy to jest właściwe? W jakim celu miałoby to służyć?
Odpowiedzi:
Wydaje się, że istnieją trzy przypadki, w których
default
oświadczenie nie jest konieczne:nie pozostały żadne inne przypadki, ponieważ istnieje ograniczony zestaw wartości, które wchodzą do
switch case
. Ale to może się zmieniać z czasem (umyślnie lub przypadkowo) i dobrze byłoby,default case
gdyby coś się zmieniło _ możesz zalogować lub ostrzec użytkownika o złej wartości.wiesz, jak i gdzie
switch case
zostanie użyty oraz jakie wartości go wprowadzą. Ponownie może się to zmienić i może być konieczne dodatkowe przetwarzanie.inne przypadki nie wymagają specjalnego przetwarzania. Jeśli tak jest, myślę, że zostaniesz poproszony o dodanie
default case
, ponieważ jest to akceptowany styl kodowania i sprawia, że kod jest bardziej czytelny.Pierwsze dwa przypadki opierają się na założeniach. Tak więc (zakładając, że pracujesz w niezbyt małym zespole, ponieważ masz regularne przeglądy kodu), nie możesz sobie pozwolić na takie założenia. Nie wiesz, kto będzie pracował z twoim kodem lub nawoływał do funkcji / wywoływania metod w twoim kodzie. Podobnie może być konieczna praca z kodem innej osoby. Posiadanie tego samego stylu kodowania ułatwi radzenie sobie z czyimś kodem (w tym z Twoim).
źródło
throw new IllegalStateException("Unrecognised case "+myEnum)
co pokazuje, gdzie i jaki jest błąd.else
klauzulę po każdym,if/else if
nawet jeśli wiesz, że to nie powinno się zdarzyć? Nie wydaje mi się to dobrym pomysłem ...Często zdarza się, że standardy kodowania firm wymagają domyślnego przypadku dla wszystkich
switch
instrukcji. Jednym z powodów jest to, że ułatwia czytelnikom znalezienie końcaswitch
. Innym, prawdopodobnie lepszym powodem jest to, że sprawia, że zastanawiasz się przez chwilę, co powinien zrobić Twój kod, gdy warunek nie spełnia twoich oczekiwań. Bez względu na powód wymagania, jeśli jest to standard firmy, należy go przestrzegać, chyba że istnieje uzasadniony powód, aby tego nie robić.Jeśli uważasz, że
switch
obejmuje to przypadki dla każdego możliwego warunku, dobrze jest umieścićassert
oświadczenie w przypadku domyślnym. W ten sposób, gdy ktoś zmieni kod i niechcący doda warunek, któregoswitch
nie obejmuje Twój , uderzyassert
i zda sobie sprawę, że musi zająć się tą częścią kodu.Jeśli spełniasz
switch
tylko kilka możliwych warunków, ale dla innych nie musisz robić nic specjalnego, możesz pozostawić domyślną skrzynkę pustą. W takim przypadku dobrym pomysłem jest dodanie komentarza wskazującego, że przypadek domyślny jest celowo pusty, ponieważ warunki, które go dotyczą, nie wymagają żadnej pracy.źródło
assert
?Jeśli „przełączysz” na czysty typ wyliczenia, niebezpiecznym jest mieć domyślną rezerwę. Gdy później dodasz wartości do typu wyliczenia, kompilator podświetli przełączniki z nowymi nieobjętymi wartościami. Jeśli masz tam domyślną klauzulę, kompilator pozostanie cichy i możesz go przegapić.
źródło
Pod wieloma względami to pytanie jest takie samo, jak często zadawane pytanie Czy potrzebuję
else
klauzuli na końcu drabinyif
/else if
obejmującej każdą opcję .Odpowiedź brzmi składniowo: nie, nie. Ale jest jednak ...
default
Punkt może być nie do (co najmniej) dwóch powodów:otherwise
od przypadku. Nie ma żadnego powodu, aby nie włączać ich do kodu źródłowego.Moja filozofia jest zawsze bardzo prosta - oceń najgorszy możliwy scenariusz z dwóch opcji i wybierz najbezpieczniejszy. W przypadku pustego
else
lubdefault
klauzuli najgorszych przypadków są opcje:Overdramatic? Może ... ale wtedy moje oprogramowanie może potencjalnie zabijać ludzi, jeśli pójdzie nie tak. Wolałbym nie ryzykować.
Tak na marginesie, że wytyczne MISRA-C {zobaczyć profil dla przynależności} polecić
default
klauzuli dla każdegoswitch
źródło
else
poif
. Ale jak powiedziałeś, nie, nie jest.Java nie zmusza cię do posiadania „domyślnej” instrukcji, ale dobrą praktyką jest posiadanie jej przez cały czas, nawet jeśli kod nigdy nie zostanie osiągnięty (w tej chwili). Oto kilka powodów:
Dzięki nieosiągalnej klauzuli domyślnej pokazujesz czytelnikowi swojego kodu, że wziąłeś pod uwagę wartości i wiesz, co robisz. Zezwalasz także na przyszłe zmiany, powiedzmy na przykład: dodana jest nowa wartość wyliczeniowa, przełącznik nie powinien po cichu ignorować nowej wartości; zamiast tego możesz rzucić tam wyjątek lub zrobić coś innego.
Aby złapać nieoczekiwaną wartość (na wypadek, gdy nie włączasz wyliczenia), która jest przekazywana - może ona być na przykład większa lub mniejsza niż oczekiwana.
Do obsługi „domyślnych” akcji - gdzie przełączniki służą do specjalnego zachowania. Na przykład zmienną można zadeklarować poza przełącznikiem, ale nie można jej zainicjować, a każdy przypadek inicjuje ją na coś innego. Wartość domyślna w tym przypadku może zainicjować ją na wartość domyślną, aby kod natychmiast po przełączniku nie powodował błędu / nie zgłosił wyjątku.
Nawet jeśli zdecydujesz się nie umieszczać niczego w ustawieniach domyślnych (bez wyjątków, rejestrowania itp.), To nawet komentarz z informacją, że uważasz, że domyślnie nigdy się nie zdarzy, może pomóc w czytelności twojego kodu; ale sprowadza się to do osobistych preferencji.
źródło
Dodałbym również, że zależy to od filozofii używanego języka. Na przykład w Erlang, gdzie jest powszechne podejście do „pozwól mu się zawiesić”, nie zdefiniowałbyś domyślnego przypadku, ale pozwoliłbyś, aby twoja
case
instrukcja wygenerowała błąd, jeśli wystąpi sytuacja, która nie jest zaspokojona.źródło
Zawsze powinieneś mieć domyślne, chyba że udowodniłeś i trwale objąłeś wszystkie sprawy. To nic nie kosztuje, a to ubezpieczenie od nieprzestrzegania instrukcji zmiany w ewoluującym programie.
Jeśli naprawdę jesteś pewien, że nie obchodzą Cię żadne inne przypadki, domyślnie: break; // nie przejmuj się, ale domyślna wartość domyślna powinna być podobna do domyślnej: wyrzuć nowy Błąd („nieoczekiwana wartość”);
Podobnie, nigdy nie powinieneś „odrzucać” nietrywialnej konstrukcji przypadku bez dodawania komentarza do efektu, który zamierzasz pominąć. Java pomyliła się na etapie projektowania.
źródło
Rozważać
i
Argumentowałbym, że jest to lepsze niż posiadanie sprawy MALE, sprawy FEMALE i sprawy domyślnej, która zgłasza wyjątek.
Podczas fazy testowania komputer sprawdzi, czy g jest KOBIETĄ. Podczas produkcji kontrola zostanie pominięta. (Tak, mikrooptymalizacja!)
Co ważniejsze, utrzymasz swój cel 100% pokrycia kodu. Jeśli napisałeś przypadek domyślny, który zgłasza wyjątek, jak byś go kiedykolwiek przetestował?
źródło
Gender . FEMALE . equals ( FEMALE ) ;
ocenia sięfalse
? Miałeś na myśli,Gender.FEMALE.equals (g)
ale ponieważ możesz polegać na tym, że odniesienia do stabilizacji są stabilne, możesz po prostu pisaćg == Gender.FEMALE
. 4. (Osobista opinia) taki kod jest znacznie trudniejszy do odczytania i spowoduje nieco więcej mylących błędów.