Czy używanie instrukcji if bez nawiasów klamrowych jest złą praktyką? [Zamknięte]

135

Widziałem taki kod:

if(statement)
    do this;
else
    do this;

Myślę jednak, że jest to bardziej czytelne:

if(statement){
    do this;
}else{
    do this;
}

Skoro obie metody działają, czy jest to po prostu kwestia preferencji, które należy zastosować, czy też jedna metoda byłaby zalecana zamiast drugiej?

jerebear
źródło
Moim zdaniem to źle, ponieważ zaczynasz polegać na wcięciach białych znaków, które prawie nigdy nie są w pełni spójne. To zaburza tok myślenia czytelnika, kiedy muszą się martwić takimi rzeczami.
Sridhar Sarnobat

Odpowiedzi:

220

Problem z pierwszą wersją polega na tym, że jeśli cofniesz się i dodasz drugą instrukcję do klauzul if lub else, nie pamiętając o dodaniu nawiasów klamrowych, kod zepsuje się w nieoczekiwany i zabawny sposób.

Jeśli chodzi o konserwację, zawsze mądrzej jest używać drugiej formy.

EDYCJA: Ned zwraca uwagę na to w komentarzach, ale myślę, że warto też tutaj linkować. To nie tylko hipotetyczne bzdury z wieży z kości słoniowej: https://www.imperialviolet.org/2014/02/22/applebug.html

