Re[7]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.11.05 13:10
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

E>>Во что же тогда программирование превратиться?


СГ>А Вы подумайте.


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

Кстати, со мной лучше на "ты", поскольку, как правило, переход на "Вы" означает начало выяснения отношений.

СГ>Если верить рекламе языков (Java, C#), то "программирование — это лёгкое и непринуждённое занятие". Обманыевает эта реклама, хотя бы пять процентов головного мозга напрягать всё-равно надо.


Ну блин, верить рекламе...
В отличии от Запада, у нас был хороший афоризм: "Хороший товар в рекламе не нуждается"
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[7]: Что вы предлагаете на замену эксепшенов?
От: Глеб Алексеев  
Дата: 21.11.05 13:19
Оценка: +1
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Единственное правильное использование ловли исключений — это чтобы в случае чего грамотно прибрать за собой.

Оставим в стороне "единственную правильность ловли исключений", это вопрос религиозный.
СГ>При наличии автоматической сборки мусора, прибрать за собой — гораздо менее актуальная задача.
Т.е. при наличии сборки мусора нарушенные инварианты программы менее вредны?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Что вы предлагаете на замену эксепшенов?
От: Глеб Алексеев  
Дата: 21.11.05 13:26
Оценка: +1
Здравствуйте, eao197, Вы писали:

E>А вот по поводу безопасности исключений если задуматься, то вообще голова кругом пойдет. Мне, например, интересно. В C++ много говорится о гарантиях безопасности (ну там базовая гарантия, сильная гарантия). А в других языках с исключениями (в том же Ruby, к примеру) от этом не упоминают. Из-за чего, спрашивается? В языках с GC нет таких пагубных последствий от исключений? Или просто их community еще до таких серьезных вопросов не доросло?

Трудно ответить, крайне мало опыта в других языках. В С++-сообществе есть много горячих тем, которые практически никого больше не волнуют, вроде "у меня работает, но что скажет Стандарт" , исключения в деструкторах, умные указатели и т.д. Но обработка ошибок — проблема фундаментальная в любом языке, и если кого-то мало волнуют вопросы безопасности исключений, то это говорит или о низкой квалификации программиста, или о низкой стоимости сбоя в разрабатываемой системе.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: А есть ли замена?
От: Глеб Алексеев  
Дата: 21.11.05 13:41
Оценка:
Здравствуйте, gear nuke, Вы писали:

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


Для этого тоже, но далеко не в первую очередь, иначе исключения были бы только в низкоуровненвых языках. Вы, как эксперт в ассемблере, смещаете акцент, ИМХО, не в ту сторону. А высокоуровневые языки существуют потому, что программы пишутся не для компьютеров, а для людей, и здесь исключения проявляют себя с лучшей стороны.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.11.05 13:54
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

E>> В языках с GC нет таких пагубных последствий от исключений?


СГ>Единственное правильное использование ловли исключений — это чтобы в случае чего грамотно прибрать за собой.

СГ>При наличии автоматической сборки мусора, прибрать за собой — гораздо менее актуальная задача.

Не сказал бы. Если бы это было так, то не придумывали бы таких вещей, как ScopeGuard.

Вот например, есть у меня класс, который содержит внутри два map-а для доступа к объекту по разным ключам:
void some_container_t::insert( const some_object_t & object )
    {
        // Если исключение произойдет здесь, то ничего страшного.
        m_first_key_map[ object.first_key() ] = &object;
        
        // А вот если здесь, то в первой карте останется элемент, для которого нет соответствия во второй карте.
        m_second_key_map[ object.second_key() ] = &object;
    }

Подобный код обеспечивает только базовую гарантию (при условии, что ее предоставляют объекты m_first_key и m_second_key). Но вот пользоваться экземпляром some_container_t уже будет нельзя. Здесь было бы более удобно, если бы some_container_t::insert предоставлял сильную гарантию -- т.е. возникновение исключения оставляет его в неизменном состоянии. Наиболее простой путь для этого -- изымать вставленный в m_first_key_map объект, если при вставке во вторую карту произошло исключение:
void some_container_t::insert( const some_object_t & object )
    {
        m_first_key_map[ object.first_key() ] = &object;

        try
            {
                m_second_key_map[ object.second_key() ] = &object;
            }
        catch( ... )
            {
                m_first_key_map.erase( object.first_key() );
                throw;
            }
    }

(хотя это и не самое удачное решение, но для демонстрации подойдет).
Более читабельный вариант был бы:
void some_container_t::insert( const some_object_t & object )
    {
        first_key_t first_key = object.first_key();
        m_first_key_map[ first_key ] = &object;
        
        // Деструктор этого объекта произведет изъятие добавленного элемента из m_first_key_map.
        insert_rollback_actor_t first_map_modification_guard( m_first_key_map, first_key );

        m_second_key_map[ object.second_key() ] = &object;

        // Запрещаем изъятие элемента, т.к. коммитим транзакцию.
        first_map_modification_guard.commit();
    }

(хотя самым безопасным было бы создание копий m_first_key_map, m_second_key_map, их модификация и операция swap с исходными значениями m_first_key_map, m_second_key_map. Однако понятно, что для некоторых задач это совершенно неприемлимо).

Теперь попробуем посмотреть, как бы это было сделано в Ruby, где есть GC. Тривиальное решение (базовая гарантия):
def insert( object )
    @first_key_map[ object.first_key ] ||= object
    @second_key_map[ object.second_key ] ||= object
end

Тривиальное решение по обеспечению сильной гарантии.
def insert( object )
    @first_key_map[ object.first_key ] ||= object
    begin
        @second_key_map[ object.second_key ] ||= object
    rescue
        @first_key_map.erase object.first_key
        raise
    end
end


А вот более изощренное решение:
def exception_guard( rescue_action )
    begin
        yield
    rescue
        rescue_action.call
        raise
    end
end

def insert( object )
    @first_key_map[ object.first_key ] ||= object
    
    exception_guard( 
        # Этот код запуститься, если возникнет исключение при вставке во вторую карту.
        Proc.new do @first_key_map.erase object.first_key end
    ) do
        @second_key_map[ object.second_key ] ||= object
    end
end


Т.е., проблемы те же. И даже способы решения приблизительно одинаковые (в Ruby даже, имхо, способы создания ScodeGuard-ов попроще). Но вот не говорят в Ruby о безопасности исключений и базовые/сильные гарантии (да и здесь .NET-приверженцы от этом не упоминают). Почему?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: Что вы предлагаете на замену эксепшенов?
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 21.11.05 14:10
Оценка: -1
Здравствуйте, Andy77, Вы писали:

СГ>>Я делю ошибки на две категории:

СГ>>1) ошибки в данных (программа на вход получила неправильные данные);
СГ>>2) ошибки в программе (программист ошибся: а) просто ошибся; б) сложно ошибся — в дизайне/архитектуре).

