Комментарии 7
Странный выбор уровня "Средний" без упоминания и раскрытия тем AutoCloseable под конструкцию try-with-resources и важной темы того, что throw это сравнительно дорогостоящее действие, которое в нагруженных системах по возможности избегают, если накладные расходы в коде (громоздкость/сложность) это позволяют, например: Mono.error c throwable, которое не будет throw в реакте.
Добрый день! Статья посвящена не механизму исключений в целом, а именно архитектурному применению исключений. Про оптимизацию речь не идет. Предполагается, что читатель уже знает, что такое try-catch, что исключения - это дорогостоящие операции.
Я бы не хотел, чтобы статья была уже об известных вещах (try-catch, try-with-resources), я хочу затрагивать именно архитектурные решения.
Как вы видите начало статьи, чтобы было понятно, что статья об архитектурных решениях, и чтобы не было заблуждения, что речь пойдет просто о механизме исключений? Возможно, поможете улучшить.
В C++ исключения не такой уж и синтаксический сахар. Попробуйте в конструкторах обойтись без них. Также, исключения неудобно сочетать с многопоточностью. Как их перебрасывать между потоками?
Механизм исключений это вовсе не синтаксический сахар. И уж конечно не замена if-else.
Огромное количество ключевых слов, вводимых и обрабатываемых VM: try-catch-finally, throws, throw.
Дополнительно VM различает Exception и Error. А так же RuntimeException и его наследников, от unchecked exceptions (остальных).
Обработка исключения это затратная по времени операция, почему?
Потому, что нужно сохранить контекст для дальнейшего правильного выполнения кода, например - рассмотрите полный блок try с return в каждой ветке. Плюс нужно отложить выброс throw исключения при наличии блока finally - сначала выполнить его. А если в нем тоже throw?!
Дополнительно, нужно правильно раскрутить обратно стэк, при большом количестве вложений методов.
Я бы добавил в статью все эти детали, чтобы глубже раскрыть всю красоту и силу механизма исключений.
Добрый день!
Я специально не раскрывал тему механизма исключений, потому что это заезженная тема и доступна в любом учебнике.
Я пытался отразить в статье именно архитектурные решения. Бизнес ставит задачу, как стоит грамотно реализовывать в коде, чтобы код был прозрачен. Отмечу, про оптимизацию речь не идет. Речь идет о гибкости системы для бизнеса.
Вы в комментарии все равно не дали ответ на вопрос, почему исключения не синтаксический сахар. Вы перечислили факты об исключениях, но они вовсе не противоречат тому, что исключения похожи на синтаксический сахар с точки зрения именно самого ЯП.
Вы уходите в детали для новичков, но я хочу опираться на тех, кто уже собаку съел на исключениях, и предложить, как архитектурно можно улучшать код. Подскажите, чего вам не хватило в статье, чтобы интерпретировать, что акцент именно на архитектуре? Примеров побольше бизнесовых? Введение вводит в заблуждение?
В exceptions на самом деле ничего особо правильного и элегантного нет. Это лишь "модернизированная" форма GOTO. Причем с т.з. зрения современного программирования безнадежно устаревшая, примерно как как и UTF-16 или UTF-32
В более современных Go, Rust, Zig от exceptions отказались намеренно, заменив на монады с парой <Result>, enum <ErrorCode>, проверяемые по
switch (ErrorCode) {
case :
case :
}
По элементарной причине - при добавлении нового типа ошибки нужно получить от компилятора Warnings, что вот тут и тут нарушается контракт, у вас пропущены жестко перечисляемые секции с case и этот новый код из соответствующего enum у вас вот тут и тут не обрабатывается, допишите пожалуйста вот там и там условия для обработки, чтоб не нарушать контракты.
Классический пример: функция recv(), получения сетевых пакетов. Вот неожиданно появился новый тип errno==EGAIN на блокирующися сокетах (в Windows его нет, в Linux есть), и теперь нужно пойти все вызовы recv() перепроверить и дописать повторные обработки, т.к. это и не ошибка вовсе, а законный поток управления - нужно не падать и не плакать в лог, а просто сделать вызов еще раз.
В Java такое с проверяемыми компилятором контрактами в теории тоже было бы возможно, если бы для каждого кода ошибки делали бы свои классы исключений. Но глядя на SQLException.getErrorCode() и подобные понимаешь, что никакой элегантности там уже никогда не будет, корректность принесена в жертву обратной совместимости. Может и хотели как лучше, а получилось как всегда.
Ну и про "элегантность" NullPointerExceptions уже не одну сотню баянов порвали, эта архитектурная ошибка на миллиард обсуждалась миллионы раз.
И это мы еще про panic() и fail fast не поговорили.

Правильное использование механизма исключений