Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
В вашем мире работают только прямые связи?
В вашем мире работают только прямые связи?Нет, всё гораздо банальнее — господин VolCh просто очень любит
Да, все говорят, что хотят/делают «максимально надежно», но на самом деле мало кто будет тратить кучу времени на то, чтобы разобрать все возможные исключения в «сервисе для загрузки фоток». Зато в сервсие обработки платежей наверняка будет разобран каждый потенциальный чих, причем не только в виде вывода сообщения об ошибке и записи в лог.Вы не поверите, но всё ровно наоборот. Потому что «в сервисе для загрузки» важно, чтобы фотки таки загрузились и если что-то куда-то не может записаться из-за разницы кодировок или слишком большой подписи вы можете это как-то попробовать пофиксить и загрузить плавильно хотя бы фотки без описаний или с частью описаний.
смотрите в оба и не позволяйте исключениям убивать ваше приложение.
public static class Exceptions
вообще промолчу. public static bool NotFatal(this Exception ex) {
return fatalExceptions.All(curFatal => ex.GetType() != curFatal);
}
public static bool IsFatal(this Exception ex) {
return !NotFatal(ex);
}
А что не так с этими методами?
Exceptions.TryFilterCatch(host.Close, Exceptions.NotFatal,
ex => logger.Error("Исключение при закрытии хоста сервиса.", ex));
IsNotFatal()
. Хорошая практика называть методы, используя глаголы в начале имени.if (!isRecoverPossible(ex)) throw;
if (isFatal(ex)) throw;
Exceptions.TryFilterCatch(host.Close, Exceptions.IsFatal,
ex => logger.Error("Исключение при закрытии хоста сервиса.", ex));
например, из вызванной функции мы получили ошибку DNS «host not found», а выше возвращаем ошибку «не могу скачать url (host not found)
причём никто не мешает ошибку передавать как сложный объект включающий и код, и тип, и описание, и стек трейс.
«Свое» исключение и есть такой объектНет. Исключения раскручивают стек. Обычные ошибки не должны этого делать. Именно этим они отличаются от исключений, и именно поэтому нельзя использовать исключения вместо ошибок. Нет, конечно, если Вы мазохист, то Вы можете сэмулировать корректную обработку ошибок нарисовав отдельный try/catch вокруг вызова каждой функции, которая теоретически может вернуть ошибку…
Нет, конечно, если Вы мазохист, то Вы можете сэмулировать корректную обработку ошибок нарисовав отдельный try/catch вокруг вызова каждой функции, которая теоретически может вернуть ошибку…
Все проблемы связанные с обработкой исключений, из-за которых и появляются статьи вроде этой
отсутствие корректной обработки ошибок
По мне, часть проблем в статье — надуманныеЭто значит одно из двух — либо Вы эти проблемы давно переросли и обладаете более глубоким внутренним пониманием техники исключений, либо Вы до этих проблем ещё недоросли. Это никоим образом не попытка Вас обидеть, это просто автоматически следует из отношения «надуманные проблемы». К сожалению, по моим личным наблюдениям, многие вопросы при всём желании невозможно объяснить до того момента, когда человек сам созреет до готовности их понять. И зачастую требуется 10-15 лет (в среднем, разумеется, это очень индивидуально) опыта в программировании, пока до людей начинают доходить некоторые вещи.
Вы несколько раз употребили оборот вроде «это неправильно», причем, как мне кажется, безосновательноНе воспримите мои слова как попытку «съехать с темы», но я честно сделал что мог и лучше объяснить не смогу. С опытом многое просто начинаешь чувствовать как правильное и неправильное, и далеко не все в состоянии внятно и аргументировано объяснить почему именно так. Раз Вы не поняли — возможно я плохо объяснил, но лучше уже не получится. А может я просто глупости говорю, и это Вы не можете мне объяснить всю глубину моих заблуждений — кто знает. ☺
исключения возникают крайне редко, их очень немного, и большая их часть просто честно убивает приложение (если в приложении и есть глобальный перехват всех исключений, то он используется для попытки вывода сообщения об исключении в лог перед тем как приложение будет аварийно завершено, а не для молчаливого заглушения исключений)
не исключено, что в целом приложение способно продолжать работуДа, это не исключено, но и гарантий на этот счёт никаких нет. Из-за некоторых ошибок банально портится внутреннее состояние приложения, и хотя оно может сделать вид что проложило работать, но творить при этом может такое, что потом фиг разберёшься, что произошло и почему — это, кстати, основная причина рекомендации обрабатывать ошибки как можно ближе к месту, где они произошли, т.к. чем мы от него дальше, тем больше накапливается вторичных ошибок и тем сложнее понять, как всё это корректно обработать. Так что как по мне — нафиг эту наивную надежду на лучшее, пусть лучше упадёт и перезапустится с нуля.
супервизор является неотъемлемой частью приложенияЯ от этого подхода давно отказался, по ряду вполне объективных причин:
например, из вызванной функции мы получили ошибку DNS «host not found», а выше возвращаем ошибку «не могу скачать url (host not found)».
Все остальные, обычные ошибки необходимо обрабатывать как можно ближе к месту, где они возникли — т.е. там, где вызывалась функция в которой произошла ошибка — только в той точке, где мы для чего-то вызвали эту функцию мы можем адекватно обработать все возможные варианты ошибок и принять решение как быть дальше, раз мы не получили от этой функции нужный нам результат.
Поэтому выкидывать исключения нужно только тогда, когда действительно необходима именно раскрутка стека — т.е. при возникновении критической ошибки
Если же пролезло в релиз, то фиксится как можно быстрее. Поэтому и удивило, что в коде выше это исключение ожидается повсеместно, будто оно норма.
Подкину ещё проблему: что, если вам нужно в цикле вызывать код, который всё время выбрасывает исключения в случае, если что-то не так?
Начнём с версионирования, потому что тут проблемы легко увидеть. Скажем я создаю метод foo, который декларирует проброс исключений A, B и C. Во второй версии метода я хочу добавить пару фишек и теперь метод foo может выкинуть также исключение D. Добавление нового исключения является несовместимым изменением, потому что существующие пользователи этого метода почти 100% не будут ловить это исключение.
try {
var user = db.users.find(userId);
var cars = db.cars.findByUser(user);
} catch (e) {
...
}
// имхо это всякое лучше чем
db.users.find(userId, function(err, user) {
if (err) {
// тут что-то сделать
return;
}
db.cars.findByUser(user, function(err, cars) {
if (err) {
// тут опять что-то сделать
return;
}
// работаем с результатом
})
})
совершенно бесполезны в случае использования колбэков или многопоточностиКолбэков — да, многопоточности — нет. (Как по мне, то гораздо большим злом являются как раз колбэки, но в языках где нет лёгких нитей и каналов или акторов приходится с этим злом мириться.)
Четверть сказали, что использовали что-то вроде метода проб и ошибок – отладка, тестирование, чтение логов, получения краш-дампов для того, чтобы выяснить какие исключения следует ловить.
Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default. Consequently, users are advised to write their code to detect and prevent a stack overflow. For example, if your application depends on recursion, use a counter or a state condition to terminate the recursive loop. Note that an application that hosts the common language runtime (CLR) can specify that the CLR unload the application domain where the stack overflow exception occurs and let the corresponding process continue.
Никто не умеет обрабатывать ошибки