Здравствуйте, Erop, Вы писали:
E>а при таком подходе умолчания неизбежно поменяются... Мы же не можем по недоступности любого файла рушить программу?
Зачем рушить? Ведь есть же такой уровень, при котором программа может принять осмысленное решение, что делать в случае отсутствия файла?
Рушить из-за отсутствия файла нужно только программы типа grep, т.е. работа которых бессмысленна целиком, если файла нет.
E>Значит нам начинает требоваться более высокий уровень гарантийй безопасности при исключениях, который так же, как и "проборос" расползается по всему коду. И что из двух дешевле в разработке, автоматическом контроле, тестировании и поддержке -- вопрос крайне тонкий E>И собственно он-то и представляет интерес, а не кидание какашками или измерения накладных расходов на SEH сам по себе...
Тут я согласен, если под "расползается" ты имеешь в виду, что весь код должен быть устойчив к исключениям.
И если в случае кодов ошибок это расползание видно явно и, как следствие №1, замусоривает код до невозможности, а как следствие №2, поощряет ленивых программеров забивать на обработку кодов, то в случае исключений код становится чистым и ясным, а игнорирование ошибки невозможно.
J>>Коды ошибок оправданы только там, где обработка ошибок происходит постоянно на всех уровнях и является именно обработкой с несколькими ветками, а не просто пробрасыванием "if(err)return err;". Потому что такое пробрасывание — это просто закат солнца исключения вручную. E>Даже в этом случае это не тоже самое, потому, что при кодах "проброс" происходит в явном месте алгоритма...
Ага. В каждой строчке (или еще хуже — в каждом подвыражении, которое теперь приходится разбивать на expression statement-ы и обвешивать замечательными "if(err)return err;"). Офигительная разница.
J>>Ничего не понял, но отвечу на то, что понял: способность функции бросать исключения — это часть ее интерфейса, совершенно верно. E>Это очень сильно иная парадигма.
Разве? Чем документирование кодов возврата отличается от документирования исключений?
E>Это примерно как "goto в программе может быть, ну пара даже может, но только в тех местах, где без goto совсем-совсем сильно нехорошо" против "goto -- обычный оператор управления потоком исполнения"... E>Это очень разные подходы, с очень разными накладными расходами, скилами архитекторов. кодеров и тестировщиков и т. д...
Не могу согласиться, сорри. return в середине функции эквивалентен goto на конец функции. Ты у нас сторонник подхода "Из функции должен быть ровно один return"? Если нет, то объясни мне, чем отличается исключение от множественного return.
E>На мой взгляд объединять их в один глупо.
Это странный вывод.
J>>Интерфейс функции — это все, что она принимает, плюс все, что она выдает обратно. Очевидно, исключения (и коды возврата) во вторую часть входят. E>А как ты относишься к возможности передавать в функцию метки для перехода в каком-то особом случае? Или, например, нескольким входам в функции? E>От этого всего отказались под воздействием идей Дейкстры, изложенных им в "Дисциплине программирования". Переход к массовым исключениям означает фактическийотказ от процедурного программирования. Это осознанный шаг? Если да, то он чем аргументируется?..
Ты, наверное, на ФУПМе учился Можешь закидать меня радиоактивными какашками, но я с этой идиомой не знаком. Сейчас прочитал в вики по диагонали и пришел к выводу, что эта радость не предусматривает return в середине функции — я прав?
Во-вторых, просто из определения, если я его правильно понял, weakest precondition — это условия, при которых операция даст нужный результат.
Так вот, weakest precondition для fopen с ненулевым результатом будет точно таким же, как для fopen, бросающей исключения в случае неудачи.
Поправь, если не так.
E>Банальный сценарий. Ты чего-то там делаешь, а в это время в фоне загудел бэкап или антивирь... E>Доступ к файлу -- это всегда гонки. Если твоя программа будет падать не каждый день, а каждую неделю, когда гонки таки случатся, то ты её просто вообще никогда не отладишь и всё.
Ну, например, вместо file_exists будет lock_file_if_exists
Здравствуйте, jazzer, Вы писали:
J>Зачем рушить? Ведь есть же такой уровень, при котором программа может принять осмысленное решение, что делать в случае отсутствия файла?
Чтобы можно было позволить себе не рушить, надо обеспечивать высокий уровень гарантий безопасности при исключениях, а это и есть то, что удорожает использование исключений...
J>Тут я согласен, если под "расползается" ты имеешь в виду, что весь код должен быть устойчив к исключениям.
Да, точно так.
J>И если в случае кодов ошибок это расползание видно явно и, как следствие №1, замусоривает код до невозможности, а как следствие №2, поощряет ленивых программеров забивать на обработку кодов, то в случае исключений код становится чистым и ясным, а игнорирование ошибки невозможно.
IMHO, всё ровно наоборот.
1) Подумали ли о том, что будет, если провалится то или это мето или просто так взяли и написали "чисто и ясно" и расслабились, НЕ ВИДНО.
2) Провал чего-то может быть очень сложным, рекурсивным и вообще маорпонимабельным.
3) Поведение описано в программе неявно, неверефицируемо, нетестируемо и труднопонимаемо...
J>Ага. В каждой строчке (или еще хуже — в каждом подвыражении, которое теперь приходится разбивать на expression statement-ы и обвешивать замечательными "if(err)return err;"). Офигительная разница.
Зачем это делать в каждом подвыражении?..
J>Разве? Чем документирование кодов возврата отличается от документирования исключений?
Тем, что исключение для объемлющего кода выглядит как goto. поток управления в ВЫЗВАЮЩЕМ коде становится непроцедурным...
J>Не могу согласиться, сорри. return в середине функции эквивалентен goto на конец функции. Ты у нас сторонник подхода "Из функции должен быть ровно один return"? Если нет, то объясни мне, чем отличается исключение от множественного return.
Читай Дейкстру.
Я не противник goto, кстати, и не противник множественного return
Я противник кода, который можно интерпретировать, как набор операций последовательно переводящих программу из одного состояния в другое.
То есть, если процедурность не страдает, то в goto нет проблемы (например выход из вложенного цикла по goto не проблема), а если страдает, то всё плохо и без goto
J>Ты, наверное, на ФУПМе учился
Нет, на проблемах. Но какое это имеет отношение к теме?
J>Можешь закидать меня радиоактивными какашками, но я с этой идиомой не знаком.
Крайне настоятельно тогда рекоммендую...
Там с азов всё идёт, так что можешь знакомые главы тупо пролистывать, но книжка очень дельная, и программисту её,в ернее изложенные в неё идеи, знать стоит. Есть по-русски и по-японски, ну и английский вариант тоже есть, есен пень
J>Сейчас прочитал в вики по диагонали и пришел к выводу, что эта радость не предусматривает return в середине функции — я прав?
В математически чистом варианте да, вернее для каждого return надо будет отдельно доказать попадание в постусловие. На практике бывает много кода, который очевидно не трудно доказуем таким образом. Даже если return'ов много...
J>Во-вторых, просто из определения, если я его правильно понял, weakest precondition — это условия, при которых операция даст нужный результат.
Это слабейшее предусловие заданного постусловия. J>Так вот, weakest precondition для fopen с ненулевым результатом будет точно таким же, как для fopen, бросающей исключения в случае неудачи. J>Поправь, если не так.
Да так. Дальше у нас возникает вопрос, допускает ли предусловие программы неоткрывающиеся файлы. Если таки да, то вариант с исключениями не канает, потому, что в некоторых допустимых предусловиями состояниях в результате выполнения попадём в состояние где выполненность постусловия неопределена...
J>Ну, например, вместо file_exists будет lock_file_if_exists
И чем это будет отличатьcя от обычного fopen?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Tanker, Вы писали:
T>Принципиальной разницы нет, и то и другое это исключения.
Тебе кажется, что возможность не разматывать стек непринципиальна?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, jazzer, Вы писали:
J>Как видишь, нехватку памяти можно обрабатывать как ты хочешь (сохранение данных и вылет без раскрутки стека), в рамках стандартного С++, безо всяких SEH-ов.
Конечно можно, можно и тоньше ещё всё устроить и запускать ту или иную обработку в зависимости от текущего аллокатора, например.
Но и сегфолт тоже стоит обрабатывать, если есть критические данные и ресурсы...
можно и всё разом тогда.
J>Везде можно установить свой обработчик и в нем делать что хочешь, включая прибивание программы с сохранением стека, отсылки минидампа разработчику и прочая и прочая.
Конечно везде, вернее везде, кроме throw...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, jazzer, Вы писали:
J>Код "прямой и модульной изначальной архитектуры" на кодах возврата на в студию. С обоснованием прямизны и модульности. J>И не забывай, мы тут говорим об обработке ошибок, так что потрудись убедить нас, что ни одной ошибки случайно не пропущено и что обрабатывать ошибки кодами возврата на порядок удобнее и безопаснее, чем исключениями. J>Просим! Просим!
Я нигде не говорил, что обрабатывать ошибки кодами возврата на порядок удобнее и безопаснее, чем исключениями. Надо читать собеседников внимательнее. Мой тезис был в том, что в большинстве практических случаев (однако естественно что ситуации оптимальные для исключений всё же есть) замена кодов возврата на исключения не приносит вообще никакой пользы. Вреда правда тоже особого нет, разве что небольшое увеличение объёма кода. Но если нет пользы, то и нет смысла.
On 27.02.2013 17:32, alex_public wrote:
> Мой тезис был в том, что в большинстве практических > случаев (однако естественно что ситуации оптимальные для исключений всё > же есть) замена кодов возврата на исключения не приносит вообще никакой > пользы.
Чево? Если код возврата — суть ошибка, то логично он должен быть заменен
на исключение (для С++), если это результат работы функции, то, конечно,
нет.
Здравствуйте, Patalog, Вы писали:
_>>Да, есть много народа, который применяет исключения везде, в том числе и где не надо. Видимо считают это чем-то типа серебряной пули... P>Т.е. позу Вы сменить не хотите. Понятно.
Так я же это не конкретно про вас, а вообще... )
P>Не ясно только где вы увидели про серебряную пулю, весь срач разгорелся как раз таки из-за позиции д'Артаньянов, которые считают серебряной пулей коды возврата, и о безусловном бане исключений с их стороны. В топике собрались разумные люди (в основном), которые понимают, что в разных ситуациях разные решения.
Безусловно. Но как раз размер области, где применение исключений полезно, и вызывает спор. У кого-то она огромна, а у кого-то минимальна. Естественно это в какой-то степени просто дело личного вкуса, т.к. оба решения при корректном кодирования будут работать одинаково правильно. Но обменяться аргументами о преимуществах своего "вкуса" вполне можно думаю...
P>А вот это сильное утверждение, которое требует столь же сильной аргументации. Не томите уже. P>Вот к примеру — чем try\catch {} сложнее чем if(err) {}? Ничем.
Банально размером кода. И не забываем про необходимость объявления классов исключений (если мы хотим делать всё совсем красиво) и т.п... Т.е. в случаях типа моего примера имеем определённый объём работы ради нулевой пользы.
P>Зато если вы завтра отрефакторите код так, что ф-я уйдет с 1-го уровня вложенности дальше — вы вдруг не забудете написать лапшу типа if(err) return err и потерять ошибку, ибо это будет не нужно.
Дело в том, что при нормальной архитектуре уход на другой уровень должен будет означать смену контекста/значения ошибки. Т.е. в любом случае надо делать не проброс ошибки, а какое-то переформатирование под новые смыслы. Ситуации, когда надо вытащить наверх самое низкоуровневое значение ошибки, очень редки (типа вашего jscript примера) при правильном проектирование и как раз их и неплохо обрабатывать исключениями.
P>И вообще, что значит "очень далеко по стеку вызовов"? Сколько вешать в граммах?
Ну я же говорил что это в какой-то степени дело личного вкуса. Которым мы тут сейчас и делимся.
P>А чем throw сложнее return? Тем что у пишущих return не принято думать о том, что возвращая ошибку нужно в той же мере заботиться об утечках и инвариантах что и в случае throw?
Если человек пишет в идиоме RAII, то ему в принципе должно быть безразлично. Но вы опять же пытаетесь показать что исключения не хуже кодов возврата. Так с этим никто и не спорит. Но они должны быть не просто не хуже, а заметно лучше, что бы появлялся смысл их применения.
Здравствуйте, Vzhyk, Вы писали:
V>Чево? Если код возврата — суть ошибка, то логично он должен быть заменен V>на исключение (для С++), если это результат работы функции, то, конечно, V>нет.
Приведи, пожалуйста, 10 примеров пар функция + код возврата, который точно ошибка...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
On 27.02.2013 18:07, Erop wrote:
> Приведи, пожалуйста, 10 примеров пар функция + код возврата, который > точно ошибка...
Это уже даже не смешно становиться. Самим еще не надоело обсуждать
сферических коней в вакууме. Понятие "ошибка" может быть только в
контексте твоей программы, а не вообще. В каких-то ситуация невыделения
памяти не ошибка, а вполне себе рабочая ситуация, которую надо
программно решить, в других нужно закончить программу с сообщением, что
память не выделилась и т.д.
Здравствуйте, Vzhyk, Вы писали:
V>Чево? Если код возврата — суть ошибка, то логично он должен быть заменен V>на исключение (для С++), если это результат работы функции, то, конечно, V>нет.
Ну мы тут уже выяснили что все подобные фразы сводятся к вопросу "а что считать ошибкой"... Но в любом случае в ответ на вашу фразу сразу возникает банальный вопрос "а зачем?". Не для галочки же просто, а должны быть какие-то преимущества от такой замены...
On 27.02.2013 18:22, alex_public wrote:
> Но в любом случае в ответ на вашу фразу сразу > возникает банальный вопрос "а зачем?". Не для галочки же просто, а > должны быть какие-то преимущества от такой замены...
Ну, например, потому, что код становится лаконичнее, чище, читать его проще.
Здравствуйте, Vzhyk, Вы писали:
>> Приведи, пожалуйста, 10 примеров пар функция + код возврата, который >> точно ошибка... V>Это уже даже не смешно становиться. Самим еще не надоело обсуждать V>сферических коней в вакууме.
поэтому и прошу привести десять КОНКРЕТНЫХ примеров того, что ТЫ САМ считаешь "ошибкой"...
А то тут какой-то грандиозный разброс мнений по этому поводу продемонстрирован, что делает обсуждение совершенно неконкретным...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
On 27.02.2013 18:35, Erop wrote:
> поэтому и прошу привести десять КОНКРЕТНЫХ примеров того, что ТЫ САМ > считаешь "ошибкой"...
Например отсутсвие файла, где данные для рассчетов лежат. Невозможность
выделить нужный мне объем памяти в конкретной задаче (например, проще
закрыть несколько других и запустить заново прогу или вообще перегрузить
комп).
On 27.02.2013 18:50, alex_public wrote:
> Это звучит правильно только для случаев отката куда-то очень далеко > назад по стеку вызовов при обработке ошибок.
Неа. Код ты пишешь в первую очередь для людей, тех кто его потом читать
будет, поддерживать (в том числе и для себя), компилятору же пофиг,
абсолютно.
Дальше, если в твоем коде так называемая "ошибка" представляет собой
типичное поведение программы, то нафига исключение, а то таким макаром и
if a<b можно через исключение написать.
хъ
P>>А вот это сильное утверждение, которое требует столь же сильной аргументации. Не томите уже. P>>Вот к примеру — чем try\catch {} сложнее чем if(err) {}? Ничем.
_>Банально размером кода. И не забываем про необходимость объявления классов исключений (если мы хотим делать всё совсем красиво) и т.п... Т.е. в случаях типа моего примера имеем определённый объём работы ради нулевой пользы.
Необходимость в новых классах исключений сильно преувеличена. Мне на практике хватает готовых из стандартной библиотки и буста.
Кроме того, в случе кодов возврата точно так же нужно городить новые enum'ы для кодов возврата.
P>>Зато если вы завтра отрефакторите код так, что ф-я уйдет с 1-го уровня вложенности дальше — вы вдруг не забудете написать лапшу типа if(err) return err и потерять ошибку, ибо это будет не нужно.
_>Дело в том, что при нормальной архитектуре уход на другой уровень должен будет означать смену контекста/значения ошибки. _>Т.е. в любом случае надо делать не проброс ошибки, а какое-то переформатирование под новые смыслы.
Ничем не отличается от исключений, кроме то, что в случае исключений мы можем на это забить, так как уровнем выше мы словим исключение по базе, а в твоем случае мы вынуждены пробрасывать\переформатировать, иначе потеряем ошибку и останемся в невалидном состоянии.
А при смене значения ошибки мы наблюдаем удивительный цирк переливания из пустого в порожнее — перекладывание из одного enum'а в другой, зачастую огороженный макросом со switch внутри.
хъ
P>>А чем throw сложнее return? Тем что у пишущих return не принято думать о том, что возвращая ошибку нужно в той же мере заботиться об утечках и инвариантах что и в случае throw?
_>Если человек пишет в идиоме RAII, то ему в принципе должно быть безразлично. Но вы опять же пытаетесь показать что исключения не хуже кодов возврата. Так с этим никто и не спорит. Но они должны быть не просто не хуже, а заметно лучше, что бы появлялся смысл их применения.
На мой вкус — кода заметно меньше, код прозрачнее, по happy path уж точно, что не маловажно для чтения оного через N времени.
А то иногда бывает так, что за обработкой ошибок не видно основной логики.
ЗЫ В библиотеках я по возможности предоставляю два вида интерфейса — с исключениями и с кодом ошибки, как это сделано в boost.asio
Здравствуйте, Vzhyk, Вы писали:
V>Например отсутсвие файла, где данные для рассчетов лежат. Невозможность V>выделить нужный мне объем памяти в конкретной задаче (например, проще V>закрыть несколько других и запустить заново прогу или вообще перегрузить V>комп).
То есть "ошибка" -- это то, после чего программу надо аварийно отгружать? Я верно понял или нет?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
On 27.02.2013 20:17, Erop wrote:
> То есть "ошибка" -- это то, после чего программу надо аварийно > отгружать? Я верно понял или нет?
В общем-то так. Все остальное — не ошибка, а требование.
Здравствуйте, Patalog, Вы писали:
P>Необходимость в новых классах исключений сильно преувеличена. Мне на практике хватает готовых из стандартной библиотки и буста. P>Кроме того, в случе кодов возврата точно так же нужно городить новые enum'ы для кодов возврата.
Ага, я тоже стандартные предпочитаю использовать. А в случае кодов возврата опять же предпочитаю сводить логику к true/false...
P>Ничем не отличается от исключений, кроме то, что в случае исключений мы можем на это забить, так как уровнем выше мы словим исключение по базе, а в твоем случае мы вынуждены пробрасывать\переформатировать, иначе потеряем ошибку и останемся в невалидном состоянии.
Такие дела обычно приводят к нарушению инкапсуляции и т.п.. По нормальному каждый уровень кода должен оставлять все внутренние детали внутри себя.
P>На мой вкус — кода заметно меньше, код прозрачнее, по happy path уж точно, что не маловажно для чтения оного через N времени. P>А то иногда бывает так, что за обработкой ошибок не видно основной логики.
Вот разделение логики и ошибок на уровне разных ключевых слов — это пожалуй единственный плюс, который можно приписать исключениям. Но он далеко не всем по вкусу. )
Здравствуйте, Vzhyk, Вы писали:
>> То есть "ошибка" -- это то, после чего программу надо аварийно отгружать? Я верно понял или нет? V>В общем-то так. Все остальное — не ошибка, а требование.
Хыхы, при таком определение ошибки я тоже готов написать что все ошибки надо обрабатывать только с помощью исключений.