Создатели Go
языка пишут :
Go не дает утверждений. Они, несомненно, удобны, но наш опыт показывает, что программисты используют их как опору, чтобы не думать о правильной обработке ошибок и составлении отчетов. Правильная обработка ошибок означает, что серверы продолжают работу после нефатальных ошибок вместо сбоев. Правильный отчет об ошибках означает, что ошибки являются прямыми и точными, спасая программиста от интерпретации большого следа сбоя. Точные ошибки особенно важны, когда программист, видящий ошибки, не знаком с кодом.
Что вы думаете об этом?
reflect.DeepEqual
, вам это точно не нужно . Это удобно, но за счет производительности (юнит-тесты - хороший пример использования). В противном случае вы можете реализовать любую проверку на равенство, подходящую для вашей «коллекции», без особых проблем.for
цикл в Go (как в C). Было бы неплохо иметь общие операции срезов, хотя сравнение усложняется, когда задействованы указатели и структуры.Ответы:
Нет, в этом нет ничего плохого,
assert
если вы используете его по назначению.То есть он предназначен для отлова случаев, которые «не могут произойти» во время отладки, а не для обычной обработки ошибок.
источник
Нет, ни ,
goto
ниassert
не являются злом. Но оба могут быть использованы неправильно.Утверждают для проверки вменяемости. Вещи, которые должны убить программу, если они не верны. Не для проверки или в качестве замены для обработки ошибок.
источник
goto
умом?goto
по чисто религиозным причинам, а затем просто используйте,goto
а не запутывайте то, что вы делаете. Другими словами: если вы можете доказать, что вы действительно нуждаетесьgoto
, и единственная альтернатива состоит в том, чтобы ввести груз бессмысленных лесов, который в конечном итоге делает то же самое, но без изменения полиции Гото ... тогда просто используйтеgoto
. Конечно, предварительным условием этого является то, что «если вы можете доказать, что вам действительно нужноgoto
». Часто люди этого не делают. Это по-прежнему не означает, что по своей сути это плохо.goto
используется в ядре Linux для очистки кодаПо этой логике контрольные точки тоже злые.
Утверждения должны использоваться как средство отладки, и ничего больше. «Зло» это когда вы пытаетесь использовать их вместо обработки ошибок.
Утверждения призваны помочь вам, программисту, обнаружить и устранить проблемы, которые не должны существовать, и убедиться, что ваши предположения остаются верными.
Они не имеют ничего общего с обработкой ошибок, но, к сожалению, некоторые программисты злоупотребляют ими как таковыми, а затем объявляют их «злыми».
источник
Мне очень нравится использовать assert. Я нахожу это очень полезным, когда я создаю приложения впервые (возможно, для нового домена). Вместо того, чтобы делать очень причудливую проверку ошибок (которую я бы посчитал преждевременной оптимизацией), я быстро пишу код и добавляю много утверждений. Узнав больше о том, как все работает, я переписываю и удаляю некоторые утверждения и изменяю их для лучшей обработки ошибок.
Из-за утверждений я трачу гораздо меньше времени на программирование / отладку программ.
Я также заметил, что утверждения помогают мне думать о многих вещах, которые могут сломать мои программы.
источник
В качестве дополнительной информации, Go предоставляет встроенную функцию
panic
. Это может быть использовано вместоassert
. Напримерpanic
напечатает трассировку стека, поэтому в некотором роде это имеет цельюassert
.источник
Их следует использовать для выявления ошибок в программе. Неплохой пользовательский ввод.
При правильном использовании они не являются злом.
источник
Это часто встречается, и я думаю, что одна проблема, которая сбивает с толку защиту утверждений, состоит в том, что они часто основаны на проверке аргументов. Итак, рассмотрим этот другой пример того, когда вы можете использовать утверждение:
Вы используете исключение для ввода, потому что ожидаете, что иногда вы получите неверный ввод. Вы утверждаете, что список отсортирован, чтобы помочь вам найти ошибку в вашем алгоритме, которую по определению вы не ожидаете. Утверждение содержится только в отладочной сборке, поэтому, несмотря на то, что проверка обходится дорого, вы не против делать это при каждом вызове подпрограммы.
Вы по-прежнему должны тестировать свой производственный код, но это другой и дополнительный способ убедиться, что ваш код правильный. Модульные тесты позволяют убедиться, что ваша подпрограмма соответствует своему интерфейсу, а утверждения - более детальный способ убедиться, что ваша реализация делает именно то, что вы ожидаете.
источник
Утверждения не являются злом, но ими можно легко злоупотреблять. Я согласен с утверждением, что «утверждения часто используются в качестве опоры, чтобы не думать о правильной обработке ошибок и сообщении о них». Я видел это довольно часто.
Лично мне нравится использовать утверждения, потому что они документируют предположения, которые я мог сделать при написании своего кода. Если эти предположения нарушаются при сохранении кода, проблема может быть обнаружена во время тестирования. Тем не менее, я хочу убрать каждое утверждение из моего кода при выполнении производственной сборки (т. Е. С использованием #ifdefs). Отбирая утверждения в производственной сборке, я исключаю риск того, что кто-то использует их как костыль.
Есть еще одна проблема с утверждениями. Утверждения проверяются только во время выполнения. Но часто бывает так, что проверка, которую вы хотели бы выполнить, могла быть выполнена во время компиляции. Желательно обнаружить проблему во время компиляции. Для программистов на C ++, boost предоставляет BOOST_STATIC_ASSERT, которая позволяет вам это делать. Для программистов на Си эта статья ( текст ссылки ) описывает метод, который можно использовать для выполнения утверждений во время компиляции.
Таким образом, я придерживаюсь практического правила: не используйте утверждения в производственной сборке и, если возможно, используйте утверждения только для вещей, которые не могут быть проверены во время компиляции (т. Е. Должны быть проверены во время выполнения).
источник
Я признаю, что использовал утверждения, не рассматривая надлежащие сообщения об ошибках. Однако это не означает, что они очень полезны при правильном использовании.
Они особенно полезны, если вы хотите следовать принципу «Ранний сбой». Например, предположим, что вы реализуете механизм подсчета ссылок. В определенных местах в вашем коде вы знаете, что счет должен быть ноль или один. А также предположим, что, если refcount неверен, программа не будет аварийно завершать работу сразу, но во время следующего цикла обработки сообщений будет трудно выяснить, почему что-то пошло не так. Утверждение было бы полезно для обнаружения ошибки ближе к ее источнику.
источник
Я предпочитаю избегать кода, который делает разные вещи в отладке и выпуске.
Полезно разбить отладчик на условие и получить всю информацию о файле / строке, а также точное выражение и точное значение.
Утверждение, что «оценивать условие только в отладке» может быть оптимизацией производительности и, как таковое, полезно только в 0,0001% программ - где люди знают, что они делают. Во всех других случаях это вредно, так как выражение может фактически изменить состояние программы:
assert(2 == ShroedingersCat.GetNumEars());
заставит программу делать разные вещи в отладке и выпуске.Мы разработали набор макросов assert, которые будут генерировать исключение, и делать это как в отладочной, так и в выпускной версии. Например,
THROW_UNLESS_EQ(a, 20);
будет выдано исключение с сообщением what (), имеющим как file, line и фактические значения a, и так далее. Только макрос будет иметь силу для этого. Отладчик может быть настроен на прерывание при «выбросе» определенного типа исключения.источник
Я не люблю утверждает, сильно. Я бы не сказал, что они злые.
По сути, assert будет делать то же самое, что и непроверенное исключение, единственное исключение состоит в том, что assert (обычно) не следует хранить для конечного продукта.
Если вы создаете сеть безопасности для себя во время отладки и сборки системы, зачем отказывать в этой сети безопасности для своего клиента, службы поддержки или кого-либо, кто сможет использовать программное обеспечение, которое вы сейчас создаете. Используйте исключения исключительно для утверждений и исключительных ситуаций. Создав соответствующую иерархию исключений, вы сможете очень быстро отличить одно от другого. За исключением этого времени подтверждение остается на месте и может предоставить ценную информацию в случае сбоя, которая в противном случае была бы потеряна.
Поэтому я полностью понимаю создателей Go, полностью удаляя утверждения и заставляя программистов использовать исключения для обработки ситуации. Этому есть простое объяснение, исключение - просто лучший механизм для работы, зачем придерживаться архаичных утверждений?
источник
Краткий ответ: нет, я считаю, что утверждения могут быть полезны
источник
Недавно я начал добавлять некоторые утверждения в свой код, и вот как я это делал:
Я мысленно делю свой код на граничный код и внутренний код. Граничный код - это код, который обрабатывает пользовательский ввод, читает файлы и получает данные из сети. В этом коде я запрашиваю ввод в цикле, который завершается только тогда, когда ввод допустим (в случае интерактивного пользовательского ввода), или выбрасываю исключения в случае невосстановимых поврежденных данных файла / сети.
Внутренний код это все остальное. Например, функция, которая устанавливает переменную в моем классе, может быть определена как
и функция, которая получает данные из сети, может выглядеть так:
Это дает мне два слоя проверок. Все, где данные определяются во время выполнения, всегда получает исключение или немедленную обработку ошибок. Тем не менее, эта дополнительная проверка
Class::f
сassert
оператором означает, что если когда-нибудь вызовет какой-то внутренний кодClass::f
, у меня все равно будет проверка работоспособности. Мой внутренний код может не передавать допустимый аргумент (потому что я, возможно, рассчиталvalue
из некоторого сложного ряда функций), поэтому мне нравится иметь утверждение в функции настройки, чтобы документировать, что независимо от того, кто вызывает функцию,value
не должно быть больше или равноend
.Похоже, это вписывается в то, что я читаю в нескольких местах, что утверждения невозможно нарушить в хорошо функционирующей программе, в то время как исключения должны быть в исключительных и ошибочных случаях, которые все еще возможны. Поскольку в теории я проверяю все входные данные, моё утверждение не должно быть возможным. Если это так, моя программа неверна.
источник
Если утверждения, о которых вы говорите, означают, что программа рвет, а затем существует, утверждения могут быть очень плохими. Это не значит, что они всегда неправильны в использовании, они представляют собой конструкцию, которую очень легко неправильно использовать. У них также есть много лучших альтернатив. Такие вещи являются хорошими кандидатами на звание зла.
Например, сторонний модуль (или любой другой модуль) практически никогда не должен выходить из вызывающей программы. Это не дает вызывающему программисту никакого контроля над тем, какой риск должна принять программа в этот момент. Во многих случаях данные настолько важны, что даже сохранение поврежденных данных лучше, чем их потеря. Утверждения могут заставить вас потерять данные.
Некоторые альтернативы утверждениям:
Некоторые ссылки:
Даже люди, отстаивающие утверждение, считают, что их следует использовать только в разработке, а не в производстве:
Этот человек говорит, что утверждения следует использовать, когда модуль имеет потенциально поврежденные данные, которые сохраняются после создания исключения: http://www.advogato.org/article/949.html . Это, безусловно, разумный момент, однако внешний модуль никогда не должен указывать, насколько важны поврежденные данные для вызывающей программы (путем выхода «для» них). Правильный способ справиться с этим - создать исключение, которое проясняет, что программа может теперь находиться в несовместимом состоянии. А поскольку хорошие программы в основном состоят из модулей (с небольшим количеством склеивающего кода в основном исполняемом файле), утверждения почти всегда неправильно.
источник
assert
Это очень полезно и может сэкономить вам много времени, когда неожиданные ошибки происходят, останавливая программу при самых первых признаках проблемы.С другой стороны, злоупотреблять им очень легко
assert
.Правильная, правильная версия будет выглядеть примерно так:
Так что ... в конечном итоге ... в целом ... Я должен согласиться, что
assert
можно злоупотреблять. Я делаю это все время.источник
assert
используется для обработки ошибок, потому что он меньше печатает.Поэтому, как разработчики языка, они должны скорее видеть, что правильная обработка ошибок может быть сделана с еще меньшим набором текста. Исключение assert, потому что ваш механизм исключения является многословным, не является решением. Ой, подождите, у Го тоже нет исключений. Жаль :)
источник
Мне захотелось ударить автора по голове, когда я увидел это.
Я все время использую утверждения в коде и заменяю их все, когда пишу больше кода. Я использую их, когда я не написал необходимую логику, и хочу получать оповещения при запуске кода, а не писать исключение, которое будет удалено по мере приближения проекта к завершению.
Исключения также легче сочетаются с рабочим кодом, который мне не нравится. Утверждение легче заметить, чем
throw new Exception("Some generic msg or 'pretend i am an assert'");
источник
Моя проблема с этими ответами в защиту утверждения состоит в том, что никто четко не определяет, чем он отличается от обычной фатальной ошибки , и почему утверждение не может быть подмножеством исключения . Теперь, с этим сказано, что если исключение никогда не будет поймано? Это делает это утверждением номенклатурой? И зачем вам когда-либо налагать ограничение на язык, на который может быть создано исключение, которое / ничто / не может обработать?
источник
func()
с отрицательным номером. Теперь, внезапно с вашими утверждениями вы вытащили ковер из-под меня и не дали мне возможности прийти в себя, вместо того, чтобы вежливо сказать мне, что я прошу, не может быть сделано. Нет ничего плохого в том, что вы обвиняете программу в ненадлежащем поведении и цитируете ее: проблема в том, что вы размываете акт принуждения к закону и приговариваете осужденного к уголовной ответственности.Да, утверждения злые.
Часто они используются там, где должна использоваться правильная обработка ошибок. Привыкайте писать правильную обработку ошибок качества производства с самого начала!
Обычно они мешают написанию юнит-тестов (если только вы не пишете пользовательское утверждение, которое взаимодействует с вашей системой тестирования). Это часто потому, что они используются там, где должна использоваться правильная обработка ошибок.
В основном они компилируются из сборок релизов, что означает, что ни один из их «тестов» недоступен, когда вы запускаете код, который вы фактически выпускаете; учитывая, что в многопоточных ситуациях худшие проблемы часто появляются только в коде выпуска, это может быть плохо.
Иногда они являются опорой для сломанных конструкций; то есть дизайн кода позволяет пользователю вызывать его так, чтобы его не вызывать, и утверждение «предотвращает» это. Исправьте дизайн!
Я написал об этом больше в своем блоге в 2005 году здесь: http://www.lenholgate.com/blog/2005/09/assert-is-evil.html
источник
Не столько зло, сколько вообще контрпродуктивно. Существует разделение между постоянной проверкой ошибок и отладкой. Assert заставляет людей думать, что все отладки должны быть постоянными и вызывает большие проблемы с читабельностью при частом использовании. Постоянная обработка ошибок должна быть лучше, чем та, где это необходимо, и поскольку assert вызывает свои собственные ошибки, это довольно сомнительная практика.
источник
я никогда не использую assert (), примеры обычно показывают что-то вроде этого:
Это плохо, я никогда этого не делаю, что если моя игра выделяет кучу монстров? почему я должен вылетать из игры, вместо этого вы должны изящно обрабатывать ошибки, поэтому сделайте что-то вроде:
источник
new
никогда не возвращаетсяnullptr
, он бросает.