Утверждают зло? [закрытый]

Go создатели языка пишут:

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

Каково Ваше мнение об этом?

195
задан 4 revs, 3 users 62% 21 October 2019 в 01:38
поделиться

17 ответов

Нет, нет ничего плохого в assert , если вы используете его по назначению.

То есть он должен быть для выявления случаев, которые "не могут случиться "во время отладки, в отличие от нормальной обработки ошибок.

  • Утверждение: сбой в самой логике программы.
  • Обработка ошибок: ошибочный ввод или состояние системы не из-за ошибки в программе.
318
ответ дан 23 November 2019 в 05:19
поделиться

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

0
ответ дан 23 November 2019 в 05:19
поделиться

Да, утверждения - зло.

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

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

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

Иногда они являются костылем для иначе сломанных проектов; т.е. дизайн кода позволяет пользователю называть его так, как он не должен ' t быть вызванным, и assert "предотвращает" это. Исправьте дизайн!

Я писал об этом больше в своем блоге еще в 2005 году здесь: http://www.lenholgate.com/blog/2005/09/assert-is-evil.html

1
ответ дан 23 November 2019 в 05:19
поделиться

Их следует использовать для обнаружения ошибок в программе. Неплохой ввод пользователя.

При правильном использовании они не злые.

30
ответ дан 23 November 2019 в 05:19
поделиться

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

3
ответ дан 23 November 2019 в 05:19
поделиться

assert очень полезен и может избавить вас от большого количества ошибок при возникновении непредвиденных ошибок за счет остановки программы при самых первых признаках проблемы.

С другой стороны, это очень легко злоупотреблять assert .

int quotient(int a, int b){
    assert(b != 0);
    return a / b;
}

Правильная, правильная версия будет примерно такой:

bool quotient(int a, int b, int &result){
    if(b == 0)
        return false;

    result = a / b;
    return true;
}

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

1
ответ дан 23 November 2019 в 05:19
поделиться

В качестве дополнительной информации go предоставляет встроенную функцию panic . Его можно использовать вместо assert . Например,

if x < 0 {
    panic("x is less than 0");
}

panic напечатает трассировку стека, поэтому в некотором роде цель assert .

30
ответ дан 23 November 2019 в 05:19
поделиться

Нет, ни goto , ни assert ] злы. Но и то и другое можно использовать неправильно.

Утверждение предназначено для проверки работоспособности. Вещи, которые должны убить программу, если они не верны. Не для проверки или замены обработки ошибок.

106
ответ дан 23 November 2019 в 05:19
поделиться

Согласно этой логике, точки останова также являются злом.

Утверждения следует использовать в качестве средства отладки , и ничего больше. "

61
ответ дан 23 November 2019 в 05:19
поделиться

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

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

5
ответ дан 23 November 2019 в 05:19
поделиться

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

Из-за утверждений я трачу гораздо меньше времени на кодирование / отладку программ.

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

39
ответ дан 23 November 2019 в 05:19
поделиться

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

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

Наличие утверждения, которое «оценивает условие только при отладке», может быть оптимизацией производительности и, как таковая, полезно только в 0,0001% программ - где люди знают, что делают. Во всех других случаях это вредно, поскольку выражение может фактически изменить состояние программы:

assert (2 == ShroedingersCat.GetNumEars ()); заставит программу делать разные вещи при отладке и выпуске.

Мы разработали набор макросов assert, которые генерируют исключение и делают это как в отладочной, так и в выпускной версии. Например, THROW_UNLESS_EQ (a, 20); вызовет исключение с сообщением what (), имеющим как file, line, так и фактические значения a, и так далее. Только макрос может это сделать. Отладчик может быть сконфигурирован так, чтобы прерываться при «выдаче» определенного типа исключения.

5
ответ дан 23 November 2019 в 05:19
поделиться

Я очень не люблю утверждения. Я бы не стал говорить, что они злые.

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

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

Итак, я полностью понимаю создателей Go, полностью удалив утверждения и заставив программистов использовать исключения для обработки ситуации. Этому есть простое объяснение, исключения - это просто лучший механизм для работы, зачем придерживаться архаичных утверждений?

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

Итак, я полностью понимаю создателей Go, полностью удалив утверждения и заставив программистов использовать исключения для обработки ситуации. Этому есть простое объяснение, исключения - это просто лучший механизм для работы, зачем придерживаться архаичных утверждений?

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

Итак, я полностью понимаю создателей Go, полностью удалив утверждения и заставив программистов использовать исключения для обработки ситуации. Этому есть простое объяснение, исключения - это просто лучший механизм для работы, зачем придерживаться архаичных утверждений?

5
ответ дан 23 November 2019 в 05:19
поделиться

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

Лично мне нравится использовать утверждения, потому что они документируют предположения, которые я мог сделать при написании кода. Если эти предположения нарушаются при сохранении кода, проблема может быть обнаружена во время тестирования. Однако я стараюсь исключать все утверждения из моего кода при создании производственной сборки (т. Е. С использованием #ifdefs). Убирая утверждения в производственной сборке, я исключаю риск того, что кто-либо может использовать их в качестве опоры.

Есть еще одна проблема с утверждениями. Утверждения проверяются только во время выполнения. Но часто бывает, что проверка, которую вы хотели бы выполнить, могла быть выполнена во время компиляции. Желательно обнаруживать проблему во время компиляции. Для программистов на C ++ boost предоставляет BOOST_STATIC_ASSERT, который позволяет вам это делать. Для программистов на C эта статья ( текст ссылки ) описывает метод, который можно использовать для выполнения утверждений во время компиляции.

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

8
ответ дан 23 November 2019 в 05:19
поделиться

assert злоупотребляют для обработки ошибок, потому что это меньше печатает.

Итак, языковым разработчикам, они скорее должны увидеть, что правильная обработка ошибок может быть выполнена с еще меньшим набором текста. Исключение assert из-за того, что ваш механизм исключения является подробным, не является решением. Подождите, у Go тоже нет исключений. Слишком плохо :

1
ответ дан 23 November 2019 в 05:19
поделиться

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

build-sorted-list-from-user-input(input)

    throw-exception-if-bad-input(input)

    ...

    //build list using algorithm that you expect to give a sorted list

    ...

    assert(is-sorted(list))

end

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

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

13
ответ дан 23 November 2019 в 05:19
поделиться

Когда я это увидел, мне захотелось ударить автора по голове.

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

Исключения также легче вписываются в производственный код, что мне не нравится. Утверждение легче заметить, чем выбросить новое исключение («Какое-то общее сообщение или« притвориться, что я утверждаю »»);

1
ответ дан 23 November 2019 в 05:19
поделиться