Почему язык НЕ использовал бы оценку Короткого замыкания?

Обычно, Вы не должны тестировать часть кода, который использует LINQ для SQL, но если Вы действительно хотите, можно использовать те же наборы данных, которые Вы запрашиваете против сервера и превращаете их в объекты в оперативной памяти и выполняете запросы LINQ против того (который использовал бы Счетные методы вместо Queryable).

Другая опция состоит в том, чтобы использовать Matt Warren mockable версия DataContext.

можно также получить SQL-операторы, которые LINQ к SQL использует путем получения их через отладчик (от объекта IQueryable), проверьте тех вручную, и затем включайте их в автоматизированные тесты.

39
задан Community 23 May 2017 в 10:30
поделиться

17 ответов

Причины НЕ использовать оценку короткого замыкания:

  1. Потому что он будет вести себя по-другому и давать разные результаты, если ваши функции, свойства Gets или методы операторов имеют побочные эффекты. И это может противоречить: A) языковым стандартам, B) предыдущим версиям вашего языка или C) предположениям типичных пользователей вашего языка по умолчанию. Это причины, по которым VB не сокращает замыкание.

  2. Потому что вы можете захотеть, чтобы компилятор имел свободу переупорядочивать и сокращать выражения, операторы и подвыражения по своему усмотрению, а не в том порядке, в котором пользователь напечатали их. Это причины, по которым SQL не сокращает замыкание (или, по крайней мере, не так, как думают большинство разработчиков, переходящих к SQL). Таким образом, SQL (и некоторые другие языки) могут вызвать короткое замыкание, но только если он решит, и не обязательно в том порядке, который вы неявно указали.

Я предполагаю, что вы спрашиваете об «автоматическом, неявном, зависящем от порядка коротком замыкании», чего большинство разработчиков ожидают от C, C ++, C #, Java и т. Д. И в VB, и в SQL есть способы явного принудительного короткого замыкания в зависимости от порядка. Однако обычно, когда люди задают этот вопрос, это вопрос «Делай то, что я имел в виду»; то есть они означают «почему он не делает то, что я хочу?», как, например, автоматически закорачивает в том порядке, в котором я его написал.

И в VB, и в SQL есть способы явного принудительного короткого замыкания, зависящего от порядка. Однако обычно, когда люди задают этот вопрос, это вопрос «Делай то, что я имел в виду»; то есть они означают «почему он не делает то, что я хочу?», как, например, автоматически закорачивает в том порядке, в котором я его написал.

И в VB, и в SQL есть способы явного принудительного короткого замыкания, зависящего от порядка. Однако обычно, когда люди задают этот вопрос, это вопрос «Делай то, что я имел в виду»; то есть они означают «почему он не делает то, что я хочу?», как, например, автоматически закорачивает в том порядке, в котором я его написал.

40
ответ дан 27 November 2019 в 02:30
поделиться

Я не знаю ни о каких проблемах с производительностью, но один из возможных аргументов, позволяющих избежать этого (или, по крайней мере, чрезмерного его использования), заключается в том, что это может сбить с толку других разработчиков.

0
ответ дан 27 November 2019 в 02:30
поделиться

Я бы сказал, что это действительно для проблем с читабельностью; если кто-то воспользуется оценкой короткого замыкания не совсем очевидным способом, специалисту по сопровождению может быть сложно взглянуть на тот же код и понять логику.

Если память не изменяет, erlang предоставляет две конструкции: стандартную и / или потом и тоже / или. Это проясняет намерение, что «да, я знаю, что это короткое замыкание, и вы тоже должны», где, как и в других случаях, намерение должно быть получено из кода.

В качестве примера, скажем, сопровождающий наткнулся на следующие строки:

if(user.inDatabase() || user.insertInDatabase()) 
    user.DoCoolStuff();

Требуется несколько секунд, чтобы распознать намерение: «если пользователя нет в базе данных, вставьте его / ее / ее; если это сработает делать крутые штуки ».

Как отмечали другие, это действительно актуально только при выполнении действий с побочными эффектами.

1
ответ дан 27 November 2019 в 02:30
поделиться

Поскольку короткое замыкание может изменить поведение IE приложения:

if(!SomeMethodThatChangesState() || !SomeOtherMethodThatChangesState())
1
ответ дан 27 November 2019 в 02:30
поделиться

Вкратце:

Если вы хотите, чтобы язык был супербезопасным (ценой удивительности), вы должны удалить короткое замыкание eval. Когда что-то «безопасное» происходит за разное время, можно использовать Timing Attack , чтобы с этим справиться. Короткое замыкание eval приводит к тому, что выполнение задач занимает разное время, что создает дыру для атаки. В этом случае,

3
ответ дан 27 November 2019 в 02:30
поделиться

Билл сослался на вескую причину не использовать короткое замыкание, а изложил это более подробно: высокопараллельные архитектуры иногда имеют проблемы с ветвлением путей управления.

