То, как вы взаимодействуете с исключениями, зависит от того, где ваш код находится в слоях приложения. В общем, отчеты об ошибках - это вопрос пользовательского интерфейса, и обычно их лучше оставить приложению, самому внешнему слою кода.
Код низкого уровня и код бизнес-логики среднего уровня часто используются разными приложениями. Поскольку разные приложения будут иметь разные политики относительно того, сколько и какие ошибки следует сообщать пользователю, код низкого и среднего уровня должен избегать обработки исключений с целью сообщения об ошибках. Пусть приложение сделает это.
Существует множество законных причин для захвата исключения в низкоуровневом и среднем уровне кода, в частности, чтобы попробовать альтернативный путь в случае сбоя основного пути, или преобразовать низкоуровневое исключение в исключение, более специфичное для текущая операция. Просто будьте осторожны, чтобы не переборщить, сделайте ваши исключения ловушками как можно более конкретными (не чрезмерно обобщайте, или вы будете ловить вещи, с которыми вы не готовы справиться), и будьте крайне критичны к подавлению исключения полностью на низком и среднем уровне. код.
Общая философия для кода низкого и среднего уровня должна заключаться в следующем: если действие, запрошенное вызывающим абонентом, не выполняется, то пусть вызывающий абонент увидит последствия - исключение.
Ваш код низкого и среднего уровня часто попадает в два лагеря: «сложные» функции, которые либо выполняют запрошенное действие, либо выдают исключение, если это невозможно, и «мягкие» функции, которые более удобны для экспериментального исследования. Если операция, вероятно, в большинстве случаев завершится с ошибкой, например, FileExists (), то, вероятно, использование исключений будет плохим, чтобы вызвать исключение при сбое и потребовать, чтобы вызывающий объект обернул все вызовы этой функции в обработчике исключений. Это создало бы больше работы для звонящего. В этом случае FileExists () должна быть «мягкой» функцией, которая возвращает true / false вместо броска. «Жесткая» версия этого может называться «RequireFile ()», который выдает, если файл не найден.
В качестве шаблона именования вы часто видите «Try» в качестве префикса к программным функциям. Таким образом, GetData () была бы сложной функцией, которая генерирует, если она не может выполнить работу, а TryGetData () была бы мягкой функцией, которая возвращает логическое значение вместо броска. В зависимости от использования, часто можно увидеть обе функции в классе или библиотеке.
Эти пары часто реализуются как одна, вызывающая другую - GetData () вызывает TryGetData () и выдает, если TryGetData () возвращает false, или TryGetData () вызывает GetData () внутри блока try..catch. Какой шаблон использовать, зависит от сложности работы, выполняемой функцией. Если случай сбоя легко обнаруживается с помощью логической логики (низкий риск исключений), тогда TryGetData будет основной реализацией. Если в случае сбоя происходит сбой по исключению, то GetData будет основной реализацией.
«Жесткие» функции позволяют вызывающему использовать все преимущества исключений для упрощения логики программы - если этот вызов завершится успешно, я могу перейти к следующему шагу, используя результаты вызова. Если этот вызов не удастся, он выдаст исключение и следующий шаг не будет выполнен. «Жесткие» функции позволяют выполнять последовательность операций с правильным допущением, что каждая операция возвращает законные результаты, потому что, если операция не может вернуть законные результаты, она выбрасывает нас из этой последовательности операций. Это позволяет вам сконцентрировать логику программы первичного пути без помех обработки ошибок пожарной бригады - анализируя коды ошибок функций при каждом вызове и решая, что с ними делать.