Kiedy ocena zwarcia jest zła?


12

Aby być bardziej jasnym, stwierdzę, że spędziłem dużo czasu z różnymi językami. Ale do tej pory albo go użyje cały czas, albo w ogóle go nie obsługuje.

Teraz zaczęłam pracę nad projektami, które wymagają VB.net i widzę, że zapewnia to w obie strony w zakresie AND i ANDALSO . Pierwszy nie powoduje zwarcia, a drugi tak.

To prowadzi mnie do zastanowienia się dlaczego? Ponieważ taka konfiguracja wydaje się sugerować, że dość często zdarza się, że ktoś chce przełączać tryby. Ale nie mogę wymyślić żadnych sytuacji, w których użycie zwarcia byłoby złym rozwiązaniem .

Wiem, że bardzo dobrze może się to przydać opcji, więc jeśli muszę to umieścić w innym miejscu, po prostu powiedz mi, gdzie.

Chociaż mam nadzieję, że jest co najmniej oficjalna odpowiedź, dlaczego posiadanie obu opcji byłoby lepsze niż zawsze wykonywanie zwarcia , gdy jest ono dostępne.



Odpowiedzi:


5

Niektóre terminy w logicznym wyrażeniu mogą mieć skutki uboczne. Czasami konieczne jest upewnienie się, że wszystkie działania niepożądane wystąpią w podanej kolejności, a żadne nie zostaną pominięte, a logika kieruje wynikiem oceny:

if not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

W innych przypadkach nie chcesz oceniać żadnego z pozostałych warunków, jeśli wcześniejsza ocena zwróci fałsz.

if IsAirborne() and not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

Niektórzy twierdzą / twierdzili, że poleganie na zwarciu w drugim przykładzie jest złą formą, ale to wchodzi w styl kodowania i systemy przekonań. Na świecie istnieje wiele bardzo dobrych fragmentów kodu, które polegają na prawie każdej funkcji zapewnianej przez język, i tak właśnie jest.

ANDALSO VB jest rześkie i wydaje się być próbą uczynienia praktyki bardziej akceptowalną.

Jak JimmyJames wskazuje w swojej odpowiedzi, mogą wystąpić wymierne implikacje wydajnościowe związane z oceną zwarcia. Języki, które nie zapewniają mechanizmu, zawsze oceniają każdy termin wyrażenia, podczas gdy te, które go udostępniają, mogą generować dodatkowe instrukcje gałęzi. Tak czy inaczej, wiele zależy od liczby kroków przetwarzania wymaganych do oceny każdego z warunków, a także od architektury kompilatora i procesora. Zwykle nie przejmowałbyś się takimi rzeczami, dopóki nie zmierzysz wąskiego gardła w kodzie i nie będziesz musiał znaleźć sposobu na jego złagodzenie. Wszelkie zasady „nie lub nie” dotyczące zezwalania na ocenę zwarciową w kodzie będą miały mniej więcej taką samą szansę na spowolnienie kodu i wczesną optymalizację, co może być całkowitą stratą czasu, dlatego zawsze mierz, a następnie optymalizuj.


4
Chociaż jest to poprawne pod względem faktycznym, nie jest to świetny projekt.
Robert Harvey

2
@RobertHarvey, nie mogę napisać systemu kontroli, który nie ma skutków ubocznych i nie mogę prawidłowo kontrolować systemu, jeśli nie zareaguję na wyniki. Innymi słowy, przełam to;).
jwdonahue

7
Nie, ale możesz przypisać wyniki tych efektów ubocznych do zmiennych boolowskich, sprawdź te zmienne w swoim ifstanie i nadal zwarcie. Zgadzam się, że pod pewnymi względami jest to stylistyczne wyróżnienie, ale ma tę zaletę, że sprawia, że ​​wszystko jest krystalicznie czyste.
Robert Harvey

