checked exceptions и Java
напиши для затравки что это такое, в чем проблема, какие есть мнения и что ты сам об этом думаешь.
а что это?
Например:
Компилятор выдаст ошибку, если не написать throws IOException. Эта "фича" в Java называется checked exceptions.
void saveString(Writer writer, String string) throws IOException {
writer.write(string);
}
Проблема следующая. Если задуматься, то checked exceptions нарушают саму концепцию исключений. Они позволяют разделить уровень обрабатывающий исключения и уровень, который их генерирует. Уровень, который работает между этими двумя, не интересуется исключительными ситуациями, так как на этом уровне их все равно не понятно как обрабатывать.
checked exception - может быть хороши как идея, но плохо реализованы, т.к. программисту позволено только задавать их - о них нельзя узнать, их нельзя шаблонизировать, нельзя автоматизировать работу с ними и т.д.
Пусть есть интерфейс DataResource и есть алгоритм, который обрабатывает данные инкапсулированные в DataResource. Пусть алгоритм реализован в методе
void doSmthWithData(DataResource)
Изначально реализации DataResource предполагает, что данные хранятся в памяти, пусть реализовано в классе DataResourceMemoryImpl, т.е. схема такая: загружаем с диска в DataResourceMemoryImpl, затем выполняем алгоритм и потом сохраняем на диск.
Теперь у меня объем данных вырос, и сразу все данные грузить не целесообразно. Я пишу реализацию DataResource, которая предполагает непрерывный доступ к диску. Т.е. реализую "ленивую" загрузку. Теперь в любой методе DataResourceDiskConnectedImpl могут просходить IO операции. Мне нужно добавить в методы throws someExceptions, но тогда их нужно добавить и в исходный интерфейс DataResource. Следовательно нужно добавить в методы реализующие алгоритм, в том числе и в doSmthWithData. Потом появляется реализация DataResource, когда идет подзагрузка данных их БД. Появляются еще всякие SQLException исключения. А что если не я писал код алгоритма, и он идет как отдельный пакет. Я не могу внести все эти изменения. Да и зачем? Понятно, что исключительный ситуации в IO никак не связаны с алгоритмом. Я буду обрабытывать их на более высоком уровне кода. Получается единственный выход, это в реализациях DataResource прятать все исключения в RuntimeException (это класс исключении компилятор не требует вносить в секцию throws). Но это решение добавляет проблемы с фильтрацие исключений в моем коде на высоком уровне (где я и хочу их обрабатывать). Теперь везде, где я хочу отловить какое-то специфичесое исключения я должен ловить RuntimeException и смотреть, что за исключение спрятано подним. Если не то, что меня интересует, то делать "ресроу". Все это делает мой код грязным. Короче появляются проблемы, бороться с которыми и призван механизм исключений.
Ну, а что про Java? Может кто знает лучше способ, чтобы решеать проблемы, что я описал в предыдущем посте.
в C# этого нет, значит отцы из Microsoft тоже считают это лишним, они скорее всего продумывали это
все многочисленные языки под .NET должны будут ее поддерживатьэто почему?
они должны будут записывать в мета данные список иключений, которые может генерировать метод
Ну, а что про Java? Может кто знает лучше способ, чтобы решеать проблемыНасколько я знаю Яву, исключения, наследованные от Exception должны присутствовать в этом списке, а исключения, наследованные от Error, можно не указывать. Так что если ты будешь наследовать все свои исключения от Error, то и проблемы никакой не будет.
как раз со своими у меня меньше проблем, я иногда даже хочу, чтобы они появлялись у меня в интерфейсах
А вот подумай сам: какая польза будет пользователю интерфейса DataResource от этого SQLException?
Он ведь использует generic-интерфейс, и понятия не имеет, что у некоторой реализации внутри есть какой-то SQL.
Что он сможет сделать с SQLException, если вдруг получит его?
Только вывести на stderr, не иначе.
Я бы предложил следующий вариант: сразу определить DataResourceException, и все низкоуровневые ошибки запаковывать туда.
Так хотя бы при грамотном проектировании пользователь сможет как-нибудь более содержательно обработать ошибку.
Вообще, эмпирический факт: программы на языках, в которых есть исключения, по жизни срут ими в stderr.
Ненавижу! Они делают это, даже если автор - это я
В Java по крайней мере виден список возможных исключений, которые туда попадут.
> А что если не я писал код алгоритма, и он идет как отдельный пакет. Я не могу внести все эти изменения.
А вот эта претензия легко обобщается. И показывает на то, что имхо является охрененным неудобством
известных мне OO-языков в плане повторного использования кода.
А именно.
Пусть есть библиотека А, некоторые классы которой реализуют интерфейс IA.
И пусть есть библиотека B, которая умеет работать с объектами, реализующими некий интерфейс IB.
Интерфейсы IA и IB фунционально похожи, может быть даже эквивалентны.
Но авторы у библиотек разные, поэтому интерфейса два, просто дважды реализовали одно и то же.
Я хочу использовать библиотеку B для работы с классами из библиотеки A.
Для любого класса, реализующего IA, я легко определю потомка, реализующего IB, но
1) классов, реализующих IA, много, заимеешься для всех определять потомков
2) если у нас есть экземпляр такого класса, никакой силой его не заставить притвориться, что он умеет IB.
То есть, малой кровью заставить совместно работать две библиотеки не получится.
Или я отстал от жизни, и эта проблема уже решена в рамках ОО-подхода?
Сгенерировать адаптеры - можно даже в рантайме.
Это как?
просто наследовать код можно не только через стандартный механизм наследования, но и с помощью делегирования (или как это правильно называется, агрегирование?)
так ты все правильно уловил с проблемой в checked exceptions
Вообще-то не в этом суть была, мне не нравиться сама идея менять там код.
> А что если не я писал код алгоритма, и он идет как отдельный пакет. Я не могу внести все эти изменения.
А вот эта претензия легко обобщается. И показывает на то, что имхо является охрененным неудобством
известных мне OO-языков в плане повторного использования кода.
А именно.
А так, в Java как раз очень несложно получить исходный код из классов (ну или внести в классы изменения). В сравнении с C и x86 например.
Вообще-то эта проблема есть во всех языках, в том числе и естественных, а не только в ООП-е.
И проблема скорее терминологическая и возникает - когда мы одно и то же называем разными словами.
2. фиксируешь/специфицируешь какой наследник IB какому наследнику IA соответствует
на основе вышеприведенных утверждений генерируешь код адаптеров.
> И проблема скорее терминологическая и возникает - когда мы одно и то же называем разными словами.
Неа.
На русском языке я напишу: "далее в тексте считаем IA и IB взаимозаменяемыми понятиями".
Ну или чуть посложнее, если это не полностью одно и то же, а частично.
Почти так же просто это записывается в функциональных языках, по крайней мере без внешнего генератора.
Тут проблемав том, что все реализации ООП предпочитают не подниматься до очень высокого уровня. Зачем вводить понятия, которые редко используются и могут быть выражены чрез уже имеющиеся.
ещё ни один холивор так не завершился, хотя суть у них та же:
разная точка зрения на похожие объекты
что на функциональных языках могут писать только математики
а сгенерить код адаптера может любой индус.
"любой индус" скорее всего быстро напишет сотню обёрток, и получит премию за рекордное количество строк за месяц
> Ну или чуть посложнее, если это не полностью одно и то же, а частично.
> Почти так же просто это записывается в функциональных языках, по крайней мере без внешнего генератора.
Подскажи, пожалуйста, где можно взять функциональное описание, которое описывает эквивалентность Posix-а и WinApi.
настолько же в функциональном стиле, насколько оригинальные API
т.е. для ФЯ - это большая проблема, что и Posix, и WinApi - не ФЯ?
зы
другие концепции в этом плане обычно менее требовательны.
тогда реши свою задачу в рамках ООП на Java
Моя задача - это про Posix и WinApi?
в рамках ООП на .Net-е она уже решена.
но меня интересовало, как на ФЯ записывается сложная(нетривиальная) эквивалентность.
> в рамках ООП на .Net-е она уже решена.
Под .Net есть объектно-ориентированный fork, sigaction, poll?
Вопрос риторический: такого быть не может в силу недостаточной объектно-ориентированности Posix (и WinAPI).
> но меня интересовало, как на ФЯ записывается сложная(нетривиальная) эквивалентность
грубо говоря, библиотечная функция принимает операции в виде аргументов-функций
для описания эквивалентности (точнее, вложения) нужно реализовать требуемые операции на основе имеющихся
это в простом случае
в сложном, у библиотеки будет функториальный интерфейс, и нужно будет отобразить
один интерфейс в другой, написав функтор
как это сделать, сразу не скажу, ни разу не пользовался в практических задачах, поэтому забыл, что вычитал в книжках
К счастью, это стандартное исключение можно возбуждать без объявления.
Оставить комментарий
bastii
Давайте пофлудимПросто интересно, что народ думает о сабже.