Jeśli chodzi o konserwację, czy „else while” bez interwencji aparatów ortodontycznych jest uważane za bezpieczne?

26

Czy else whilebez interwencji aparatów ortodontycznych uważa się za „bezpieczną” konserwację?

Pisanie if-elsekodu bez nawiasów klamrowych jak poniżej ...

if (blah)
    foo();
else
    bar();

... niesie ryzyko, ponieważ brak nawiasów klamrowych sprawia, że ​​bardzo łatwo przypadkowo zmienić znaczenie kodu.

Czy jednak poniżej jest również ryzykowne?

if (blah)
{
    ...
}
else while (!bloop())
{
    bar();
}

Czy też else whilebez interwencji nawiasów klamrowych uważa się za „bezpieczny”?

Mehrdad
źródło
20
dla mnie else whilewygląda obrzydliwie. Użyłbym else { while (condition) { ... } }.
Joachim Sauer,
7
Myślę, że jest to zbyt subiektywne, aby odpowiedzieć poprawnie ... sam bym tego nie zrobił, ponieważ nie oczekuję pętli i myślę, że nie spodziewam się, że czytelność będzie trudna.
johannes,
7
Chciałbym wyodrębnić metodę dla while-stuff
gnat
12
Szczerze mówiąc, to mnie przeraża. ifjest oceniany tylko raz, ale whileoznacza pętlę, więc połączenie obu daje mi bezpodstawne wrażenie, że ifjest częścią pętli ... jakoś ...
user281377
4
A co jeśli w elseklauzuli chcesz zrobić while i zrobić coś więcej? Proszę po prostu użyć aparatów ortodontycznych.
Carlos Campderrós,

Odpowiedzi:

57

To przypomina mi ten kod:

if ( ... ) try {
..
} catch (Exception e) {
..
} else {
...
}

Za każdym razem, gdy łączysz dwa rodzaje bloków, zapominając o nawiasach klamrowych i nie zwiększając wcięć, tworzysz kod bardzo trudny do zrozumienia i utrzymania.

Sułtan
źródło
18
Dobry przykład. Co za okropny sposób to napisać.
Lew
4
Wow, ta odpowiedź jest absurdalnie przekonująca!
Mehrdad,
Możesz łatwo skonfigurować nowoczesne IDE do automatycznego formatowania kodu przy zapisywaniu - w tym wstawianie nawiasów klamrowych i korygowanie wcięcia. To tylko połowa argumentów. Prawidłowe wcięcie nie stanowi problemu dla czytelności, niezależnie od tego, czy są nawiasy klamrowe, czy nie.
Hans-Peter Störr,
55

Być może dzieje się tak, ponieważ nauczyłem się mojego handlu ( dawno temu) za pomocą metody Jackson Entity Structure Diagram , ale zgadzam się z poglądem, że jedynym poprawnym niehamowanym terminem po an iflub elsejest następna if(tj. Pozwalająca na else ifdrabinę)

Cokolwiek innego (bez zamierzonej gry słów) pozostawia możliwość nieporozumień i / lub problemów konserwacyjnych. To jest główny aspekt pomysłu PO jako „niebezpieczny”.

Byłbym również bardzo klatkowy, jeśli chodzi o umieszczenie linii while()na tej samej linii, co else- czy to na sztywno, czy nie. Nie odczytuje mnie to wprost ... brak dodatkowych masek wcięcia, że ​​jest to elseklauzula. A brak jasności powoduje nieporozumienia (patrz wyżej).

Dlatego w tym przykładzie zdecydowanie zalecam / polecam (i nalegam, w moim zespole) na:

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

Oczywiście oczekiwałbym również odpowiednich komentarzy.

-- Edytować --

Niedawno Apple ucierpiało z powodu luki w protokole SSL, spowodowanej słabą poprawką konserwacyjną - która dodała drugą linię do nieobjętej pojedynczej linii. A więc odłóżmy na bok pomysł, że pojedyncze nieskalowane linie są w porządku?

Andrzej
źródło
2
Zgadzam się, czy jest to jedyny poprawny termin, aby podążać za innym. Gdyby istniał else while, prawdopodobnie nawet nie zauważyłbym, że istnieje szybkie zapętlenie kodu, zwłaszcza jeśli warunek, którego szukałem, był spełniony przez if.
Drake Clarris,
3
To jest zabawne. Wszyscy mówią, że łatwiej jest czytać, jeśli wszystko jest w nawiasach klamrowych. Uważam, że jest odwrotnie. Jeśli jest to tylko jedno zdanie, trzymanie go poza nawiasami klamrowymi ułatwia czytanie. Mniej bałaganu. Być może dlatego, że zawsze tak robiłem.
Jeff Davis,
2
@JeffDavis to dobry haczyk. „Łatwiej czytać” to typowe zaproszenie do bezużytecznej świętej wojny. Ja na przykład wolę nawiasy klamrowe, ale nie z powodu nieistotnego śmieci „easytoread” (dla mnie na przykład jest dokładnie odwrotnie), ale dlatego, że trudniej jest przerwać dalszą obsługę kodu. Nawiasem mówiąc, OP napisał to lepiej w swoim pytaniu: czy else whilebez interwencji aparatu ortodontycznego uważa się za „bezpieczny” ?
komar
@JeffDavis - Wiem, że ten wątek ma dwa lata, ale Apple niedawno odkryło, dlaczego nie stosowanie nawiasów klamrowych nie jest dobrym pomysłem andrewbanks.com/…
Andrew
@Andrew Przy okazji, język Apple Swift teraz wyraźnie zabrania kontroli przepływu w jednym wierszu. Ten błąd może być jednym z powodów tego.
Sulthan
6

