Здравствуйте. Зашёл спор со старшим инженером-программистом о создании своих собственных эксепшенов. Он считает, что не стоит их писать, если там не добавляешь никакой новой функциональности (по сути только название меняешь), мол, не нужно плодить лишние сущности. Я в некоторых источниках в сети видел/слышал, что нужно писать свои собственные эксепшены, а не выкидывать класс Exception или выкидывать специфический эксепшн в каком-то другом, левом слое (например, вышестоящем; как пример - выкидывать во view SQLException). Причём это говорили/писали опытные программисты. Сам я тоже согласен с ними. Пока стараюсь делать именно так.
Так как лучше делать? (в плане стиля, а также поддерживаемости и надёжности программы)
если там не добавляешь никакой новой функциональности (по сути только название меняешь), мол, не нужно плодить лишние сущности
Совет сродни экономии на переменных: с таким успехом можно делать трехэтажные цепочки вызовов, по пять вложенных циклов и прочую лабуду, чтобы сущности не плодить. Главное - поддерживать читаемость на необходимом уровне.
Но "читаемость" - понятие субъективное, поэтому даже увидев конкретный код можно только голосованием устанавливать правоту (т.е. для большинства читателей некий вариант был бы более понятным), а уж "на пальцах" никто точно не скажет, как будет лучше, ведь у каждого свои картины в сознании всплывают.
Приведу пример когда я иногда использую свои эксепшены. Есть некий бин который ищет что то в бд, но транзакцией ты управлять по каким-то причинам не можешь. Простого SQL эксепшена мне не достаточно, мне нужно точно знать что с базой. Поэтому я выделяю ошибки попыток коннекта в ResourcesNotAvailableEx, а остальные уже как критичные, когда ты не знаешь состояния системы. И потом уже их обрабатываю, могу менять логику в зависимости от ошибок
Исключения класса Exception действительно выбрасывать не надо. Исключение должно быть конкретным. В стандартной библиотеке есть исключения почти на все случаи жизни. Вот их-то и надо выбрасывать. А если подходящего нет, тогда наследовать свой вариант.
То-то и оно. Для каждого слоя или общей операции можно создать своё абстрактное исключение (абстрактное не в плане абстрактных классов в Джаве, а вообще). Или это тоже плохая практика!?
А что скажете по поводу выбрасывания специфических эксепшенов в слоях, которые вообще не связаны с объектами, которые могут выбрасывать эти эксепшены (пример я привёл выше)?
MaxLich, в вопросе выбрасывания специфических эксепшенов в слоях, которые вообще не связаны с объектами я солидарен с Джошуа Блохом, который рекомендует в статье 61 главы 9 своей книги "Java Эффективное программирование" выбрасывать исключения соответствующие абстракции.
если там не добавляешь никакой новой функциональности
Сам по себе тип исключения - это уже новая функциональность, потому что можно гибко управлять обработкой в catch-блоках. Собственно, в основном для этого специализированные классы исключений и создают. Если такого управления нет, то и делать свои классы не нужно.
Если такого управления нет, то и делать свои классы не нужно.
Инициатива должна идти от исключения, а не от обработки: если исключение может быть описано лучше, чем позволяет стандартный тип, то лучше унаследоваться и бросать более специфичный тип. А перехватывать можно (и нужно!) базовый, если большего не требуется.
Сам механизм исключений намекает на коммуникацию между слоями, которые должны быть слабо связаны. Поэтому нельзя так опрометчиво полагаться на нынешнюю логику перехватывающей стороны.
MaxLich, кмк, класс Exception бросать нельзя никогда. Но исключения должны соответствовать уровню своего появления. Довольно часто даже в стандартных библиотеках распространена ситуация, когда промежуточный слой не в силах обработать низкоуровневое исключение и оборачивает его своим, более высокоуровневым. Это вполне допустимо.
MaxLich, отталкивайтесь от логики приложения. Если причина появления проблемы одна и та же, но разные вординги, то можно воспользоваться и базовым типом. Если причины разные и эта разница важна (для выбрасывающего кода, и не важно, что там нужно "отлавливающему"), то лучше унаследоваться и подчеркнуть отличие в названии.
Но способность чувствовать баланс между читаемостью и лаконичностью - это, имхо, самый важный навык для программиста, работающего в команде.
Академически - прав ты, практически - прав твой коллега.
Если нет сложной логики управления исключниями, то и плодить их особого смысла нет.
Мне, напрмиер, за много времени своей практики, ни разу не приходилось делать что-либо в зависимости от типа исключения.
Тут больше не про специфическую обработку эксепшенов, а про абстрагирование. По идеи, для малой связности слоёв программы один слой не должен знать о том, что творится внутри другого слоя - он просто должен передавать ему какие-то команды и получать результаты этих команд. Как известно, результатов вызова команды (метода) может быть эксепшн. Вот и возникает вопрос, что кидать? Например, есть архитектура MVC. В глубинах модели есть модуль, работающий с базой данных. При ошибках в этом модуле кидаются эксепшены (SQLException, в данном случае). Вот тут и возникает вопрос, что с ними делать. Не пробрасывать же до самого верха, самого абстрактного слоя (модели, фасада). Даже если делать так, то что потом делать с этими эксепшенами в других слоях (во вью и контроллере)!?
MaxLich, это все демагогия.
Если БД наепнулась, то какая разница, какое исключение кидать? Всё равно в 90% случаев просто необходимо перехватить это исключение и показать заглушку. Ну ты можешь кинуть SQLException, дальше что? Отловишь его и кинешь RuntimeException?
Разные виды исключений нужны для ситуаций, когда у нас такой код:
Вопрос поставлен не правильно.
Свои exception это ни хорошо и не плохо.
Вопрос в другом - "Зачем?"
Какой смысл несут свои исключения.
Как только вы ответите на этот вопрос, вам будет понятно "хорошо это или плохо"
Так я и спрашиваю, насколько это плохая или хорошая практика, нужно ли так делать или не нужно. Выше товарищи уже привели некоторые доводы в пользу написания своих эксепшенов. Я придерживаюсь их мнения.
Ответ зависит от "зачем?".
Кто их будет обрабатывать?
Если вы пишите библиотеку или фреймворк, то скорее всего - да.
Т.к. исключение это один из видов "контракта".
Если же прикладная программа, то тут вопрос спорный.
Возможно уже существующие исключения вполне покрывают ваши задачи.
Тут нужно смотреть на свой проект.
Чаще всего хватает стандартных Exception, но при использовании собственных библиотек с очень узкой спецификой, стоит обзавестись собственными исключениями.
Как стоит делать?
Исключения стоит всегда отлавливать и никогда не выбрасывать просто так. Программа в исключительной ситуации должна обработать исключение и сообщить пользователю, что возникла ошибка, прервать выполнение кода с ошибкой и перевести пользователя на предыдущий экран или в область, где гарантируется стабильная работа.