Здравствуйте, eao197, Вы писали:
... E>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.
Здравствуйте, vayerx, Вы писали:
V>Здравствуйте, bexab, Вы писали:
B>>Наверное в том, что корректно работающую программу проще переделать в быструю, чем быструю в корректно работающую. V>Согласен. Оптимизировать/рефакторить программу многократно проще, когда она полностью работает и ее код покрыт тестами.
При условии, что для этой оптимизации не требуется полностью изменить алгоритм и структуры данных программы. А вот если потребуется — пишите все с начала.
With best regards
Pavel Dvorkin
Re[20]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Здравствуйте, eao197, Вы писали:
S>>>В языке никаких проблем сделать nothrow я не вижу.
E>>А он уже есть nothrow, но используется пока только для new.
ЮЖ>
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>Здравствуйте, eao197, Вы писали:
S>>>>В языке никаких проблем сделать nothrow я не вижу.
E>>>А он уже есть nothrow, но используется пока только для new.
ЮЖ>>
// Бросает исключение в случае пустой последовательности.
T max_element( FI begin, FI end );
// Не бросает исключений, но вызывает abort.
T max_element( FI begin, FI end, nothrow );
Правда здесь все только на уровне соглашений.
E>2. Где в стандартной библиотеке C++ еще используется nothrow, кроме operator new?
Там где имена функций/операторов одинаковы для throw и nothrow версий. Собственно только в new/delete.
Re[22]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, Юрий Жмеренецкий, Вы писали:
E>>1. Это что? ЮЖ>Вариант реализации вот этого: ЮЖ>
ЮЖ>// Бросает исключение в случае пустой последовательности.
ЮЖ>T max_element( FI begin, FI end );
ЮЖ>// Не бросает исключений, но вызывает abort.
ЮЖ>T max_element( FI begin, FI end, nothrow );
ЮЖ>
ЮЖ>Правда здесь все только на уровне соглашений.
Понятно. Именно об этом я и говорил, просто не было времени искать в документации, к какому конкретно типу относится nothrow, поэтому указал в прототипе nothrow без типа.
E>>2. Где в стандартной библиотеке C++ еще используется nothrow, кроме operator new? ЮЖ>Там где имена функций/операторов одинаковы для throw и nothrow версий. Собственно только в new/delete.
Вот об этом и речь. Хотя такое же соглашение можно было применить и для max_element.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[23]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>>>2. Где в стандартной библиотеке C++ еще используется nothrow, кроме operator new? ЮЖ>>Там где имена функций/операторов одинаковы для throw и nothrow версий. Собственно только в new/delete.
E>Вот об этом и речь. Хотя такое же соглашение можно было применить и для max_element.
А зачем нужна throw-версия для max_element ? После выброса исключения там два варианта: поймать и обработать, поймать и перевыбросить другое(более высокоуровневое) исключение. Первый случай сразу можно заменить на nothrow версию(с явной обработкой перед попыткой вызова), во-втором случае можно сразу выкинуть исключение необходимого типа.
Re[25]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>>>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода. CC>>Но это не значит что надо туда пхать весь функционал, который только можно придумать.
E>Хорошо, давай так: ты бы предпочел использовать:
E>a) только вариант max_element с необходимостью проверки возвращаемого значения; E>b) вариант max_element с выбросом исключений и max_element_reference без выброса исключений
В конкретном случае, если нет готового и известного мне на данный момент max_element, идеально подходящего под нужды задачи, я напишу свой, который будет делать то, что мне нужно. И уж точно не буду морочить себе голову какой из них кошернее. И совершенно точно не буду искать библиотеку, в которой есть такой вариант max_element — это не тот функционал, ради которого стоит так заморачиваться.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[24]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>А зачем нужна throw-версия для max_element ? После выброса исключения там два варианта: поймать и обработать, поймать и перевыбросить другое(более высокоуровневое) исключение.
Вообще-то три. ЮЖ>Первый случай сразу можно заменить на nothrow версию(с явной обработкой перед попыткой вызова), во-втором случае можно сразу выкинуть исключение необходимого типа.
Как насчет "проигнорировать и позволить вызывающему коду разобраться с проблемой"?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[25]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, Sinclair, Вы писали:
... ЮЖ>>Первый случай сразу можно заменить на nothrow версию(с явной обработкой перед попыткой вызова), во-втором случае можно сразу выкинуть исключение необходимого типа. S>Как насчет "проигнорировать и позволить вызывающему коду разобраться с проблемой"?
Если исключение вызвано невозможностью выполнения постусловий, то здесь генерация исключений оправдана. В случае с max_element нарушены предусловия. Именно с этой точки зрения throw вариант — избыточен. Если кому-нибудь все же необходимо такое поведение — пишут свой кидающий вариант.
Re[24]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, Юрий Жмеренецкий, Вы писали:
E>>>>2. Где в стандартной библиотеке C++ еще используется nothrow, кроме operator new? ЮЖ>>>Там где имена функций/операторов одинаковы для throw и nothrow версий. Собственно только в new/delete.
E>>Вот об этом и речь. Хотя такое же соглашение можно было применить и для max_element.
ЮЖ>А зачем нужна throw-версия для max_element ?
Еще раз: программисты ошибаются. ОШИБАЮТСЯ!
Это означает, что даже если программист думает, что max_element вызывается для непустой последовательности, то наивное использование max_element:
А вот если max_element будет выбрасывать исключение в случае пустой последовательности, то программа окажется во вполне определенном состоянии -- раскрутка стека по исключению.
Для фанатов производительности и изящного STL-стиля стандартная библиотека должна так же предоставлять небросающий вариант под именем max_element_reference (или max_element_pointer, или max_element_iterator), который возвращает итераторы.
Но я еще нигде не видел убедительных доказательств того, что лишний if в начале max_element, проверяющий последовательность на пустоту, способен привести к существенным накладным расходам.
Так же я не понимаю аргументов вида -- кому нужно, пусть сами проверяют возвращаемые значения, реализуют собственные политики обработки ошибок или пишут собственные варианты max_element. Это все работа, которую разработчики вынуждены проделывать снова и снова. А значит ее можно было бы сделать один раз -- в стандартной библиотеке. Либо же они ее вообще не делают, не проверяют результат max_element и оставляют в своих программах очередные бомбы замедленного действия.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[25]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
... ЮЖ>>А зачем нужна throw-версия для max_element ?
E>Еще раз: программисты ошибаются. ОШИБАЮТСЯ!
Не спорю... E>Это означает, что даже если программист думает, что max_element вызывается для непустой последовательности, то наивное использование max_element: E>
E>может оставлять программу в неопределенном состоянии.
... E>А вот если max_element будет выбрасывать исключение в случае пустой последовательности, то программа окажется во вполне определенном состоянии -- раскрутка стека по исключению.
Это фиктивное состояние, которое возникло при ошибке. И которое потенциально может быть "проглочено" вышестояшим catch(exception&). Т.е. программа не упадет, а сделает вид что все хорошо. Только от бага в ней это не спасает.
E>Но я еще нигде не видел убедительных доказательств того, что лишний if в начале max_element, проверяющий последовательность на пустоту, способен привести к существенным накладным расходам.
, то это логическая ошибка.
E>Так же я не понимаю аргументов вида -- кому нужно, пусть сами проверяют возвращаемые значения, реализуют собственные политики обработки ошибок или пишут собственные варианты max_element. Это все работа, которую разработчики вынуждены проделывать снова и снова. А значит ее можно было бы сделать один раз -- в стандартной библиотеке.
Контраргументы приведены в здесь
Здравствуйте, Юрий Жмеренецкий, Вы писали:
E>>А вот если max_element будет выбрасывать исключение в случае пустой последовательности, то программа окажется во вполне определенном состоянии -- раскрутка стека по исключению. ЮЖ>Это фиктивное состояние, которое возникло при ошибке. И которое потенциально может быть "проглочено" вышестояшим catch(exception&). Т.е. программа не упадет, а сделает вид что все хорошо. Только от бага в ней это не спасает.
Ну все, приплыздец. Я просто не знаю, что против этого возразить. Функция max_element выбрасывает исключение, поскольку она не может работать в условиях пустой последовательности. Программа проглатывает это исключение и делает вид, что все нормально... Какой смысл вообще говорить о таких программах?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Юрий Жмеренецкий, Вы писали:
E>>>А вот если max_element будет выбрасывать исключение в случае пустой последовательности, то программа окажется во вполне определенном состоянии -- раскрутка стека по исключению. ЮЖ>>Это фиктивное состояние, которое возникло при ошибке. И которое потенциально может быть "проглочено" вышестояшим catch(exception&). Т.е. программа не упадет, а сделает вид что все хорошо. Только от бага в ней это не спасает.
E>Ну все, приплыздец. Я просто не знаю, что против этого возразить. Функция max_element выбрасывает исключение, поскольку она не может работать в условиях пустой последовательности. Программа проглатывает это исключение и делает вид, что все нормально... Какой смысл вообще говорить о таких программах?
Ну а как же это: E>Еще раз: программисты ошибаются. ОШИБАЮТСЯ!
Сначала все работает хорошо, в max_element всегда(!) передаются валидные данные, поэтому обработчика нет. Порефакторили, _ошиблись_, где-то стоит корневой обработчик который молча проглотил, возможно скинув в лог информацию. Но программа продолжает работать дальше. Возможно такое ?
Кроме того, в условиях когда все функции(а-ля max_element) начинают кидать исключения по любому поводу, становится существенно сложнее писать код со strong guarantee.
Re[28]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Сначала все работает хорошо, в max_element всегда(!) передаются валидные данные, поэтому обработчика нет. Порефакторили, _ошиблись_, где-то стоит корневой обработчик который молча проглотил, возможно скинув в лог информацию. Но программа продолжает работать дальше. Возможно такое ?
Возможно, но это все гораздо лучше разыменования невалидного итератора.
ЮЖ>Кроме того, в условиях когда все функции(а-ля max_element) начинают кидать исключения по любому поводу, становится существенно сложнее писать код со strong guarantee.
Это не повод считать существующий вариант max_element мегаудачным решением.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[29]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>Сначала все работает хорошо, в max_element всегда(!) передаются валидные данные, поэтому обработчика нет. Порефакторили, _ошиблись_, где-то стоит корневой обработчик который молча проглотил, возможно скинув в лог информацию. Но программа продолжает работать дальше. Возможно такое ?
E>Возможно, но это все гораздо лучше разыменования невалидного итератора.
Чем лучше ? тем что у нас система в непредсказуемом состоянии, от которой можно ожидать все что угодно?
ЮЖ>>Кроме того, в условиях когда все функции(а-ля max_element) начинают кидать исключения по любому поводу, становится существенно сложнее писать код со strong guarantee.
E>Это не повод считать существующий вариант max_element мегаудачным решением.
По крайней мере к нему легко прикручивается любое поведение, хотя это уже не аргумент...
Re[30]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>>Сначала все работает хорошо, в max_element всегда(!) передаются валидные данные, поэтому обработчика нет. Порефакторили, _ошиблись_, где-то стоит корневой обработчик который молча проглотил, возможно скинув в лог информацию. Но программа продолжает работать дальше. Возможно такое ?
E>>Возможно, но это все гораздо лучше разыменования невалидного итератора. ЮЖ>Чем лучше ? тем что у нас система в непредсказуемом состоянии, от которой можно ожидать все что угодно?
Я исхожу из тезиса, что выброшенное исключение дает C++ программисту простой способ прервать проблемную ситуацию и восстановить работоспособность программы где-то наверху. Либо же завершить программу с более-менее явной диагностикой.
А вот разыменование невалидного итератора может привести к наведенной ошибке, которая может проявится через неопределенное время в непредсказуемом месте. Вам бы хотелось разбираться с падением банковской системы, которая должна работать в режиме 24x7 под нагрузкой в несколько тысяч транзакций в секунду из-за того, что месяц назад при некорректном использовании max_element был испорчен какой-то байтик в памяти?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[31]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>>>Сначала все работает хорошо, в max_element всегда(!) передаются валидные данные, поэтому обработчика нет. Порефакторили, _ошиблись_, где-то стоит корневой обработчик который молча проглотил, возможно скинув в лог информацию. Но программа продолжает работать дальше. Возможно такое ?
E>>>Возможно, но это все гораздо лучше разыменования невалидного итератора. ЮЖ>>Чем лучше ? тем что у нас система в непредсказуемом состоянии, от которой можно ожидать все что угодно?
E>Я исхожу из тезиса, что выброшенное исключение дает C++ программисту простой способ прервать проблемную ситуацию и восстановить работоспособность программы где-то наверху.
Восстановить работоспособность не всегда возможно, баги(а мы о них) разные бывают.
Здесь я говорю только об исключениях, которые возникают в случае невыполнения предусловий.
E>Либо же завершить программу с более-менее явной диагностикой.
Тут всплывает одна проблема — обеспечение целостности данных, которыми программа оперировала в момент возникновения бага. Если раскручивать стек, то _возможно_ что будут выполнены некоторые операции, которые нарушат целостность. Тут опять всплывает строгая гарантия.
E>А вот разыменование невалидного итератора может привести к наведенной ошибке, которая может проявится через неопределенное время в непредсказуемом месте.
Некорректная работа в случае замалчивания о произошедшей ошибке может привести к такому же результату.
E>Вам бы хотелось разбираться с падением банковской системы, которая должна работать в режиме 24x7 под нагрузкой в несколько тысяч транзакций в секунду из-за того, что месяц назад при некорректном использовании max_element был испорчен какой-то байтик в памяти?
Вот почему-то все думают что если я использую nothrow версию, то я не проверяю параметры... Это неверно. Они не проверяются только если их значения можно гарантировать, основываясь на текущем состоянии. Это _другой_ подход. На пост и предусловиях, assert'ax, тестировании и документации, на существовании контрактов.
Разыменование невалидного итератора — эта ситуация которой не может быть вообще. Исходя из пост и предусловий можно доказывать корректность программы(несколько преувеличено, но я думаю что понятно о чем я). В Вашем случе — баг рассматривается как нечто, которое может вполне себе спокойно существовать в работающей программе.
Для обеспечения совсем уж 100% надежности применяются другие методы, например N-version programming.
Re[32]: Почему преждевременная оптимизация - корень всех зол
Здравствуйте, Юрий Жмеренецкий, Вы писали:
E>>Вам бы хотелось разбираться с падением банковской системы, которая должна работать в режиме 24x7 под нагрузкой в несколько тысяч транзакций в секунду из-за того, что месяц назад при некорректном использовании max_element был испорчен какой-то байтик в памяти? ЮЖ>Вот почему-то все думают что если я использую nothrow версию, то я не проверяю параметры...
Вы может и проверяете. Я не всегда проверяю. Из-за чего временами приходится выискивать баги, связанные с битой памятью.
ЮЖ>Разыменование невалидного итератора — эта ситуация которой не может быть вообще. Исходя из пост и предусловий можно доказывать корректность программы(несколько преувеличено, но я думаю что понятно о чем я).
Нет, я не понимаю. Так же я не понимаю, о каких пред- и постусловиях можно говорить в C++ -- в C++ это разве что благая воля программиста (использование assert-ов или условий проверки).
ЮЖ>В Вашем случе — баг рассматривается как нечто, которое может вполне себе спокойно существовать в работающей программе.
Боюсь, что это не только в моем случае. Это, насколько я могу судить, повсеместное явление.
Более того, люди даже разрабатывают способы разработки программ, которые выживают в условиях присутствия багов — Making reliable distributed systems <b>in the presence of sodware errors</b> И достигают немалых успехов.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.