Zawsze uczono mnie trzymać wszystko w nawiasach klamrowych, wcięcia i komentarze. Uważam, że łatwiej jest odczytać i wykryć błędy. Osobiście uważam, że modułowość jest kluczem, więc zawsze pisałbym taki kod:

    if(blah)
    {
     ....
    }
    else
    {
       while(!bloop()
       {
        bar;
       }
    }
CodeCompileHack
źródło
6

Chciałbym wyodrębnić metody i uczynić go

if ( blah )
{
    ...
}
else
{
   newMethod();
}

Zobacz „metodę ekstrakcji” wyjaśnioną na stronie katalogu refaktoryzacji :

Masz fragment kodu, który można zgrupować razem.

Zmień fragment w metodę, której nazwa wyjaśnia cel tej metody.

void printOwing() {
    printBanner();

    //print details
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + getOutstanding());
}

                                                                                                         http://www.refactoring.com/catalog/arrow.gif

void printOwing() {
    printBanner();
    printDetails(getOutstanding());
}

void printDetails (double outstanding) {
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + outstanding);
}
użytkownik470365
źródło
Zależy ... jeśli na przykład pętla while używała danych na poziomie funkcji, musisz teraz przekazać te dane do poziomu modułu (lub klasy, jeśli używasz C ++). A jeśli tylko mały fragment kodu, lubisz trywialne metody. Ale czasami, w zależności od okoliczności, zgodziłbym się.
Andrew,
1
Kompilatory +1 Smart C ++ mogą wstawiać funkcję. W środowisku .Net małe funkcje są lepsze dzięki JIT.
Job
4

Uznałbym to za zły nawyk kodowania. Czasami działa idealnie dobrze i nie będziesz mieć problemu z kompilacją i uruchomieniem kodu. W innych przypadkach może to powodować poważne błędy i będziesz spędzać godziny na naprawianiu tego błędu.

Zawsze zaleca się modularyzację kodu. Jeśli musisz umieścić pętlę while w innej części, umieść ją w bloku, aby inni podczas pracy nad twoim kodem mogli łatwo zrozumieć logikę.

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

Dobrą praktyką jest umieszczanie kodu w blokach. Ułatwia to także zrozumienie i debugowanie.

Sandeep Gupta
źródło
4

Może być dobrze, jeśli pozostanie takie proste, chociaż osobiście mi się to nie podoba i wolę używać nawiasów klamrowych nawet w najprostszych blokach kodu if / else. Dla mnie to po prostu porządniej.

Jednak tam, gdzie robi się bałagan, zagnieżdżasz się, jeśli / else zapętli niektóre z nawiasami klamrowymi bez nich. Pętla While w środku całego tego spaghetti! Tak źle pracowałem z kodem, a debugowanie i zrozumienie jest koszmarem. Wynika to z pierwszego punktu, że jest w porządku, gdy pozostaje prosty i jesteś z niego zadowolony, ale potem inni programiści przychodzą i dodają do niego różne rzeczy, prawdopodobnie jeśli jeszcze w obrębie pętli while. Jeśli jest napisane czysto, to szansa na to jest mniejsza.

Chodzi o to, aby wyjaśnić wszystko, aby inni programiści mogli zobaczyć na pierwszy rzut oka, co jest dobre, a co złe. Napisz kod, aby wzorzec wyglądał poprawnie i nie zgrzewał.

Drugą stroną tego jest to, że być może widziałem niektórych ludzi twierdzących, że w niektórych przypadkach brzmi to dobrze. Jeśli mam zasób, muszę wykonać to przetwarzanie jeszcze podczas oczekiwania na coś, zrób to. Nawet dla mnie nadal nie ma różnicy w zagnieżdżaniu pętli while w bloku else.

Daniel Hollinrake
źródło
3

Cóż, pomimo tego, że wszyscy twierdzą, że używają aparatu ortodontycznego i wydają się je kochać, tak naprawdę wolę coś przeciwnego. Używam aparatu ortodontycznego tylko wtedy, gdy muszę, ponieważ uważam, że bez niego jest bardziej czytelny i zwięzły.

if (...)
   foo();
else while(...)
   bar();

... Właściwie uważam to za " else while(...)" wyjątkowo czytelne! To nawet brzmi jak zwykły angielski! Ale myślę, że ludzie uznają to za dziwne, ponieważ co najmniej niezwykłe.

