B>1. Если надо писать строки, то имхо использование Writer более наглядно, чем использование OutputStream; B>2. Я бы не кидал checked exception наружу, т.е. либо тупо логировать его, либо оборачивать в unchecked; B>3. В зависимости от задачи (в случае, когда надо писать отдельные строки) возможно изменение String[] на String ... может быть более удобным пользователю;
Что касается 1 и 3. согласен. А вот 2 -- спорный пункт. Совершенно не факт, что в данном случае с IOException'ом нужно обязательно что-то сделать. Вполне возможно, что данный writeLines -- это не единственный утилитный метод, а есть еще readLines и еще некоторое количество подобных методов, которые используются совместно в неком методе performSomeHighLevelWork, который, кстати, может сам может использовать низкоуровневое Java IO API. Поэтому, вместо того, чтобы в каждом из методов типа writeLines писать
} catch (IOException e) {
throw new IllegalStateException("Unexpected exception occured during blah-blah-blah", e);
}
может оказаться проще написать это один раз в performSomeHighLevelWork. Ну и естественно, не забыть cause.
Здравствуйте, bolshik, Вы писали:
B>>>Да, теоретически возможно, но, имхо, в данном случае преимущество обработки такой ситуации меньше, чем увеличение объема и уменьшение читабельности кода, необходимого для этого. D>>Думаю, это зависит от критичности приложения и необходимого уровня информативности возможных исключений.
B>На самом деле, я сразу не сообразил, что ошибки-то в этом нет (в случае оборачивания в unchecked; как альтернатива можно использовать логирование). Кинуть эксепшн в обоих случаях (и при write(), и при close()) не получится ==> надо выбирать что-то одно. Я выбираю вариант, когда эксепшн из close() перезатирает эксепшн из write(). Эта ситуация мне не нравится меньше, чем когда наверх летит эксепшн от write(), и остается открытый поток.
Ты же поток не закроешь, если кинешь исключение о том, что не получилось его закрыть.
Если код, например, построить таким образом:
OutputStream out = new smth.getOutputStream();
try
{
out.write( data );
}
finally
{
try
{
out.close();
}
catch( Exception ignored ){}
}
То будет выполнена попытка закрытия поток, и наверху мы получим "правильное исключение".
Ещё можно ввести флажок, а каким образом вызван блок finally: нормально или из-за исключения, и, анализируя флажок, принимать решение, подавлять исключение, возникшее при закрытии потока, или выбрасывать его наверх. Только это уже как-то мудрено получается. Я обычно использую приведёный код.
Исходный код мне импонировал больше своей лаконичностью. Хотя конечно же надо ещё смотреть на то где этот метод используется.
B> throw new IllegalStateException("Unexpected exception occured during writing to file. File: " B> + file.getAbsolutePath() + ", data to write: " + Arrays.toString(lines));
Эй, а cause? Так по логам нельзя будет восстановить причину ошибки.
Здравствуйте, bolshik, Вы писали:
B> И на текущем этапе моей девелоперской жизни я вижу только минусы checked exceptions перед unchecked.
Не согласен. Зачастую уровень, который кидает исключение, сам не может с ним справится. Самый простой и наглядный пример — открытие файла, спрятанное в вызовах и затребованное пользователем. Тут логично вынести обработку исключения поближе к пользователю.
Здравствуйте, bolshik, Вы писали:
MAP>>Что-то не понял для чего так оборачивать метод writeLinesImpl и почему не кидать IOException наерх?
B>Потому что IOException — checked exception.
А в чём проблема то? Там, наверху, в зависимости от того, что и куда пишем, сами разберутся, что с исключением делать.
По коду. Если возникло исключение во время работы методов write, то, возможно, будет исключение и при попытке закрыть поток, но так как закрытие находится в блоке finally, то исключение от попытки закрытия потока подавит "настоящее" исключение, то есть возможно потеряется истинная причина исключительной ситуации.
1. Если надо писать строки, то имхо использование Writer более наглядно, чем использование OutputStream;
2. Я бы не кидал checked exception наружу, т.е. либо тупо логировать его, либо оборачивать в unchecked;
3. В зависимости от задачи (в случае, когда надо писать отдельные строки) возможно изменение String[] на String ... может быть более удобным пользователю;
Итого:
public void writeLines(File file, String encoding, String ... lines) throws IllegalStateException {
try {
writeLinesImpl(file, encoding, lines);
} catch (IOException e) {
throw new IllegalStateException("Unexpected exception occured during writing to file. File: "
+ file.getAbsolutePath() + ", data to write: " + Arrays.toString(lines));
}
}
private void writeLinesImpl(File file, String encoding, String ... lines) throws IOException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), encoding));
try {
for (String line : lines) {
writer.write(line);
writer.newLine();
}
// writer.flush(); // implicitly called at writer.close() invocation
} finally {
writer.close();
}
}
Здравствуйте, dshe, Вы писали:
D>Что касается 1 и 3. согласен. А вот 2 -- спорный пункт. Совершенно не факт, что в данном случае с IOException'ом нужно обязательно что-то сделать. Вполне возможно, что данный writeLines -- это не единственный утилитный метод, а есть еще readLines и еще некоторое количество подобных методов, которые используются совместно в неком методе performSomeHighLevelWork, который, кстати, может сам может использовать низкоуровневое Java IO API. Поэтому, вместо того, чтобы в каждом из методов типа writeLines писать D>
D> } catch (IOException e) {
D> throw new IllegalStateException("Unexpected exception occured during blah-blah-blah", e);
D> }
D>
D>может оказаться проще написать это один раз в performSomeHighLevelWork.
Это да, лень — одно из оснвных достоинств разрабочика. Понятно, что не бывает универсального решения, которое было бы лучшим во всех ситуациях. Мое предложение относится к 'standalone method'.
Здравствуйте, Donz, Вы писали:
D>А в чём проблема то? Там, наверху, в зависимости от того, что и куда пишем, сами разберутся, что с исключением делать.
В том, что неудобно. Там, наверху, должны сами решать, хотят они обрабатывать эксепшн или не хотят (мы со своей стороны четко прописываем IllegalStateException в сигнатуре, плюс пишем джавадок, т.е. даем всю необходимую информацию). В случае же с checked exception наверху должны всегда производить обработку.
D>По коду. Если возникло исключение во время работы методов write, то, возможно, будет исключение и при попытке закрыть поток, но так как закрытие находится в блоке finally, то исключение от попытки закрытия потока подавит "настоящее" исключение, то есть возможно потеряется истинная причина исключительной ситуации.
Да, теоретически возможно, но, имхо, в данном случае преимущество обработки такой ситуации меньше, чем увеличение объема и уменьшение читабельности кода, необходимого для этого.
Здравствуйте, Donz, Вы писали:
D>Подмена IOException на IllegalStateException, ИМХО, некорректна.
А логическое обоснование можно?
D>К тому же, хотя ты и написал ниже, что объявление метода через throws тоже не нравится, но меня такой вариант, если в данном месте я не хочу ничего обрабатывать, вполне устраивает.
Да ради Бога, я ж не настаиваю, на том, что мой подход самый правильный подход™
D>>>По коду. Если возникло исключение во время работы методов write, то, возможно, будет исключение и при попытке закрыть поток, но так как закрытие находится в блоке finally, то исключение от попытки закрытия потока подавит "настоящее" исключение, то есть возможно потеряется истинная причина исключительной ситуации.
B>>Да, теоретически возможно, но, имхо, в данном случае преимущество обработки такой ситуации меньше, чем увеличение объема и уменьшение читабельности кода, необходимого для этого. D>Думаю, это зависит от критичности приложения и необходимого уровня информативности возможных исключений.
На самом деле, я сразу не сообразил, что ошибки-то в этом нет (в случае оборачивания в unchecked; как альтернатива можно использовать логирование). Кинуть эксепшн в обоих случаях (и при write(), и при close()) не получится ==> надо выбирать что-то одно. Я выбираю вариант, когда эксепшн из close() перезатирает эксепшн из write(). Эта ситуация мне не нравится меньше, чем когда наверх летит эксепшн от write(), и остается открытый поток.
Здравствуйте, bolshik, Вы писали:
B>Я ж человек ленивый, предпочитаю использовать стандартное и готовое. Но! Есть вариант, поражающий своей точностью — заводим свой unchecked CantWriteToFileException, и кидаем его в этом случае. IOException просто отдыжает
Ну в общем, я предпочитаю кинутые VM исключения сохранять приблизительно такими, какие они есть, а не создавать исключение другого класса.
К тому же, ты сам сказал выше:
Все модули общаются через строго определенный надор интерфейсов, в которых зафиксированы эксепшны, которые могут методы и указано, в каких случаях это происходит, т.е. мы можем понять, когда стоит их ловить и обрабатывать...
checked исключение в интерфейсе можно зафиксировать в отличие от unchecked. Уповать на хороший жавадок и то, что пользователь твоей библиотеки будет вдумчиво его читать, всё же не стоит.
Здравствуйте, bolshik, Вы писали:
B>Что значит '... в отличие от unchecked'? Кто-то запещает объявить в интерфейсе метод с деклацацией unchecked эксепшна во throws?
Ок, можно, но всё равно смысла нет Ни разу, кстати, не видел, чтобы кто-то объявлял unchecked исключения в интерфейсе
D>>Уповать на хороший жавадок и то, что пользователь твоей библиотеки будет вдумчиво его читать, всё же не стоит.
B>Равно как и на то, что пользователь не будет делать catch (Exception ignore) {}
В этом случае программист точно сознательно забьёт на обработку. А джавадок он может невнимательно прочитать и про объявление исключения в интерфейсе забыть.
В общем, каждый остался при своём мнении Предлагаю дискуссию закончить.
С пятницей
Согласен, весьма распространненная ошибка.
Вот даже при конфигурации log4j надо указывать не \n, а $n, иначе переводы строк будут не те и лог смотреть будет не приятно
Здравствуйте, aefimov, Вы писали:
A>Вот даже при конфигурации log4j надо указывать не \n, а $n, иначе переводы строк будут не те и лог смотреть будет не приятно
Ой, а можно чуть подробнее, гед надо указывать. Спасибо.
Здравствуйте, bolshik, Вы писали:
B>Здравствуйте, Donz, Вы писали:
D>>А в чём проблема то? Там, наверху, в зависимости от того, что и куда пишем, сами разберутся, что с исключением делать.
B>В том, что неудобно. Там, наверху, должны сами решать, хотят они обрабатывать эксепшн или не хотят (мы со своей стороны четко прописываем IllegalStateException в сигнатуре, плюс пишем джавадок, т.е. даем всю необходимую информацию). В случае же с checked exception наверху должны всегда производить обработку.
А что мешает им кинуть выше? Ведь checked на то и checked чтобы обратить внимание на то, что метод не может принять решение что делать дальше. Т.е. сами по себе checked конечно не панацея, но отказываться от них полностью — суть зло.
Я обычно руководствуюсь простыми правилами:
1. Утилитный класс или внутренняя логика — checked
2. Компонентный (например dao) — unchecked либо один большой checked
Здравствуйте, aka50, Вы писали:
A>А что мешает им кинуть выше?
Под 'наверху должны всегда производить обработку' я имел ввиду как оборачивание в try-catch, так и объявление во throws.
A>Ведь checked на то и checked чтобы обратить внимание на то, что метод не может принять решение что делать дальше.
Имхо ситауция, когда метод кидает unchecked, не означает, что метод принял решение, что делать дальше
A>Т.е. сами по себе checked конечно не панацея, но отказываться от них полностью — суть зло.
Видишь, здесь разные подходы — мне кажется, что пользователю моего класса удобнее работать, не будучи обязанным ловить какие бы то ни было эксепшны. Но при этом вся информация по поводу того, что может вылететь и в каких случаях, должна быть доступна (равно как и cause ). И на текущем этапе моей девелоперской жизни я вижу только минусы checked exceptions перед unchecked.
A>Я обычно руководствуюсь простыми правилами: A>1. Утилитный класс или внутренняя логика — checked A>2. Компонентный (например dao) — unchecked либо один большой checked
Здравствуйте, bolshik, Вы писали:
D>>А в чём проблема то? Там, наверху, в зависимости от того, что и куда пишем, сами разберутся, что с исключением делать.
B>В том, что неудобно. Там, наверху, должны сами решать, хотят они обрабатывать эксепшн или не хотят (мы со своей стороны четко прописываем IllegalStateException в сигнатуре, плюс пишем джавадок, т.е. даем всю необходимую информацию). В случае же с checked exception наверху должны всегда производить обработку.
Подмена IOException на IllegalStateException, ИМХО, некорректна. К тому же, хотя ты и написал ниже, что объявление метода через throws тоже не нравится, но меня такой вариант, если в данном месте я не хочу ничего обрабатывать, вполне устраивает.
D>>По коду. Если возникло исключение во время работы методов write, то, возможно, будет исключение и при попытке закрыть поток, но так как закрытие находится в блоке finally, то исключение от попытки закрытия потока подавит "настоящее" исключение, то есть возможно потеряется истинная причина исключительной ситуации.
B>Да, теоретически возможно, но, имхо, в данном случае преимущество обработки такой ситуации меньше, чем увеличение объема и уменьшение читабельности кода, необходимого для этого.
Думаю, это зависит от критичности приложения и необходимого уровня информативности возможных исключений.
Здравствуйте, bolshik, Вы писали:
B>Здравствуйте, aka50, Вы писали:
A>>Т.е. сами по себе checked конечно не панацея, но отказываться от них полностью — суть зло.
B>Видишь, здесь разные подходы — мне кажется, что пользователю моего класса удобнее работать, не будучи обязанным ловить какие бы то ни было эксепшны. Но при этом вся информация по поводу того, что может вылететь и в каких случаях, должна быть доступна (равно как и cause ). И на текущем этапе моей девелоперской жизни я вижу только минусы checked exceptions перед unchecked.
Дело в том, что checked обязывает перехватывать исключение, что дает определенную гарантию _осмысленной обработки_. Не зря в Runnable нету throws Exception, а в Callable есть, т.к. в случае с Callable эти ексепшины будут гарантированно будут обработаны Executor-ом а далее пользователем в методе Future#get. По этому unchecked — это для случаев неустранимых ошибок (например падение dao уровня), что согласись в случае с чтением из файла таковым не является. Принять решение "шеф все пропало" может только код выше, который знает, что за файл он читает (конфиг и тогда RuntimeException("Пепец, нету конфига")) или my.doc и тогда красивое окошечко "не хотите ли более правильно файлик показать"...
Так вот представь, что последовательность вызовов module1 -> module2 -> module3 при чем module1 — это компонентный класс. Таким образом если везде используются checked всю обработку ошибок можно сконцентрировать в module1. В случае uncheked в module1 придется обороачивать это все try { } catch (Excetpion e) throw new Module1Exception(e) и не будет ни каких шансов обработать ситуацию (т.к. module3 может бросить что угодно, не будешь же весь call graph на предмет javadoc-ов просмтаривать).
Здравствуйте, LeonidV, Вы писали:
LV>Не согласен. Зачастую уровень, который кидает исключение, сам не может с ним справится. Самый простой и наглядный пример — открытие файла, спрятанное в вызовах и затребованное пользователем. Тут логично вынести обработку исключения поближе к пользователю.
Дык пусть обрабатывает unchecked, кто ж ему мешает-то?
Здравствуйте, aka50, Вы писали:
A>Дело в том, что checked обязывает перехватывать исключение, что дает определенную гарантию _осмысленной обработки_.
Я бы сказал, что так задумывалось, но на деле мы зачастую видим catch (IOException ignore) {}.
A>Не зря в Runnable нету throws Exception, а в Callable есть, т.к. в случае с Callable эти ексепшины будут гарантированно будут обработаны Executor-ом а далее пользователем в методе Future#get.
А что, если бы в сигнатуре не было бы объявления throws Exception, в Executor'е нельзя было бы делать catch (Exception)?
A>По этому unchecked — это для случаев неустранимых ошибок (например падение dao уровня), ...
Очень спорное утверждение. По такой логике получается, что спринговский DataAccessException — вполне себе устранимый эксепшн, а какой-нить java.sql.Statement.execute() неустранимый?
A>...что согласись в случае с чтением из файла таковым не является.
Во-первых, запись, во-торых не соглашусь — все зависит от задачи
A>Принять решение "шеф все пропало" может только код выше, который знает, что за файл он читает (конфиг и тогда RuntimeException("Пепец, нету конфига")) или my.doc и тогда красивое окошечко "не хотите ли более правильно файлик показать"...
Так пусть же он принимает это решение на основании анализа checked exception'a.
A>Так вот представь, что последовательность вызовов module1 -> module2 -> module3 при чем module1 — это компонентный класс. Таким образом если везде используются checked всю обработку ошибок можно сконцентрировать в module1. В случае uncheked в module1 придется обороачивать это все try { } catch (Excetpion e) throw new Module1Exception(e)...
Вот как-то не дается мне глубина этой логики. Что есть такого у checked, что позволяет 'всю обработку ошибок сконцентрировать', а в случае unchecked 'придется обороачивать это все try { } catch (Excetpion e) throw new Module1Exception(e)'...
A>...и не будет ни каких шансов обработать ситуацию (т.к. module3 может бросить что угодно, не будешь же весь call graph на предмет javadoc-ов просмтаривать).
Module3 дурак что ли бросать все, что угодно? Все модули общаются через строго определенный надор интерфейсов, в которых зафиксированы эксепшны, которые могут методы и указано, в каких случаях это происходит, т.е. мы можем понять, когда стоит их ловить и обрабатывать...
Здравствуйте, bolshik, Вы писали:
B>Здравствуйте, aka50, Вы писали:
A>>Дело в том, что checked обязывает перехватывать исключение, что дает определенную гарантию _осмысленной обработки_. B>Я бы сказал, что так задумывалось, но на деле мы зачастую видим catch (IOException ignore) {}.
Проблемы трудностей выстрела в свою ногу — проблемы практикующих такие выстрелы.
A>>Не зря в Runnable нету throws Exception, а в Callable есть, т.к. в случае с Callable эти ексепшины будут гарантированно будут обработаны Executor-ом а далее пользователем в методе Future#get. B>А что, если бы в сигнатуре не было бы объявления throws Exception, в Executor'е нельзя было бы делать catch (Exception)?
В случае с Runnable видно: выше никого нет (разве что Thread.UncaughtExceptionHandler), а в случае с Callable интерфейс явно говорит, что ошибка будет обработана (хотя бы в виде ExecutionExeception).
A>>По этому unchecked — это для случаев неустранимых ошибок (например падение dao уровня), ... B>Очень спорное утверждение. По такой логике получается, что спринговский DataAccessException — вполне себе устранимый эксепшн, а какой-нить java.sql.Statement.execute() неустранимый?
Я, если честно, не в восторге от подхода spring-а к тотальному отказу от checked. Но с другой стороны spring обычно используется для объединения компонент. В этом случае компонент обязан сам разбираться с проблемами и бросать unchecked и узкий набор checked только в крайнем случае, т.к. во многих программах забытый unchecked скорее всtго пришибет весь поток и хорошо если это будет не main поток.
A>>Принять решение "шеф все пропало" может только код выше, который знает, что за файл он читает (конфиг и тогда RuntimeException("Пепец, нету конфига")) или my.doc и тогда красивое окошечко "не хотите ли более правильно файлик показать"... B>Так пусть же он принимает это решение на основании анализа checked exception'a.
Кто? Если writeData кинет unchecked кто будет принимать решение? Или это должен делать сам writeData. А если у нас несколько writeData, которые еще и не так просто в один загнать? Если у нас writeData зарыт в другом классе и к writeData у нас нет javadoc (если обязывать это все вести в javadoc — получим проблему с актуальностью). Тогда вопрос, почему бы не использовать возможности компилятора?
A>>Так вот представь, что последовательность вызовов module1 -> module2 -> module3 при чем module1 — это компонентный класс. Таким образом если везде используются checked всю обработку ошибок можно сконцентрировать в module1. В случае uncheked в module1 придется обороачивать это все try { } catch (Excetpion e) throw new Module1Exception(e)... B>Вот как-то не дается мне глубина этой логики. Что есть такого у checked, что позволяет 'всю обработку ошибок сконцентрировать', а в случае unchecked 'придется обороачивать это все try { } catch (Excetpion e) throw new Module1Exception(e)'...
То, что все внутренние методы будут промаркированны соответствующими ексепшонами (возможно даже иерархией, типа ProtoException <- ProtoValidationExecetpion <- ProtoMissingFieldException). В случае unckecked я должен буду проанализировать весь call graph чтобы этот ProtoMissingField аж до самого main не вылетел, когда просто забылил или не знали что такое может выскочить.
A>>...и не будет ни каких шансов обработать ситуацию (т.к. module3 может бросить что угодно, не будешь же весь call graph на предмет javadoc-ов просмтаривать). B>Module3 дурак что ли бросать все, что угодно? Все модули общаются через строго определенный надор интерфейсов, в которых зафиксированы эксепшны, которые могут методы и указано, в каких случаях это происходит, т.е. мы можем понять, когда стоит их ловить и обрабатывать...
Так и я о том же, но котролировать внутри модуля проще именно checked, т.е. все методы внутри модуля кидаются разнымими внутримодульными ексепшонами... Наверх вылетают либо "страшные" ConcurrentModification-ы которые однозначно показывают — мега проблема либо небольшой набор checked (в случае с spring они unchecked, но пользоваться unchked особо не заставляют).
Вот посуди сам, разработчик забыл перехватить IO при попытки записи в кеш неких данных, и из вызова module1.findData вылетело Module1(IOException("Can't write /tmp/2342SSDGF.dat")) О чем это скажет тому, кто пользуется module1 и может даже не подозревать что там вообще файлы используются? Правильнее будет Mudule1CacheOperationFailed("Can't write to cache file", IOExce(...)), но для того, чтобы проконтролировать все это легче использовать checked.
Здравствуйте, bolshik, Вы писали:
B>Здравствуйте, aka50, Вы писали:
A>>Дело в том, что checked обязывает перехватывать исключение, что дает определенную гарантию _осмысленной обработки_. B>Я бы сказал, что так задумывалось, но на деле мы зачастую видим catch (IOException ignore) {}.
А вообще какой-то спор не правильный... в инете полно флейма на эту тему... т.е. нужно смотреть конкретную задачу и условия, в которых пишется приложение... Архитектуру... в общем использовать или не использовать checked — "it depends".
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, bolshik, Вы писали:
D>>>Подмена IOException на IllegalStateException, ИМХО, некорректна. B>>А логическое обоснование можно?
B>Оно в API доке к классу IllegalStateException.
Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.
Нет у процесса сейчас права на запись в файл — чем не 'illegal or inappropriate time'?
B>Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.
B>Нет у процесса сейчас права на запись в файл — чем не 'illegal or inappropriate time'?
Состояние внешней среды не является состоянием "Java environment or Java application"
Здравствуйте, aka50, Вы писали:
A>Проблемы трудностей выстрела в свою ногу — проблемы практикующих такие выстрелы.
С одной стороны да, а с другой лично меня отчаянно раздражает необходимость обработки checked, которые методы стандартной библиотеки объявляют на каждый чих. Очень не хочется заставлять пользователей своего кода испытвать те же чувства.
A>В случае с Runnable видно: выше никого нет (разве что Thread.UncaughtExceptionHandler), а в случае с Callable интерфейс явно говорит, что ошибка будет обработана (хотя бы в виде ExecutionExeception).
Имхо то, что у call стоит throws Exception значит не то, что 'ошибка будет обработана', а то, что код, работающий с этим интерфейсом, должен писать обработчик Exception.
A>Я, если честно, не в восторге от подхода spring-а к тотальному отказу от checked. Но с другой стороны spring обычно используется для объединения компонент.
Ну, скажем, DataAccessException используется для объединения с субд.
A>В этом случае компонент обязан сам разбираться с проблемами и бросать unchecked и узкий набор checked только в крайнем случае, т.к. во многих программах забытый unchecked скорее всtго пришибет весь поток и хорошо если это будет не main поток.
A>Кто? Если writeData кинет unchecked кто будет принимать решение? Или это должен делать сам writeData. А если у нас несколько writeData, которые еще и не так просто в один загнать?
Как кто — вызывающий код будет принимать решение. Т.е. разработчик, когда использует метод, смотрит, какие эксепшны у него объявлены, читает джавадок и понимает, стоит или нет их обрабатывать.
A>Если у нас writeData зарыт в другом классе и к writeData у нас нет javadoc (если обязывать это все вести в javadoc — получим проблему с актуальностью). Тогда вопрос, почему бы не использовать возможности компилятора?
По такой логике джавадок вообще вредная вещь, потому что порождает проблемы с актуальностью?
A>То, что все внутренние методы будут промаркированны соответствующими ексепшонами (возможно даже иерархией, типа ProtoException <- ProtoValidationExecetpion <- ProtoMissingFieldException). В случае unckecked я должен буду проанализировать весь call graph чтобы этот ProtoMissingField аж до самого main не вылетел, когда просто забылил или не знали что такое может выскочить.
А кто мешает сделать ProtoException <- ProtoValidationExecetpion <- ProtoMissingFieldException unchecked а анализировать их только тогда, когда это действительно нужно?
A>Так и я о том же, но котролировать внутри модуля проще именно checked, т.е. все методы внутри модуля кидаются разнымими внутримодульными ексепшонами... Наверх вылетают либо "страшные" ConcurrentModification-ы которые однозначно показывают — мега проблема либо небольшой набор checked (в случае с spring они unchecked, но пользоваться unchked особо не заставляют).
A>Вот посуди сам, разработчик забыл перехватить IO при попытки записи в кеш неких данных, и из вызова module1.findData вылетело Module1(IOException("Can't write /tmp/2342SSDGF.dat")) О чем это скажет тому, кто пользуется module1 и может даже не подозревать что там вообще файлы используются? Правильнее будет Mudule1CacheOperationFailed("Can't write to cache file", IOExce(...)), но для того, чтобы проконтролировать все это легче использовать checked.
По-моему, это другая сторона той же медали, что и catch (Exception) {}. Нормальный чувак не будет писать catch (Exception) {}, и не будет же игнорировать unchecked эксепшны, объявленные во throws, а с unchecked геморроя меньше.
Здравствуйте, aka50, Вы писали:
A>А вообще какой-то спор не правильный... в инете полно флейма на эту тему... т.е. нужно смотреть конкретную задачу и условия, в которых пишется приложение... Архитектуру... в общем использовать или не использовать checked — "it depends".
Здравствуйте, Blazkowicz, Вы писали:
B>Состояние внешней среды не является состоянием "Java environment or Java application"
Почему же, можно трактовать так, что запущено джава-приложение, у которого нет прав на запись в файл, т.е. 'Java application is not in an appropriate state for the requested operation'.
Здравствуйте, bolshik, Вы писали:
B>>Состояние внешней среды не является состоянием "Java environment or Java application"
B>Почему же, можно трактовать так, что запущено джава-приложение, у которого нет прав на запись в файл, т.е. 'Java application is not in an appropriate state for the requested operation'.
Тогда таким образом можно трактовать любое исключение. Ну не вовремя ява-машина запустилась: сервер сгорел или у пользователя настроение плохое
IOException — даже само название класса исключения говорит о том, что произошла ошибка ввода/вывода, то есть надо смотреть в сторону работы с потоками.
IllegalStateException — ява-машина не готова запустить какой-либо метод или выполнить операцию из-за состояния самой ява-машины, а не внешнего состояния, как это уже сказал Blazkowicz
Здравствуйте, Donz, Вы писали:
D>Ты же поток не закроешь, если кинешь исключение о том, что не получилось его закрыть. D>Если код, например, построить таким образом: D>
D>OutputStream out = new smth.getOutputStream();
D>try
D>{
D> out.write( data );
D>}
D>finally
D>{
D> try
D> {
D> out.close();
D> }
D> catch( Exception ignored ){}
D>}
D>
D>То будет выполнена попытка закрытия поток, и наверху мы получим "правильное исключение". D>Ещё можно ввести флажок, а каким образом вызван блок finally: нормально или из-за исключения, и, анализируя флажок, принимать решение, подавлять исключение, возникшее при закрытии потока, или выбрасывать его наверх. Только это уже как-то мудрено получается. Я обычно использую приведёный код.
Да, правильно, я протупил, так все хорошо будет.
Единственно что, это как раз пример увеличения объема кода и уменьшения читабельности.
Здравствуйте, Donz, Вы писали:
D>Тогда таким образом можно трактовать любое исключение. Ну не вовремя ява-машина запустилась: сервер сгорел или у пользователя настроение плохое D>IOException — даже само название класса исключения говорит о том, что произошла ошибка ввода/вывода, то есть надо смотреть в сторону работы с потоками. D>IllegalStateException — ява-машина не готова запустить какой-либо метод или выполнить операцию из-за состояния самой ява-машины, а не внешнего состояния, как это уже сказал Blazkowicz
Да, ок, согласен, что IOException точнее указывает на то, что произошла ошибка i/o, чем ISE.
Я ж человек ленивый, предпочитаю использовать стандартное и готовое. Но! Есть вариант, поражающий своей точностью — заводим свой unchecked CantWriteToFileException, и кидаем его в этом случае. IOException просто отдыжает
Здравствуйте, bolshik, Вы писали:
B>Здравствуйте, aka50, Вы писали:
A>>В случае с Runnable видно: выше никого нет (разве что Thread.UncaughtExceptionHandler), а в случае с Callable интерфейс явно говорит, что ошибка будет обработана (хотя бы в виде ExecutionExeception).
B>Имхо то, что у call стоит throws Exception значит не то, что 'ошибка будет обработана', а то, что код, работающий с этим интерфейсом, должен писать обработчик Exception.
Что в общем-то одно и то же — принуждение к обработке. try { } catch( Exception ignore) {} — это тоже своего рода обработка.
A>>Я, если честно, не в восторге от подхода spring-а к тотальному отказу от checked. Но с другой стороны spring обычно используется для объединения компонент. B>Ну, скажем, DataAccessException используется для объединения с субд.
Это и есть иллюстрация подхода "it depends" и правила "unchecked — это критическое событие". Т.к. доступ к бд — это отдельный модуль (который еще может помимо прочего еще и прозрачно ексепшины преобразовывать). При этом DataAccessException вполне сочетается с критическим событием и как минимум сессию в web приложении полюбому грохать... При этом при ошибке sql no records found, лучше наверное возвращать пустой список или null, чем швыряться unchecked. В случае с writeFile решение о том, фатально это или нет должен принять внешний код, и чтобы не было у него сурпризов в виде uchecked их лучше сделать checked. B>По такой логике джавадок вообще вредная вещь, потому что порождает проблемы с актуальностью?
Да, т.к. это примерно то же самое, что сделать все методы Object, а уже внутри проверять. Реальные типы описывать в javadoc. Зато пользователю будет удобно можно пихать в метод что угодно...
К стати, как вариант можно делать два метода, writeAndForget() и writeData() throws IOException
Здравствуйте, aka50, Вы писали:
A>Да, т.к. это примерно то же самое, что сделать все методы Object, а уже внутри проверять. Реальные типы описывать в javadoc. Зато пользователю будет удобно можно пихать в метод что угодно...
Имел ввиду параметры методов типа doIt(Object param1, Object param2)
Поскольку имхо мы уже чутка зацикливаемся, официально заявляю, что твоя точка зрения мне понятна
Не могу с уверенностью сказать, что понятно объяснил свою
Подход к использованию checked/unchecked, при котором checked не используются, а unchecked корректно описываются в контракте метода, мне нравится больше.
Засим предлагаю завершить
Здравствуйте, Donz, Вы писали:
D>Ну в общем, я предпочитаю кинутые VM исключения сохранять приблизительно такими, какие они есть, а не создавать исключение другого класса.
Это здорово, вот если бы только исключения VM были unchecked...
D>К тому же, ты сам сказал выше:
D>
D>Все модули общаются через строго определенный надор интерфейсов, в которых зафиксированы эксепшны, которые могут методы и указано, в каких случаях это происходит, т.е. мы можем понять, когда стоит их ловить и обрабатывать...
D>checked исключение в интерфейсе можно зафиксировать в отличие от unchecked.
Что значит '... в отличие от unchecked'? Кто-то запещает объявить в интерфейсе метод с деклацацией unchecked эксепшна во throws?
D>Уповать на хороший жавадок и то, что пользователь твоей библиотеки будет вдумчиво его читать, всё же не стоит.
Равно как и на то, что пользователь не будет делать catch (Exception ignore) {}
Здравствуйте, ddocker, Вы писали:
D>аяй-яй, что же вы так тестовые задания всем интернетом решаете: http://company.yandex.ru/inside/job/dev_bugtracker.xml
Интересно, что скажут по этому обсуждению экзаменаторы из Яндекса