Здравствуйте, Tanker, Вы писали:
T>По твоему исключения SEH, как ты предложил, это сишный подход ? Т.е. ты видишь серьезные отличие между try catch и __try __except ? Я даже и не знаю, как быть.
Нууу при определённых флагах в VC это вполне может быть одним и тем же. ))) А вообще __try __except — это всё же не C++. )))
хъ
_>На самом деле я просто смотрю сколько народа готово использовать исключения даже в приведённом мною случае. И каждый высказавшийся за это увеличивает моё согласие с решением разных компаний забанить исключения в целом. Понятна моя мысль? )
Мысль предельно простая, чего ж тут не понять.
Обоснование, правда, как это всегда бывает с простыми и ясными для понимания, но не правильными решениями, подкачало.
хъ
_>При нормальном проектирование модульности обработка ошибок в большинстве случаев будет идти на предыдущем уровне стека вызовов.
Это высказывание "ниачем" (с), примерно на уровне "хорошо быть богатым и красивым"
Когда нечего сказать, начинают говорить про некое "нормальное проектирование" и т.д.
Я привел конкретное проектное решение, где спользование исключений оправдано, ящетаю.
Точно так же как и кодов возврата, там где это опять таки оправдано.
Если вы не согласны — обоснуйте, если исходных данных не достаточно — спрашивайте.
_>А в тех редких случаях, когда это не так, как раз и есть смысл использовать исключения.
Видимо у меня эти случаи не такие уж и редкие. Это конечно из-за отсутствия "нормального проектирования", ясное дело.
Да и вообще, народ который пользуется исключениями поголовно этим страдает. Вкупе с необычной формой мазохизма.
Только некоторые отдельные товарищи стоят в позе д'Артаньяна.
_>Вот вы написали что не понимаете про глубину стека и тут же приводите буквально идеальный пример этого. Причём замечу что даже с использование того же слова ("протаскивать коды возврата из самой глубины на самый вверх"). У вас как раз тот самый необычный случай, когда вся обработка идёт только на самом высоком уровне — идеальное применение исключений.
Там не никакой обработки, исключения там используются просто как удобный транспорт для передачи тех же кодов возврата наружу.
И да, про глубину стека я прекрасно понимаю, я не понимаю "должны приводить" вкупе с "глубокой раскрутке стека".
Никто никому не должен, тем более глобально. Имхо, если функция не может выполнить свой контракт при корректно заданных предусловиях, либо при этом нарушается инвариант (что в принципе то же самое) — нужно бросить исключение.
Поглядел по диагонали на свой код — кода возврата 90% использую только в вырожденном случае (true or false) и ф-х типа validate\check etc.
Волосы при этом мягкие и шелковистые, про глубину стека для принятия решения что применить — вспоминаю наверное в последнюю очередь, если вспоминаю вообще.
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Patalog, Вы писали:
P>>ЗЫ Судя по всему тебе не интересно обсуждение, тебе интересно погыгыкать.
_>На самом деле я просто смотрю сколько народа готово использовать исключения даже в приведённом мною случае. И каждый высказавшийся за это увеличивает моё согласие с решением разных компаний забанить исключения в целом. Понятна моя мысль? )
Между тем твой пример как раз демонстрирует недостатки обработки исключительных ситуаций через коды возврата: если в CreateNewProfile что-то пойдет не так, то это будет просто проигнорировано и дальнейший код будет либо пытаться работать с неполностью созданным профилем со всякими непредсказуемыми спец-эффектами либо будет перегружен проверками IsProfileValid, что и читаемость ухудшит и от производительности откушает. Да и сама ReadProfile возвращает только bool и если вышло false, то не ясно то ли это просто отсутсвие ранее сохраненного профиля (вполне ожидамая ситуация), то ли испорченнй профиль или ошибка чтения из файла ("глотать" эти ситуации создавая новый профиль может быть сильно нехорошо).
В то же время с незабанеными исключениями этот фрагмент может выглядеть точно так же: ReadProfile так же возвращает bool, говорящий нужно ли создавать новый профиль или нет (если отсутствие профиля не является исключительной ситуацией), а в случае "чего-то не так" и ReadProfile и CreateNewProfile кидают исключения (причем где-нибудь глубоко по дереву своих вызовов).
Здравствуйте, Erop, Вы писали:
L>>Ну ты же так и ниасилил обосновать, зачем тебе нужен подобный фестиваль. Все, что мы услышали — это то, что ты "знаешь, как". Ну, знай дальше.
E>Ну я же не нанимался учить тебя альтернативным подходам к использованию или неиспользованию исключений?..
Мания величия?
E>Я утверждаю, что код с гарантиями будет сложнее и неэффективнее кода без гарантий. Только и всего.
Утверждаешь — доказывай, чо.
E>Но если тебе не интересно это обсуждение, то я не очень понимаю, что ты тут пишешьи зачем? Сожержание той пары книжек, из которых ты узнал про обработку исключений и про строгую и базовую гарантии ты пересказываешь не особо точно, примерно на уровне статьи из вики. Наверное для каких-то целей этого достаточно. Дальнейшее твоё участи в обсуждении какой смысл должно по твоему нести-то?
У тебя приступ шизофрении? С чего ты взял, что я тут тебе какие-то книжки пересказывать собираюсь?
Здравствуйте, Patalog, Вы писали:
P>Видимо у меня эти случаи не такие уж и редкие. Это конечно из-за отсутствия "нормального проектирования", ясное дело.
Это в каждом конкретном случае надо смотреть. Например ваш пример с вызовами из jscript'a похоже как раз отлично подходящий для исключений. Но не хотите же вы сказать что у вас большинство проектов по такой схеме работают?
P>Да и вообще, народ который пользуется исключениями поголовно этим страдает. Вкупе с необычной формой мазохизма. P>Только некоторые отдельные товарищи стоят в позе д'Артаньяна.
Да, есть много народа, который применяет исключения везде, в том числе и где не надо. Видимо считают это чем-то типа серебряной пули...
P>И да, про глубину стека я прекрасно понимаю, я не понимаю "должны приводить" вкупе с "глубокой раскрутке стека". P>Никто никому не должен, тем более глобально. Имхо, если функция не может выполнить свой контракт при корректно заданных предусловиях, либо при этом нарушается инвариант (что в принципе то же самое) — нужно бросить исключение. P>Поглядел по диагонали на свой код — кода возврата 90% использую только в вырожденном случае (true or false) и ф-х типа validate\check etc. P>Волосы при этом мягкие и шелковистые, про глубину стека для принятия решения что применить — вспоминаю наверное в последнюю очередь, если вспоминаю вообще.
Всё очень просто и я уже даже писал кому-то здесь об этом. Вы безусловно можете применять исключения везде, вне зависимости от глубины стека вызова. Но имеет смысл их применять только для случаев обработки где-то очень далеко по стеку вызовов, т.к. в противоположном случае они просто не приносят никаких бонусов (а код при этом усложняют) по сравнению с теми же кодами возврата.
Здравствуйте, rusted, Вы писали:
R>Между тем твой пример как раз демонстрирует недостатки обработки исключительных ситуаций через коды возврата: если в CreateNewProfile что-то пойдет не так, то это будет просто проигнорировано и дальнейший код будет либо пытаться работать с неполностью созданным профилем со всякими непредсказуемыми спец-эффектами либо будет перегружен проверками IsProfileValid, что и читаемость ухудшит и от производительности откушает.
Если бы CreateNewProfile могла завершиться неудачей (неудачу выделения оперативки не считаем), то в моём коде безусловно была бы обработка соответствующей ошибки. Не надо подменять одну задачку другой — я написал именно то, что хотел написать. Хотя собственно говоря и ваш вариант задачки ничего не изменил бы в дискуссии, просто мой пример тогда бы чуть по другому выглядел.
R>Да и сама ReadProfile возвращает только bool и если вышло false, то не ясно то ли это просто отсутсвие ранее сохраненного профиля (вполне ожидамая ситуация), то ли испорченнй профиль или ошибка чтения из файла ("глотать" эти ситуации создавая новый профиль может быть сильно нехорошо).
Т.е. в случае повреждения профиля программка больше не сможет штатно работать, пока кто-то не исправит проблему и не перезапустит её? ) Интересная логика конечно))) Хотя в определённых областях и такое может быть. Но здесь подразумевалось всё же немного другое.
R>В то же время с незабанеными исключениями этот фрагмент может выглядеть точно так же: ReadProfile так же возвращает bool, говорящий нужно ли создавать новый профиль или нет (если отсутствие профиля не является исключительной ситуацией), а в случае "чего-то не так" и ReadProfile и CreateNewProfile кидают исключения (причем где-нибудь глубоко по дереву своих вызовов).
Это решение другой задачки, а не той, которую обсуждал я. И если обсудить какую-то другую изначальную логику, то я вполне могу допустить вариант, в котором исключения будут полезны. Например в случае если ошибка в функции ReadProfile на существующем профиле обязательно должна прерывать всё исполнение программы.
_>Мммм на мой взгляд правильнее решать эти задачи с точки зрения правильной архитектуры, а не таких убойных вещей как исключения. А точнее логичнее сделать у подобных классов приватный конструктор (без всяких исключений и двух фаз) и создавать их только своей функцией, которая умеет в начале проверить что все необходимые возможности железа и т.п. присутствуют.
Это как посмотреть. Конечно, приведенные мной вещи чаще создаются через фабрики, и там для контроля ошибок возможностей море. Но это не исключает основной идеи о том, что объект, который нельзя никак использовать, не должен быть создан вообще.
_>Жаль только с выделением памяти такой фокус не прокатывает. Точнее технические то можно (собственно new — как раз и есть такая особая функция), но тогда во-первых будет дико загромождённый код, а во-вторых обработка нехватки памяти в любом случае сводится к очень специфичным делам. Так что тут по любому исключения хороши.
Есть более жизненный пример — класс "натуральная дробь". Реализация базовых операций с дробями (сложение, вычитание, умножение, деление и т.п.) Очевидно, что если значение знаменателя, переданное в конструктор такого объекта, равно нулю, то смысла в такой дроби нет. Здесь самый разумный вариант — дать по рукам выкинуть исключение.
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, jazzer, Вы писали:
J>>Правда? Это только в двухстрочных примерах все так хорошо и разницы не видно. J>>А на самом деле внутри твоей функции ReadProfile зовется еще 50 функций на 10 уровнях вложенности. И ни одна из них, заметь, не способна обработать ошибку на своем уровне, и ей остается лишь передать ошибку на верхний уровень, который способен принять решение "Не считалось? Ну и хрен с ним, создадим новый".
_>Описаны очень чёткие симптомы кривой и не модульной изначальной архитектуры.
Код "прямой и модульной изначальной архитектуры" на кодах возврата на в студию. С обоснованием прямизны и модульности.
И не забывай, мы тут говорим об обработке ошибок, так что потрудись убедить нас, что ни одной ошибки случайно не пропущено и что обрабатывать ошибки кодами возврата на порядок удобнее и безопаснее, чем исключениями.
Просим! Просим!
Здравствуйте, alex_public, Вы писали:
_>Вы очень хорошо обосновали почему и как тут можно использовать исключения. Собственно с этим никто и не спорил. Вопрос в том зачем их тут использовать, если решение без них работает как минимум не хуже. Принцип Оккама как бы никто не отменял...
Вы сначала продемонстрируйте свое "не хуже", а потом уже про бритье поговорим.
Здравствуйте, Abyx, Вы писали:
A>а тебе надо организовать приз за каждый пропущенный код ошибки.
Зачем? Я и так знаю, что совсем избежать ошибок такого рода не получится...
Я просто из этого знания делаю вывод, что надо выбирать такие методы программирования, для которых это нефатально...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
E>>>Ну то есть мы возвращаемся к исходному тезису "а что же такое ошибка?" J>>Ага, причем тезис был мой E>Ну тут у разных сторон есть разные ответы на этот вопрос
Не сомневаюсь. Но это не тот вопрос, ответ на который мы ищем. Правильный вопрос — как обрабатывать то, что ты считаешь ошибкой — кодами возврата или исключениями? Мое мнение — исключения должны быть средством по умолчанию. Коды ошибок оправданы только там, где обработка ошибок происходит постоянно на всех уровнях и является именно обработкой с несколькими ветками, а не просто пробрасыванием "if(err)return err;". Потому что такое пробрасывание — это просто закат солнца исключения вручную.
J>>Логика очень простая: функция должна выполнить некое задание, которое ей дает вызывающий код. J>>Если она это задание выполнить не может, она бросает исключение. J>>Вот и все. E>То есть исключения -- это уже не ошибка, поле которой мы то ли отгружаемся, то ли сохраняемся и отгружаемся, а обычня часть интерфейса функции. Так?
Ничего не понял, но отвечу на то, что понял: способность функции бросать исключения — это часть ее интерфейса, совершенно верно.
Интерфейс функции — это все, что она принимает, плюс все, что она выдает обратно. Очевидно, исключения (и коды возврата) во вторую часть входят.
Или, иными словами, то, как функция сообщает об ошибках — часть ее интерфейса. Это относится и к исключениям, и к кодам возврата.
E>Не жалко процедурного стиля программирования и слабейшего предусловия с ним?..
э?
J>>Т.е. open_file(path) должна бросать исключение, если файла нет. Но при этом может параллельно существовать небросающий интерфейс, например, bool file_can_be_open(path, mode), bool path_is_well_formed(path).
E>То, что true из file_can_be_open(path, mode), не гарантирует возможности открыть файл, так как это два РАЗНЫХ запроса, между которыми может вклиниться другой потокЪпроцесс/компьютер не смущает?..
Очевидно, если ты предполагаешь такие гонки, надо программировать иначе
Здравствуйте, landerhigh, Вы писали:
E>>Ну я же не нанимался учить тебя альтернативным подходам к использованию или неиспользованию исключений?.. L>Мания величия?
В смысле? Я не думаю, что мне это нужно и не уверен, что я это смогу. При чём тут МВ?
Или ты про себя лбимого?
E>>Я утверждаю, что код с гарантиями будет сложнее и неэффективнее кода без гарантий. Только и всего. L>Утверждаешь — доказывай, чо.
Ну, например, переаллокация буфера массива просто в лоб проще и прямее того же самого, но с гарантиями...
L>У тебя приступ шизофрении? С чего ты взял, что я тут тебе какие-то книжки пересказывать собираюсь?
Я не знаю, что ты собираешься, но пока что из того, что ты написал, были или просто всякие дразнилки и обижалки, или пересказ банальностей из пары книжек.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, jazzer, Вы писали:
J>Не сомневаюсь. Но это не тот вопрос, ответ на который мы ищем. Правильный вопрос — как обрабатывать то, что ты считаешь ошибкой — кодами возврата или исключениями? Мое мнение — исключения должны быть средством по умолчанию.
А этот вопрос сильно зависит от того что же мы таки считаем ошибкой. Грубо говоря, Если недоступность к файлу в fopen мы считаем таки ошибкой, то ответ будет один, а если нет, то другой...
Но ты же пишешь так: J>>>Логика очень простая: функция должна выполнить некое задание, которое ей дает вызывающий код. J>>>Если она это задание выполнить не может, она бросает исключение. J>>>Вот и все.
а при таком подходе умолчания неизбежно поменяются... Мы же не можем по недоступности любого файла рушить программу? Значит нам начинает требоваться более высокий уровень гарантийй безопасности при исключениях, который так же, как и "проборос" расползается по всему коду. И что из двух дешевле в разработке, автоматическом контроле, тестировании и поддержке -- вопрос крайне тонкий
И собственно он-то и представляет интерес, а не кидание какашками или измерения накладных расходов на SEH сам по себе...
J>Коды ошибок оправданы только там, где обработка ошибок происходит постоянно на всех уровнях и является именно обработкой с несколькими ветками, а не просто пробрасыванием "if(err)return err;". Потому что такое пробрасывание — это просто закат солнца исключения вручную.
Даже в этом случае это не тоже самое, потому, что при кодах "проброс" происходит в явном месте алгоритма...
J>Ничего не понял, но отвечу на то, что понял: способность функции бросать исключения — это часть ее интерфейса, совершенно верно.
Это очень сильно иная парадигма.
Это примерно как "goto в программе может быть, ну пара даже может, но только в тех местах, где без goto совсем-совсем сильно нехорошо" против "goto -- обычный оператор управления потоком исполнения"...
Это очень разные подходы, с очень разными накладными расходами, скилами архитекторов. кодеров и тестировщиков и т. д...
На мой взгляд объединять их в один глупо.
J>Интерфейс функции — это все, что она принимает, плюс все, что она выдает обратно. Очевидно, исключения (и коды возврата) во вторую часть входят.
А как ты относишься к возможности передавать в функцию метки для перехода в каком-то особом случае? Или, например, нескольким входам в функции?
От этого всего отказались под воздействием идей Дейкстры, изложенных им в "Дисциплине программирования". Переход к массовым исключениям означает фактическийотказ от процедурного программирования. Это осознанный шаг? Если да, то он чем аргументируется?..
J>Или, иными словами, то, как функция сообщает об ошибках — часть ее интерфейса. Это относится и к исключениям, и к кодам возврата.
Возможно я отстал и уже придумали, как обработку исклчений запихать в weekest_precondition, если это так -- поделись, пожалуйста, если нет, то ответь на вопрос чем обосновывается при этом отказ от доказуемости кода?
E>>Не жалко процедурного стиля программирования и слабейшего предусловия с ним?.. J>э?
Гугол? (я там выше сослался прямо на основополагающую работу)
J>Очевидно, если ты предполагаешь такие гонки, надо программировать иначе
В смысле "такие гонки"? Сейчас ОС многозадачные, ко многим реурсам есть доступ у многих пользователей со многих компов, к тому же...
Банальный сценарий. Ты чего-то там делаешь, а в это время в фоне загудел бэкап или антивирь...
Доступ к файлу -- это всегда гонки. Если твоя программа будет падать не каждый день, а каждую неделю, когда гонки таки случатся, то ты её просто вообще никогда не отладишь и всё.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
[]
_>Это в каждом конкретном случае надо смотреть.
Это понятно, и в той же мере относится к вашему примеру с профилями.
Но вы почему-то из разных мнений по этому вопросу, вызванных недостатком информации, пытаетесь сделать вывод о лютом баттхерте сторонников исключений.
_>Например ваш пример с вызовами из jscript'a похоже как раз отлично подходящий для исключений.
Как раз таки концептуально это не правильное использование исключений.
И пример этот я привел для того, чтобы показать где еще исключения могут быть удобнимы.
_>Но не хотите же вы сказать что у вас большинство проектов по такой схеме работают?
Упаси бог. Это жуткий легаси, который я вынужден поддерживать вот уже 3-й год.
Сейчас правда я его отрефакторил до такой степени, что это практически с 0 написанный код.
Но нек. решения я вынужден поддерживать, в т.ч. проброс ошибок, ибо это публичный контракт и на это завязано куча решений 3-х лиц.
P>>Да и вообще, народ который пользуется исключениями поголовно этим страдает. Вкупе с необычной формой мазохизма. P>>Только некоторые отдельные товарищи стоят в позе д'Артаньяна.
_>Да, есть много народа, который применяет исключения везде, в том числе и где не надо. Видимо считают это чем-то типа серебряной пули...
Т.е. позу Вы сменить не хотите. Понятно.
Не ясно только где вы увидели про серебряную пулю, весь срач разгорелся как раз таки из-за позиции д'Артаньянов, которые считают серебряной пулей коды возврата, и о безусловном бане исключений с их стороны. В топике собрались разумные люди (в основном), которые понимают, что в разных ситуациях разные решения.
хъ
_>Всё очень просто и я уже даже писал кому-то здесь об этом. _>Вы безусловно можете применять исключения везде, вне зависимости от глубины стека вызова.
Ясное дело просто. Конечно могу, средство (язык) позволяет, вы мне не начальник, с чего я у вас разрешение буду спрашивать?
_>Но имеет смысл их применять только для случаев обработки где-то очень далеко по стеку вызовов, _>т.к. в противоположном случае они просто не приносят никаких бонусов (а код при этом усложняют) по сравнению с теми же кодами возврата.
А вот это сильное утверждение, которое требует столь же сильной аргументации. Не томите уже.
Вот к примеру — чем try\catch {} сложнее чем if(err) {}? Ничем. Зато если вы завтра отрефакторите код так, что ф-я уйдет с 1-го уровня вложенности дальше — вы вдруг не забудете написать лапшу типа if(err) return err и потерять ошибку, ибо это будет не нужно.
И вообще, что значит "очень далеко по стеку вызовов"? Сколько вешать в граммах?
А чем throw сложнее return? Тем что у пишущих return не принято думать о том, что возвращая ошибку нужно в той же мере заботиться об утечках и инвариантах что и в случае throw?
Здравствуйте, MTD, Вы писали:
MTD>Не стоит искать смысл, там где его нет. У меня сложилось мнение, что в данной теме ты просто троллишь, выдумываешь сферических коней и просишь их обосновать.
Если даже это и так, то зачем ты написал это вот своё собщение?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Patalog, Вы писали:
P>Вот к примеру — чем try\catch {} сложнее чем if(err) {}?
Примерно тем же, чем goto сложнее чем if|while. Программа утрачивает процедурность...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
T>> Т.е. ты видишь серьезные отличие между try catch и __try __except ? E>Конечно вижу. Обработчик SEH может вызвать terminate() ДО раскрутки стека
Блин. Еще раз: открой для себя set_new_handler.
Required behavior: A new_handler shall perform one of the following:
— make more storage available for allocation and then return;
— throw an exception of type bad_alloc or a class derived from bad_alloc; — terminate execution of the program without returning to the caller;
Как видишь, нехватку памяти можно обрабатывать как ты хочешь (сохранение данных и вылет без раскрутки стека), в рамках стандартного С++, безо всяких SEH-ов.
То же относится к set_terminate:
Required behavior: A terminate_handler shall terminate execution of the program without returning to the caller.
Default behavior: The implementation’s default terminate_handler calls abort().
и set_unexpected:
Required behavior: An unexpected_handler shall not return. See also 15.5.2.
Default behavior: The implementation’s default unexpected_handler calls std::terminate().
Везде можно установить свой обработчик и в нем делать что хочешь, включая прибивание программы с сохранением стека, отсылки минидампа разработчику и прочая и прочая.
Важное отличие от at_exit — установку обработчика можно откатить, в то время как то, что зарегистрировано в atexit, никак уже не уберешь (разве что свою инфраструктуру городить для этого).
Здравствуйте, Erop, Вы писали:
T>>По твоему исключения SEH, как ты предложил, это сишный подход ? E>Я где-то предлагал SEH? Это ты про сегфолт что ли? Поверх SEH можно сделать обработку похожую на сигналы, но весь SEH для этого не нужен
Конечно предполагал. Тебе еще надо допилить SEH до приемлемого юзания. Получится ровно то же, только на коленке.
T>> Т.е. ты видишь серьезные отличие между try catch и __try __except ? E>Конечно вижу. Обработчик SEH может вызвать terminate() ДО раскрутки стека
Принципиальной разницы нет, и то и другое это исключения.
Здравствуйте, alex_public, Вы писали:
T>>По твоему исключения SEH, как ты предложил, это сишный подход ? Т.е. ты видишь серьезные отличие между try catch и __try __except ? Я даже и не знаю, как быть.
_>Нууу при определённых флагах в VC это вполне может быть одним и тем же. ))) А вообще __try __except — это всё же не C++. )))
Разумеется, речь то про сишную обработку исключений.