3
@jwdonahue Można używać „dużych słów”, jeśli ryzyko pomyłki jest niskie. Ryzyko pomyłki i pominięcia poszczególnych niuansów takiego bloku kodu jest niezwykle wysokie i może być katastrofalne dla logiki. Nigdy nie jest dobrze zmusić czytelnika do myślenia bardzo mocno.
jpmc26

5
„Niektóre terminy w logicznym wyrażeniu mogą mieć skutki uboczne” - Chociaż to stwierdzenie otwierające jest poprawne, wydaje mi się, że ta odpowiedź nie wskazuje, że poleganie na skutkach ubocznych jest złe . O wiele gorzej niż poleganie na ocenie zwarciowej, aby zapobiec fałszywym ocenom. Co sugeruje ta odpowiedź, może być złą formą.
aroth

20

Najwyraźniej twoje pytanie nie dotyczy tego, czy zwarcie jest dobre czy złe, ale dlaczego VB.NET zapewnia operatorom to i bez niego. Mając to na uwadze, odpowiedź na

kiedy ocena zwarcia jest zła?

jest po prostu: gdy narusza kompatybilność wsteczną .

Ok, teraz możesz powiedzieć, że VB.NET nie jest bardzo wstecznie kompatybilny ze starym VB6 lub VBA, jednak przynajmniej niektóre części tego języka są. Decyzja Microsoftu o zachowaniu starej semantyki AND i OR (bez zwarć) spowodowała, że ​​przy przenoszeniu starych programów VB na VB.NET istnieje ogromna kategoria błędów.

Z drugiej strony projektanci języka VB.NET prawdopodobnie podzielili się twoją opinią na temat zwarć. Kiedy dobrze pamiętam, pierwsze wersje przedpremierowe VB.NET zapewniały operatorom AND lub OR zwarcie, ale opinie programistów musiały być tak złe, że MS wycofało tę decyzję, zanim pojawiła się VB.NET 1.0. Dlatego projektanci postanowili wdrożyć go pod kątem nowych słów kluczowych ANDALSOoraz ORELSEjako kompromis między wsteczną kompatybilnością a użytecznością.

IMHO to była dobra decyzja. W ostatnim dziesięcioleciu musiałem przenieść kilka starszych programów i nie musiałem przeprowadzać silnej analizy wpływu dla każdego wyrażenia logicznego, w tym AND i / lub OR (zamierzony kalambur), aby to zadanie było o wiele łatwiejsze i bardziej ekonomiczne. Z drugiej strony, ilekroć muszę napisać nowe wyrażenie logiczne w VB.NET, moim domyślnym wyborem dla operatorów są formy zwarciowe, do czego jestem przyzwyczajony z C, C ++, C # itp. I pozwala napiszę kilka idiomów w bardziej zwięzłej formie (nawet jeśli ANDALSO potrzebuje 4 znaków więcej do pisania).

Jeśli nie jesteś przekonany, polecam przeczytać świetny artykuł Joela Spolsky'ego na temat zestawów słuchawkowych Martian , który mówi o tym, dlaczego wczesne decyzje projektowe w rozwoju oprogramowania nie mogą być łatwo odwołane, gdy dany komponent, język lub interfejs API dotrą do bazy użytkowników o określonym rozmiarze .


Ok, to kwalifikuje się jako rant, a link do zestawów marsjańskich wcale nie jest powiązany.
jwdonahue

6
@jwdonahue: Nie mam pojęcia, dlaczego uważasz, że to rant, wręcz przeciwnie. A artykuł o zestawach Martian Headset mówi o tym, dlaczego niektóre decyzje projektowe dotyczące rozwoju oprogramowania podjęte kilkadziesiąt lat temu nie mogą być łatwo odwołane, gdy dany komponent, język lub interfejs API osiągną bazę użytkowników o określonym rozmiarze. Czy analogia nie jest tak trudna do zrozumienia? VB6 był bardzo popularny w przeszłości i jestem pewien, że wciąż sto tysięcy firm na świecie ma krytyczne aplikacje działające w VB6 lub VBA.
Doc Brown

