Как я могу улучшить свою проверку и обработку ошибок?

13

В последнее время я пытался понять, что такое правильное количество проверок и каковы правильные методы.

У меня есть несколько вопросов по этому поводу:

Как правильно проверить наличие ошибок (неверный ввод, плохие состояния и т. Д.)? Что лучше: явно проверять наличие ошибок или использовать такие функции, как утверждения, которые можно оптимизировать из окончательного кода? Я чувствую, что явно проверяю беспорядок в программе с большим количеством дополнительного кода, который не должен выполняться в большинстве случаев в любом случае - и не говоря уже о том, что большинство ошибок заканчиваются неудачей сброса / выхода. Зачем загромождать функцию явными проверками, чтобы просто прервать? Я искал утверждения против явной проверки ошибок и нашел немного, чтобы действительно объяснить, когда делать то или другое.

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

Malloc returning null, check explictly
API user inserting odd input for functions, use asserts

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

скоро
источник
3
Хороший вопрос, но я думаю, что он мог бы лучше подойти для одного из родственных сайтов (программистов?).
Спасибо, я не был уверен. Я думал, так как это было довольно связано с кодом SO было бы хорошо.
Anon
3
Простой ответ: «Вот почему были изобретены исключения. Получите лучший язык».
DeadMG
1
@DeadMG: setjmp/ longjmpдоступны в C, поэтому вам не нужен новый язык.
user786653
3
@DeadMG: У кого-то, кто не может сделать правильную проверку ошибок C, есть шанс снежного кома в аду получить правильную обработку исключений C ++ ...
Кодер

Ответы:

4

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

Карл Билефельдт
источник
2

Проверяйте в любое время что угодно (это могло измениться после вашей последней проверки), что не на 100% под вашей командой. А также: во время разработки даже не доверяй себе! ;-)

Ококок ... «что-нибудь» предназначено для того, чтобы быть прочитанным как проверка на такие вещи, которые могут вызвать ненормальное прерывание или что-то, что может заставить ваше приложение / систему делать то, что он не должен делать.

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

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

алк
источник
1
+1 за «проверить все». Я не покупаю аргумент беспорядка кода: любой программист должен уметь различать проверку ошибок и реальную логику в любом случае.
Стийн
2

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

Прежде всего - я бы сказал, что нет причин, по которым любая отдельная ошибка, возвращаемая подчиненным методом, не должна обрабатываться. А ошибки и исключения - это больше, чем возвращаемые значения или все try / catch.

  1. Просто бросать и ловить недостаточно.
    Посмотрите на это : где автор объясняет, что простое обнаружение, но бездействие потенциально подавляет исключение, и, если не будет сделано достаточно, чтобы устранить ущерб, - это хуже, чем просто допустить выполнение кода. Точно так же просто написание оператора «log» при открытии файла или ошибке чтения может помочь найти причину - но к тому времени, когда программа завершает работу, это может привести к повреждению данных! Недостаточно сказать, что у меня есть много попыток / поймать - более важно знать, что они действительно делают!

  2. Не злоупотребляйте попыткой поймать.
    Иногда - в основном ленивые или наивные программисты думают, что после написания достаточного количества try / catch их работа заканчивается и становится легкой. Довольно часто лучше применять корректирующие действия и возобновлять, чем просто сбрасывать все целиком. Если это невозможно, нужно решить, на какой уровень вам нужно вернуться. В зависимости от контекста и серьезности, попробуйте поймать вложенность требует тщательного проектирования. Например, увидеть это и это

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

  4. Определите, каков наилучший возможный результат:
    все, что должно быть сделано в условиях исключения, очень важно. Например, если в одном из наших случаев - медиаплеер обнаружит, что у него нет полных данных, которые должны быть воспроизведены для пользователя - что он должен делать?

    • либо пропустите какую-то плохую часть и посмотрите, сможет ли она добиться успеха с хорошими вещами.
    • если это произойдет слишком много, подумайте, можно ли перейти к следующей песне.
    • если он обнаружит, что не может прочитать какой-либо файл - остановитесь и покажите что-нибудь.
    • в то же время
    • под каким государством игрок должен POP-UP для пользователя и
    • когда он должен нести сам по себе?
    • Должно ли это "остановить" вещи, чтобы попросить пользователя обратной связи
    • или это должно поместить небольшую ненавязчивую заметку об ошибке в некоторый угол?

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

  5. Иногда нам нужно проверять исключения, прежде чем они возникнут. Наиболее распространенным примером является ошибка деления на ноль. В идеале нужно проверить, что перед тем, как возникнет такое исключение - и если это так, - постарайтесь поставить наиболее подходящее ненулевое значение и двигаться дальше, а не совершать самоубийство!

  6. Очистка. По крайней мере, это то, что вы должны сделать! Если случается, что функция открывает 3 файла, а четвертый не открывается - само собой разумеется, первые 3 должны были быть закрыты. Передача этой работы на уровень выше - плохая идея. если вы решили совсем не уходить без очистки памяти. И самое главное - даже если вы пережили исключение, сообщите об этом выше, что все пошло не так, как обычно.

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

Лучший справочник: Code Craft глава 6 - доступна для скачивания

Дипан Мехта
источник
1

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

Также используйте проверку ошибок в релизе, вы можете прибегнуть к чему-то простому:

if(somethinghitthefan)
     abort();

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

Просмотрщики событий и журналы совершенно бесполезны по сравнению с тем abort(), кто их проверяет?

кодировщик
источник
exit / abort == худший пользовательский опыт: приложение просто исчезает, не сообщая, почему ..
stijn
@stijn: abortразбивается на отладчик / создает дамп. exitэто плохо, да. Хотя я предпочитаю __asm int 3больше всего.
Кодер
это верно, и в C / C ++ я склонен писать утверждения, используя также __asm ​​int 3, но никогда не показывая, по крайней мере, описание того, почему, а предпочтительно также строку и файл. Тогда, по крайней мере, клиент может дать информацию о том, что именно произошло.
Стийн
0

Различные вещи, которые вы можете сделать, это:
1. Читать и ассимилировать много кода в сети и посмотреть, как это делается. 2. Использовать
некоторые инструменты отладки, чтобы помочь вам найти области ошибок.
3. Помнить о тривиальных ошибках из-за неправильных назначений и синтаксические ошибки.
4. Некоторые худшие ошибки возникают из-за логических ошибок в программе, которые труднее найти. Для этого вы можете найти и найти, или для более сложных, попробуйте поговорить с людьми или использовать ресурсы, такие как Stackoverflow , Wikipedia , Google, чтобы получить помощь от люди.

DCV
источник