СГ>>Ошибки категори (1) легко обрабатывается без механизма exceptions, так надо проектировать просто.


A>Писать функции, возвращающие код ошибки? Иногда так и стоит делать, но за правило я бы это ни в коем случае не брал.


Правильное решение известно
Автор: Andrei N.Sobchuck
Дата: 21.07.05
, но, увы, не везде применимо. Как по техническим, так и по синтаксическим причинам.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[6]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 21.11.05 14:57
Оценка:
eao197 wrote:

> А вот по поводу безопасности исключений если задуматься, то вообще

> голова кругом пойдет. Мне, например, интересно. В C++ много говорится
> о гарантиях безопасности (ну там базовая гарантия, сильная гарантия).
> А в других языках с исключениями (в том же Ruby, к примеру) от этом не
> упоминают. Из-за чего, спрашивается? В языках с GC нет таких пагубных
> последствий от исключений? Или просто их community еще до таких
> серьезных вопросов не доросло?

Скорее второе. Ну и действительно важные приложения (типа app-серверов)
стараются писать так, чтобы в случае вылета исключений можно было бы
просто прибить working set у вылетевшего модуля и запустить его заново.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[3]: А есть ли замена?
От: gear nuke  
Дата: 21.11.05 15:00
Оценка:
Здравствуйте, Глеб Алексеев,

