Powiedzmy, że mam warunek boolowski a AND b OR c AND d
i używam języka, w którym AND
precedens jest wyższy niż w przypadku operacji OR
. Mógłbym napisać ten wiersz kodu:
If (a AND b) OR (c AND d) Then ...
Ale tak naprawdę odpowiada to:
If a AND b OR c AND d Then ...
Czy są jakieś argumenty za lub przeciw dołączaniu obcych nawiasów? Czy praktyczne doświadczenie sugeruje, że warto je uwzględnić ze względu na czytelność? Czy może to znak, że deweloper musi naprawdę usiąść i nabrać pewności w podstawach swojego języka?
coding-style
operator-precedence
Jeff Bridgman
źródło
źródło
2 * 3 + 2
może być taki sam,(2 * 3) + 2
ale drugi jest łatwiejszy do odczytania.Odpowiedzi:
Dobrzy programiści starają się pisać kod, który jest przejrzysty i poprawny . Nawiasy w warunkach warunkowych, nawet jeśli nie są ściśle wymagane, pomagają w obu przypadkach.
Jeśli chodzi o przejrzystość , pomyśl o nawiasach takich jak komentarze w kodzie: nie są one absolutnie konieczne, a teoretycznie kompetentny programista powinien być w stanie znaleźć kod bez nich. A jednak te wskazówki są niezwykle pomocne, ponieważ:
Ponadto dodatkowe nawiasy, podobnie jak wcięcia, białe znaki i inne standardy stylu, pomagają wizualnie uporządkować kod w logiczny sposób.
Jeśli chodzi o poprawność , warunki bez nawiasów są receptą na głupie błędy. Kiedy się zdarzają, mogą być błędami, które są trudne do znalezienia - ponieważ często niepoprawny stan będzie się zachowywał przez większość czasu i tylko czasami zawiedzie.
I nawet jeśli dobrze to zrobisz, następna osoba, która popracuje nad twoim kodem, może tego nie zrobić, dodając błędy do wyrażenia lub niezrozumienie logiki, a tym samym dodając błędy w innym miejscu (jak słusznie podkreśla LarsH).
Zawsze używam nawiasów do wyrażeń, które łączą się
and
ior
(a także do operacji arytmetycznych z podobnymi priorytetami).źródło
Nie ma znaczenia, czy jesteś pewny swojego języka. Bardziej liczy się znajomość języka n00b, który podąża za tobą.
Napisz swój kod w najczystszy i najbardziej jednoznaczny sposób. Dodatkowy nawias często pomaga (ale nie zawsze). Umieszczenie tylko jednego wyrażenia w wierszu często pomaga. Spójność w stylu kodowania często pomaga.
Jest coś takiego jak zbyt wiele nawiasów, ale jest to jedna z tych sytuacji, w których nie potrzebujesz porady - poznasz ją, gdy ją zobaczysz. W tym momencie refaktoryzuj kod, aby zmniejszyć złożoność instrukcji, zamiast usuwać nawiasy.
źródło
There is such a thing as too many parenthesis
- nie jesteś oczywiście lisper;)tak
Zawsze powinieneś używać nawiasów ... nie kontrolujesz kolejności pierwszeństwa ... programista kompilatora tak. Oto historia, która mi się przytrafiła na temat niestosowania nawiasów. Wpłynęło to na setki ludzi w okresie dwóch tygodni.
Prawdziwy powód świata
Odziedziczyłem aplikację z ramką główną. Któregoś dnia przestało działać. To jest to ... po prostu przestało.
Moim zadaniem było jak najszybsze działanie. Kod źródłowy nie był modyfikowany przez dwa lata, ale nagle przestał. Próbowałem skompilować kod, który zepsuł się na linii XX. Spojrzałem na linię XX i nie mogłem powiedzieć, co spowodowałoby przerwanie linii XX. Poprosiłem o szczegółowe specyfikacje dla tej aplikacji i nie było żadnych. Linia XX nie była winowajcą.
Wydrukowałem kod i zacząłem go przeglądać od góry do dołu. Zacząłem tworzyć schemat blokowy tego, co się działo. Kod był tak zawiły, że ledwie mogłem go zrozumieć. Zrezygnowałem z próbowania schematu blokowego. Bałam się dokonywać zmian, nie wiedząc, jak ta zmiana wpłynie na resztę procesu, zwłaszcza, że nie miałem szczegółowych informacji o tym, co zrobiła aplikacja ani gdzie była w łańcuchu zależności.
Postanowiłem więc zacząć od górnej części kodu źródłowego i dodać białe znaki i hamulce linii, aby kod był bardziej czytelny. Zauważyłem, że w niektórych przypadkach występowały warunki, które się łączyły
AND
iOR
nie można było jednoznacznie odróżnić, które dane byłyAND
edytowane i jakie dane byłyOR
edytowane. Zacząłem więc umieszczać nawiasy wokół warunkówAND
iOR
warunków, aby były bardziej czytelne.Gdy powoli przesuwałem się w dół, aby go wyczyścić, okresowo zapisywałem swoją pracę. W pewnym momencie próbowałem skompilować kod i wydarzyło się coś dziwnego. Błąd przeskoczył, przekroczył pierwotny wiersz kodu i był teraz niższy. Więc kontynuowałem, rozróżniając
AND
iOR
warunki za pomocą parens. Kiedy skończyłem sprzątać, zadziałało. Domyśl.Następnie postanowiłem odwiedzić sklep operacyjny i zapytać, czy ostatnio zainstalowali jakieś nowe komponenty na ramie głównej. Powiedzieli tak, niedawno zaktualizowaliśmy kompilator. Hmmmm
Okazuje się, że stary kompilator niezależnie oceniał wyrażenie od lewej do prawej. Nowa wersja kompilatora oceniała również wyrażenia od lewej do prawej, ale niejednoznaczny kod, co oznacza niejasną kombinację
AND
iOR
nie można było rozwiązać.Czego się nauczyłem z tego ... ZAWSZE, ZAWSZE, ZAWSZE używajcie parenów do oddzielonych
AND
warunków iOR
warunków, kiedy są one używane w połączeniu ze sobą.Uproszczony przykład
IF Product = 191 OR Product = 193 AND Model = "ABC" OR Product = 201 OR Product = 202 AND Model = "DEF" ...
(kod zaśmiecony kilkoma z nich)To jest uproszczona wersja tego, co napotkałem. Były też inne warunki ze złożonymi wyrażeniami logicznymi.
Pamiętam, że postanowiłem to:
IF ((Product = 191 OR Product = 193) AND Model = "ABC") OR ((Product = 201 OR Product = 202) AND Model = "DEF") ...
Nie mogłem go przepisać, ponieważ nie było specyfikacji. Pierwotnego autora już dawno nie było. Pamiętam intensywną presję. Cały statek towarowy pozostawiono w porcie i nie można go było rozładować, ponieważ ten mały program nie działał. Bez ostrzeżenia. Brak zmian w kodzie źródłowym. Przyszło mi do głowy, aby zapytać Operacje sieciowe, czy coś zmodyfikowały po tym, jak zauważyłem, że dodanie parens zmieniło błędy.
źródło
Tak, jeśli są mieszane „i” i „lub”.
Również dobrym pomysłem jest (), co jest logicznie jednym sprawdzeniem.
Chociaż najlepiej jest używać dobrze nazwanych funkcji predykatów i eksmitować większość kontroli i warunków, pozostawiając je proste i czytelne.
źródło
a AND b
prawdopodobnie należy ją zastąpić funkcją lub wstępnie obliczoną wartością boolen, która ma bardziej opisową nazwę.Nawiasy są semantycznie redundantne, więc kompilator nie dba o to, ale to czerwony śledź - prawdziwą troską jest czytelność i zrozumienie programisty.
Zajmę tutaj radykalne stanowisko i udzielę serdecznego „nie” nawiasom w środku
a AND b OR c AND d
. Każdy programista powinien na pamięć wiedzieć, że pierwszeństwo w wyrażeniach boolowskich NIE JEST> I> LUB , podobnie jak pamiętanie Proszę wybacz mojej drogiej cioci Sally wyrażeń algebraicznych. Nadmiarowa interpunkcja po prostu dodaje bałaganu wizualnego przez większość czasu w kodzie, bez korzyści dla czytelności programisty.Ponadto, jeśli zawsze używasz nawiasów w wyrażeniach logicznych i algebraicznych, rezygnujesz z możliwości używania ich jako markera „dzieje się tutaj coś trudnego - uważaj!” Oznacza to, że w przypadkach, w których chcesz zastąpić domyślny priorytet i dokonać oceny dodania przed pomnożeniem lub LUB przed AND, nawiasy są ładną czerwoną flagą dla następnego programisty. Zbyt wiele z nich korzysta, gdy nie są potrzebne, a Ty stajesz się Chłopcem, Który Płakał Wilkiem.
Zrobiłbym wyjątek dla wszystkiego poza sferą algebry (boolowskiej lub nie), takiej jak wyrażenia wskaźnikowe w C, gdzie wszystko bardziej skomplikowane niż standardowe idiomy, takie jak
*p++
lubp = p->next
prawdopodobnie powinny być nawiasowane, aby utrzymać dereferencje i arytmetykę prosto. I oczywiście nic z tego nie dotyczy języków takich jak Lisp, Forth lub Smalltalk, które używają jakiegoś rodzaju polskiego zapisu do wyrażeń; ale w przypadku większości głównych języków logiczne i arytmetyczne pierwszeństwo jest całkowicie ustandaryzowane.źródło
AND
vsOR
jest dość prostym przypadkiem, o którym chciałbym wiedzieć inni deweloperzy z mojego zespołu. Martwię się, że czasami „używanie nawiasów dla jasności” to tak naprawdę „używanie nawiasów, więc nigdy nie muszę się martwić, aby nauczyć się pierwszeństwa”..member
zanim operatorzy unarne, unarne przed operatorów binarnych,*
a/
przed+
i-
przed<
a>
i==
przed&&
przed||
przed zadaniem. Zasady te są łatwe do zapamiętania, ponieważ pasuje do mojego „zdrowego rozsądku” o tym, jak zwykle stosowane są operatorzy (np, nie dałoby==
większy priorytet niż+
lub1 + 1 == 2
przestaje działać), a obejmują one 95% pytań pierwszeństwa Musiałbym .Jak to widze:
TAK Plusy:
TAK Wady:
NIE Plusy:
NIE Wady:
źródło
3 * a^2 + 2 * b^2
łatwiejszy do odczytania(3 * (a^2)) + (2 * (b^2))
, ponieważ format i pierwszeństwo są znane i standardowe. Podobnie, możesz (być ekstremalnie) zabronić używania funkcji i makr (lub kompilatorów!), Aby uczynić semantykę twojego kodu bardziej wyraźnym. Oczywiście nie jestem zwolennikiem tego, ale mam nadzieję odpowiedzieć na twoje pytanie, dlaczego istnieją ograniczenia (równowaga) w wyrażaniu rzeczy.Jeśli nikt inny nie będzie musiał ponownie patrzeć na mój kod, nie sądzę, żebym się tym przejmował.
Ale z mojego doświadczenia:
Prawie zawsze to robię, ponieważ ufam, że potrafię szybko czytać i nie popełniać drobnych błędów dużo więcej przy użyciu parens niż nic innego.
W twoim przypadku prawie na pewno zrobiłbym coś takiego:
Tak, to więcej kodu. Tak, mogę zamiast tego robić fantazyjne operatory bool. Nie, nie podoba mi się ta szansa, że w przyszłości, gdy przeglądam kod ponad 1 rok, źle odczytałem operatorów fantazyjnych bool. Co jeśli pisałbym kod w języku, który miał inny priorytet ORAZ / LUB i musiałbym wrócić, aby to naprawić? Czy mam zamiar powiedzieć: „aha! Pamiętam tę sprytną rzecz, którą zrobiłem! Nie musiałem uwzględniać parens, kiedy pisałem ten ostatni rok, dobrze, że teraz pamiętam!” jeśli tak się stanie (lub gorzej, ktoś inny, kto nie był świadomy tego sprytu lub został wrzucony w sytuację typu „napraw jak najszybciej”)?
Rozdzielenie za pomocą () znacznie ułatwia szybkie przeglądanie i zrozumienie później ...
źródło
ab = a AND b
?ab
, że pozostanie niezmieniony, jeśli niea AND b
.Ogólna sprawa
W języku C # mnożenie i dzielenie ma pierwszeństwo przed dodawaniem i odejmowaniem.
Mimo to StyleCop, narzędzie, które wymusza wspólny styl w bazie kodu z dodatkowym celem, aby zmniejszyć ryzyko wprowadzenia błędów przez kod, które mogą nie być wystarczająco jasne, ma regułę SA1407 . Ta reguła wyświetli ostrzeżenie z fragmentem kodu takim jak ten:
Oczywiste jest, że wynik jest , ale
7
nie9
, ale StyleCop sugeruje umieszczenie nawiasu:Twoja szczególna sprawa
W twoim konkretnym przypadku istnieje pierwszeństwo AND w stosunku do OR w konkretnym języku, którego używasz.
Nie tak zachowuje się każdy język. Wielu innych traktuje AND i OR równo.
Jako programista, który pracuje głównie z C #, kiedy zobaczyłem twoje pytanie po raz pierwszy i przeczytałem fragment kodu bez czytania tego, co napisałeś wcześniej, moją pierwszą pokusą było skomentowanie, że te dwa wyrażenia nie są takie same. Mam nadzieję, że przeczytałem całe pytanie całkowicie przed komentowaniem.
Ta szczególność i ryzyko, że niektórzy programiści mogą wierzyć, że AND i OR mają ten sam priorytet, sprawia, że jeszcze ważniejsze jest dodanie nawiasu.
Nie pisz kodu, aby pokazać, że jesteś mądry. Napisz kod w celu zapewnienia czytelności, w tym przez osoby, które mogą nie znać każdego aspektu języka.
źródło
Jak wszyscy mówili, używaj nawiasów za każdym razem, gdy sprawia, że wyrażenie jest bardziej czytelne. Jeśli jednak wyrażenie jest skomplikowane, radzę wprowadzić nowe funkcje dla podwyrażeń .
źródło
Jeśli ściśle używasz języka w liczbie pojedynczej, być może. Teraz weź wszystkie języki, które znasz, od najmłodszych do najbardziej nowoczesnych, od skompilowanych, przez skrypty, przez SQL, aż po własną DSL, którą wymyśliłeś w zeszłym miesiącu.
Czy pamiętasz dokładne zasady pierwszeństwa dla każdego z tych języków, nie patrząc?
źródło
„Czy powinienem używać nawiasów w logicznych instrukcjach, nawet jeśli nie jest to konieczne”.
Tak, ponieważ dwie osoby uznają je za pomocne:
Następny programista, którego wiedza, kompetencje lub styl mogą być inne
Przyszłość, która wróci do tego kodu w późniejszym terminie!
źródło
Złożone warunki warunkowe to „algebra boolowska”, którą piszesz na kilka sposobów, dzięki czemu wygląda ona prawie dokładnie tak jak algebra, a na pewno używasz parens do algebry , prawda?
Naprawdę przydatne są zasady negacji:
Lub w nieco jaśniejszym formacie:
co tak naprawdę jest po prostu algebrą, gdy jest napisane jako:
Ale możemy również zastosować myślenie w zakresie algebraicznego uproszczenia i ekspansji:
chociaż w kodzie musisz napisać:
lub w nieco jaśniejszym formacie:
Zasadniczo, warunek jest nadal tylko wyrażeniem algebraicznym, a poprzez wyraźne użycie nawiasów można łatwiej zastosować różne reguły algebraiczne, które już znasz do wyrażenia, w tym starą koncepcję „uproszczenia lub rozwinięcia tej formuły”.
źródło
!(A + B) <=> !A + !B
i-1*(A + B) = -A + -B
nie powinno operator zostały odwrócone od+
celu*
w drugiej wypowiedzi?Użyję nawiasów, nawet jeśli jest to opcjonalne, dlaczego, ponieważ pomaga to lepiej zrozumieć dla wszystkich, zarówno dla tego, kto pisze kod, jak i dla tego, który jest gotowy do zobaczenia tego kodu. W twoim przypadku nawet operatorzy logiczni mają pierwszeństwo, może na początku działać dobrze, ale nie możemy powiedzieć, że pomoże ci to w każdym przypadku. więc wolę nawias użytkownika w każdych warunkach, które mogą wymagać lub opcjonalnie.
źródło
Tak. Powinieneś używać w każdym przypadku, gdy uważasz, że kod będzie bardziej przejrzysty. Pamiętaj, że twój kod powinien być wystarczająco jasny, aby inni mogli zrozumieć bez czytania twoich komentarzy wewnątrz kodu. Dobrą praktyką jest używanie nawiasów i nawiasów klamrowych. Pamiętaj również, że może to zależeć od konkretnej praktyki Twojej firmy / zespołu. Po prostu zachowaj jedno podejście i nie mieszaj.
źródło