W końcu wszyscy robimy to z idiotycznymi szelkami, ponieważ ... no wiesz.

Dagnele
źródło
3
będzie to szczególnie czytelne po niektórych niewinnych zmianach opiekuna else while(...) bar();w czymś takim jak else while(...) foobar(); bar();:)
gnat
3
cóż, powiedziałbym, że to całkiem głupi i niebezpieczny niewinny opiekun. Znam zasadę głupia, aby uniknąć głupich błędów ... ale posunięcie się do tej pory jest dość smutne. Ale wiedziałem, że dostanę takie komentarze i opinie. Nie ma problemu.
Dagnelies,
2
„Zawsze koduj tak, jakby osoba, która zachowa Twój kod, będzie brutalnym psychopatą, który wie, gdzie mieszkasz”. ( Alan Braggins )
komar
1
Cóż, wszystko sprowadza się do tego, co uważasz za najgłupszy poziom kogoś, kto pracuje nad twoim kodem. Twierdzę, że jeśli twój „opiekun” zostanie skonfuzowany przez te cztery linie kodu ... to masz ogromny problem. A jeśli to gwałtowny psychol, masz dwa. ;)
Dagnelies
1
jeśli - no cóż, link, o którym mowa powyżej, rozszerza wersję tego cytatu: Programator 1: „Jest tu miły cytat -„ Zawsze koduj tak, jakby osoba, która będzie utrzymywać Twój kod, była brutalnym psychopatą, który wie, gdzie mieszkasz ” . Programator 2: (patrzy na opiekuna) „Co masz na myśli„ jak gdyby ”?
komar
2

Zawsze zakładam aparat ortodontyczny, tylko dlatego, że możesz dodać kolejną linię, gdy się spieszysz, wciąć ją, zapomnieć o aparatach ortodontycznych i podrapać się w głowę, co się dzieje. Trzymam klamrę otwierającą na tej samej linii, ale to nie ma znaczenia. W obu przypadkach lepiej je mieć.

if(blah) {
    foo();
}
else {
    bar();
}
Tsvetomir Dimitrov
źródło
Pozycjonowanie nawiasów klamrowych prawdopodobnie wywołuje więcej argumentów niż cokolwiek innego (a być może włącznie) religii!
Andrew
Zgoda. Zedytuję moją odpowiedź, aby podkreślić ich istnienie, a nie pozycję.
Tsvetomir Dimitrov,
2

Co jest takiego złego w aparatach ortodontycznych, że tak wiele osób próbuje ich unikać?

Jaki problem dokładnie else whilerozwiązuje?

Nawiasy klamrowe są tanie i dobre, a intencje kodu są oczywiste i jasne, w przeciwieństwie do sprytnych i dowcipnych.

Cytując filozofię Uniksa:

Reguła jasności: Klarowność jest lepsza niż spryt.

Ponieważ konserwacja jest tak ważna i tak droga, pisz programy, jakby najważniejszą komunikacją, jaką wykonują, nie był komputer, który je wykonuje, ale ludzie, którzy będą czytać i utrzymywać kod źródłowy w przyszłości (w tym ty sam).

Tulains Córdova
źródło
1

Nie ma w tym nic złego

if (blah)
    foo();
else
    bar();

tak jak nie ma w tym nic złego

if (blah) foo(); else bar();

w odpowiednich okolicznościach (warunki mogą się różnić, ale ten konkretny styl najlepiej jest stosować, gdy masz dużo powtarzalnego kodu - wtedy widok każdej linii jest ważniejszy niż wcięcie stylistyczne)

Ale jeśli wybierzesz jeden sposób, trzymaj się go - spójność jest królem. Zatem twój drugi przykład jest bardzo zły, ponieważ jeśli wyrażenie zawiera nawiasy kwadratowe dla swojej instrukcji, instrukcja while powinna znajdować się w nawiasach dla klauzuli else, a nie poza nią.


poza tym widziałem ten kod wcześniej:

if (x) foo()
{
  bar();
}

i został napisany przez samego kodującego nazistę (który nalegał na nawiasy na wszystko).

gbjbaanb
źródło
1

Nowoczesne IDE można łatwo skonfigurować w celu sformatowania (w tym usunięcia lub dodania niepotrzebnych nawiasów klamrowych) i / lub ponownego wpisania kodu przy zapisywaniu pliku. Twój przykład automatycznie wyglądałby na przykład

if (blah) {
  blub();
} else
  while (!bloop()) {
    bar();
  }

Wgłębienie zawsze sprawia, że ​​zagnieżdżanie jest dobrze widoczne, nawet bez zbędnych nawiasów klamrowych. Jeśli więc wymusisz takie ustawienia IDE, nie widzę żadnego ryzyka.

Osobiście uważam, że kod, który pomija nawiasy klamrowe i łamanie linii, jest bardziej czytelny, ponieważ pozwala uniknąć bałaganu:

if (blah) blub();
else while (!bloop()) bar();

Ale oczywiście wielu programistów bardzo chętnie kłóci się o takie rzeczy na zawsze i jeden dzień.

Hans-Peter Störr
źródło