Nasza organizacja ma wymaganą zasadę kodowania (bez żadnego wyjaśnienia), która:
if… else if konstrukcje powinny być zakończone klauzulą else
Przykład 1:
if ( x < 0 )
{
x = 0;
} /* else not needed */
Przykład 2:
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
Do jakiego typu edge case ma to służyć?
Co mnie również niepokoi, jeśli chodzi o powód, to fakt, że w przykładzie 1 nie jest potrzebny, else
ale w przykładzie 2 . Jeśli powodem jest możliwość ponownego else
użycia i rozszerzalność, myślę, że należy je zastosować w obu przypadkach.
assert(false, "should never go here")
może mieć sensif (x < 0) { x = 0; } else { if (y < 0) { x = 3; }}
. Możesz też po prostu przestrzegać takich zasad, z których wiele jest głupich, po prostu dlatego, że jest to wymagane.< 0
sprawdzania), więc assert idzie aby zawiesić program w prawdopodobnie najczęstszym przypadku, gdy wartości mieszczą się w oczekiwanych granicach.Odpowiedzi:
Jak wspomniano w innej odpowiedzi, pochodzi to z wytycznych kodowania MISRA-C. Celem jest programowanie obronne, pojęcie często używane w programowaniu o znaczeniu krytycznym.
Oznacza to, że każdy
if - else if
musi kończyć się aelse
, a każdyswitch
musi kończyć się adefault
.Są ku temu dwa powody:
Kod samodokumentujący. Jeśli napiszesz,
else
ale zostawisz to puste, oznacza to: „Zdecydowanie rozważyłem scenariusz, w którym aniif
nie, ani nieelse if
są prawdziwe”.Brak pisania
else
tam oznacza: „albo rozważyłem scenariusz, w którym aniif
ani nieelse if
są prawdziwe, albo zupełnie zapomniałem o tym pomyśleć i potencjalnie jest tutaj gruby błąd w moim kodzie”.Zatrzymaj niekontrolowany kod. W oprogramowaniu o znaczeniu krytycznym musisz pisać solidne programy, które uwzględniają nawet bardzo mało prawdopodobne. Możesz więc zobaczyć kod taki jak
Ten kod będzie całkowicie obcy dla programistów pecetów i informatyków, ale ma doskonały sens w przypadku oprogramowania o znaczeniu krytycznym, ponieważ wychwytuje przypadek, w którym „mybool” został uszkodzony z jakiegokolwiek powodu.
Historycznie rzecz biorąc, można by się obawiać uszkodzenia pamięci RAM z powodu zakłóceń elektromagnetycznych / szumów. Nie stanowi to dziś większego problemu. O wiele bardziej prawdopodobne jest, że uszkodzenie pamięci występuje z powodu błędów w innym miejscu w kodzie: wskaźników do niewłaściwych lokalizacji, błędów poza zakresem tablicy, przepełnienia stosu, niekontrolowanego kodu itp.
Tak więc przez większość czasu taki kod powraca, aby uderzyć się w twarz, gdy napiszesz błędy na etapie implementacji. Oznacza to, że może być również używany jako technika debugowania: program, który piszesz, informuje Cię, kiedy napisałeś błędy.
EDYTOWAĆ
Odnośnie tego, dlaczego
else
nie jest potrzebny po każdym pojedynczymif
:An
if-else
lubif-else if-else
całkowicie obejmuje wszystkie możliwe wartości, które może mieć zmienna. Ale prosteif
stwierdzenie niekoniecznie obejmuje wszystkie możliwe wartości, ma znacznie szersze zastosowanie. Najczęściej chcesz po prostu sprawdzić pewien warunek, a jeśli nie jest spełniony, nie rób nic. Wtedy po prostu nie ma sensu pisać programów obronnych, które obejmowałyby tenelse
przypadek.Dodatkowo zaśmiecałoby to całkowicie kod, gdybyś pisał pusty
else
po każdymif
.MISRA-C: 2012 15.7 nie podaje żadnego uzasadnienia, dlaczego
else
nie jest potrzebne, po prostu stwierdza:źródło
if/else if/else
skompilowałeś się zgodnie z oczekiwaniami? A potem jeszcze jeden do zweryfikowania poprzedniego weryfikatora?mybool
ma typu boolowskiego, jak miało to miejsce, zanim C otrzymał swój własnybool
; wtedy kompilator nie zrobiłby tego założenia bez dodatkowej analizy statycznej). A na temat „Jeśli napiszesz inny, ale zostawisz go pustym, oznacza to:„ Zdecydowanie rozważyłem scenariusz, w którym ani jeśli, ani inaczej, jeśli nie są prawdziwe ”.”: Moją pierwszą reakcją jest założenie, że programista zapomniał wstawić kod inny blok, w przeciwnym razie po prostu stoi pusty blok else? Odpowiedni// unused
byłby komentarz, a nie tylko pusty blok.else
blok musi zawierać jakiś komentarz, jeśli nie ma kodu. Powszechną praktyką pustyelse
jest jeden średnik plus komentarz:else { ; // doesn't matter }
. Ponieważ nie ma powodu, dla którego ktokolwiek mógłby po prostu wpisać wcięty, pojedynczy średnik we własnym wierszu. Podobna praktyka jest czasami stosowane w pustych pętli:while(something) { ; // do nothing }
. (oczywiście kod z podziałami wierszy. Komentarze SO na to nie pozwalają)Twoja firma postępowała zgodnie ze wskazówkami dotyczącymi kodowania MISRA. Istnieje kilka wersji tych wytycznych, które zawierają tę zasadę, ale od MISRA-C: 2004 † :
W MISRA-C: 2012 , która zastępuje wersję z 2004 roku i jest obecną rekomendacją dla nowych projektów, ta sama zasada istnieje, ale ma numer 15.7 .
Przykład 1: w pojedynczej instrukcji if programista może potrzebować sprawdzić n liczbę warunków i wykonać pojedynczą operację.
Podczas normalnego użytkowania wykonywanie operacji nie jest konieczne przez cały czas, gdy
if
jest używane.Przykład 2: Tutaj programista sprawdza n liczbę warunków i wykonuje wiele operacji. W regularnego stosowania
if..else if
jest jakswitch
może trzeba przeprowadzić operację jak domyślnie. Więc użycieelse
jest potrzebne zgodnie ze standardem misra† Aktualne i wcześniejsze wersje tych publikacji można kupić w sklepie internetowym MISRA ( przez ).
źródło
else
klauzula będzie nieosiągalna? (Zamiast tego zostaw ostateczny warunek, może wyrzuć błąd?)Ta dodatkowa opcja zmniejszy zakres kodu twojego programu.
Z mojego doświadczenia z przenoszeniem jądra linuxa lub kodu Androida na inną platformę, wiele razy robimy coś nie tak iw logcat'ie widzimy błąd jak
źródło
__FILE__
i__LINE__
makra są przydatne, aby ułatwić znalezienie lokalizacji źródłowej, jeśli wiadomość zostanie kiedykolwiek wydrukowana.Tylko krótkie wyjaśnienie, ponieważ zrobiłem to około 5 lat temu.
Nie ma (w większości języków) żadnego wymagania składniowego, aby zawierać
else
instrukcję "null" (i jest to zbędne{..}
), aw "prostych, małych programach" nie ma takiej potrzeby. Ale prawdziwi programiści nie piszą „prostych, małych programów” i, co równie ważne, nie piszą programów, które zostaną użyte raz, a następnie wyrzucone.Kiedy pisze się if / else:
wszystko wydaje się proste i nie ma nawet sensu dodawania
{..}
.Ale któregoś dnia, za kilka miesięcy, jakiś inny programista (nigdy nie popełniłbyś takiego błędu!) Będzie musiał „ulepszyć” program i doda instrukcję.
Nagle
doSomethingElse
jakby zapomina, że to powinno być welse
nodze.Więc jesteś dobrym małym programistą i zawsze używasz
{..}
. Ale piszesz:Wszystko jest dobrze, dopóki ten nowy dzieciak nie dokona modyfikacji o północy:
Tak, jest nieprawidłowo sformatowany, ale tak samo jest z połową kodu w projekcie, a „autoformatator” jest obciążany przez wszystkie
#ifdef
instrukcje. Oczywiście rzeczywisty kod jest znacznie bardziej skomplikowany niż ten przykład zabawki.Niestety (lub nie), od kilku lat nie mam takich rzeczy, więc nie mam na myśli świeżego „prawdziwego” przykładu - powyższy jest (oczywiście) wymyślony i trochę szalony.
źródło
To po to, by uczynić kod bardziej czytelnym dla późniejszych odniesień i aby było jasne, do późniejszego recenzentem, że pozostałe przypadki obsługiwane przez ostatnie
else
są zrobić nic przypadki, tak że nie są one pomijane jakoś na pierwszy rzut oka.Jest to dobra praktyka programistyczna, dzięki której kod można wielokrotnie wykorzystywać i rozszerzać .
źródło
Chciałbym uzupełnić - i częściowo zaprzeczyć - wcześniejszym odpowiedziom. Chociaż z pewnością powszechne jest użycie if-else, jeśli w sposób podobny do przełącznika, który powinien obejmować pełny zakres możliwych do pomyślenia wartości wyrażenia, w żaden sposób nie gwarantuje się, że jakikolwiek zakres możliwych warunków jest w pełni spełniony. To samo można powiedzieć o samej konstrukcji przełącznika, stąd wymóg użycia klauzuli domyślnej, która wyłapuje wszystkie pozostałe wartości i może, jeśli i tak nie jest wymagana, służyć jako zabezpieczenie asercji.
Samo pytanie zawiera dobry kontrprzykład: Drugi warunek w ogóle nie odnosi się do x (co jest powodem, dla którego często wolę bardziej elastyczny wariant oparty na if niż wariant oparty na przełączniku). Z przykładu jasno wynika, że jeśli warunek A jest spełniony, x należy ustawić na określoną wartość. Jeśli A nie zostanie spełniony, testowany jest warunek B. Jeśli jest spełnione, to x powinno otrzymać inną wartość. Jeśli ani A, ani B nie są spełnione, to x powinno pozostać niezmienione.
Tutaj widzimy, że należy użyć pustej gałęzi else, aby skomentować zamiary programisty względem czytelnika.
Z drugiej strony nie rozumiem, dlaczego musi istnieć klauzula else, szczególnie w przypadku ostatniego i najbardziej wewnętrznego stwierdzenia if. W C nie ma czegoś takiego jak „else if”. Jest tylko wtedy i jeszcze. Zamiast tego, według MISRA, konstrukcja powinna być formalnie wcięta w ten sposób (i powinienem był umieścić otwierające nawiasy klamrowe we własnych wierszach, ale nie podoba mi się to):
Kiedy MISRA prosi o umieszczenie nawiasów klamrowych wokół każdej gałęzi, zaprzecza sobie, wspominając „jeśli ... inaczej, jeśli konstrukcje”.
Każdy może sobie wyobrazić brzydotę głęboko zagnieżdżonych drzew if else, patrz tutaj na marginesie . Teraz wyobraź sobie, że ta konstrukcja może zostać dowolnie rozszerzona w dowolnym miejscu. Wtedy proszenie o klauzulę else na końcu, ale nie nigdzie indziej, staje się absurdalne.
Jestem więc pewien, że ludzie, którzy opracowali wytyczne MISRA, mieli na myśli zamiar - jak gdyby - inaczej.
W końcu sprowadza się to do dokładnego zdefiniowania, co oznacza konstrukt „jeśli ... inaczej, jeśli”
źródło
Podstawowym powodem jest prawdopodobnie pokrycie kodu i niejawne inne: jak zachowa się kod, jeśli warunek nie jest prawdziwy? Aby przeprowadzić autentyczne testy, potrzebujesz sposobu, aby sprawdzić, czy test został wykonany z warunkiem fałszywym. Jeśli każdy przypadek testowy przechodzi przez klauzulę if, Twój kod może mieć problemy w świecie rzeczywistym z powodu warunku, którego nie przetestowałeś.
Jednak niektóre warunki mogą przypominać przykład 1, np. W zeznaniu podatkowym: „Jeśli wynik jest mniejszy niż 0, wprowadź 0”. Nadal musisz mieć test, w którym warunek jest fałszywy.
źródło
Logicznie rzecz biorąc, każdy test zakłada dwie gałęzie. Co robisz, jeśli jest prawdą, i co robisz, jeśli jest fałszywa.
W przypadkach, w których którakolwiek gałąź nie ma funkcjonalności, rozsądne jest dodanie komentarza wyjaśniającego, dlaczego nie musi mieć funkcjonalności.
Może to być korzystne dla następnego programisty utrzymania ruchu. Nie powinni musieć szukać zbyt daleko, aby zdecydować, czy kod jest poprawny. Możesz coś w rodzaju Prehunt the Elephant .
Osobiście pomaga mi to, ponieważ zmusza mnie do spojrzenia na inny przypadek i oceny go. Może to być warunek niemożliwy, w takim przypadku mogę zgłosić wyjątek, ponieważ umowa jest naruszona. Może to być łagodne, w takim przypadku komentarz może wystarczyć.
Twój przebieg może się różnić.
źródło
W większości przypadków, gdy masz tylko jedno
if
oświadczenie, prawdopodobnie jest to jeden z takich powodów:Przykład
Ale kiedy to robisz
if .. else if
, prawdopodobnie jest to jeden z powodów, takich jak:A jeśli
if .. else if
obejmuje wszystkie możliwości, w takim przypadku ostatniaif (...)
nie jest potrzebna, możesz ją po prostu usunąć, ponieważ w tym momencie jedynymi możliwymi wartościami są te objęte tym warunkiem.Przykład
I w większości z tych powodów możliwe jest, że coś nie pasuje do żadnej z Twoich kategorii
if .. else if
, stąd potrzeba załatwienia ich w końcowejelse
klauzuli, obsługa może odbywać się poprzez procedurę biznesową, powiadomienie użytkownika, mechanizm błędu wewnętrznego, ..itp.Przykład
Ta ostatnia
else
klauzula jest dość podobna do kilku innych rzeczy w językach, takich jakJava
iC++
, takich jak:default
case w instrukcji switchcatch(...)
która pojawia się po wszystkich konkretnychcatch
blokachfinally
w klauzuli try-catchźródło
Nasze oprogramowanie nie miało krytycznego znaczenia dla misji, ale zdecydowaliśmy się również skorzystać z tej reguły ze względu na programowanie obronne. Dodaliśmy wyjątek rzutowania do teoretycznie nieosiągalnego kodu (przełącznik + if-else). I to wiele razy uratowało nas, ponieważ oprogramowanie szybko zawodziło, np. Gdy został dodany nowy typ i zapomnieliśmy zmienić jeden lub dwa jeśli inaczej lub przełączyć. Jako bonus bardzo łatwo było znaleźć problem.
źródło
Cóż, mój przykład dotyczy niezdefiniowanego zachowania, ale czasami niektórzy ludzie starają się być fantazyjni i nie udaje im się to, spójrz:
Prawdopodobnie nigdy byś się nie spodziewał, że
bool
tak nie jest,true
anifalse
jednak może się to zdarzyć. Osobiście uważam, że jest to problem spowodowany przez osobę, która decyduje się na coś wymyślnego, ale dodatkoweelse
stwierdzenie może zapobiec dalszym problemom.źródło
Obecnie pracuję z PHP. Stworzenie formularza rejestracyjnego i formularza logowania. Po prostu używam tylko jeśli i jeszcze. Nie ma innego, jeśli lub cokolwiek, co jest niepotrzebne.
Jeśli użytkownik kliknie przycisk Prześlij -> przechodzi do następnej instrukcji if ... jeśli nazwa użytkownika zawiera mniej niż „X” znaków, to alert. Jeśli się powiedzie, sprawdź długość hasła i tak dalej.
Nie ma potrzeby stosowania dodatkowego kodu, takiego jak inny, jeśli mogłoby to zmniejszyć niezawodność czasu ładowania serwera w celu sprawdzenia całego dodatkowego kodu.
źródło