GN>>Смысл исключений — увеличить скорость работы. Вместо постоянных лишних проверок вводится иной механизм, отнимающий время лишь в исключительных случаях. []


ГА>Для этого тоже, но далеко не в первую очередь, иначе исключения были бы только в низкоуровненвых языках. Вы, как эксперт в ассемблере, смещаете акцент, ИМХО, не в ту сторону. А высокоуровневые языки существуют потому, что программы пишутся не для компьютеров, а для людей, и здесь исключения проявляют себя с лучшей стороны.


Ну я с "не той стороны" всё равно противоречий не вижу . В HLL основной упор делается на лёгкость понимания человеком — так исключения и упрощают код, исключая из исходника множество проверок. И не дают возможность "забыть" проверить. Скорость и простота в данном случае сильно связаны. Если смотреть с позиции HLL — то, естесственно, в первую очередь простота более заметна .
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[8]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 21.11.05 15:10
Оценка: 1 (1) +1
eao197 wrote:

> Т.е., проблемы те же. И даже способы решения приблизительно одинаковые

> (в Ruby даже, имхо, способы создания ScodeGuard-ов попроще). Но вот не
> говорят в Ruby о безопасности исключений и базовые/сильные гарантии
> (да и здесь .NET-приверженцы от этом не упоминают). Почему?

На Ruby обычно, в основном, скрипты пишут. Ну а там упадет — и ладно. В
C#/Java в десктопных приложениях тоже такой же подход, в основном.

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

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[9]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.11.05 16:40
Оценка:
Здравствуйте, Cyberax, Вы писали:

>> Т.е., проблемы те же. И даже способы решения приблизительно одинаковые

>> (в Ruby даже, имхо, способы создания ScodeGuard-ов попроще). Но вот не
>> говорят в Ruby о безопасности исключений и базовые/сильные гарантии
>> (да и здесь .NET-приверженцы от этом не упоминают). Почему?

C>На Ruby обычно, в основном, скрипты пишут. Ну а там упадет — и ладно.


Ну не скажи. Есть и скрипты, которые работают в режиме 24x7
Вот у меня, скажем, есть Ruby скрипты, которые архивируют старые логи и делают snapshot-ы восстановочных БД. Затем засыпают, просыпаются и повторяют свои действия.

Один раз упали (причина, кстати, то же была интересная ). Итог -- быстро исчерпалось свободное место на тестовом сервере.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[7]: Что вы предлагаете на замену эксепшенов?
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.11.05 04:33
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Ничего неожиданного в этом нет. С самого начала известно, что соединение может разорваться в любой момент, да и денег на счете может быть меньше чем запрошено.
И что? Сергей, вам что, непонятно, чем отличается успешная отправка килобайта данных от отправки только половины? Или вы не догадываетесь, что невозможно предусмотреть все мыслимые случаи в низкоуровневой библиотеке, т.к. это противоречит принципам инкапсуляции?
Нет, я пожалуй воздержусь от дальнейшего разжевывания. Ну-ка, приведите мне пример кода, на любом языке, который выполняет следующие действия:
1. Снимает заданное количество рублей со счета А
2. Кладет это количество рублей на счет Б.
3. Записывает данные о транзакции в файл
4. Если что-то не удалось сделать, отправляет письмо на определенный адрес, с указанием подробностей ошибки.

