Re[18]: Проверяемые исключения -- почему нет в C#?
От: _FRED_ Черногория
Дата: 06.08.10 11:31
Оценка:
Здравствуйте, Sinclair, Вы писали:

_FR>>Обсуждение началось с этого вот:

_FR>>

_FR>>И вот тут, если есть checked exceptions, я становлюсь обязан вписать это исключение в сигнатуру ForEach. И в сигнатуру IAction, естественно. А это — чья-то 3rd-party library, и перекомпилировать я её не могу. Тупик.


_FR>>Не тупик. Позвольте узнать, приходилось ли вам активно пользоваться фильтрами исключений?

S>Мне — нет. Я не так часто пишу на бейсике. А, собственно, какое отношение этот вопрос имеет к теме топика?

То, что вы говорите, что их применять сложно. я же сказал, что в таком случае топик напоминает обсуждения за/против "var".

S>Переход к фильтрам исключений в контексте checked exceptions — опять epic fail. Потому, что реально компилятор ничего не проверяет — нет никакой гарантии, что я своими фильтрами всё покрыл.


Проверяемые компилятором контракты исключений я в своих сообщениях нигде не упоминал. Почему на них всё сводите? То, что я вам возразил не имеет никакого отношения к тому, что вы называете "checked exceptions". И я это уже третий пост к ряду вам твержу, а вы почему-то не обращаете внимания. Ладно, не буду больше ёрничать.

Просто напомню, что я говорю просто о спецификации или даже декларации (в дукументации, например) исключений.

_FR>>По методу, который вы вызываете. Это часто бывает очень полезно, знаете ли, почитать, в каких ситуациях метод бросает исключения и какого типа эти исключения. Полезно как раз для того, что бы перехватывать то, что нужно, а не то, что вам кажется очевидным.

S>Не надо ёрничать.

И не думал. А как ещё я должен был бы донести до вас свою мысль?

S>>>Раскопать то место, в котором упомянуто про оборачивание исключений, будет весьма нетривиально.

_FR>>Как так? О чём вы? Напомню, что выглядит это обычно как табличка из двух колонок: слева тип исключения, справа — описание ситуации, которая к нему приведёт. Если это для вас "нетривиально", давайте сразу же прекратим молоть воду в ступе.
S>Не надо ёрничать.

Я вот не уличал вас ни в чём, когда вы стали рассказывать мне про отличие throw; от throw X; Откуда же мне знать, на сколько подробно мне стоит излагать свою точку зрения, что бы вам не показалось, что я "ёрничаю". Нет, на полном серьёзе. Простите пожалуйста, если не нароком оскорбил. Отвлекаться мне не хотелось.

S>Лучше подумайте головой. Вот я почитал документацию по свойству Customer.Name. Написано чётко: бросает NameNotDefined. Вы что, сёръезно полагаете, что очевидным будет также почитать документацию по *.Where?

S>Лично мне вот кажется, что это неочевидные грабли.

Конечно. Неужели кто-то сможет гарантировать, что Enumerable.Where, Queryable.Where и MyProvider.Where будут бросать строго один набор исключений и при совершенно одинаковых условиях? Вряд ли.

_FR>>Да, не редко бывает, что не почитаешь документацию и удивляешься.

_FR>>И кого же я должен считать нехорошим человеком: проектировщиков языка, которые что-то сделали не очевидное для меня или себя, не удосужевшегося сразу же залезть в документацию и узнать, как надо делать? Как вы считаете, а?
S>Всю документацию заранее не прочитаешь.

При чём здесь "заранее"? Ответьте мне, кто виноват? Я, заметьте, пытаюсь прямо отвечать на ваши вопросы, в то время, как вы подчти на кадый мой вопрос даёте уклончивый ответ в стиве "вот я сейчас скажу что-то, а ты подумай". Спасибо, это интересно конечно же, но у нас сейчас не лекция, а диалог и мне было бы намного проще, если бы я получал конкретные ответы на свои простые и односложные вопросы.

S>Вот у некоторых тут есть лейбл "эксперт", но даже это не означает, что нет мест, которые, скажем, nikov знает лучше. Смысл языка — не в брейнфаке. Пользоваться языком должно быть легко. Я написал фрагмент кода, который вы предлагаете оборудовать крайне неочевидным поведением, и при этом намекаете на то, что не читать документацию — плохо. Тем временем linq специально спроектирован так, чтобы его пользователи не были обязаны знать, во что именно разворачиваются where и order by.


Первоочередная задача проектирвания линка всё-таки не в этом, а второстепенных может быть довольно много, что бы какую-то одну выделять среди прочих. Как раз обилие документации на тему того, во чо же оно разворачивается заставляем меня усомнится в вашем выводе.

_FR>>Конечно, если всё упрощать, то можно и восе обойтись одмим единственным типом исключений и универсальным обработчиком вида Debug.Print(ex.ToString()), но это мало интересно — что бы понять мою точку зрения надо рассмотреть менее простые ситуации.

S>Я вам пытаюсь объяснить, что именно это — и есть последствия checked exceptions. Потому что честная игра по их правилам в лучшем случае сложна, в худшем — невозможна.

ОК, последние ваши слова (ниже отквочено) меня удовлетворили. Спасибо.

_FR>>Предположите, что обработать XEception из колбэка вам нужно одим образом, а тот же XException из обёртки — другим, и посмотрите, на сколько усложнится код тогда.

S>Я же вам объяснил: я не против TIE. Отсутствие checked exceptions позволяет вам, как разработчику библиотеки, принимать решение, заворачивать или не заворачивать. Если вам кажется, что пользователю захочется раздельно обрабатывать исключения — заворачивайте, жалко что ли. Но checked exceptions лишают вас возможности не заворачивать, а она — жизненно необходима. Я привёл простые примеры, где именно.

Так всё-таки получается, что в некоторых ситуациях с колбэками тупик — это именно прозрачная передача исключений вверх вместо оборачивания их. Собственно об этом я и говорил.
Help will always be given at Hogwarts to those who ask for it.
Re[16]: Проверяемые исключения -- почему нет в C#?
От: Aikin Беларусь kavaleu.ru
Дата: 06.08.10 11:55
Оценка:
Здравствуйте, Sinclair, Вы писали:

A>>На какую строчку ругаться компилятору? На обе? Или все же анализировать тип something? А если реализация IQueriable совсем не лэйзи (если это возможно)?

S>Как раз здесь всё просто. Правила проверки сигнатур с checked exceptions не оставляют места неопределённостям. Where принимает метод только с определённой сигнатурой. Если он бросает что-то не то, то компилятор будет ругаться на строчке 1.
Т.е. вариантов два:
1) аргумент Where() имеет сигнатуру "throws Nothing" и код выглядит так:
var ages = something.Where(c => {try {return c.Name == "Pete";} catch {return false;};}).Select(c => c.Age);

Неплохо так
2) аргумент Where() имеет сигнатуру throws Exception (ага!) и теперь уже нужно заворачивать в try/catch любую конструкцию с Where

S>Если же у нас будет рассогласование в сигнатурах предиката, принятого в методе Where, и сигнатуры MoveNext, то компилятор вообще не дойдет до пользовательского кода, сломавшись на MoveNext.

Вот вот! Сплошные палки в колеса.
Как вам тип: IEnumerable<T, TException>?
Или сигнатура метода (вроде ничего не напутал)?
IEnumerable<T, TException> Where<T, TException>(Func<bool, T> throws TException predicate) throws TException

Немного спасает ситуацию вывод типов который выводит TException из сигнатуры predicate.


Вопрос _FRED_: тебе какой вариант больше нравится?
1)
var ages = something.Where(c => {try {return c.Name == "Pete";} catch {return false;};}).Select(c => c.Age);

foreach(var age in ages)

или 2)
try {
var ages = something.Where(c => {return c.Name == "Pete";).Select(c => c.Age);
} catch {/* ну мы-то знаем, что Where у something ленивое! Но всё равно нужно залогировать на всякий случай */ log.Warning("something обленился лениться")};}

// где-то в далекой-далекой галактике
try {
foreach(var age in ages)
} catch {/* чё-то делаем с исключением */ };}


СУВ, Aikin
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
Re[19]: Проверяемые исключения -- почему нет в C#?
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.08.10 04:54
Оценка: +1
Здравствуйте, _FRED_, Вы писали:
_FR>То, что вы говорите, что их применять сложно. я же сказал, что в таком случае топик напоминает обсуждения за/против "var".
Я не говорю, что их применять сложно. Сами по себе — нет, не сложно. Сложно ловить одно исключение двумя способами сразу — ровно вдвое сложнее, чем одним.


_FR>Проверяемые компилятором контракты исключений я в своих сообщениях нигде не упоминал. Почему на них всё сводите? То, что я вам возразил не имеет никакого отношения к тому, что вы называете "checked exceptions". И я это уже третий пост к ряду вам твержу, а вы почему-то не обращаете внимания. Ладно, не буду больше ёрничать.

Тогда мне вообще непонятно, на что именно вы возражаете. На выхваченную из контекста фразу что ли?
_FR>Просто напомню, что я говорю просто о спецификации или даже декларации (в дукументации, например) исключений.
А я вот как раз ничего не говорю о спецификациях исключений, не проверяемых компилятором. Они не создают ни затруднений, ни улучшений.

_FR>И не думал. А как ещё я должен был бы донести до вас свою мысль?