Nie bardzo rozumiem, jak naprawdę pasuje artykuł z „Marsjańskimi główkami”. To, co jest konieczne do zapewnienia interoperacyjności między X i Y (np. Nakrętki i śruby), to mieć oddzielne standardy dla X i Y, tak aby w najgorszym przypadku nakrętka pomieściła nieco gorszą niż podana śrubę i odwrotnie. Należy spróbować napisać specyfikację, aby uniknąć niepotrzebnego dokręcania nakrętek lub śrub lub niepotrzebnego nachylenia między nakrętkami i śrubami, ale osobne określenie obu połówek umożliwia znacznie bardziej niezawodne współdziałanie niż próba posiadania jednej specyfikacji służyć obu stronom.
supercat

3
@ supercat: chodzi o to, aby już istniały i były w użyciu biliony orzechów (lub linii kodu VB6), a teraz śruby (lub w tym przypadku kompilator VB) zostaną zastąpione przez nową generację. Jeśli istniejące nakrętki pasują tylko do śrub niemetrycznych, nie jest opłacalne, aby nowsze śruby były tylko systemem metrycznym.
Doc Brown

tl; dr: VB jest dialektem języka BASIC, języka pochodzącego z 1964 roku, aw języku BASIC Andoperacja nie zwiera, ani w SQL (1974), ani w FORTRAN (1956), ani w Pascalu (1970).
Ben

3

kiedy ocena krótkoterminowa jest zła?

Stają się one złe , gdy tylko zaczniesz polegać na skutkach ubocznych wyrażeń, które spodziewasz się wykonać przy ocenie wyniku logicznego.


1

Zastrzeżenie : jest to nieco ezoteryczne, ponieważ w prawie wszystkich przypadkach programiści nie powinni się tym martwić. Ale ... może wystąpić pogorszenie wydajności z powodu oceny warunkowej, ponieważ tworzy rozgałęzienie w trakcie wykonywania. Operacja bez zwarcia nie rozgałęzia się i jest bardziej przewidywalna.

Powodem, dla którego rzadko ma to znaczenie, jest to, że koszt jest zwykle niewielki, a także zwykle przeważa koszt oceny drugiego (lub trzeciego itd.) Warunku. Będzie to miało znaczenie tylko w drogich obliczeniowo procedurach, gdy wymagana jest wysoka wydajność i może nadal nie mieć znaczenia.


Myślę, że do tej pory możesz zoptymalizować tylko logiczne stwierdzenie, w końcu musisz zdobyć oddziały.
jwdonahue

@jwdonahue Nie rozumiem o co ci chodzi. Przepraszam.
JimmyJames

Mówimy tutaj o logice kombinatorycznej. Ocena zwarcia lub nie, masz jeden lub więcej warunków, które należy ocenić w zależności od wyniku wcześniejszego terminu. W związku z tym dotyczy to rozgałęzień.
jwdonahue

1
@jwdonahue Oczywiście, ale każde zwarcie jest dodatkową gałęzią. W niektórych scenariuszach wykonanie dwóch wyrażeń (na przykład) jest szybsze niż sprawdzenie wyniku pierwszego przed wykonaniem drugiego, nawet jeśli często zdarza się, że drugie wyrażenie jest nieistotne. Ponownie jest to rzadko ważne. Przypadek, który ktoś mi to zrobił, dotyczył mnożenia macierzy, gdzie masz wiele prostych ocen.
JimmyJames

1
Zaktualizowałem swoją odpowiedź, dziękuję.
jwdonahue

0

Pascal nie zdefiniował, czy AND i OR używają oceny zwarcia, czy nie, co daje najgorsze z obu światów.

C i C ++ mają operacje bitowe i | co w praktyce zapewnia operacje bez zwarć. A kompilatory mają swobodę oceny w dowolny sposób, jeśli nie robi to zauważalnej różnicy.


@Deduplicator: Jak zauważono, Pascal nie zdefiniował, czy AND / OR używa oceny zwarcia. To znaczy „nie wiedzieć”.
supercat
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.