clee
źródło
17
I zawsze powinieneś kodować pod kątem łatwości utrzymania. W końcu jestem prawie pewien, że kompilator nie obchodzi, której formy używasz. Twoi współpracownicy mogą jednak być pistacjami, jeśli wprowadzisz błąd z powodu głupiego błędu nawiasu klamrowego.
Esteban Araya
12
Albo możesz użyć języka, który nie używa nawiasów do bloków kodu ...
Tor Valamo,
10
@ lins314159 - Nie, mam na myśli jak Python. Ponieważ jestem szowinistą pod tym względem.
Tor Valamo,
18
Inne błędy dowodowe mogą (i się zdarzają): imperialviolet.org/2014/02/22/applebug.html
Ned
8
Twierdzenie, że błąd SSL jest argumentem na korzyść nawiasów klamrowych, jest nieszczere. To nie jest tak, jakby programista zamierzał pisać, if (…) { goto L; goto L; }ale zapomniał o nawiasach klamrowych. Jest całkowicie przypadkowe, że „if (…) {goto L; goto L; } `tak się składa, że ​​nie jest to błąd bezpieczeństwa, ponieważ nadal jest to błąd (tylko nie taki, który ma konsekwencje dla bezpieczeństwa). Na innym przykładzie sytuacja może potoczyć się w przeciwnym kierunku, a kod bez klamry może być przypadkowo bezpieczny. W trzecim przykładzie kod bez klamr byłby początkowo wolny od błędów, a programista wprowadziłby literówkę podczas dodawania nawiasów klamrowych.
Pascal Cuoq,
117

Jednym z problemów związanych z pomijaniem bloków instrukcji jest niejednoznaczność else. Oznacza to, że języki inspirowane językiem C ignorują wcięcia, więc nie ma możliwości ich oddzielenia:

if(one)
    if(two)
        foo();
    else
        bar();

Od tego:

if(one)
    if(two)
        foo();
else
    bar();
doynax
źródło
9
To znacznie poważniejszy problem niż ten, o którym mowa w górnej odpowiedzi (dodanie drugiego stwierdzenia).
3
rzeczywiście, ta odpowiedź faktycznie zabrała mnie od cynicznego przeczytania tych odpowiedzi do łagodnego zaniepokojenia faktem, że mogłem popełnić ten błąd.
omikes
4
Jeśli ktoś jeszcze się zastanawiał, jak ja właściwie C to interpretuje, test, który przeprowadziłem z GCC, interpretuje ten kod w pierwszej kolejności. tpcg.io/NIYeqx
horta
4
„niejednoznaczność” to niewłaściwy termin. Nie ma żadnej dwuznaczności w tym, jak parser to zobaczy: elsechciwie wiąże się z najbliższym, najbardziej wewnętrznym if. Problem pojawia się, gdy C lub podobne języki są kodowane przez ludzi, którzy tego nie wiedzą, nie myślą o tym lub nie wypili jeszcze wystarczająco kawy - więc piszą kod, który ich zdaniem zrobi jedną rzecz, ale specyfikacja języka mówi, że parser musi zrobić coś innego, co może być zupełnie inne. I tak, to kolejny solidny argument przemawiający za tym, aby zawsze dodawać nawiasy klamrowe, nawet jeśli gramatyka oznacza je jako teoretycznie „niepotrzebne”.
underscore_d
35

Mój ogólny wzór jest taki, że jeśli zmieści się w jednej linii, zrobię:

if(true) do_something();

Jeśli istnieje klauzula else lub kod, na którym chcę wykonać, truema znaczną długość, użyj nawiasów klamrowych:

if(true) {
    do_something_and_pass_arguments_to_it(argument1, argument2, argument3);
}

if(false) {
    do_something();
} else {
    do_something_else();
}

Ostatecznie sprowadza się to do subiektywnej kwestii stylu i czytelności. Jednak ogólny świat programowania dzieli się na dwie części (w przypadku języków używających nawiasów klamrowych): albo używaj ich cały czas bez wyjątku, albo używaj ich cały czas z wyjątkiem. Należę do tej drugiej grupy.

Matchu
źródło
4
Chociaż jest to tak łatwe, jak napisanie if(true){ do_something(); }, po co ryzykować, że inny programista wprowadzi poważny błąd w przyszłości (przegląd całkowity błąd kodu ssl „goto fail” firmy Apple).
Craig
9
Żadna liczba nawiasów nie zwalnia opiekuna od używania mózgu. Popieram ideę "bez nawiasów, jeśli mieści się w jednym wierszu", ponieważ, cóż, dla mnie takie if jest tylko wersją trójskładnikowego operatora if, w którym nie trzeba nic robić w części "after:" potrójny. A dlaczego ktoś miałby wprowadzać nawiasy do trójskładnika, jeśli ?
Michał M
Wcale się nie zgadzam, że ostatecznie jest to subiektywne, ani że wpływa tylko na styl i czytelność. Jako ktoś, kto marnował czas próbując debugować problemy, okazało się, że były spowodowane brakującymi ogranicznikami bloków (i nie zauważaniem ich braku), ponieważ musiałem użyć stylu kodowania, który pomija je, gdy są `` niepotrzebne '' - i który czytał o wielu straszne błędy prawdopodobnie spowodowane przez takie style kodowania - myślę, że jest to bardzo obiektywna, praktyczna kwestia. Jasne, ze stylem narzucającym ograniczniki, nadal możemy o nich zapomnieć, ale z pewnością - przynajmniej - pamięć mięśniowa znacznie zmniejsza prawdopodobieństwo, że to zrobimy.
underscore_d
10

Używam programu formatującego kod IDE, którego używam. To może się różnić, ale można to ustawić w Preferencjach / Opcjach.

Podoba mi się ten:

if (statement)
{
    // comment to denote in words the case
    do this;
    // keep this block simple, if more than 10-15 lines needed, I add a function for it
}
else
{
    do this;
}
Pentium10
źródło
5
Jest to całkowicie subiektywna kwestia stylu, osobiście nie podoba mi się nadmiarowość linii zawierających tylko nawiasy klamrowe. Ale hej.
Matchu
14
Popieram ten styl. Większość ludzi czyta kod od lewej do prawej, co powoduje, że nasze oczy są zakotwiczone w lewej krawędzi ekranu. Pomaga wizualnie oddzielić i wyodrębnić kod do logicznych bloków kroków.
mloskot
6
Zawsze wolałem ten styl. O wiele łatwiej jest znaleźć odpowiedni nawias zamykający. Więc zajmuje dużo miejsca? Użyj mniejszej czcionki.
dzień
4
Zawsze łatwiej „skanować” kod, gdy nawiasy klamrowe znajdują się w osobnych wierszach. To dotyczy wszystkiego; klasy, metody, instrukcje if i while, i tak dalej. Nigdy nie lubiłem mieć tej pierwszej klamry na tej samej linii ...
Svish
2
Białe znaki są tanie, zwłaszcza jeśli masz IDE z możliwością składania kodu.
Moo
10

„Zasada”, którą kieruję się jest następująca:

Jeśli instrukcja „if” testuje, aby coś zrobić (wywołanie funkcji IE, zmienne konfiguracyjne itp.), Użyj nawiasów.

if($test)
{
    doSomething();
}

Dzieje się tak, ponieważ czuję, że musisz wyjaśnić, jakie funkcje są wywoływane i dokąd zmierza przepływ programu, w jakich warunkach. Zrozumienie przez programistę dokładnie, jakie funkcje są wywoływane i jakie zmienne są ustawione w tym warunku, jest ważne, aby pomóc im dokładnie zrozumieć, co robi twój program.

Jeśli instrukcja „if” testuje, aby przestać coś robić (sterowanie przepływem IE w pętli lub funkcji), użyj jednej linii.

if($test) continue;
if($test) break;
if($test) return;

W tym przypadku dla programisty ważne jest szybkie odkrycie, jakie są wyjątkowe przypadki, w których nie chcesz, aby kod działał, a wszystko to jest objęte $ test, a nie blokiem wykonawczym.

Marcus Harrison
źródło
8

Posiadanie nawiasów klamrowych od samego początku powinno pomóc w uniknięciu konieczności debugowania tego:

if (statement)
     do this;
else
     do this;
     do that;
Matt Bishop
źródło
1
Wydaje się, że jest to akceptowane uzasadnienie, ale (aby zagrać tutaj adwokata diabła), czy pojedyncza dodatkowa reguła podświetlania składni również nie rozwiązałaby tego problemu, jednocześnie oszczędzając jedną linię?
Ken
2
Tak samo będzie z IDE, które koryguje wcięcie po trafieniu ;:)
Sam Harwell
5

Użyj nawiasów klamrowych dla wszystkich instrukcji if, nawet tych prostych. Lub przepisz prostą instrukcję if, aby użyć operatora trójargumentowego:

if (someFlag) {
 someVar= 'someVal1';
} else {
 someVar= 'someVal2';
}

Wygląda o wiele ładniej tak:

someVar= someFlag ? 'someVal1' : 'someVal2';

Ale używaj operatora trójskładnikowego tylko wtedy, gdy jesteś absolutnie pewien, że w blokach if / else nie ma nic więcej!

leepowers
źródło
2

Z mojego doświadczenia jedyną (bardzo) małą zaletą pierwszej postaci jest czytelność kodu, druga forma dodaje „szumu”.

Ale dzięki nowoczesnym IDE i automatycznemu generowaniu kodu (lub autouzupełnianiu) zdecydowanie zalecam używanie drugiego formularza, nie będziesz spędzać dodatkowego czasu na pisaniu nawiasów klamrowych i unikniesz niektórych z najczęstszych błędów.

Jest wystarczająco dużo robaków pochłaniających energię, ludzie po prostu nie powinni otwierać drzwi, by tracić dużo czasu.

Jedną z najważniejszych zasad do zapamiętania podczas pisania kodu jest spójność. Każda linia kodu powinna być napisana w ten sam sposób, niezależnie od tego, kto ją napisał. Bycie rygorystycznym zapobiega "występowaniu" błędów;)

To samo dotyczy jasnego i jawnego nazywania zmiennych, metod, plików lub prawidłowego wcięcia ich ...

Kiedy moi uczniowie akceptują ten fakt, przestają walczyć z własnym kodem źródłowym i zaczynają postrzegać kodowanie jako naprawdę interesujące, stymulujące i twórcze działanie. Rzucają wyzwanie swoim umysłom, a nie nerwom!

thomas.g
źródło
2

To kwestia preferencji. Osobiście używam obu stylów, jeśli mam wystarczającą pewność, że nie będę już musiał dodawać zdań, używam pierwszego stylu, ale jeśli to możliwe, używam drugiego. Ponieważ nie można już dodawać stwierdzeń do pierwszego stylu, słyszałem, że niektórzy odradzają jego używanie. Jednak druga metoda wymaga dodatkowego wiersza kodu i jeśli Ty (lub Twój projekt) używasz tego rodzaju stylu kodowania, pierwsza metoda jest bardzo preferowana w przypadku prostych instrukcji if:

if(statement)
{
    do this;
}
else
{
    do this;
}

Myślę jednak, że najlepszym rozwiązaniem tego problemu jest Python. Dzięki strukturze blokowej opartej na białych znakach nie masz dwóch różnych metod tworzenia instrukcji if: masz tylko jedną:

if statement:
    do this
else:
    do this

Chociaż ma to „problem”, że nie możesz w ogóle używać nawiasów klamrowych, zyskujesz korzyść polegającą na tym, że nie ma już linii niż pierwszy styl i ma moc dodawania większej liczby instrukcji.

Udziel Paulowi
źródło
Sam myślę, że sposób, w jaki Python obsługuje instrukcje if-else, jest bardzo brzydki, ale z drugiej strony nie jestem programistą Pythona (jeszcze)
metoda pomocy
1

Zawsze starałem się, aby mój kod był standardowy i wyglądał jak najbliżej tego samego. Ułatwia to innym czytanie, gdy są odpowiedzialne za aktualizację. Jeśli zrobisz pierwszy przykład i dodasz do niego linię w środku, zakończy się niepowodzeniem.

Nie zadziała:

if (instrukcja) zrób to; i to; inaczej zrób to;

Joe
źródło
1

Osobiście używam pierwszego stylu tylko rzucam wyjątek lub przedwcześnie wracam z metody. Jak sprawdzanie argumentów na początku funkcji, ponieważ w takich przypadkach rzadko mam więcej niż jedną rzecz do zrobienia i nigdy nie ma innej.

Przykład:

if (argument == null)
    throw new ArgumentNullException("argument");

if (argument < 0)
    return false;

W przeciwnym razie używam drugiego stylu.

Nate Heinrich
źródło
1

Moje osobiste preferencje to mieszanka białych znaków i nawiasów w następujący sposób:

if( statement ) {

    // let's do this

} else {

    // well that sucks

}

Myślę, że wygląda to na czysty i sprawia, że ​​mój kod jest bardzo łatwy do odczytania, a co najważniejsze - debugowania.

Szymon
źródło
0

Zgadzam się z większością odpowiedzi w tym, że lepiej jest być wyraźnym w swoim kodzie i używać nawiasów klamrowych. Osobiście przyjąłbym zestaw standardów kodowania i upewniłbym się, że wszyscy w zespole je znają i przestrzegają. Tam, gdzie pracuję, używamy standardów kodowania opublikowanych przez IDesign.net dla projektów .NET.

Kane
źródło
0

Wolę zakładać klamrę kręconą Ale czasami pomaga operator trójskładnikowy.

Zamiast :

int x = 0;
if (condition) {
    x = 30;
} else {
    x = 10;
}

Należy po prostu zrobić: int x = condition ? 30 : 20;

Wyobraź sobie również przypadek:

if (condition)
    x = 30;
else if (condition1)
    x = 10;
else if (condition2)
    x = 20;

Byłoby znacznie lepiej, gdybyś założył klamrę kręconą.

fastcodejava
źródło