Пожалуйста, воздержитесь от использования исключений. А мы посмотрим.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 22.11.05 08:16
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Если верить рекламе языков (Java, C#), то "программирование — это лёгкое и непринуждённое занятие". Обманыевает эта реклама, хотя бы пять процентов головного мозга напрягать всё-равно надо.


Не очень хотелось высказываться здесь, но, похоже, у нас разные подходы к получению значения 5 процентов.
А Вы знаете языки, которые не заставляют разработчика напрягаться вообще?
Re[8]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 22.11.05 10:03
Оценка: -9
Здравствуйте, Sinclair, Вы писали:

S>Ну-ка, приведите мне пример кода, на любом языке, который выполняет следующие действия:

S>1. Снимает заданное количество рублей со счета А
S>2. Кладет это количество рублей на счет Б.
S>3. Записывает данные о транзакции в файл
S>4. Если что-то не удалось сделать, отправляет письмо на определенный адрес, с указанием подробностей ошибки.

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


Во-первых, и в главных, не "Ну-ка"-йте тут. Что ещё за моду взяли.
Во-вторых, Вы забыли определить какими примитивами разрешено пользоваться.
А то ведь, можно и так:
PROCEDURE Move (VAR src, dst, sum: REAL): BOOLEAN;
BEGIN
  IF src >= sum THEN
    src := src - sum;
    dst := dst + sum;
...
Re[2]: Что вы предлагаете на замену эксепшенов?
От: Глеб Алексеев  
Дата: 22.11.05 10:31
Оценка:
Здравствуйте, reductor, Вы писали:

R>Существует множество вариантов


R>например, обработка через continuation passing


А можно маленький примерчик применения CPS вместо исключений?
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[9]: Что вы предлагаете на замену эксепшенов?
От: mrozov  
Дата: 22.11.05 10:47
Оценка: 3 (1) +3
Здравствуйте, Сергей Губанов, Вы писали:

СГ>PROCEDURE Move (VAR src, dst, sum: REAL): BOOLEAN;

СГ>BEGIN
СГ> IF src >= sum THEN
СГ> src := src — sum;
СГ> dst := dst + sum;
СГ>...
СГ>[/pascal]

Совершенно очевидно, что такой код к использованию не пригоден, правда?
А вообще — слишком много внимания к проблеме, не стоящей выеденного яйца. Комрад не понимает, что такое исключения и пытается бороться с несуществующими проблемами. Пускай борется в одиночку.
Re[9]: Что вы предлагаете на замену эксепшенов?
От: akasoft Россия  
Дата: 22.11.05 11:02
Оценка: 1 (1)
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Во-первых, и в главных, не "Ну-ка"-йте тут. Что ещё за моду взяли.


Сергей, это дружественная форма общения. Мы тут давно знаем, кто такой Антон, кто ты, тесный круг общения позволяет между собой иногда отбрасывать условности реального мира. Эта фраза — не оскорбление, это эмоциональный заряд. Поверь, как бы мы не спорили о "всём сущем", к тебе как личности отношение самое дружественное.

СГ>А то ведь, можно и так:
СГ>PROCEDURE Move (VAR src, dst, sum: REAL): BOOLEAN;
СГ>BEGIN
СГ>  IF src >= sum THEN
СГ>    src := src - sum;
СГ>    dst := dst + sum;
СГ>...
СГ>


Ага! И полюбому зачисляем на счёт-приёмник сумму. Здорово. Все бы так уже богачами были.
... << RSDN@Home 1.2.0 alpha rev. 617>>
Re[9]: Что вы предлагаете на замену эксепшенов?
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.11.05 11:25
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Во-первых, и в главных, не "Ну-ка"-йте тут. Что ещё за моду взяли.


СГ>Во-вторых, Вы забыли определить какими примитивами разрешено пользоваться.

Такими, которые обеспечивают ACID. Т.е. снятие/положение денег — некая сложная, но атомарная операция. Не обязательно приводить их полный код. Можно пользоваться ими как черными ящиками.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 22.11.05 14:06
Оценка: 6 (1)
Здравствуйте, akasoft, Вы писали:

СГ>>А то ведь, можно и так:
СГ>>PROCEDURE Move (VAR src, dst, sum: REAL): BOOLEAN;
СГ>>BEGIN
СГ>>  IF src >= sum THEN
СГ>>    src := src - sum;
СГ>>    dst := dst + sum;
СГ>>...
СГ>>


A>Ага! И полюбому зачисляем на счёт-приёмник сумму. Здорово. Все бы так уже богачами были.


Напоминаю синтаксис инструкции IF языков Modula/Oberon/Component Pascal:

IF ... THEN ... END
IF ... THEN ... ELSE ... END
IF ... THEN ... ELSIF ... THEN ... END
IF ... THEN ... ELSIF ... THEN ... ELSIF ... THEN ... END
...

т.е. в конце инструкции стоит END
Re[10]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 22.11.05 14:12
Оценка: -1
Здравствуйте, Sinclair, Вы писали:

S>Такими, которые обеспечивают ACID. Т.е. снятие/положение денег — некая сложная, но атомарная операция. Не обязательно приводить их полный код. Можно пользоваться ими как черными ящиками.


Программа, я так понимаю, работает в банке со счета которого деньги снимаются.
  TYPE
    СчётВУдалённомБанке* = POINTER TO ABSTRACT RECORD END;

    ЛокальныйСчёт* = POINTER TO RECORD
      остаток: Деньги;
      журнал: Журнал; (* not NIL *)
      (* ... *)
    END;

    Журнал* = POINTER TO ABSTRACT RECORD END;


  PROCEDURE (this: СчётВУдалённомБанке) Зачислить* (сумма: Деньги; откуда: Откуда; причинаОтказа: Причина): BOOLEAN, NEW, ABSTRACT;

  PROCEDURE (this: Журнал) РапортОбУдачномОсуществленииДенежногоПеревода* (src: ЛокальныйСчёт; dst: СчётВУдалённомБанке; сумма: Деньги), NEW, ABSTRACT;
  PROCEDURE (this: Журнал) РапортОбОтказеУдалённогоБанкаНаЗачислениеДенег* (src: ЛокальныйСчёт; dst: СчётВУдалённомБанке; сумма: Деньги; причина: Причина), NEW, ABSTRACT;
  PROCEDURE (this: Журнал) РапортОНехваткеДенегНаСчётеДляОсуществленияДенежногоПеревода* (src: ЛокальныйСчёт; dst: СчётВУдалённомБанке; сумма: Деньги), NEW, ABSTRACT;


  PROCEDURE (this: ЛокальныйСчёт) ОсуществитьДенежныйПеревод* (счёт: СчётВУдалённомБанке; сумма: Деньги): BOOLEAN;
    VAR результат: BOOLEAN; причинаОтказа: Причина;
  BEGIN 
    результат := FALSE;
    IF (счёт # NIL) & (сумма > 0) THEN    
      this.НачалоЭксклюзивнойОперации;
      IF this.остаток >= сумма THEN
        IF счёт.Зачислить(сумма, this.ДеньгиОтМеня, причинаОтказа) THEN
          this.остаток := this.остаток - сумма;
          this.журнал.РапортОбУдачномОсуществленииДенежногоПеревода(this, счёт, сумма);
          результат := TRUE;
        ELSE
          this.журнал.РапортОбОтказеУдалённогоБанкаНаЗачислениеДенег(this, счёт, сумма, причинаОтказа)
        END
      ELSE
        this.журнал.РапортОНехваткеДенегНаСчётеДляОсуществленияДенежногоПеревода(this, счёт, сумма)
      END;
      this.КонецЭксклюзивнойОперации;
    END;
    RETURN результат
  END ОсуществитьДенежныйПеревод;

Запись в лог и отправку по e-mail делает объект Журнал.
Re[11]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.11.05 14:29
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

Т.е. вот этот вызов:
СГ>
СГ>      this.НачалоЭксклюзивнойОперации;
СГ>


гарантированно завершается успешно? Всегда, при любых условиях?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.