Spędziłem większość ostatnich kilku lat pracując głównie z C # i SQL. Każdy programista, z którym pracowałem przez ten czas, miał zwyczaj umieszczać nawias otwierający funkcji lub instrukcji przepływu w nowym wierszu. Więc ...
public void MyFunction(string myArgument)
{
//do stuff
}
if(myBoolean == true)
{
//do something
}
else
{
//do something else
}
Zawsze uderzyło mnie to, jak mało miejsca to jest, szczególnie w instrukcjach if / else. Wiem, że w późniejszych wersjach C # istnieją alternatywy, takie jak:
if(myBoolean == true)
//do something on one line of code
Ale mało kto ich używał. Wszyscy zrobili kręcone szelki na nowej linii.
Potem wróciłem do robienia JavaScript po długiej nieobecności. W mojej pamięci, programiści JavaScript robili dokładnie to samo curly-nawiasy klamrowe-nowa linia, ale przy wszystkich fantazyjnych nowych bibliotekach i innych rzeczach, większość programistów umieszcza nawias otwierający po deklaracji:
function MyJavaScriptFunction() {
//do something
}
Widać w tym sens, ponieważ odkąd stosowanie zamknięć i wskaźników funkcji stało się popularne w JavaScript, oszczędza dużo miejsca i czyni rzeczy bardziej czytelnymi. Zastanawiałem się więc, dlaczego nie było postrzegane jako zrobione w C #. W rzeczywistości, jeśli wypróbujesz powyższą konstrukcję w Visual Studio 2013, faktycznie sformatuje ją dla Ciebie, umieszczając otwierający nawias w nowej linii!
Teraz widziałem to pytanie w Code Review SE: https://codereview.stackexchange.com/questions/48035/questions-respactions-let-me-tell-you-about-you, w którym dowiedziałem się, że w Javie język, którego nie znam zbyt dobrze, uważa się za rygorystyczny sposób otwierania nawiasów klamrowych zaraz po deklaracji, w nowoczesnym stylu JavaScript.
Zawsze rozumiałem, że C # był pierwotnie wzorowany na Javie i był zgodny z wieloma tymi samymi podstawowymi standardami kodowania. Ale w tym przypadku wydaje się, że nie. Zakładam więc, że musi być dobry powód: jaki jest powód? Dlaczego programiści C # (i Visual Studio) wymuszają otwieranie nawiasów klamrowych w nowej linii?
źródło
if(myBoolean == true)
nie ma dla mnie sensu. Skoro już to robimy, a nieif ((myBoolean == true) == true)
? Po prostuif (myBoolean)
i to wystarczy. Przepraszam, mój wkurzony zwierzak.Odpowiedzi:
Klamrą na końcu linii jest starożytny standard K&R C, z książki Briana Kernighana i Dennisa Ritchiego The C Programming Language , którą opublikowali w 1978 roku po wspólnym wynalezieniu systemu operacyjnego UNIX i języka programowania C (myślę, że C był zaprojektowane głównie przez Ritchie), w AT&T.
Kiedyś toczyły się wojny o „jeden prawdziwy styl aparatów ortodontycznych”.
Ritchie wynalazł język C, a Kernighan napisał pierwszy samouczek, gdy na ekranach komputera pojawiło się tylko kilka wierszy tekstu. W rzeczywistości prace nad UNICS (późniejszym UNIX) rozpoczęły się od DEC PDP-7, w którym jako interfejs użytkownika zastosowano maszynę do pisania, drukarkę i taśmę papierową. UNIX i C zostały ukończone na PDP-11, z 24-wierszowymi terminalami tekstowymi. Tak więc przestrzeń pionowa była naprawdę na wagę złota. Wszyscy dzisiaj mamy nieco lepsze wyświetlacze i drukarki o wyższej rozdzielczości, prawda? To znaczy, nie wiem o tobie, ale mam teraz przed sobą trzy (3) 24-calowe wyświetlacze 1080p. :-)
Ponadto, tak wiele z tej małej książki The C Programming Language to próbki kodu, które umieszczenie nawiasów klamrowych na końcach linii zamiast na ich własnych liniach rzekomo pozwoliło zaoszczędzić znaczną ilość pieniędzy na drukowaniu.
Naprawdę ważna jest spójność w całym projekcie lub przynajmniej w danym pliku kodu źródłowego.
Nie są również badania naukowe pokazujące, że klamra z własnej linii (wcięcie na tym samym poziomie co w kodzie, w rzeczywistości) poprawia zrozumienie kodu wbrew temu, co ludzie myślą, że myślą o estetyce. Wyjaśnia czytelnikowi, wizualnie i instynktownie, który kod działa w jakim kontekście.
Nawiasem mówiąc, C # zawsze wspierał ocenę pojedynczego polecenia po wyrażeniu rozgałęziającym. W rzeczywistości to jedyna rzecz, jaką robi, nawet teraz. Wstawienie kodu w nawiasy klamrowe po wyrażeniu rozgałęziającym sprawia, że jedno polecenie jest goto (kompilator tworzy zakres za pomocą instrukcji jmp). C ++, Java, C # i JavaScript są w mniejszym lub większym stopniu oparte na C, w większości z tymi samymi podstawowymi regułami analizy. W tym sensie C # nie jest „oparty na Javie”.
Podsumowując, jest to trochę kwestia religijna / wojenna. Ale tam są badania co czyni go dość oczywiste, że umieszczenie kodu w blokach poprawia ludzkie zrozumienie. Kompilator nie przejmował się tym mniej. Ale jest to również związane z powodem, dla którego nigdy nie umieszczam wiersza kodu za gałęzią bez nawiasów klamrowych - dla mnie lub innego programisty jest to zbyt łatwe, aby umieścić tam inną linię kodu później i poślizgnąć się na fakcie, że nie będzie wykonać w tym samym kontekście z linią tuż przed nią lub po niej.
EDYCJA : Wystarczy spojrzeć na błąd Apple,
goto fail
aby znaleźć doskonały przykład tego dokładnie problemu, który miał bardzo poważne konsekwencje w świecie rzeczywistym.staje się...
W takim przypadku
doSomethingElse()
wykonuje się za każdym razem, niezależnie od wyniku testu, ale ponieważ jest wcięty do tego samego poziomu codoSomething()
instrukcja, łatwo go przeoczyć. To nie jest tak naprawdę dyskusyjne; badania potwierdzają to. Jest to duże źródło błędów wprowadzonych do kodu źródłowego podczas konserwacji.Mimo to przyznaję, że składnia zamknięcia JavaScript wygląda trochę głupio z nawiasami klamrowymi na własnych liniach ... estetycznie. :-)
źródło
begin
iend
zamiast nawiasów klamrowych, co sprawia, że takich błędów naprawdę trudno przeoczyć, a także bardziej surowe w zakresie umieszczania średników - ale wydając 4 dni w zeszłym roku debugowanie problemu we wbudowanym C, który ostatecznie wynikał z braku umiejscowienia nawiasów klamrowych ... Myślę, że powinna istnieć opcja kompilatora, która zobowiązuje nawiasy klamrowe do instrukcji sterujących!Powodem jest to, że programiści C # robią to, ponieważ jest to domyślne ustawienie automatycznego formatowania programu Visual Studio. Chociaż to ustawienie można zmienić, większość ludzi tego nie robi, dlatego wszyscy programiści w zespole muszą zdecydować się na większość.
Co do tego, dlaczego jest to ustawienie domyślne w Visual Studio, nie wiem.
źródło
Jak postawiłem hipotezę w tej odpowiedzi tutaj - https://softwareengineering.stackexchange.com/a/159081/29029 - Podejrzewam, że decyzja o zastosowaniu Allmana może być oznaką dziedzictwa Pascala, biorąc pod uwagę, że Hejlsberg stworzył Delphi zanim zaprojektował C # . To samo co wielkość Pascala dla nazw metod.
Ja osobiście wierzę w powiedzenie „w Rzymie postępujcie tak, jak Rzymianie”. Używam Allman's w C #, ale K&R w Javie. Jestem do tego tak przyzwyczajony, że zmiana konwencji w jakikolwiek sposób jest dla mnie niepokojąca.
Uważam, że pewna różnorodność konwencji jest w rzeczywistości korzystna dla „wielojęzycznego” programisty, ponieważ pomaga zapamiętać język, w którym obecnie kodują, i ułatwia różnicowanie różnych nawyków. Można powiedzieć, że jest to mentalny odpowiednik pamięci mięśniowej.
źródło
goto fail
używania wcięcia do kontrolowania przepływu programu, ludzie naturalnie chcą to zrobić, więc widzisz to, co się wykonuje. Jeśli jest źle wcięte, to po prostu nie działa. Konieczność odkodowania, co oznaczają te nawiasy klamrowe, niezależnie od tego, czy faktycznie odzwierciedlają wcięcia, to dodatkowa praca wykraczająca poza zrozumienie programu. Wcięcie jest zbędne dla nawiasów klamrowych, więc dlaczego programiści używają go, jeśli nawiasy klamrowe są przydatne? Głębokie zagnieżdżanie jest niezrozumiałe w żadnym języku. Po prostu mówię.Konwencja, którą kojarzysz z Javą, to styl K&R lub „One true brace style” i oryginalnie pochodzi z C. Ta styl wcięcia strony z czcigodnego pliku Jargon pokazuje, ile lat ma to rozróżnienie.
Zawsze myślałem, że styl Allmana i jego warianty są odzwierciedleniem tego, jak autorzy myślą o kodzie, podnosząc ograniczniki bloków do poziomu słów kluczowych podobnych do tego, w jaki sposób niektóre języki używają „początku” i „końca” wokół bloków kodu.
źródło