Возьмем для примера архитектуру NVIDIA CUDA. пример. Графические чипы используют архитектуру SIMT, что означает, что один и тот же код выполняется во многих параллельных потоках. Однако этот работает только , если все потоки каждый раз выполняют одну и ту же условную ветвь. Если разные потоки используют разные пути кода, оценка сериализуется - это означает, что преимущество распараллеливания теряется, потому что некоторые из потоков должны ждать , в то время как другие выполняют альтернативную ветвь кода.

Короткое замыкание. фактически включает в себя ветвление кода, поэтому операции короткого замыкания могут быть вредными для архитектур SIMT, таких как CUDA.

- Но, как сказал Билл, это аппаратное обеспечение. Что касается языков , я бы ответил на ваш вопрос решительным нет : предотвращение короткого замыкания не имеет смысл.

4
ответ дан 27 November 2019 в 02:30
поделиться

Если вы хотите, чтобы правая часть оценивалась:

if( x < 13 | ++y > 10 )
    printf("do something\n");

Возможно, вы хотели, чтобы y увеличивался независимо от того, не имеет ли x <13. Хорошим аргументом против этого является создание условия без побочных эффектов обычно являются лучшей практикой программирования.

3
ответ дан 27 November 2019 в 02:30
поделиться

Ada не делает этого по умолчанию. Чтобы принудительно выполнить оценку короткого замыкания, вы должны использовать , а затем или или еще вместо и или или .

Проблема в том, что при некоторых обстоятельствах это действительно замедляет работу. Если второе условие вычисляется быстро, а первое условие почти всегда верно для «и» или ложно для «или», то дополнительная инструкция проверки-перехода является своего рода пустой тратой. Однако я понимаю, что в современных процессорах с предикторами ветвления дело обстоит не так. Другая проблема заключается в том, что компилятор может знать, что вторая половина дешевле или может выйти из строя, и может захотеть изменить порядок проверки соответствующим образом (чего нельзя было бы сделать, если определено поведение при коротком замыкании).

Я слышал возражения, что это может привести к неожиданному поведению кода в случае, когда второй тест побочные эффекты. ИМХО, это «неожиданно» только в том случае, если вы не очень хорошо знаете свой язык, но некоторые будут спорить с этим.

Если вам интересно, что настоящие разработчики языка говорят по этому поводу, вот отрывок из Ada 83 (исходный язык) Обоснование :

Операнды логического выражения такие как A и B можно оценить в любой порядок. В зависимости от сложности термина B может быть больше эффективный (на некоторых, но не на всех машины) для оценки B только тогда, когда член A имеет значение ИСТИНА. Эта однако это решение оптимизации взяты компилятором, и это будет неверно предполагать, что это оптимизация всегда делается. В других ситуации, которые мы можем захотеть выразить сочетание условий, в которых каждое состояние должно быть оценено (имеет смысл) только если предыдущий состояние выполнено. Оба из них вещи могут быть сделаны с коротким замыканием формы управления ...

В Алголе 60 можно добиться эффекта оценки короткого замыкания только использование условных выражений, поскольку полная оценка выполняется иначе. Это часто приводит к конструкции, следовать которым утомительно ...

Некоторые языки не определяют, как логические условия должны быть оценен. Как следствие программы на основе оценки короткого замыкания будет не быть портативным. Это ясно иллюстрирует необходимость разделения логические операторы от короткого замыкания формы контроля.

5
ответ дан 27 November 2019 в 02:30
поделиться

Одно преимущество, о котором я могу думать, заключается в том, что некоторые операции могут иметь побочные эффекты, которые вы можете ожидать.

Пример:

if (true || someBooleanFunctionWithSideEffect()) {
    ...
}

Но обычно это не одобряется.

7
ответ дан 27 November 2019 в 02:30
поделиться

Язык программирования Ada поддерживал оба логических оператора, которые не замыкались ( И , ИЛИ ), чтобы разрешить компилятор для оптимизации и, возможно, распараллеливания конструкций, и операторы с явным запросом на короткое замыкание ( И ТОГДА , ИЛИ ИНАЧЕ ), когда это требуется программисту. Обратной стороной такого двойного подхода является то, что язык становится немного более сложным (1000 проектных решений, принятых одним и тем же принципом «давайте сделаем и то и другое!», Сделают язык программирования НАМНОГО более сложным в целом; -).

2
ответ дан 27 November 2019 в 02:30
поделиться

VB6 не использует оценку короткого замыкания, я не знаю, используются ли в более новых версиях, но я сомневаюсь в этом. Я считаю, что это просто потому, что более старые версии этого не сделали, и потому что большинство людей, которые использовали VB6, не ожидали, что это произойдет, и это привело бы к путанице.

Это лишь одна из причин, по которым это произошло. мне чрезвычайно трудно выйти из новичка-программиста VB, который писал спагетти-код, и продолжить свой путь настоящего программиста.