Например, внятно её изложив. Скажем, приведя примерный алгоритм выяснения того, почему всё-таки catch не ловит того, чего нужно.

_FR>Конечно. Неужели кто-то сможет гарантировать, что Enumerable.Where, Queryable.Where и MyProvider.Where будут бросать строго один набор исключений и при совершенно одинаковых условиях? Вряд ли.

Гарантировать — нет. Но ожидать этого будет разумно. Есть принцип наименьшего удивления. К примеру, мало кто из новичков знает наизусть, как работает Enumerable Pattern в шарпе. Но вот то, что у полученного результата GetEnumerator всегда вызывается IDisposable.Dispose(), если он есть, оказывается не только приятным, но и логичным.
И так в этом паттерне всюду — куда ни ткни. Соблюдение логики и здравого смысла позволяет сэкономить на штудировании документации.

_FR>>>И кого же я должен считать нехорошим человеком: проектировщиков языка, которые что-то сделали не очевидное для меня или себя, не удосужевшегося сразу же залезть в документацию и узнать, как надо делать? Как вы считаете, а?

S>>Всю документацию заранее не прочитаешь.

_FR>При чём здесь "заранее"? Ответьте мне, кто виноват?

А, вам серъёзно интересно? Ну тогда отвечу: нехорошим человеком считать не надо никого. А вас можно считать немножко самонадеянным. В данном, конечно, случае. Вот если бы оказалось, что вы попробовали перенести опыт, полученный вами в одной части языка/среды на соседнюю их часть — и он оказался бы там неприменим, вот тогда стоило бы считать разработчиков языка/среды опрометчивыми. Так и с исключениями — почему-то когда я употребляю мой метод, бросающий MyException, в любом месте программы, всё ведёт себя корректно. Внутри foreach, while, for, if и так далее — всё работает единым образом. Но стоит употребить его справа от where — и начинаются какие-то приключения.


_FR>Первоочередная задача проектирвания линка всё-таки не в этом, а второстепенных может быть довольно много, что бы какую-то одну выделять среди прочих. Как раз обилие документации на тему того, во чо же оно разворачивается заставляем меня усомнится в вашем выводе.

Сомневаться — неотъемлемое право любого человека.


_FR>Так всё-таки получается, что в некоторых ситуациях с колбэками тупик — это именно прозрачная передача исключений вверх вместо оборачивания их. Собственно об этом я и говорил.


Нет, эта ситуация тупиком быть не может. Потому, что у вас нет компилятора, который бы требовал прозрачно передавать исключения. Вы понимаете разницу между свободным выбором и его отсутствием?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[20]: Проверяемые исключения -- почему нет в C#?
От: _FRED_ Черногория
Дата: 10.08.10 06:57
Оценка:
Здравствуйте, samius, Вы писали:

S>>>Причем здесь фильтры исключений, если при наличии checked exceptions для того чтобы скормить компилятору произвольный Action, нужно потребовать чтобы ForEach выкидывал все типы Exception? Тупик.

_FR>>Ничего не понял "checked exceptions" вообще говоря, большого влияния на данный вопрос не оказывают — чекед там компилятором или документацией не так важно.
S>Как же так? Бумага все стерпит, а компилятор — нет. Если checked компилятором, то надо ублажать компилятор, иначе нечего будет запускать. А если checked документацией — то запускаться будет как минимум.

Ну и что с того, что "будет запускаться"? Нерабочий код (код, поведение которого не соответствует документации, то есть предъявляемым требованиям) и в Африке не рабочий — не важно, не компиляется он и есть в виде исходников или запускается и ведёт себя не так, как задукументированно. От кода, который бросает неизвестно что и неизвестно когда столько же проку, как и не от компилируемого кода.

_FR>>Достаточно потребовать, что бы "ForEach" (это просто пример метода?) выкидавал только что-то типа TIE, что будет означать, что все вопросы — к колбэку.

S>кроме TIE он может еще много чего выкинуть.
_FR>>Давай, может, конкретнее, с примерчиком? в чём я не прав?
S>пусть есть ForEach, который вызвал callback, который вызвал LINQ2Obj запрос, который с callback-ами и т.п. А в тех callback-ах случилось NRE.
S>Что вылетит из ForEach-а, и как добраться до NRE? Ниужели разматывать клубок TIE?

Тут на самом деле два интересных момента. Первый: если ты оборачиваешь какое-то исключение, то делать это "тупо" попросту глупо. Надо делать это умно. Например так:

try {
  // …
} catch(MyException) {
  throw;
} catch(Exception ex) {
  throw new MyException(ex.Message, ex);
}//try


Тогда подобных траблов не будет. Второе (если приходится работать с кодом, который ведёт себя "тупо"): вместо InnerException достаточно ориентироватся на Exception::GetBaseException().
Help will always be given at Hogwarts to those who ask for it.
Re[21]: Проверяемые исключения -- почему нет в C#?
От: samius Япония http://sams-tricks.blogspot.com
Дата: 10.08.10 08:08
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, samius, Вы писали:


S>>Как же так? Бумага все стерпит, а компилятор — нет. Если checked компилятором, то надо ублажать компилятор, иначе нечего будет запускать. А если checked документацией — то запускаться будет как минимум.


_FR>Ну и что с того, что "будет запускаться"? Нерабочий код (код, поведение которого не соответствует документации, то есть предъявляемым требованиям) и в Африке не рабочий — не важно, не компиляется он и есть в виде исходников или запускается и ведёт себя не так, как задукументированно. От кода, который бросает неизвестно что и неизвестно когда столько же проку, как и не от компилируемого кода.


Спорно. Скомпилированный код может работать при некотором стечении обстоятельств, в отличии от того, который не скомпилировался. Да и то что он скомпилировался, еще не означает что он ведет себя не так как задокументировано, либо будет когда-нибудь задокументировано (а возможно никогда).

_FR>>>Достаточно потребовать, что бы "ForEach" (это просто пример метода?) выкидавал только что-то типа TIE, что будет означать, что все вопросы — к колбэку.

S>>кроме TIE он может еще много чего выкинуть.
_FR>>>Давай, может, конкретнее, с примерчиком? в чём я не прав?
S>>пусть есть ForEach, который вызвал callback, который вызвал LINQ2Obj запрос, который с callback-ами и т.п. А в тех callback-ах случилось NRE.
S>>Что вылетит из ForEach-а, и как добраться до NRE? Ниужели разматывать клубок TIE?

_FR>Тут на самом деле два интересных момента. Первый: если ты оборачиваешь какое-то исключение, то делать это "тупо" попросту глупо. Надо делать это умно. Например так:


_FR>
_FR>try {
_FR>  // …
_FR>} catch(MyException) {
_FR>  throw;
_FR>} catch(Exception ex) {
_FR>  throw new MyException(ex.Message, ex);
_FR>}//try
_FR>


А как будет "тупо"?

_FR>Тогда подобных траблов не будет. Второе (если приходится работать с кодом, который ведёт себя "тупо"): вместо InnerException достаточно ориентироватся на Exception::GetBaseException().


Ой-ой-ой... Есть риск найти что-нибудь неспецифицированное но обернутое для соответствия документации.
Пример. Читаем данные из системы транспорта, которая если что не так, кидает TransportException (специфицировано). Ну и вот, GetBaseException вытянет из клубка SocketException, который не соответствует НИЧЕМУ. Что с ним делать дальше?
Re[22]: Проверяемые исключения -- почему нет в C#?
От: _FRED_ Черногория
Дата: 10.08.10 08:56
Оценка:
Здравствуйте, samius, Вы писали:

S>>>Как же так? Бумага все стерпит, а компилятор — нет. Если checked компилятором, то надо ублажать компилятор, иначе нечего будет запускать. А если checked документацией — то запускаться будет как минимум.

_FR>>Ну и что с того, что "будет запускаться"? Нерабочий код (код, поведение которого не соответствует документации, то есть предъявляемым требованиям) и в Африке не рабочий — не важно, не компиляется он и есть в виде исходников или запускается и ведёт себя не так, как задукументированно. От кода, который бросает неизвестно что и неизвестно когда столько же проку, как и не от компилируемого кода.

S>Спорно. Скомпилированный код может работать при некотором стечении обстоятельств, в отличии от того, который не скомпилировался. Да и то что он скомпилировался, еще не означает что он ведет себя не так как задокументировано, либо будет когда-нибудь задокументировано (а возможно никогда).


Нить рассуждений не утеряна? В чем спор-то? В том, что иногда какой-то скомпилированный код как-то будет работать я не сомневаюсь. Так можно сказать вообще о 100 процентах всего скомпилированного кода. А толку то что? А нарушение неким кодом его, кода, спецификации, делает его нерабочим в некотором другом смысле. Если не видно разницы, продолжать не интересно.

_FR>>>>Достаточно потребовать, что бы "ForEach" (это просто пример метода?) выкидавал только что-то типа TIE, что будет означать, что все вопросы — к колбэку.

S>>>кроме TIE он может еще много чего выкинуть.
_FR>>>>Давай, может, конкретнее, с примерчиком? в чём я не прав?
S>>>пусть есть ForEach, который вызвал callback, который вызвал LINQ2Obj запрос, который с callback-ами и т.п. А в тех callback-ах случилось NRE.
S>>>Что вылетит из ForEach-а, и как добраться до NRE? Ниужели разматывать клубок TIE?
_FR>>Тут на самом деле два интересных момента. Первый: если ты оборачиваешь какое-то исключение, то делать это "тупо" попросту глупо. Надо делать это умно. Например так:
_FR>>try {
_FR>>  // …
_FR>>} catch(MyException) {
_FR>>  throw;
_FR>>} catch(Exception ex) {
_FR>>  throw new MyException(ex.Message, ex);
_FR>>}//try


