Если язык по своей природе поддерживает исключения, то предпочтительно генерировать исключения, и клиенты могут перехватить исключение, если они не хотят, чтобы оно приводило к сбою. Фактически, клиенты вашего кода ожидают исключений и будут сталкиваться со многими ошибками, потому что они не будут проверять возвращаемые значения.
Есть несколько преимуществ использования исключений, если у вас есть выбор.
Сообщения
Исключения содержат читаемые пользователем сообщения об ошибках, которые могут быть использованы разработчиками для отладки или даже отображены пользователям, если это необходимо. Если потребительский код не может обработать исключение, он всегда может записать его в журнал, чтобы разработчики могли просматривать журналы, не останавливаясь на каждой другой трассировке, чтобы выяснить, какое было возвращаемое значение, и отобразить его в таблице, чтобы выяснить, что было фактическое исключение.
С возвращаемыми значениями дополнительная информация не может быть легко предоставлена. Некоторые языки поддерживают вызовы методов для получения последнего сообщения об ошибке, поэтому эта проблема немного смягчается, но для этого требуется, чтобы вызывающий абонент делал дополнительные вызовы, а иногда требуется доступ к «специальному объекту», который несет эту информацию.
В случае сообщений об исключениях я предоставляю как можно больше контекста, например:
Политика имени "foo" не может быть получена для пользователя "bar", на который есть ссылка в профиле пользователя.
Сравните это с кодом возврата -85. Какой из них вы бы предпочли?
Стеки вызовов
Исключения обычно также имеют подробные стеки вызовов, которые помогают отлаживать код быстрее и быстрее, а также могут регистрироваться вызывающим кодом при желании. Это позволяет разработчикам точно определить проблему с точной линией, и, следовательно, является очень мощным. Еще раз, сравните это с файлом журнала с возвращаемыми значениями (такими как -85, 101, 0 и т. Д.), Какой из них вы бы предпочли?
Сбой быстрого предвзятого подхода
Если метод вызывается где-то, что дает сбой, он выдаст исключение. Вызывающий код должен либо явно подавить исключение, либо произойдет сбой. Я обнаружил, что это действительно удивительно, потому что во время разработки и тестирования (и даже в производстве) код быстро дает сбой, заставляя разработчиков это исправлять. В случае возвращаемых значений, если проверка на возвращаемое значение пропущена, ошибка игнорируется, и ошибка появляется где-то неожиданно, обычно с более высокой стоимостью отладки и исправления.
Обертывание и развертывание исключений
Исключения могут быть обернуты внутри других исключений, а затем развернуты при необходимости. Например, ваш код может выдать то, ArgumentNullException
что вызывающий код может обернуть внутри, UnableToRetrievePolicyException
потому что эта операция завершилась неудачно в вызывающем коде. Хотя пользователю может отображаться сообщение, аналогичное приведенному выше примеру, некоторый диагностический код может развернуть исключение и обнаружить, что ArgumentNullException
оно вызвало проблему, что означает ошибку кодирования в коде вашего потребителя. Это может затем запустить оповещение, чтобы разработчик мог исправить код. Такие сложные сценарии нелегко реализовать с помощью возвращаемых значений.
Простота кода
Это немного сложнее объяснить, но я изучил это кодирование как с возвращаемыми значениями, так и с исключениями. Код, который был написан с использованием возвращаемых значений, обычно вызывает вызов и затем выполняет серию проверок того, что было возвращаемым значением. В некоторых случаях он будет вызывать другой метод и теперь будет иметь другую серию проверок для возвращаемых значений из этого метода. За исключением исключений, обработка исключений намного проще в большинстве, если не во всех случаях. У вас есть блоки try / catch / finally, причем среда выполнения старается изо всех сил выполнить код в блоках finally для очистки. Даже вложенные блоки try / catch / finally относительно легче отслеживать и поддерживать, чем вложенные if / else и связанные возвращаемые значения из нескольких методов.
Вывод
Если используемая вами платформа поддерживает исключения (особенно такие как Java или .NET), то вам определенно следует предположить, что нет другого способа, кроме как генерировать исключения, потому что на этих платформах есть рекомендации по созданию исключений, и ваши клиенты будут ожидать так. Если бы я использовал вашу библиотеку, я бы не стал проверять возвращаемые значения, потому что я ожидаю, что будут выданы исключения, именно таков мир на этих платформах.
Однако, если бы это был C ++, то было бы немного сложнее определить, потому что большая кодовая база уже существует с кодами возврата, а большое количество разработчиков настроено на возврат значений в отличие от исключений (например, Windows изобилует HRESULT) , Кроме того, во многих приложениях это также может быть проблемой производительности (или, по крайней мере, восприниматься как таковая).
try
/catch
существует для. Кроме того, вы можете поместить вашtry
/catch
гораздо дальше вверх по стеку в более подходящее место для его обработки (что позволяет разделить проблемы).