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

Я решил его в конечном счете с тайм-аутом на onblur событии (благодаря совету друга, который не является StackOverflow):

<input id="myInput" onblur="setTimeout(function() {alert(clickSrc);},200);"></input>
<span onclick="clickSrc='mySpan';" id="mySpan">Hello World</span>

Работы и в FF и в IE.

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

19 ответов

Нет, нет ничего плохого в 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
поделиться

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

Но просто выполните n раз вашего профилирования, и сохраните только x % ваших наблюдений, те, которые вокруг медианы, потому что медиана является «надежной статистикой» (в отличие от среднего), на которую не влияют отклонения (отклонения являются именно тем значением, которое вы хотите не принимать во внимание при выполнении такого профилирования).

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

-121--4244691-

Задокументированный способ добавления элементов управления к JFileChooser осуществляется с помощью метода setAccessory (JComponent) .

JTextField field = new JTextField("Hello, World");
JPanel accessory = new JPanel();
accessory.setLayout(new FlowLayout());
accessory.add(field);

JFileChooser chooser = new JFileChooser();
chooser.setAccessory(accessory);
int ret = chooser.showOpenDialog(frame);

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

Чтобы расположить компонент в нужном положении, вероятно, придется провести график компонента и манипулировать им. Это был бы очень хрупкий подход, и вам может быть лучше просто построить свой диалог.

Это может включать в себя выбор файла:

JFileChooser chooser = new JFileChooser();
chooser.addActionListener(new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
    // TODO - wire into something
    System.out.println(e);
  }
});

JTextField field = new JTextField("Hello, World");

JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(chooser, BorderLayout.CENTER);
panel.add(field, BorderLayout.SOUTH);
-121--4378786-

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

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

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

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

Некоторые альтернативы утверждениям:

  • Использование отладчика,
  • Консоль / база данных / другое ведение журнала
  • Исключения
  • Другие типы обработки ошибок

Некоторые ссылки:

Даже люди, выступающие за assert, считают, что их следует использовать только в разработке, а не , а не в производстве:

Этот человек говорит, что утверждения следует использовать, когда модуль имеет потенциально поврежденные данные, которые сохраняются после создания исключения: http://www.advogato.org/article/949. html . Это, безусловно, разумный момент, однако внешний модуль не должен никогда предписывать, насколько важны поврежденные данные для вызывающей программы (выходом «за» их). Правильный способ справиться с этим - создать исключение, которое проясняет, что программа теперь может находиться в несогласованном состоянии. А поскольку хорошие программы в основном состоят из модулей (с небольшим количеством связующего кода в основном исполняемом файле), утверждения почти всегда - неправильный поступок.

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