S>А как будет "тупо"?


_FR>>try {
_FR>>  // …
_FR>>// } catch(MyException) {
_FR>>//   throw;
_FR>>} catch(Exception ex) {
_FR>>  throw new MyException(ex.Message, ex);
_FR>>}//try


_FR>>Тогда подобных траблов не будет. Второе (если приходится работать с кодом, который ведёт себя "тупо"): вместо InnerException достаточно ориентироватся на Exception::GetBaseException().


S>Ой-ой-ой... Есть риск найти что-нибудь неспецифицированное но обернутое для соответствия документации.


Конечно, когда код работает с исключениями как попало (оборачивает всё подряд, не видит разницы между wrap и replace) будет бедлам. В передачи исключений между слоями должен быть порядок. В противном случае единственно возможный сценарий обработки исключения: это логирование и вне зависимости от вида исклюения вывод о том, что "всё пропало, шеф, всё пропало" и сделать более точной обработки попросту нельзя. В таком случае вся иерархия исключений не нужна совсем.

S>Пример. Читаем данные из системы транспорта, которая если что не так, кидает TransportException (специфицировано). Ну и вот, GetBaseException вытянет из клубка SocketException, который не соответствует НИЧЕМУ. Что с ним делать дальше?


Что значит "не соответствует НИЧЕМУ" А как, почему и что необходимо обрабатывать? Мне очень сложно давать коментарии по поводу имеющегося в сознании собеседника кода, не зная, какие у него там ещё сложности есть помимо показанного. Пожалуй, в дальнейшем и не беду. Если есть желание что-то пообсуждать, надо видеть что есть и какие есть средства, а обрабатывать сферические исключения можно любым конём
Help will always be given at Hogwarts to those who ask for it.
Re[23]: Проверяемые исключения -- почему нет в C#?
От: samius Япония http://sams-tricks.blogspot.com
Дата: 10.08.10 09:13
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, samius, Вы писали:


_FR>>>Ну и что с того, что "будет запускаться"? Нерабочий код (код, поведение которого не соответствует документации, то есть предъявляемым требованиям) и в Африке не рабочий — не важно, не компиляется он и есть в виде исходников или запускается и ведёт себя не так, как задукументированно. От кода, который бросает неизвестно что и неизвестно когда столько же проку, как и не от компилируемого кода.


S>>Спорно. Скомпилированный код может работать при некотором стечении обстоятельств, в отличии от того, который не скомпилировался. Да и то что он скомпилировался, еще не означает что он ведет себя не так как задокументировано, либо будет когда-нибудь задокументировано (а возможно никогда).


_FR>Нить рассуждений не утеряна? В чем спор-то?

Какая там нить? Спорю с конкретной фразой, которую я выделил. Продолжать не собираюсь.

_FR>>>>>Достаточно потребовать, что бы "ForEach" (это просто пример метода?) выкидавал только что-то типа TIE, что будет означать, что все вопросы — к колбэку.

S>>>>кроме TIE он может еще много чего выкинуть.
_FR>>>>>Давай, может, конкретнее, с примерчиком? в чём я не прав?
S>>>>пусть есть ForEach, который вызвал callback, который вызвал LINQ2Obj запрос, который с callback-ами и т.п. А в тех callback-ах случилось NRE.
S>>>>Что вылетит из ForEach-а, и как добраться до NRE? Ниужели разматывать клубок TIE?
_FR>>>Тут на самом деле два интересных момента. Первый: если ты оборачиваешь какое-то исключение, то делать это "тупо" попросту глупо. Надо делать это умно. Например так:
_FR>
_FR>>>try {
_FR>>>  // …
_FR>>>} catch(MyException) {
_FR>>>  throw;
_FR>>>} catch(Exception ex) {
_FR>>>  throw new MyException(ex.Message, ex);
_FR>>>}//try
_FR>


S>>А как будет "тупо"?


_FR>
_FR>>>try {
_FR>>>  // …
_FR>>>// } catch(MyException) {
_FR>>>//   throw;
_FR>>>} catch(Exception ex) {
_FR>>>  throw new MyException(ex.Message, ex);
_FR>>>}//try
_FR>


Я так понимаю, что ты предлагаешь выстреленный однажды TIE больше не заворачивать? Но что делать, если в спецификации метода, который его ловит, нет TIE? Он должен его обернуть. Как иначе? В свою очередь, когда этот метод используется в неком выражении в качестве callback-а, выражение может выкинуть TIE. И т.п.
"Тупо" заворачивай, или "не тупо", а цепочка будет следующая
TIE -> SomeE -> TIE -> AnotherE ...

_FR>>>Тогда подобных траблов не будет. Второе (если приходится работать с кодом, который ведёт себя "тупо"): вместо InnerException достаточно ориентироватся на Exception::GetBaseException().


S>>Ой-ой-ой... Есть риск найти что-нибудь неспецифицированное но обернутое для соответствия документации.


_FR>Конечно, когда код работает с исключениями как попало (оборачивает всё подряд, не видит разницы между wrap и replace) будет бедлам. В передачи исключений между слоями должен быть порядок. В противном случае единственно возможный сценарий обработки исключения: это логирование и вне зависимости от вида исклюения вывод о том, что "всё пропало, шеф, всё пропало" и сделать более точной обработки попросту нельзя. В таком случае вся иерархия исключений не нужна совсем.


S>>Пример. Читаем данные из системы транспорта, которая если что не так, кидает TransportException (специфицировано). Ну и вот, GetBaseException вытянет из клубка SocketException, который не соответствует НИЧЕМУ. Что с ним делать дальше?


_FR>Что значит "не соответствует НИЧЕМУ" А как, почему и что необходимо обрабатывать? Мне очень сложно давать коментарии по поводу имеющегося в сознании собеседника кода, не зная, какие у него там ещё сложности есть помимо показанного. Пожалуй, в дальнейшем и не беду. Если есть желание что-то пообсуждать, надо видеть что есть и какие есть средства, а обрабатывать сферические исключения можно любым конём


Пообсуждать желания нет. Я лишь хотел показать, что GetBaseException может вытащить непойми что, с которым неизвестно что делать. В сознании у меня была абстрактная система, в спецификации которой указано что она может выкинуть некий TransportException, в то время как конкретные реализации транспорта оборачивают свои специфичные исключения типа SocketException, RemotingTransportException и т.п. в вышеозначенный TransportException. Тот кто вызовет GetBaseException получит исключение, с которым он не будет знать что делать. Ну а если будет — то это будет нарушением LSP.
Re[24]: Проверяемые исключения -- почему нет в C#?
От: _FRED_ Черногория
Дата: 10.08.10 09:37
Оценка:
Здравствуйте, samius, Вы писали:

_FR>>>>Ну и что с того, что "будет запускаться"? Нерабочий код (код, поведение которого не соответствует документации, то есть предъявляемым требованиям) и в Африке не рабочий — не важно, не компиляется он и есть в виде исходников или запускается и ведёт себя не так, как задукументированно. От кода, который бросает неизвестно что и неизвестно когда столько же проку, как и не от компилируемого кода.

S>>>Спорно. Скомпилированный код может работать при некотором стечении обстоятельств, в отличии от того, который не скомпилировался. Да и то что он скомпилировался, еще не означает что он ведет себя не так как задокументировано, либо будет когда-нибудь задокументировано (а возможно никогда).
_FR>>Нить рассуждений не утеряна? В чем спор-то?
S>Какая там нить? Спорю с конкретной фразой, которую я выделил. Продолжать не собираюсь.

А разницу между "работает" и "при некотором стечении обстоятельств" неужели я должен объяснять? Как известно "при некотором стечении обстоятельств" и незаряженная пушка раз в год выстреливает

S>Я так понимаю, что ты предлагаешь выстреленный однажды TIE больше не заворачивать?


Что бы что-то предлагать, нужно знать детали проблемы. А я же говорю, что врапятся исключения так, как я показал, если нету разумных доводов к тому, что бы врапить самого себя. Я таких "разумных" доводов в настоящий момент припомнит или придумать не могу.

S>Но что делать, если в спецификации метода, который его ловит, нет TIE? Он должен его обернуть. Как иначе? В свою очередь, когда этот метод используется в неком выражении в качестве callback-а, выражение может выкинуть TIE. И т.п.

S>"Тупо" заворачивай, или "не тупо", а цепочка будет следующая
S>TIE -> SomeE -> TIE -> AnotherE ...

Во-первых, мне не ясно, что мешает "раскрывать" TIE перед тем, как заврапить его. В данном случае TIE не не сёт сам по себе никакой информации, это маркер того, что исключение брошено внешним кодом. Коду выше по стеку (чем метод, который вызывает метод с колбэком) понятия не имеет о колбэках (скорее всего) и знать ему о них не нужно.

Во-вторых, действительно ли разумно можно обработать на самом верху в показанной цепочке самое первоначальное исключение? Возможно, в такой ситуации было бы разумно оборачивать колбэк. Вариантов того, как можно сделать очень много и без видения "поля боя" обсуждать все _детали_ бесперспективно.

_FR>>Что значит "не соответствует НИЧЕМУ" А как, почему и что необходимо обрабатывать? Мне очень сложно давать коментарии по поводу имеющегося в сознании собеседника кода, не зная, какие у него там ещё сложности есть помимо показанного. Пожалуй, в дальнейшем и не беду. Если есть желание что-то пообсуждать, надо видеть что есть и какие есть средства, а обрабатывать сферические исключения можно любым конём


S>Пообсуждать желания нет. Я лишь хотел показать, что GetBaseException может вытащить непойми что, с которым неизвестно что делать.


Конечно может. Это зависит от того, как принято в той или иной системе обрабатывать исключения. Когда система работает "тупо", либо передавая прозрачно всё что случилось наверх или опять же "тупо" заворачивая всё без разбору, в некоторых случаях работа с такой системой будет очень простой, не просить каши и не перегревать мозги. Но такая система не будет "полной", потому что не позволяет дать ответа на любой вопрос, не позволяет адекватно отреагировать на любое проишествие. Это опять к слову о "может работать при некотором стечении обстоятельств". Я не люблю пологаться на неподконтрольное мне "стечение", да ещё и на "некоторое".

S>В сознании у меня была абстрактная система, в спецификации которой указано что она может выкинуть некий TransportException, в то время как конкретные реализации транспорта оборачивают свои специфичные исключения типа SocketException, RemotingTransportException и т.п. в вышеозначенный TransportException. Тот кто вызовет GetBaseException получит исключение, с которым он не будет знать что делать. Ну а если будет — то это будет нарушением LSP.


Тут ни слова о колбэках, поэтому что ответить на такое в контексте данного обсуждения я даже не знаю Пример GetBaseException я дал для конкретного сценария. Сейчас якобы читаю этот сценарий, но не нахожу связи с тем, на что я отвечал, когда

пусть есть ForEach, который вызвал callback, который вызвал LINQ2Obj запрос, который с callback-ами и т.п. А в тех callback-ах случилось NRE.

Я очень боюсь за других строить связи между кажущимися мне несвязанными "задачами".
Help will always be given at Hogwarts to those who ask for it.
Re[25]: Проверяемые исключения -- почему нет в C#?
От: samius Япония http://sams-tricks.blogspot.com
Дата: 10.08.10 10:00
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, samius, Вы писали:


S>>Какая там нить? Спорю с конкретной фразой, которую я выделил. Продолжать не собираюсь.


_FR>А разницу между "работает" и "при некотором стечении обстоятельств" неужели я должен объяснять? Как известно "при некотором стечении обстоятельств" и незаряженная пушка раз в год выстреливает

Не должен. Я спорю с утвреждением что нескомпилированный код == код, бросающий что попало.

S>>Я так понимаю, что ты предлагаешь выстреленный однажды TIE больше не заворачивать?


_FR>Что бы что-то предлагать, нужно знать детали проблемы. А я же говорю, что врапятся исключения так, как я показал, если нету разумных доводов к тому, что бы врапить самого себя. Я таких "разумных" доводов в настоящий момент припомнит или придумать не могу.


Я не предлагал врапить самого себя.

S>>Но что делать, если в спецификации метода, который его ловит, нет TIE? Он должен его обернуть. Как иначе? В свою очередь, когда этот метод используется в неком выражении в качестве callback-а, выражение может выкинуть TIE. И т.п.

S>>"Тупо" заворачивай, или "не тупо", а цепочка будет следующая
S>>TIE -> SomeE -> TIE -> AnotherE ...

_FR>Во-первых, мне не ясно, что мешает "раскрывать" TIE перед тем, как заврапить его. В данном случае TIE не не сёт сам по себе никакой информации, это маркер того, что исключение брошено внешним кодом. Коду выше по стеку (чем метод, который вызывает метод с колбэком) понятия не имеет о колбэках (скорее всего) и знать ему о них не нужно.


Ну дак надо ж ПИСАТЬ! Притом что TIE не несет сам по себе никакой информации ни в этом, ни в других случаях. Это такой Special Case очень не по месту. Маркер можно было прикрутить любым другим способом. У каждого исключения есть хэштаблица — хоть туда сунуть.

_FR>Во-вторых, действительно ли разумно можно обработать на самом верху в показанной цепочке самое первоначальное исключение? Возможно, в такой ситуации было бы разумно оборачивать колбэк. Вариантов того, как можно сделать очень много и без видения "поля боя" обсуждать все _детали_ бесперспективно.


Можно ли как-то разумно обработать TIE кроме его разворачивания или заворачивания?

S>>Пообсуждать желания нет. Я лишь хотел показать, что GetBaseException может вытащить непойми что, с которым неизвестно что делать.


S>>В сознании у меня была абстрактная система, в спецификации которой указано что она может выкинуть некий TransportException, в то время как конкретные реализации транспорта оборачивают свои специфичные исключения типа SocketException, RemotingTransportException и т.п. в вышеозначенный TransportException. Тот кто вызовет GetBaseException получит исключение, с которым он не будет знать что делать. Ну а если будет — то это будет нарушением LSP.


_FR>Тут ни слова о колбэках, поэтому что ответить на такое в контексте данного обсуждения я даже не знаю Пример GetBaseException я дал для конкретного сценария. Сейчас якобы читаю этот сценарий, но не нахожу связи с тем, на что я отвечал, когда

_FR>

_FR>пусть есть ForEach, который вызвал callback, который вызвал LINQ2Obj запрос, который с callback-ами и т.п. А в тех callback-ах случилось NRE.

_FR>Я очень боюсь за других строить связи между кажущимися мне несвязанными "задачами".

калбэки подразумевались в контексте. Они должны были читать данные, достающиеся из абстрактного транспорта. GetBaseException в таком случае не помог бы принять решение без нарушения LSP.

Разворачивание TIE проблему решает, но разворачивание не вставить в лямбду.
Re[26]: Проверяемые исключения -- почему нет в C#?
От: _FRED_ Черногория
Дата: 10.08.10 10:47
Оценка:
Здравствуйте, samius, Вы писали:

S>>>Какая там нить? Спорю с конкретной фразой, которую я выделил. Продолжать не собираюсь.

_FR>>А разницу между "работает" и "при некотором стечении обстоятельств" неужели я должен объяснять? Как известно "при некотором стечении обстоятельств" и незаряженная пушка раз в год выстреливает
S>Не должен. Я спорю с утвреждением что нескомпилированный код == код, бросающий что попало.

А я конкретно такого нигде и не утверждал

S>>>Я так понимаю, что ты предлагаешь выстреленный однажды TIE больше не заворачивать?


_FR>>Что бы что-то предлагать, нужно знать детали проблемы. А я же говорю, что врапятся исключения так, как я показал, если нету разумных доводов к тому, что бы врапить самого себя. Я таких "разумных" доводов в настоящий момент припомнит или придумать не могу.


S>Я не предлагал врапить самого себя.


А я этого нигде не утверждал Я обсуждал конкретный пример "тупой" обёртки исключений. Показал, как он отвечает на слова:

пусть есть ForEach, который вызвал callback, который вызвал LINQ2Obj запрос, который с callback-ами и т.п. А в тех callback-ах случилось NRE.
Что вылетит из ForEach-а, и как добраться до NRE? Ниужели разматывать клубок TIE?


Я вот не понимаю: что-то конкретное хочется выяснить или есть желание попридераться к словам? Тогда так и надо говорить? хочу попридераться к словам "этим", "этим" и "этим", потому что… и достаточно подробное объяснение, которое не требовало бы дополнительный уточнений. А то иначе смотрите что получается: начали с двух абзацев, а во что превратилось Я могу написать робота, который будет каждое слово в ответе мне квотить, что-то в ответ этому слову дописывать и ждать, "что скажут", затем могу опубликовать робота, что бы каждый так мог так же поступать. И кому от этого будет лучше? а что станет понятного в нашей дискуссии от того, что кто-то сказал "Я не предлагал врапить самого себя." Проиблизимся ли мы к какой либо цели или подобные реплики лишь добавляют энтропии? А нужна ли тут энтропия?

S>>>Но что делать, если в спецификации метода, который его ловит, нет TIE? Он должен его обернуть. Как иначе? В свою очередь, когда этот метод используется в неком выражении в качестве callback-а, выражение может выкинуть TIE. И т.п.

S>>>"Тупо" заворачивай, или "не тупо", а цепочка будет следующая
S>>>TIE -> SomeE -> TIE -> AnotherE ...
_FR>>Во-первых, мне не ясно, что мешает "раскрывать" TIE перед тем, как заврапить его. В данном случае TIE не не сёт сам по себе никакой информации, это маркер того, что исключение брошено внешним кодом. Коду выше по стеку (чем метод, который вызывает метод с колбэком) понятия не имеет о колбэках (скорее всего) и знать ему о них не нужно.
S>Ну дак надо ж ПИСАТЬ! Притом что TIE не несет сам по себе никакой информации ни в этом, ни в других случаях. Это такой Special Case очень не по месту. Маркер можно было прикрутить любым другим способом. У каждого исключения есть хэштаблица — хоть туда сунуть.

Мне вот не понятно реплика про "Ну дак надо ж ПИСАТЬ!" Она означает, что "надо будет писать больше кода" или что-то другое? Зачем заставлять собеседника _догадываться_ о том, что вы имеете в виду Почему нельзя прямо говорить, а всё на окольности тянет

S>Маркер можно было прикрутить любым другим способом. У каждого исключения есть хэштаблица — хоть туда сунуть.


Покажите, как после этого можно было бы работать с такими маркерами? А в случае, когда у вас есть кто-то в цепочке вызовов, который что-оборачивает помимо вашей воли, как быть? Как попросить его обернуть хэштаблицу?

С оборачиваниями можно использовать такой вот код:

Action action = delegate { throw new FileNotFoundException(); };
try {
  M(action);
} catch(CallbackException ex) {
  if(ex is ICallbackException<IOException>) {
    // Разбираем любой IOException, в том числе и наш FileNotFoundException
  } else {
    throw;
  }//if
}//try


Да, в шрпе это не так элегантно, как можно было бы сделать на Немерле, но что мы обсуждаем: неправильность подхода или нецелесообразность его применения в силу ограниченности инструментальный средств?

_FR>>Во-вторых, действительно ли разумно можно обработать на самом верху в показанной цепочке самое первоначальное исключение? Возможно, в такой ситуации было бы разумно оборачивать колбэк. Вариантов того, как можно сделать очень много и без видения "поля боя" обсуждать все _детали_ бесперспективно.


S>Можно ли как-то разумно обработать TIE кроме его разворачивания или заворачивания?


Конечно. Ну что это за мода спорить таким образом: ну представьте себе что ли, что вам самому задали подобный вопрос. Неужели вы бы не придумали ни одного ответа? Ни одного? А вы посмотрите, почитайте как в обсуждениях выше Синклер "перехватывал" (предлагал) и "обрабатывал" FileNotFound — по вашему, там подразумевалась "разумная" обработка или нет? Там вполне "разумной" обработкой называлось логирование. Этот ответ вас устроит?

S>>>Пообсуждать желания нет. Я лишь хотел показать, что GetBaseException может вытащить непойми что, с которым неизвестно что делать.

S>>>В сознании у меня была абстрактная система, в спецификации которой указано что она может выкинуть некий TransportException, в то время как конкретные реализации транспорта оборачивают свои специфичные исключения типа SocketException, RemotingTransportException и т.п. в вышеозначенный TransportException. Тот кто вызовет GetBaseException получит исключение, с которым он не будет знать что делать. Ну а если будет — то это будет нарушением LSP.

_FR>>Тут ни слова о колбэках, поэтому что ответить на такое в контексте данного обсуждения я даже не знаю Пример GetBaseException я дал для конкретного сценария. Сейчас якобы читаю этот сценарий, но не нахожу связи с тем, на что я отвечал, когда

_FR>>

_FR>>пусть есть ForEach, который вызвал callback, который вызвал LINQ2Obj запрос, который с callback-ами и т.п. А в тех callback-ах случилось NRE.

_FR>>Я очень боюсь за других строить связи между кажущимися мне несвязанными "задачами".
S>калбэки подразумевались в контексте. Они должны были читать данные, достающиеся из абстрактного транспорта. GetBaseException в таком случае не помог бы принять решение без нарушения LSP.
S>Разворачивание TIE проблему решает, но разворачивание не вставить в лямбду.

Ну вот видите, оказывается я должен был догадаться о том, что "подразумевалось в контексте" №вашего сознания№.Спасибо, но подобными талантами я не обладаю. Ведь даже после того, как я попросил ясно изложить проблемы вы не смогли это сделать без того, что бы не сказать, что и где подразумевается. Поэтому я и говорю, что мне сложно что либо сказать, не видя примера кода, по поводу которого меня просят высказаться.
Help will always be given at Hogwarts to those who ask for it.
Re[27]: Проверяемые исключения -- почему нет в C#?
От: samius Япония http://sams-tricks.blogspot.com
Дата: 10.08.10 14:09
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Я вот не понимаю: что-то конкретное хочется выяснить или есть желание попридераться к словам? Тогда так и надо говорить? хочу попридераться к словам "этим", "этим" и "этим", потому что… и достаточно подробное объяснение, которое не требовало бы дополнительный уточнений.


Выяснить — нет. Конечно было бы любопытно что-нибудь внезапное выяснить, но т.к. не могу сказать что, то и назвать цель данного дискасса выяснением я не могу. Придираться к словам — нет, не самоцель. Пытался привести обсуждение к опровержению некоторых твоих высказываний, но...

_FR>А то иначе смотрите что получается: начали с двух абзацев, а во что превратилось Я могу написать робота ...


... результат действительно удручает.

_FR>а что станет понятного в нашей дискуссии от того, что кто-то сказал "Я не предлагал врапить самого себя." Проиблизимся ли мы к какой либо цели или подобные реплики лишь добавляют энтропии? А нужна ли тут энтропия?


Ты не понял меня, я не понял тебя, попытался догадаться что ты мне хотел сказать и ответил на догадку.

На остальные реплики я предпочту не отвечать, т.к. отмечаю некоторый "накал" и даже переход на "вы". Уверяю, у меня нет цели засчитывать слив или доказать что-либо ценой ухудшения взаимовпечатлений (слово отношения я уж не стал употреблять).

Потому хочу принести извинения за то что пришлось догадываться о подразумеваемых мной вещах (не думал что выражаюсь неясно. перечитал — да, так и есть). И предлагаю завершить нашу дискуссию мирным путем. Акцент на слове "завершить", потому как продолжать в таком духе не стоит.
Re[28]: Проверяемые исключения -- почему нет в C#?
От: _FRED_ Черногория
Дата: 10.08.10 14:37
Оценка:
Здравствуйте, samius, Вы писали:

_FR>>а что станет понятного в нашей дискуссии от того, что кто-то сказал "Я не предлагал врапить самого себя." Проиблизимся ли мы к какой либо цели или подобные реплики лишь добавляют энтропии? А нужна ли тут энтропия?


S>Ты не понял меня, я не понял тебя, попытался догадаться что ты мне хотел сказать и ответил на догадку.


Ну а действительно зачем строить догадки, когда ожно спросить "Что имелось в виду"?

S>На остальные реплики я предпочту не отвечать, т.к. отмечаю некоторый "накал" и даже переход на "вы".


Ну это тоже Синклер виноват — стал меня на "вы" называть, а я стал просто всем "выкать" безо всякого накала, в качесве более вежливого обращения не имея ничего дурного в мыслях. Честно — можно посмотреть любые мои последние сообщения. В "вы" нет ничего личного.

S>Уверяю, у меня нет цели засчитывать слив или доказать что-либо ценой ухудшения взаимовпечатлений (слово отношения я уж не стал употреблять).

S>Потому хочу принести извинения за то что пришлось догадываться о подразумеваемых мной вещах (не думал что выражаюсь неясно. перечитал — да, так и есть).

Если уж кому и следует извиниться, то мне — не сдержан-то я, сам вижу, но пытаюсь как могу объяснить, что ведение дискуссии по тому пути, которым она идёт, бесполезно. Синклер отвечает на мои вопросы более чем загадочно, а ты переключаешь всё внимание на несущественные детали. которые могут быть истолкованы по разному и прямого отношения к обсуждаемой теме не имеют. Да ещё и "примеры ситцаций" всё изменяются и изменяются и как они связаны с тем, что было в прошлом сообщении — для меня не очевидно.

S>И предлагаю завершить нашу дискуссию мирным путем. Акцент на слове "завершить", потому как продолжать в таком духе не стоит.


Ну а раз так, смотри о чём речь. Простые постулаты, из которых я исходил, в этом вот месте:

"checked exceptions" вообще говоря, большого влияния на данный вопрос не оказывают — чекед там компилятором или документацией не так важно.


1. Метод должен задекларировать выбрасываемые им исклюения так же, как он декларирует возвращаемое значение или допустимые значения параметров.
2. Если задекларированное поведение отличается от действительного, то метод не является рабочим, то есть поведение метода становится непредсказуемым и ещё не ясно, что "опаснее" — не компилдирующийся метод или сктмпилированный, но ведущий себя неизвестно как.

Но между проверяемыми компилятором исключениями и декларируемыми исключениями есть разница. Например в том, что документации можно сказать "этот метод бросает A, Б и всё, что вылетит из из колбэка" там, где это удобно (но это не везде удобно).
Help will always be given at Hogwarts to those who ask for it.
Re[29]: Проверяемые исключения -- почему нет в C#?
От: samius Япония http://sams-tricks.blogspot.com
Дата: 10.08.10 16:06
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, samius, Вы писали:


S>>Ты не понял меня, я не понял тебя, попытался догадаться что ты мне хотел сказать и ответил на догадку.


_FR>Ну а действительно зачем строить догадки, когда ожно спросить "Что имелось в виду"?


Виноват, постараюсь исправиться.

_FR>Ну это тоже Синклер виноват — стал меня на "вы" называть, а я стал просто всем "выкать" безо всякого накала, в качесве более вежливого обращения не имея ничего дурного в мыслях. Честно — можно посмотреть любые мои последние сообщения. В "вы" нет ничего личного.


Заметил, что вы с ним "выкаете", но не отследил кто начал.

_FR>Если уж кому и следует извиниться, то мне — не сдержан-то я, сам вижу, но пытаюсь как могу объяснить, что ведение дискуссии по тому пути, которым она идёт, бесполезно.


Удалось, объяснил!

_FR>Синклер отвечает на мои вопросы более чем загадочно, а ты переключаешь всё внимание на несущественные детали. которые могут быть истолкованы по разному и прямого отношения к обсуждаемой теме не имеют.


Ниже попытаюсь раскрыть их отношение, но если они и после этого покажутся несущественными — оставим их.

_FR>Да ещё и "примеры ситцаций" всё изменяются и изменяются и как они связаны с тем, что было в прошлом сообщении — для меня не очевидно.


То что ситуации меняются — это нормально. Все меняется. И код тоже. И категоричные мнения меняются в зависимости от ситуаций. Связь попытаюсь раскрыть.

S>>И предлагаю завершить нашу дискуссию мирным путем. Акцент на слове "завершить", потому как продолжать в таком духе не стоит.


_FR>Ну а раз так, смотри о чём речь. Простые постулаты, из которых я исходил, в этом вот месте:

_FR>

_FR>"checked exceptions" вообще говоря, большого влияния на данный вопрос не оказывают — чекед там компилятором или документацией не так важно.


да-да, и здесь я подметил что в одном случае код не компилится, а в другом выполняется.

_FR>1. Метод должен задекларировать выбрасываемые им исклюения так же, как он декларирует возвращаемое значение или допустимые значения параметров.

_FR>2. Если задекларированное поведение отличается от действительного, то метод не является рабочим, то есть поведение метода становится непредсказуемым и ещё не ясно, что "опаснее" — не компилдирующийся метод или сктмпилированный, но ведущий себя неизвестно как.

_FR>Но между проверяемыми компилятором исключениями и декларируемыми исключениями есть разница. Например в том, что документации можно сказать "этот метод бросает A, Б и всё, что вылетит из из колбэка" там, где это удобно (но это не везде удобно).

Sinclair попросил представить на минуту что речь идет об linq
Автор: Sinclair
Дата: 03.08.10
. Минута затянулась и в контексте этой минуты я продолжаю рассуждать, но уже не об одном вызове linq, а о целой цепочке callback-ов, вызываемых ForEach-ем, linq-ом и т.п.
Каждый такой callback — суть метод, имеющий некоторую спецификацию. И пусть перечень выкидываемых исключений. Тогда
а) либо документация callback-а должна специфицировать TIE. Это решение само-по себе не очень, особенно если callback сам не принимает других callback-ов, но вызывает методы, кидающие TIE в том числе.
б) такой callback не должен выкидывать TIE, а значит он его должен либо заворачивать, и тогда мы получим цепочку SomeException->TIE->SomeException->TIE->NRE, либо разворачивать, тогда получим цепочку SomeException->SomeException.

Случай а) не интересен, т.к. TIE просто превращается в люк для просовывания любых исключений, обернутых в него.

По поводу случая б) пошла энтропия. Ты предложил заворачивать не по-тупому, а по-умному. Моя вина, теперь очевидно, что ты подразумевал цепочку TIE->TIE->TIE->NRE. Второе твое предложение — использовать GetBaseException. На что я собственно посадил сферо-коня на некий абстрактный транспорт, который должен был выкинуть что-то вроде следующей цепочки
TIE->SomeException->TIE->TransportException->SocketException. Тогда GetBaseException вернул бы SocketException, который не специфицирован у абстрактного транспорта, заворачивающего специфичные исключения в специфицированный TransportException.

Еще один аспект — непонятно, как писать лучше, заворачивать или разворачивать?!?!?! ПОлучается что в одном случае надо заворачивать (усложнять анализ), в другом разворачивать (с потерей стека), в третьем — пробрасывать TIE (с расширением спеска исключений метода). Плачет реюз методов.

Да не будет забыт Aikin, который (как мне кажется) пытался донести что анонимные методы и лямбды — суть те же методы, которые должны придерживаться тех же правил, что и обычные методы, а значит по твоим постулатам придерживаться исключений, описанных в документации. Но как им адресовать документацию? Это же анонимные методы и лямбды. Да и нет возможности в лямбдах исключения заворачивать и разворачивать (в анонимных методах можно). Подразумеваю что лямбда от анонимного метода отличается наличием блока выражений.

Т.е. если бы было верно то что попросил представить на минуту Синклер (TIE из linq), то был бы ад, и никакие фильтры исключений не охладили бы его до приемлемой температуры.

По поводу того, какую пользу приносит TIE — у меня честно нет никаких догадок. Впрочем, через рефлекшн я методы не вызываю последнее время, и вопрос пользы TIE для меня абстрактен (но любопытен).
Re[30]: Проверяемые исключения -- почему нет в C#?
От: _FRED_ Черногория
Дата: 10.08.10 18:23
Оценка:
Здравствуйте, samius, Вы писали:

_FR>>Да ещё и "примеры ситцаций" всё изменяются и изменяются и как они связаны с тем, что было в прошлом сообщении — для меня не очевидно.


S>То что ситуации меняются — это нормально. Все меняется. И код тоже. И категоричные мнения меняются в зависимости от ситуаций. Связь попытаюсь раскрыть.


Связь нужна была вот для чего: когда ситуация усложняется, очень полезно посмотреть на всё сразу — тогда можно увидеть, что получившуюся после "уточнений" проблуму вообще стоит решать не так, как решали первоначальную формулировку задачи. Вот почему я всегда прошу ясно и подробно описывать ситуацию — потому что в разных головах она может представляться по-разному.

_FR>>1. Метод должен задекларировать выбрасываемые им исклюения так же, как он декларирует возвращаемое значение или допустимые значения параметров.

_FR>>2. Если задекларированное поведение отличается от действительного, то метод не является рабочим, то есть поведение метода становится непредсказуемым и ещё не ясно, что "опаснее" — не компилдирующийся метод или сктмпилированный, но ведущий себя неизвестно как.

_FR>>Но между проверяемыми компилятором исключениями и декларируемыми исключениями есть разница. Например в том, что документации можно сказать "этот метод бросает A, Б и всё, что вылетит из из колбэка" там, где это удобно (но это не везде удобно).

S>Sinclair попросил представить на минуту что речь идет об linq
Автор: Sinclair
Дата: 03.08.10
. Минута затянулась


Немного отстранися, но сразуже потом вернёмся. Есть неоке утверждение У. Есть факт, подтверждающий справедливость утверждения. Является ли он достаточным, что бы считать утверждение доказанным? С другой стороны есть факт, опровергающий утверждение. Достаточно ли его, что бы считать утверждение ложным?

Возвращаемся. Пример с линком, и я не отрицал этого, во многих случах удачно подтверждает, что без оборачивания жить лучше (и легче и удобнее и прочее) чем с оборачиванием. Намного даже лучше — не возьмусь с этим спорить. Но в некоторых случаях (когда колбэк выбрасывает InvalidOperationException) мы попадаем в ловушку этой простоты — и не можем адекватно отреагировать именно на исключение, брошенное колбэком, а не линком.

В более навороченных методах с колбэками, тем более связанных с развесистой иерархией IOException, где отвалиться может много чего и всё в разных местах, не обёрнутое исключение станет более вредным для вызывающего. И там, повторюсь, тупик наступает с случае прозрачной передачи наверх по стеку произошедшего в колбэке. Тупик, потому что не понятно, на каком этапе произошла ошибка — перед, во время или после колбэка. Что бы разрулить данную ситуацию надо или как-то специально оборачивать колбэк перед передачей куда-то или оборачивать исключение в методе, в который колбэк передаётся. В разных случаях более удачным оказывается или первое или второе. Но без оборачивания никак.

S>и в контексте этой минуты я продолжаю рассуждать, но уже не об одном вызове linq, а о целой цепочке callback-ов, вызываемых ForEach-ем, linq-ом и т.п.


Так рассуждать в корне не верно. Я использую простые правила:
1. исключение из колбэка оборачивается в CallbackException (если это не CallbackException)
2. обработка CallbackException должна осуществляться тем, кто передаёт колбэк. Тем, кто выше него по стеку CallbackException ничего полезного не скажет. Обработка может заключаться в перебросе какого-то другого исключения или же в чём-то другом, например, принятии решения о неудачном завершении операции.

Вот теперь, если будет какой-то не гипотетический пример "целой цепочки callback-ов", можно будет посмотреть, как оно будет работать. Например:

void Main() {
  M1();
}

void M1() {
  Action callback = delegate { Debug.Print("Callback!"); };
  try {
    M2(callback);
  } catch(CallbackException ex) { // фильтрации\проверки опускаю, 
                                  // показывал выше как они выглядят, 
                                  // если в них есть необходимость
    // А тут смотрим: или
    throw ex.InnerException;
    // или
    throw MyException(ex.Message, ex.InnerException);
    // или
    return;
    // В зависимости от того, какой контракт M1 нам нужен.
    // Но выше код не знает про колбэк и ничего про него не получает.
  }//try
}

void M2(Action callback) {
  // <…>
  M3(callback); // Просто передаём всё как есть,
                // ничего не заем ни про колбэк,
                // ни про его обработку.
  // <…>
}

void M3(Action callback) {
  // <…>

  try {
    // <…>
    callback();
    // <…>
  } catch(CallbackException) {
    throw;
  } catch(Exception ex) { // *
    throw CallbackException.Wrap(ex);
  }//try

  // <…>
}


* — мы можем в M2/M1 потребовать (через документацию) что бы колбэк выбрасывал бы только XException и ловить соотвтственно только его. То есть то, что мы ловим базовый Exception здесь не принципиально.

Прежде чем делать выводы о том, как такой подход будет плох в таком-то и таком-то сценарии, давайте сначала посмотрим код сценария, а не словесное описание, что бы потом небыло "ну подразумевалось то", "очевидно это" и "относилось к тому". Сценариев комбинирования вызова методов, передачи в них колбэком и прочего очень много самых разнообразных и один общий пример я привести не могу. Но в каждом частном случае разобраться как оно должно быть всегда можно.

S>Каждый такой callback — суть метод, имеющий некоторую спецификацию. И пусть перечень выкидываемых исключений. Тогда

S>а) либо документация callback-а должна специфицировать TIE. Это решение само-по себе не очень, особенно если callback сам не принимает других callback-ов, но вызывает методы, кидающие TIE в том числе.
S>б) такой callback не должен выкидывать TIE, а значит он его должен либо заворачивать, и тогда мы получим цепочку SomeException->TIE->SomeException->TIE->NRE, либо разворачивать, тогда получим цепочку SomeException->SomeException.

Теперь предлагаю рассмотреть конкретные примеры кода, а не цепочки, потому что интересным и важным здесь являются не сами цепочки, а то, откуда они появляются. И, вполне возможно, мне удастся показать, как быть в случае той или иной цепочки и как предотвратить ту или иную ситаёвину.

S>Еще один аспект — непонятно, как писать лучше, заворачивать или разворачивать?!?!?! ПОлучается что в одном случае надо заворачивать (усложнять анализ), в другом разворачивать (с потерей стека), в третьем — пробрасывать TIE (с расширением спеска исключений метода). Плачет реюз методов.


На счёт "реюза" не понял: ИМХО, каждый метод должен знать, что внутри него может произойти. А так да — иногда нужно одно, иногда другое — зависит только от того, как мы сами хотим. А вот чего нам надо хотеть, что бы не получилось неоднозначно надо рассматривать на примерах кода.

S>Да не будет забыт Aikin,


Ой, пропустил. Отвечу потом там прямо. пока не готов.

S>Т.е. если бы было верно то что попросил представить на минуту Синклер (TIE из linq), то был бы ад, и никакие фильтры исключений не охладили бы его до приемлемой температуры.


Я про TIE и линк говорил мало: но я много раз просил сказать, как быть с IOE и чёткого ответа не получил. Про линк я тут развёрнуто выше ответил, что с ним-то всё просто. а в сложны примерах всё немного по-другому.

S>По поводу того, какую пользу приносит TIE — у меня честно нет никаких догадок. Впрочем, через рефлекшн я методы не вызываю последнее время, и вопрос пользы TIE для меня абстрактен (но любопытен).


Конкретно TIE я назвал как известный аналог. В рабочем коде его использовать для того, что я написал — это Я предлагаю на конкретных приёмах разобрать глюки, которые на первый взгял могут показаться в слуе использования CallbackException. конечно, он добавляет косвенности и связанной с ней сложности, но тупикового в нём ничего нет, а, напротив, есть некая дополнительная информация, которая в некоторых случаях может быть весьма полезной.
Help will always be given at Hogwarts to those who ask for it.
Re[31]: Проверяемые исключения -- почему нет в C#?
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.08.10 07:39
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Связь нужна была вот для чего: когда ситуация усложняется, очень полезно посмотреть на всё сразу — тогда можно увидеть, что получившуюся после "уточнений" проблуму вообще стоит решать не так, как решали первоначальную формулировку задачи. Вот почему я всегда прошу ясно и подробно описывать ситуацию — потому что в разных головах она может представляться по-разному.


Эта ситуация и в одной-то голове может представляться по-разному в зависимости от контекста. Особенно это касается ситуаций, специально выдуманных для опровержения утверждений оппонента.

_FR>Немного отстранися, но сразуже потом вернёмся. Есть неоке утверждение У. Есть факт, подтверждающий справедливость утверждения. Является ли он достаточным, что бы считать утверждение доказанным?

В общем случае нет, но это зависит от утверждения и факта. Например, факта существования языка C# достаточно для истинности утвреждения о существовании такого языка.

_FR>С другой стороны есть факт, опровергающий утверждение. Достаточно ли его, что бы считать утверждение ложным?

Если факт достоверен и верно истолкован — то утверждение однозначно ложно. В дальнейшем можно лишь говорить о справедливости утвреждения в некоторых условиях, с оговорками, либо в более мягкой форме (иногда, в большинстве случаев, скорее всего, как правило, и т.п.)

Ну вот опять. Виной тому мое математическое образование. Всю математику я благополучно забыл, а вот педантизм в отношении чужих высказываний остался.

Но я понял, что ты не претендуешь на категоричную истину своих утверждений, в то время как я продолжаю давить на примеры, в отношении которых те утверждения не справедливы. Отступление было об этом?

_FR>Возвращаемся. Пример с линком, и я не отрицал этого, во многих случах удачно подтверждает, что без оборачивания жить лучше (и легче и удобнее и прочее) чем с оборачиванием. Намного даже лучше — не возьмусь с этим спорить. Но в некоторых случаях (когда колбэк выбрасывает InvalidOperationException) мы попадаем в ловушку этой простоты — и не можем адекватно отреагировать именно на исключение, брошенное колбэком, а не линком.

С этим можно бороться оборачиванием колбэка в метод, оборачивающий исключения. Ты об этом написал ниже. Но я предпочитаю бороться решая конкретную проблему, вместо того чтобы платформа оборачивала бы все исключения как в случае с TIE и рефлекшном.

_FR>В более навороченных методах с колбэками, тем более связанных с развесистой иерархией IOException, где отвалиться может много чего и всё в разных местах, не обёрнутое исключение станет более вредным для вызывающего. И там, повторюсь, тупик наступает с случае прозрачной передачи наверх по стеку произошедшего в колбэке. Тупик, потому что не понятно, на каком этапе произошла ошибка — перед, во время или после колбэка. Что бы разрулить данную ситуацию надо или как-то специально оборачивать колбэк перед передачей куда-то или оборачивать исключение в методе, в который колбэк передаётся. В разных случаях более удачным оказывается или первое или второе. Но без оборачивания никак.


S>>и в контексте этой минуты я продолжаю рассуждать, но уже не об одном вызове linq, а о целой цепочке callback-ов, вызываемых ForEach-ем, linq-ом и т.п.


_FR>Так рассуждать в корне не верно. Я использую простые правила:

_FR>1. исключение из колбэка оборачивается в CallbackException (если это не CallbackException)
В свою очередь я предполагал передавать в качестве колбэка метод, который по документации не является колбэком и в его контракте(документации) нет никаких CallbackException (пример ниже). Чтобы сделать как ты говоришь, такой метод нужно будет обернуть в нечто, обертывающее его исключения в CallbackException. Это усложнит код, но это решение призвано решать частную проблему. Мне пока не приходилось программно отделять исключения колбэка от исключений метода, его вызывающего.

_FR>2. обработка CallbackException должна осуществляться тем, кто передаёт колбэк. Тем, кто выше него по стеку CallbackException ничего полезного не скажет. Обработка может заключаться в перебросе какого-то другого исключения или же в чём-то другом, например, принятии решения о неудачном завершении операции.

+1

_FR>Вот теперь, если будет какой-то не гипотетический пример "целой цепочки callback-ов", можно будет посмотреть, как оно будет работать. Например:


К примеру у меня единственное замечание, а именно потеря стека в случае
throw ex.InnerException;

о чем уже упоминал Sinclair.

Если нужно развернуть, то лучше сделать нечто вроде
throw ExceptionHelper.CloneAndWrap(ex.InnerException);

т.е. клонировать ex.InnerException, и в качестве InnerException положить ex.InnerException. Так мы сохраним и стек оригинального и тип возбуждаемого исключения, а при желании и Message и прочее.
Но не будем отвлекаться на эту тему.

_FR>Прежде чем делать выводы о том, как такой подход будет плох в таком-то и таком-то сценарии, давайте сначала посмотрим код сценария, а не словесное описание, что бы потом небыло "ну подразумевалось то", "очевидно это" и "относилось к тому". Сценариев комбинирования вызова методов, передачи в них колбэком и прочего очень много самых разнообразных и один общий пример я привести не могу. Но в каждом частном случае разобраться как оно должно быть всегда можно.


static void Main()
{
    var collection = CreateSomeCollection();
    try
    {
        PrintCollection(collection);
    }
    catch(Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

public static void PrintCollection(SomeCollectionn collection) // throws InvalidOperationException, ArgumentNullException
{
    if(collection == null)
        throw new ArgumentNullException("collection");
    try
    {
         collection.ForEach(x => PrintItem(x)); // ForEach throws CallbackException, ArgumentNullException
    }
    catch(CallbackException ex)
    {
        /// ?????
    }
    catch(Exception ex)
    {
        /// ????
    }
}

public static void PrintItem(X x) // throws ArgumentNullException
{
    // опущено.
}


Метод PrintCollection не предназначен для поглощения исключений. Он может либо завернуть пришедший CallbackException либо развернуть его с потерей стека, но в случае исключения из ForEach-а обязан что-либо выкинуть. Полагаю что ты согласишься с тем, что CallbackException вносить в спецификацию метода PrintCollection не стоит.
Как ты собственно видишь try/catch метод-а PrintCollection? Нужен ли CallbackException внутри цепочки исключений снаружи PrintCollection?

Метод PrintCollection в свою очередь сам может выступать в роли колбэка. И его цепочка будет опять обернута в CallbackException.

S>>Еще один аспект — непонятно, как писать лучше, заворачивать или разворачивать?!?!?! ПОлучается что в одном случае надо заворачивать (усложнять анализ), в другом разворачивать (с потерей стека), в третьем — пробрасывать TIE (с расширением спеска исключений метода).

Об этом пример выше.

S>>Плачет реюз методов.


_FR>На счёт "реюза" не понял: ИМХО, каждый метод должен знать, что внутри него может произойти. А так да — иногда нужно одно, иногда другое — зависит только от того, как мы сами хотим. А вот чего нам надо хотеть, что бы не получилось неоднозначно надо рассматривать на примерах кода.


Я хочу написать метод, который бы работал в различных сценариях. Не хочу делать перегрузки, в зависимости от того, какая цепочка исключений будет нужна снаружи. Стоит ли CallbackException таких усложнений в общем случае?
Re[32]: Проверяемые исключения -- почему нет в C#?
От: _FRED_ Черногория
Дата: 11.08.10 09:55
Оценка:
Здравствуйте, samius, Вы писали:

_FR>>Связь нужна была вот для чего: когда ситуация усложняется, очень полезно посмотреть на всё сразу — тогда можно увидеть, что получившуюся после "уточнений" проблуму вообще стоит решать не так, как решали первоначальную формулировку задачи. Вот почему я всегда прошу ясно и подробно описывать ситуацию — потому что в разных головах она может представляться по-разному.


S>Эта ситуация и в одной-то голове может представляться по-разному в зависимости от контекста. Особенно это касается ситуаций, специально выдуманных для опровержения утверждений оппонента.


Я дипломатично об этом умолчал

S>Но я понял, что ты не претендуешь на категоричную истину своих утверждений, в то время как я продолжаю давить на примеры, в отношении которых те утверждения не справедливы. Отступление было об этом?


Именно.

_FR>>Но в некоторых случаях (когда колбэк выбрасывает InvalidOperationException) мы попадаем в ловушку этой простоты — и не можем адекватно отреагировать именно на исключение, брошенное колбэком, а не линком.

S>С этим можно бороться оборачиванием колбэка в метод, оборачивающий исключения. Ты об этом написал ниже. Но я предпочитаю бороться решая конкретную проблему, вместо того чтобы платформа оборачивала бы все исключения как в случае с TIE и рефлекшном.

Покажи пожалуйста пример того, как разобраться при вызове Enumerable.Aggregate<T>(IEnumerable<T>, Func<T, T, T>) из-за чего произошло IOE? Если не оборачивать, то только проверки. Это самый лучший и самый правильный способ — во-первых, предотвращаем исключение, не нарываясь на него, во-вторых ободимся без колдунства с оборачиваниями. А если проверка может не иметь смысла (как например с IOException, когда при проверке файл может быть на диске, а через "мнгновение" уже нет)? Можешь показать пример решения конкретной проблемы, о которым ты говоришь?

_FR>>В более навороченных методах с колбэками, тем более связанных с развесистой иерархией IOException, где отвалиться может много чего и всё в разных местах, не обёрнутое исключение станет более вредным для вызывающего. И там, повторюсь, тупик наступает с случае прозрачной передачи наверх по стеку произошедшего в колбэке. Тупик, потому что не понятно, на каком этапе произошла ошибка — перед, во время или после колбэка. Что бы разрулить данную ситуацию надо или как-то специально оборачивать колбэк перед передачей куда-то или оборачивать исключение в методе, в который колбэк передаётся. В разных случаях более удачным оказывается или первое или второе. Но без оборачивания никак.


S>>>и в контексте этой минуты я продолжаю рассуждать, но уже не об одном вызове linq, а о целой цепочке callback-ов, вызываемых ForEach-ем, linq-ом и т.п.

_FR>>Так рассуждать в корне не верно. Я использую простые правила:
_FR>>1. исключение из колбэка оборачивается в CallbackException (если это не CallbackException)
S>В свою очередь я предполагал передавать в качестве колбэка метод, который по документации не является колбэком

Можно подробнее? Что значит"метод, который по документации не является колбэком"? Имхо, метод стоновится колбэком тогда, когда мы этот метод специфическим образом используем. То есть "колбэк" — это не атрибут метода.Колбэком может стать любой метод.

S>и в его контракте(документации) нет никаких CallbackException (пример ниже).


Ага, речь не о колбэк-методах, а о методах, в которые передаётся колбэк: Потому что только в конракте этих методом имеет смысл иметь CallbackException.

S>Чтобы сделать как ты говоришь, такой метод нужно будет обернуть в нечто, обертывающее его исключения в CallbackException. Это усложнит код, но это решение призвано решать частную проблему. Мне пока не приходилось программно отделять исключения колбэка от исключений метода, его вызывающего.


Не понимаю. Можно пример посмотреть?

_FR>>Вот теперь, если будет какой-то не гипотетический пример "целой цепочки callback-ов", можно будет посмотреть, как оно будет работать. Например:


S>К примеру у меня единственное замечание, а именно потеря стека …


Что там делать — дело хозяйское. Можно хоть спутник запустить. Это механика. к подходу отношения не имеющая. видно будет ние при разборе примера.

S>static void Main()
S>{
S>    var collection = CreateSomeCollection();
S>    try
S>    {
S>        PrintCollection(collection);
S>    }
S>    catch(Exception ex)
S>    {
S>        Console.WriteLine(ex.ToString());
S>    }
S>}

S>public static void PrintCollection(SomeCollectionn collection) // throws InvalidOperationException, ArgumentNullException
S>{
S>    if(collection == null)
S>        throw new ArgumentNullException("collection");
S>    try
S>    {
S>         collection.ForEach(x => PrintItem(x)); // ForEach throws CallbackException, ArgumentNullException
S>    }
S>    catch(CallbackException ex)
S>    {
S>        /// ?????
S>    }
S>    catch(Exception ex)
S>    {
S>        /// ????
S>    }
S>}

S>public static void PrintItem(X x) // throws ArgumentNullException
S>{
S>    // опущено.
S>}


S>Метод PrintCollection не предназначен для поглощения исключений. Он может либо завернуть пришедший CallbackException либо развернуть его с потерей стека, но в случае исключения из ForEach-а обязан что-либо выкинуть. Полагаю что ты согласишься с тем, что CallbackException вносить в спецификацию метода PrintCollection не стоит.


Именно так.

S>Как ты собственно видишь try/catch метод-а PrintCollection? Нужен ли CallbackException внутри цепочки исключений снаружи PrintCollection?



Нужен или нет, решать пользователю. по мне, он не обязателен и не невозможен. Я бы написал как-то так:

S>public static void PrintCollection(SomeCollectionn collection) // throws InvalidOperationException, ArgumentNullException
S>{
S>    if(collection == null)
S>        throw new ArgumentNullException("collection");
S>      try
S>    {
S>         collection.ForEach(x => PrintItem(x)); // ForEach throws CallbackException, ArgumentNullException
S>    }
S>    catch(CallbackException ex)
S>    {
            // IOE, ибо в контакте метода указан он
            // По идее, можно написать тут всё что душе угодно
            // зависит от спецификации того, как должен вести себя 
            // PrintCollection когда в collection есть невалидные с точки зрения того,
            // что делает PrintCollection (то есть PrintItem) элементы
        throw new InvalidOperationException(ex.Message, ex.InnerExptioon);
            // А можно даже так:
        throw new InvalidOperationException("Some item in collection is null");
            // Можно для пущей убедительности убедиться, что в InnerException именно ANE
S>    }
S>    catch(Exception ex)
S>    {
S>        /// ????
            // Если я правильно понял контракты методов, сюда мы попасть не должны вовсе,
            // то есть catch(Exception ex) в данном методе не нужен.
S>    }
S>}



S>Метод PrintCollection в свою очередь сам может выступать в роли колбэка. И его цепочка будет опять обернута в CallbackException.


Ну ёлки-палки "может"-"не может" неужели сложно пример показать? Как например планируется вызывать PrintCollection

S>>>Плачет реюз методов.


_FR>>На счёт "реюза" не понял: ИМХО, каждый метод должен знать, что внутри него может произойти. А так да — иногда нужно одно, иногда другое — зависит только от того, как мы сами хотим. А вот чего нам надо хотеть, что бы не получилось неоднозначно надо рассматривать на примерах кода.


S>Я хочу написать метод, который бы работал в различных сценариях. Не хочу делать перегрузки, в зависимости от того, какая цепочка исключений будет нужна снаружи.


А я хочу атомную подводную лодку и не хочу работать.

S>Стоит ли CallbackException таких усложнений в общем случае?


Опять не понимаю, чем обусловлено "хочу" выше. Сложно что ли пример показать? Типа вот есть у меня так и так, ты предлагаешь это и это. я вот смотрю и не могу понять как, потому что если этак, то то, а если сяк, то тото. Ну почему нельзя вести разговорр в там ключе Если бы я был вашим доктором и получал деньги за потраченное время, то давно озолотился бы. Но мы в поликлиннике где мильём пациентов, поэтому или сами всё рассказывайте-показывайте понятно, или идите на колоноскопию — там всё ясно будет.
Help will always be given at Hogwarts to those who ask for it.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.