Здравствуйте, maxkar, Вы писали:
_>>Вот такие дела при говнокоде с автоматическими исключениями. M>Все там нормально. Только исключения нужно на правильный уровень выносить. Показываю на java, потому что без разницы в данном контексте.
Естественно нормально, вы же тут как раз нормальную архитектуру нарисовали, а не "автоматическую". Так что с этим вопросов нет, вопросы в сравнение объёма работы для реализации такого и для варианта без исключений...
M>И так далее. В большинстве случаев обертка вешается глобально на всю функцию. Ну и хэлперы правильные, конечно же. Все нормально разбирается. На "внешние" обертки кода не много (не каждый вызов нужно покрывать, а весь блок).
Такой код получается далеко не во всех случаях. К примеру если мы читаем вариативный конфиг, то там легко возможна ситуация когда например неудача readIntField не означает испорченный конфиг. Соответственно мы получим код, где внутри одной функции будет куча вызовов readIntField обвешанных персональными try/catch... Кстати, вот как раз java код обычно и славится такими соплями...
M>Пожалуйста, приведите мой же пример (те же два уровня) с сохранением той же информации об ошибках — имени поля и имени структуры, где произошла ошибка. И все это — на кодах ошибок, пожалуйста. Заметьте, что типы ошибок вам также придется описывать (ну не влезают нужные данные в код возврата). Ну и на лесенку if'ов (и переоборачивание) хочется посмотреть. Представьте еще, что в readFieldGroup читается 10 полей, а не два. На сколько сильно изменится ваш код? Кстати, мой код различает ошибки "файл не считался потому что диск начал сыпаться" и "файл имеет неправильный формат" (оба с нужной информацией).
Да одно объявление классов этих исключений, с их полями и конструкторами, перекроет любые if'ы по объёму. Что касается "типов ошибок" в варианте с кодами возвратов, то даже так с ходу и не припомню видел ли я такое чудо вообще когда-нибудь. )))
Здравствуйте, Erop, Вы писали:
X>>на протяжении всего треда, я вижу лишь обратное. (в реальности-то, оно давно обосновано и доказано) E>Смотри, ты пишешь же на С++ и с исключениями, и весь твой код обеспечивает как минимум базовую гарантию безопасности?
E>Если ты так или иначе работаешь в команде, то предлагаю тебе эксперимент. E>Объявляешь приз в 100 баксов за каждый выявленный в твоём коде случай нарушения базовой гарантии и башляешь до тех пор, пока не расстанешься с иллюзиями
КО говорит, что неиспользование исключений не избавляет от этой проблемы. Посему спрашивается, к чему это было?
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, jazzer, Вы писали:
J>>Понятна, конечно. Называется "выбрасываем с водой ребенка". Я прямо так и представляю себе, заполняешь ты форму, скидываешь на диск, запускаешь прогу, а она тебе: " У Вас в файле неонка ошибка, а где конкретно — не скажу, ибо мне совершенно ни к чему знать из-за какой конкретно ерунды файл не читается корректно, ищи сам".
_>Ох, и почему очевидные вещи надо разъяснять на пальцах... Ну ок, раз не выходит в общем, объясню на конкретном примере.
Ну наконец-то. Сейча мы увидим сияющий код, правда?
_>Ты хочешь подробные описания ошибок для пользователя? Ну так с помощью исключений это будет СЛОЖНЕЕ сделать при нормальной архитектуре и вообще невозможно при так любимой тобою "автоматической".
_>Значит смотрим на твой же конкретный пример (стек вызовов: read_profile -> load_files -> load_file -> read_file -> read_header -> read_field_group -> read_named_field -> read_integer). Как я понимаю при автоматическом сценарии (это то, что ты вроде как пропагандируешь и то что я назвал немодульным говнокодом) у нас read_integer кидает исключение, а ловится оно где-то вокруг read_profile. Ну так в таком случае мы можем сказать пользователю только то, что "где-то вместо цифры встретила буква" и всё! Мы даже имя файла сообщить не сможем, т.к. ни read_integer, ни код вокруг read_profile его не знает. Не говоря уже о каких-то ещё деталях типа имени поля. Вот такие дела при говнокоде с автоматическими исключениями.
Мда. Погугли про chained exceptions, что ли. Аргументация уровня детского сада, честное слово.
_>Если же мы захотим сделать нормальный код, но на исключениях, то нам придётся ставить промежуточные обработчики исключений на каждом уровне, кидающие при этом сами другие исключения (действующие на другом уровне и содержащие другую информацию). Т.е. блоки try/catch/throw размножатся по всей этой цепочке и на каждом уровне будут исключения своего типа. Это безусловно будет корректно работать, но по объёму кода очевидно будет превосходить вариант с просто кодами возврата, не привнося при этом ни единого преимущества над ними.
Show me the code. Твое голословное "очевидно" не катит.
_>>>Соответственно у нас может быть 4 варианта: _>>>1. Тупой проброс кодов возврата с нижнего уровня — это не модульный говнкод. _>>>2. Автоматическая работа с исключениями с нижнего уровня — это не модульный говнкод, но чуть меньшего объёма чем вариант 1. _>>>3. Необходимая обработка кодов возврата на своём уровне, с возвратом осмысленных значений на каждом уровне. Это нормальный код. _>>>4. Работа через исключения с необходимой обработкой их на каждом уровне. Это нормальный код, но занимающий больший объём чем вариант 3. J>>Последний пункт неплохо бы доказать.
_>Что там доказывать то? При одинаковом количестве блоков, очевидно что try/catch+определение класса исключения займёт больше места чем банальный if. А насчёт количества блоков смотри выше.
Show me the code. Твое голословное "очевидно" не катит.
Ну и ты в который раз игнорируешь вопрос: J>>И заодно еще расскажи, как ты гарантируешь, что твой read_profile не вернет true в случае ошибки где-то в потрохах загрузки.
"Очевидно" (с), потому что нечего сказать.
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, maxkar, Вы писали:
_>>>Вот такие дела при говнокоде с автоматическими исключениями. M>>Все там нормально. Только исключения нужно на правильный уровень выносить. Показываю на java, потому что без разницы в данном контексте.
_>Естественно нормально, вы же тут как раз нормальную архитектуру нарисовали, а не "автоматическую". Так что с этим вопросов нет, вопросы в сравнение объёма работы для реализации такого и для варианта без исключений...
Ну и где сравнение? Или опять "очевидно"? Тебя который раз просят код привести. Походу не дождемся.
M>>И так далее. В большинстве случаев обертка вешается глобально на всю функцию. Ну и хэлперы правильные, конечно же. Все нормально разбирается. На "внешние" обертки кода не много (не каждый вызов нужно покрывать, а весь блок).
_>Такой код получается далеко не во всех случаях. К примеру если мы читаем вариативный конфиг, то там легко возможна ситуация когда например неудача readIntField не означает испорченный конфиг. Соответственно мы получим код, где внутри одной функции будет куча вызовов readIntField обвешанных персональными try/catch... Кстати, вот как раз java код обычно и славится такими соплями...
Для этих случаев пишутся специальные функции, очевидно. Типа readIntField(field, default).
M>>Пожалуйста, приведите мой же пример (те же два уровня) с сохранением той же информации об ошибках — имени поля и имени структуры, где произошла ошибка. И все это — на кодах ошибок, пожалуйста. Заметьте, что типы ошибок вам также придется описывать (ну не влезают нужные данные в код возврата). Ну и на лесенку if'ов (и переоборачивание) хочется посмотреть. Представьте еще, что в readFieldGroup читается 10 полей, а не два. На сколько сильно изменится ваш код? Кстати, мой код различает ошибки "файл не считался потому что диск начал сыпаться" и "файл имеет неправильный формат" (оба с нужной информацией).
_>Да одно объявление классов этих исключений, с их полями и конструкторами, перекроет любые if'ы по объёму. Что касается "типов ошибок" в варианте с кодами возвратов, то даже так с ходу и не припомню видел ли я такое чудо вообще когда-нибудь. )))
Я так и из всего этого словоблудия не понял, будет демонстрация того, как замечательно пробрасывается вся необходимая информация на кодах возврата или нет?
Тебя же попросили привести код. Не, никак? Не кодируется сегодня?
Здравствуйте, ambel-vlad, Вы писали:
E>>Если ты так или иначе работаешь в команде, то предлагаю тебе эксперимент. E>>Объявляешь приз в 100 баксов за каждый выявленный в твоём коде случай нарушения базовой гарантии и башляешь до тех пор, пока не расстанешься с иллюзиями
AV>КО говорит, что неиспользование исключений не избавляет от этой проблемы. Посему спрашивается, к чему это было?
Обсуждался довольно простой вопрос -- обеспечивается ли азовая гарантия В РЕАЛНОСТИ...
Исключения тут правда не при чём. Просто если исключения летают редко, то становится сильно менее важно, обеспечивается базовая гарантия или нет
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, jazzer, Вы писали:
J>Для этих случаев пишутся специальные функции, очевидно. Типа readIntField(field, default).
Ага, которая и будет реализована через те самые try/catch, т.к. нижележащая функция у нас работает через исключения...
J>Я так и из всего этого словоблудия не понял, будет демонстрация того, как замечательно пробрасывается вся необходимая информация на кодах возврата или нет? J>Тебя же попросили привести код. Не, никак? Не кодируется сегодня?
Ну приведи реальный (а не как у тебя были перед этим с исключениями гуляющими с нижнего уровня) рабочий пример с исключениями. Только полный пример, со всеми throw, try/catch и определениями классов исключений. А я тогда запишу его без исключений и сравним размер.
Здравствуйте, alex_public, Вы писали:
_>Естественно нормально, вы же тут как раз нормальную архитектуру нарисовали, а не "автоматическую". Так что с этим вопросов нет, вопросы в сравнение объёма работы для реализации такого и для варианта без исключений...
Так вы же сами просили "ошибки подробно" описывать. И говорили, что на кодах ошибок это проще, чем на исключениях . И я в предыдущем сообщении показывал, как это будет "по-умолчанию" с тремя уровнями исключений (без дополнительной обертки в readFieldGroup и т.п.). Завернуть все в unchecked и отлавливать на верхнем уровне тоже можно, но во вполне конкретных случаях и понимая, зачем и что с этим делать. Я за проработку обработки ошибок на ранних стадиях. Поэтому переоборачивание ошибок на границах слоев абстрации для меня — действие по умолчанию. Все исключения методов должны быть только в терминах интерфейса. Поэтому абстрактный ProfileService не может принципиально выбрасывать IOException. ProfileException — может. ProfileNotFound — может. А вот IOException — никогда.
M>>И так далее. В большинстве случаев обертка вешается глобально на всю функцию. Ну и хэлперы правильные, конечно же. Все нормально разбирается. На "внешние" обертки кода не много (не каждый вызов нужно покрывать, а весь блок).
_>Такой код получается далеко не во всех случаях. К примеру если мы читаем вариативный конфиг, то там легко возможна ситуация когда например неудача readIntField не означает испорченный конфиг. Соответственно мы получим код, где внутри одной функции будет куча вызовов readIntField обвешанных персональными try/catch... Кстати, вот как раз java код обычно и славится такими соплями...
Не будет. jazzer правильный пример привел. Для опциональных полей будут опциональные обертки (которые при этом еще по контракту и состояние потока оставляют во вполне определенном состоянии, а не "где сломалось"). Там же отсутствие поля — вполне ожидаемая ситуация. В крайнем случае, будут возвращать null/not null или какой-нибудь простенький Option с методом hasValue(). А вот IOException будет пробрасываться дальше. Как вы на кодах ошибок будете в данной ситуации действовать? Причем вам теперь нужно проверять, что именно там сломалось:
errcode = readInt(...);
if (errcode != BAD_FORMAT)
return errcode;
И если вдруг поломок будет более одной, все будет еще сложнее (несколько проверок после каждой функции). Если же вы каким-то другим способом предложите переписать код "с использованием кодов ошибок", я подобное же преобразование сделаю и для java, заменив только коды ошибок исключениями.
M>>Пожалуйста, приведите мой же пример (те же два уровня) с сохранением той же информации об ошибках — имени поля и имени структуры, где произошла ошибка.
_>Да одно объявление классов этих исключений, с их полями и конструкторами, перекроет любые if'ы по объёму. Что касается "типов ошибок" в варианте с кодами возвратов, то даже так с ходу и не припомню видел ли я такое чудо вообще когда-нибудь. )))
"Одно объявление классов ... с их полями и конструкторами" — это не свойство исключений. Это свойство поставленной вами задачи "выводить ошибки подробно". И большое количество классов следует из того, что классов ошибок на самом деле много и их нужно как-то описывать. Поэтому не важно, как именно вы это будете делать — исключениями, кодами ошибок или монадой со строго типизированными ошибками. Если убрать это требование, у меня будут исключения с одним/двумя конструкторами (делегирующим родителю) и вообще без полей, например. Т.е. проблема к исключениям отношения не имеет. Да, в Java record и discriminated union очень многословно руками записывают. Мне это надоело и при следующей необходимости discriminated union я их себе сделаю (на xtext + кодогенерация). В данном случае исключения — частный случай discriminated union (открытый или закрытый в зависимости от ситуации). Но, повторюсь, это не проблема исключений, это проблема описания обычных типов данных. Какой-нибудь struct для тех же случаев (вместе с инициализацией) будет ничуть не лучше (а то и хуже). А так как struct вернуть из метода еще и не так просто, то на "кодах возврата" подробная информация обычно как раз не делается. Банально не удобно и получается очень много кода.
Да, еще одна проблема "на кодах возврата". Исключения, все-таки, представляют собой открытое легко расширяемое множество с некоторыми концепциями именования. Это с большой долей вероятносит гарантирует, что "двух одинаковых" исключений в никаких библиотеках не будет (именование пакетов вроде com.acme.product...). А вот набор кодов ошибок ограничен. Так что вполне вероятно, что две библиотеки будут иметь пересекающиеся диапазоны кодово ошибок с различной семантикой? Что вы будете делать в этом случае? Делать кучу оберток вокруг одной из библиотек, переводя ее коды в коды своего приложения? Будете вручную на каждый вызов переделывать кучи ошибок (почти предыдущий вариант, только обработка по месту вызова)? Или ничего не будете делать и предоставите пользователю возможность угадывать, что же на самом деле там сломалось с кодом ошибки 0x3211? Даже "исключения по-умолчанию" (без корректного оборачивания на нужных уровнях) придут с правильным описанием ошибки (правда, слишком низкоуровневым) и гадать нужно будет не так много.
Здравствуйте, Erop, Вы писали:
E>>>Если ты так или иначе работаешь в команде, то предлагаю тебе эксперимент. E>>>Объявляешь приз в 100 баксов за каждый выявленный в твоём коде случай нарушения базовой гарантии и башляешь до тех пор, пока не расстанешься с иллюзиями
AV>>КО говорит, что неиспользование исключений не избавляет от этой проблемы. Посему спрашивается, к чему это было?
E>Обсуждался довольно простой вопрос -- обеспечивается ли азовая гарантия В РЕАЛНОСТИ... E>Исключения тут правда не при чём. Просто если исключения летают редко, то становится сильно менее важно, обеспечивается базовая гарантия или нет
С какой радости становится сильно менее важно?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[55]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
Здравствуйте, Erop, Вы писали:
I>>Да просто иногда под процедурным понимают императивное. E>Ну Дейкстра вроде так обзывал, но это правда всё равно. E>Джаззер как бы показал, что код на исключениях эквивалентен полнейшему ужасу. Странно, что он считает это аргументом в защиту исключений...
То что он выглядит не сильно приятно не отменяет того, что это он переписан в процедурном подходе. Это раз. И покажи не ужас, когда ошибку можно обработать на 4-5 уровней выше нежели ее обнаружение? И чтобы два раза не переписывать, то добавим, что верхняя фунция внутри себя вызывает не одну функцию, а три-пять. И те внутри себя тоже вызывают что-то. И при обработке ошибок на верхнем уровне хотелось бы знать что за ошибка произошла и в какой именно функции. А чтобы еще более весело стало, то функции, в которых возникают ошибки пишутся другими командами. Посему их изменить ты не можешь. А коды ошибок они используют одинаковые.
Здравствуйте, alex_public, Вы писали:
_>Так это очень просто. И так read_integer у нас ругается на букву, не важно исключением или кодом возврата.
ОК.
_>Но коду использующему функцию read_file совершенно ни к чему знать из-за какой конкретно ерунды файл не читается корректно.
Возможно. Но не обязательно.
_>Аналогично и коду использующему read_profile должно быть абсолютно пофиг какой конкретно из файлов не прочитался.
А вот тут мимо. Код, который использует read_profile, знает как отработать ошибочную ситуацию. Как минимум что-то кинуть в лог. А то потом устанешь гадать, например, почему же не сохранились настройки с прошлого запуска.
Здравствуйте, alex_public, Вы писали:
_>Значит смотрим на твой же конкретный пример (стек вызовов: read_profile -> load_files -> load_file -> read_file -> read_header -> read_field_group -> read_named_field -> read_integer). Как я понимаю при автоматическом сценарии (это то, что ты вроде как пропагандируешь и то что я назвал немодульным говнокодом) у нас read_integer кидает исключение, а ловится оно где-то вокруг read_profile. Ну так в таком случае мы можем сказать пользователю только то, что "где-то вместо цифры встретила буква" и всё! Мы даже имя файла сообщить не сможем, т.к. ни read_integer, ни код вокруг read_profile его не знает. Не говоря уже о каких-то ещё деталях типа имени поля.
Кто тебе сказал что не можем? Еще как можем. Исключения можно вкладывать друг в друга. А то при помощи кодов ошибок сообщить это гораздо сложнее.
Здравствуйте, jazzer, Вы писали:
E>>IMHO, всё ровно наоборот. E>>1) Подумали ли о том, что будет, если провалится то или это мето или просто так взяли и написали "чисто и ясно" и расслабились, НЕ ВИДНО. J>Аналогично не видно, обработали ли код возврата или это просто функция возвращает void, или если обработали, то все ли возможные значения обработаны.
Кстати, еще один момент. Разработчики вызываемой функции добавили новый код возврата. И забыли об этом обрадовать тех, кто использует ее. Да, раздолбайство. Да, этого не должно быть. Но это реальность. Что делать в кодом, который вызывает такую функцию? Добавлять еще один if на неизвестные коды? И так с каждым вызовом делать?
Здравствуйте, andyp, Вы писали:
A>Часто бывает так, что поймавший просто не знает что делать с ошибкой.
А зачем он ловит исключение если не знает что с ним делать? Шоб було?
A>Я часто всякую математику пишу. Есть "классная" мысль — кидать domain_error, если не попал в область определения функции (ну например корень из отрицательного числа пытаешься подсчитать). Так вот, не понятно, что с этим исключением делать на верхнем уровне после вызовов 100500 корней внизу.
А почему оно не обрабатывается на более низких уровнях?
A>В результате — УГ и отладка за автора.
Заставь дурака молиться, то он и лоб расшибет. В данном случае смена инстумента (замена исключений на коды возврата) ничем не поможет. Скорее только ухудщит все.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[54]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
E>>Здравствуйте, jazzer, Вы писали:
J>Э-э-э.... Надеюсь, не надо доказывать, что от статических переменных можно элементарно избавиться, передавая их всюду (как это делается в функциональных языках, там для этого даже спецсахар есть в виде монад)?
Для анализа можно и не передавать, а разрешить возвращать что-то чуть более сложное, чем примитивные типы. Вместо обычного int везде возвращать Either Exception Int и т.п.. То, что оно откомпилируется в другой код, в данном случае не важно (он будет эквивалентен коду с проверками).
И еще по поводу "можно". Не просто можно, а сделано на практике. Подробности здесь и далее по ссылке. Фактически там описана та самая монада (Either AbruptCompletion) и несколько "продвинутых" функций (try конвертирует одну монаду в другую). Функциональыне языки в этом месте очень сильно повлияли на java (не только монада, но и то, что у каждого statement есть "значение"). Что интересно, throw, break и continue являются частными случаями одного и того же AbruptCompletion. И во многих местах могут обрабатываться совершенно одинаково. Так что анализу определенных свойств программы исключения совершенно не мешают.
Re[55]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
Здравствуйте, Erop, Вы писали:
E>Так что тема всё та же. Знает кто-то удобную математическую модель кода с исключениями или её пока не придумали (возможно её и нельзя вообще придумать, фиг его знает)...
Придумали, придумали. В java есть. Типичная монада вроде бы. И доказывать свойства вроде definite assignment и некоторые другие соврешенно не мешает.
При понимании модели легко позволяет описывать, что именно делают ужасы вроде
for (i = 0; i < 10; i++) {
try {
return i;
} finally {
continue;
}
}
Re[57]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
Здравствуйте, Erop, Вы писали:
E>Окей, вот мы размножили все catch'и так, словно каждый оператор завёрнут в свой индивидуальный try{}catch, и даже смогли вычислить wp от постусловия программы для содержимого всех этих catch... E>Как теперь эту кучу предикатов склеить обратно в предикат для того catch, который мы пишем реально?..
Так банально же... Для каждой строки предусловие "предыдущий фрагмент завершился успешно И некий предикат ИЛИ предыдущий фрагмент завершился с исключением А". И склеивается оно вполне нормально — "первый шаг завершился с ошибкой ИЛИ первый шаг завершился успешно И с предикатом И второй шаг завершился с ошибкой" и т.д.
E>Суть же подхода Дейкстры состоит в том, что мы можем записать условие того, попадём мы в постусловие программы или нет для любого места в программе, и при этом условие не будет зависеть от пути, по которому мы в это место попали. Только от значений переменных и всё.
А что мешает то? В catch мы попадаем, если есть ошибка. Задача catch — восстановить все варианты блока try{}catch{}. Если мы имеем некий формализм по описанию исключений, мы знаем, в какой строке выше какие исключения могут происходить. В чем проблема то? Если ошибки нет, мы в catch не попадем. Если ошибку не обработали, то мы вообще в весь остаток функции не попадем.
E>Я понима, как получить из кода с исключениями эквивалентный на кодах возвратов и goto, так скажем, но он будет непроцедурный. Я понимаю, как введением очень массового размножения кода и массовы же return из середины функций, написать в каком-то смысле эквивалентный и процедурный, но этот эквивалентный и процедурный будет ОЧЕНЬ СЛОЖНЫМ. И не понятно как его свернуть обратно в относительно простой. То есть как по предикатам этого "эквивалентнго" кода восстановать аналогичные предикаты для исходного?
Кстати, а вы допускаете return в середине функции? Без него некоторые программы читаются гораздо хуже (глубокая вложенность из if'ов читается тяжеловато). А с ними возникают все те же проблемы — как объединять все предикаты из разных return на выходе из программы (например, чтобы проверить очистку ресурсов).
Re[59]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
Здравствуйте, Erop, Вы писали:
E>Мы говорим, что любое исключение может вылететь из любого места, то есть и мест выхода из функции становится больше и мест, где надо проверять коды вохврата больше и вариантов того, что могут и в каких конкретно случаях вернуть становится бесконечно много, строго говоря, и если мы начинаем переписывать код в таких предположениях, то он сильно усложняется, а в предикатаз появляется открытая часть (или ошибка произвольного типа, произошедшая в произвольном месте)...
А зачем так делать? Откуда там произвольные исключения? Можно ведь взять checked exceptions, например, и ограничить их спектр. Так что проблем не будет. То, что c++ не использует checked exception, это его проблемы. К тому же для доказательства свойств можно и какой-то свой аналог их ввести (описывать в документации, проверять теми же контрактами и т.п.). Все равно контракты обычно проверяются самими программмистами (а в большинстве случаев контракты вообще отсутствуют, так как программисты не любят писать документацию).
E>Собственно этот вот переход от явно перечисленных мест/причин провалу к открытому множеству того и другого и делает программу малопонятной и труднодоказуемой, если вообще доказуемой.
Забудьте вы про доказуемость. Дейкстра свой труд писал давным давно, тогда многое было по-другому. Его утверждения про доказуемость применимы в первую очередь к неполиморфным участкам кода. Как только появляется полиморфмизм, все доказательства и контракты усложняются. Если полиморфизм открытый (пользователь может создать еще наследников классов или передать что-то свое в библиотеку), ситуация еще более усложняется.
И еще. Я очень плохо представляю, как можно доказывать базовые гарантии обработки ошибок в реальной жизни. Проблема очень простая. Пусть что-то у нас сломалось, мы решили очистить ресурсы и вернуть код ошибки. Вопрос: как доказать, что мы не поймаем переполнение стека в процессе очистки уже выделенных ресурсов? Как вы будете это доказывать в условиях полиморфизма? При этом все нужно доказывать в каком-то обобщенном виде, ведь мы могли уже считать к этому моменту XML DOM неизвестной глубины и теперь будем его очищать. Какие контракты будут на пользовательские классы и т.п., чтобы гарантировать желательное поведение "по очистке", если пользовательский класс инициализировался (создался фабрикой, например)?
Кстати, что там будет с переполнением стека в C++? На той же java я его могу поймать и обработать. Да, это нужно далеко не везде, но все же может быть нужно. Например, я запускаю какой-нибудь рекурсивный поисковой алгоритм в отдельном потоке. Если алгоритм прошел, хорошо. Если не прошел (не хватило стека), я запускаю другой алгоритм (более медленный/с худшими результатами) и получаю результат от него. Можно делать подобное в процедурном стиле? И как вы будете в этом случае доказывать, что "стека на очистку данных хватит даже если где-то в середине вычисления стека для того шага не хватило"?
E>>Обсуждался довольно простой вопрос -- обеспечивается ли базовая гарантия В РЕАЛНОСТИ... E>>Исключения тут правда не при чём. Просто если исключения летают редко, то становится сильно менее важно, обеспечивается базовая гарантия или нет
AV>С какой радости становится сильно менее важно?
С такой, что нам всё равно, что будет в случае исключения, которого не будет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[56]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
Здравствуйте, ambel-vlad, Вы писали:
AV>То что он выглядит не сильно приятно не отменяет того, что это он переписан в процедурном подходе. Это раз. И покажи не ужас, когда ошибку можно обработать на 4-5 уровней выше нежели ее обнаружение? И чтобы два раза не переписывать, то добавим, что верхняя фунция внутри себя вызывает не одну функцию, а три-пять. И те внутри себя тоже вызывают что-то. И при обработке ошибок на верхнем уровне хотелось бы знать что за ошибка произошла и в какой именно функции. А чтобы еще более весело стало, то функции, в которых возникают ошибки пишутся другими командами. Посему их изменить ты не можешь. А коды ошибок они используют одинаковые.
Во-первых, ты смешиваешь несколько разных, независимых обстоятельств.
1) Что красивее
2) Что дороже
3) Что надёжнее
Собственно (1) я вообще не обсуждаю
Что касается (2) и (3), то использование всяких отмотчиков стеков RAII и т. д. в целом повышает надёжность кода на тему утечек. Правда совсем уж гарантий от них не даёт. Но какой-то уровень таки даёт, то есть в целом для среднего кода повышает его надёжность, повышает стоимость написания, но, возможно, снижает стоимость поддержки.
Использование исклчений понижает надёжность кода, повышает стоимость поддержки, и, возможно и стоимость разработки.
Чтобы компенсировать негатив от внедрения исклбчений приходится вводить соглашения, вроде базовой гарантии при исключениях, которая снова повышает надёжность, ещё раз повышает стоимость разработки, но, нозможно снижает стоимость поддержки, если она реально дастигнута, о всяком случае...
Я думаю, что ты со всем этим согласен, и весь вопрос в балансе этих вкладов.
А тут уже начинают становиться важными подробности...
Ну там, готовы ли мы, что иногда будем падать? То есть какое падение в надёжность от перехода "RAII+исключения по исключительным случам" -> "исключения на каждый чих" мы можем себе позволить, и какую часть этого падения НА ПРАКТИКЕ удастся скомпенсровать введением базовой гарантии, хотя бы частичным.
Вот по моему опыту переноса больших программ, могу сказать, что течь базовой гарантии была третьим источником трудноотлаживаемых багов после багов/отличий коспиляторов и порядка инициализации и вообще работы статических переменных...
Что как бы намекает
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>>>Обсуждался довольно простой вопрос -- обеспечивается ли базовая гарантия В РЕАЛНОСТИ... E>>>Исключения тут правда не при чём. Просто если исключения летают редко, то становится сильно менее важно, обеспечивается базовая гарантия или нет
AV>>С какой радости становится сильно менее важно? E>С такой, что нам всё равно, что будет в случае исключения, которого не будет...
Зато нам не все равно что будет в случае ошибки. Проблем никуда не делась.