0
ответ дан 27 November 2019 в 02:30
поделиться

Оценка короткого замыкания автоматически обеспечивает условную оценку части выражения.

Основным преимуществом является то, что это упрощает выражение.

Производительность можно улучшить, но вы можете также соблюдайте штраф за очень простые выражения.

Другим следствием является то, что могут быть затронуты побочные эффекты оценки выражения.

В общем, использование побочных эффектов не является хорошей практикой, но в некотором конкретном контексте , это могло бы быть предпочтительным решением.

0
ответ дан 27 November 2019 в 02:30
поделиться

Уже есть отличные отзывы о проблеме с побочными эффектами , но я ничего не видел в аспекте производительности вопроса.

Если вы не разрешаете оценку короткого замыкания, проблема производительности заключается в том, что необходимо оценивать обе стороны, даже если это не изменит результат. Обычно это не проблема, но может иметь значение при одном из следующих двух обстоятельств:

  • Код находится во внутреннем цикле, который вызывается очень часто
  • Оценка выражений связана с высокими затратами (возможно, IO или дорогостоящее вычисление)
0
ответ дан 27 November 2019 в 02:30
поделиться

Не то чтобы я думаю это то, что сейчас происходит на любом языке, но было бы довольно интересно передать обе стороны операции разным потокам. Большинство операндов можно было заранее определить так, чтобы они не мешали друг другу, поэтому они были бы хорошими кандидатами для передачи разным процессорам.

Этот вид вещей имеет значение для высокопараллельных процессоров, которые, как правило, оценивают несколько ветвей и выбирают одну.

Эй, это немного натянуто, но вы спросили: «Зачем нужен язык» ... а не «Почему язык».

2
ответ дан 27 November 2019 в 02:30
поделиться

Язык Lustre не использует оценку короткого замыкания. В if-then-elses обе ветви then и else оцениваются на каждом тике, и одна из них считается результатом условного выражения в зависимости от оценки условия.

Причина в том, что этот язык и другие языки синхронного потока данных , используйте краткий синтаксис, чтобы говорить о прошлом. Каждую ветвь необходимо вычислить так, чтобы прошлое каждой было доступно, если это станет необходимым в будущих циклах. Предполагается, что язык функциональный, так что это не имеет значения, но вы можете вызывать из него функции C (и, возможно, заметить, что они вызываются чаще, чем вы думали).

В Lustre написание эквивалента

if (y <> 0) тогда 100 / y else 100

- типичная ошибка новичка. Деления на ноль не избежать,

2
ответ дан 27 November 2019 в 02:30
поделиться

Посмотрите на мой пример Короткое замыкание логического оператора SQL Server , который показывает, почему определенный путь доступа в SQL более эффективен, если логическое короткое замыкание не использовал. В моем примере в блоге показано, как на самом деле использование логического короткого замыкания может нарушить ваш код, если вы предполагаете короткое замыкание в SQL, но если вы прочитаете рассуждение , почему SQL сначала оценивает правую часть, вы Посмотрим, что это правильно, и это приведет к значительному улучшению пути доступа.

4
ответ дан 27 November 2019 в 02:30
поделиться

Я бы сказал, что в 99 случаях из 100 я бы предпочел операторы короткого замыкания по производительности.

Но есть две важные причины, по которым я не могу их использовать. . (Между прочим, мои примеры находятся на C, где && и || закорачивают, а & и | нет.)

1.) Если вы хотите вызвать две или более функций в операторе if независимо от значения возвращается первым.

if (isABC() || isXYZ()) // short-circuiting logical operator
    //do stuff;

В этом случае isXYZ () вызывается, только если isABC () возвращает false. Но вы можете захотеть, чтобы isXYZ () вызывалась несмотря ни на что.

Вместо этого вы делаете это:

if (isABC() | isXYZ()) // non-short-circuiting bitwise operator
    //do stuff;

2.) Когда вы выполняете логические вычисления с целыми числами.

myNumber = i && 8; // short-circuiting logical operator

не обязательно то же самое, что:

myNumber = i & 8; // non-short-circuiting bitwise operator

В этой ситуации вы действительно можете получить разные результаты, потому что оператор короткого замыкания не обязательно оценивает все выражение. И это делает его практически бесполезным для логической математики. Так что в этом случае я бы использовал вместо этого операторы без короткого замыкания (побитовые).

Как я уже намекал, эти два сценария действительно редки для меня. Но вы можете видеть, что для обоих типов операторов есть реальные причины программирования. К счастью, в большинстве популярных сегодня языков есть и то, и другое. Даже в VB.NET есть сокращающие операторы AndAlso и OrElse. Если в современном языке нет обоих, я бы сказал, что он отстал от времени и действительно ограничивает программиста.

4
ответ дан 27 November 2019 в 02:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: