Re[5]: Что вы предлагаете на замену эксепшенов?
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.11.05 11:35
Оценка: 193 (25) +10
Здравствуйте, Сергей Губанов, Вы писали:
СГ>то это и делать.
Сергей, ваши представления о программировании все еще катастрофически далеки от реальности.
Вы, судя по вашему ответу, считаете, что
а) программа должна трактовать все случаи как равновероятные
б) вся информация для принятия решения доступна ровно там, где выполняется действие.
И то и другое — заблуждения.
Начнем с последнего. Как правило, с неожиданной ситуацией сталкивается код самого нижнего уровня. Что значит "неожиданная ситуация"? Это выражение означает "невозможно выполнить запрошенное действие". Например, мы пытаемся записать килобайт данных в TCP сокет. Упс! Сокет закрылся — например, оборвали кабель, или другая сторона явно разорвала соединение. Внешнему коду, который позвал метод send, вообще ничего не известно про состояние сети. И не может быть известно в силу инкапсуляции — он пишет в какой-то поток, не более того. Это может быть файл, сокет, или блоб-поле в базе данных.
Даже если клиент умен, и предварительно спросил у сокета, можно ли посылать, вовсе не факт, что проблема не возникнет в процессе работы метода:
if(s.IsConnected)
{
  s.Send(myData); /// ошибка где-то в середине передачи
}

Что делать? Ага, проверим код результата:
if(s.IsConnected)
{
  switch(s.Send(myData))
    {
      case SOCKET_DISCONNECTED: ...
        case BUFFER_OVERFLOW: ...
        case ...: ...
        else: // уфф, пронесло, все в порядке.
    }
}

Все здорово до тех пор, пока у нас действительно достаточно информации. Но ведь этот клиентский код, в свою очередь, может быть всего лишь низкоуровневой оберткой над отправкой данных. Что ему делать? По ТЗ надо отсылать письмо. Прекрасно. У нас код нижнего уровня должен знать адрес администратора и уметь отправлять почту.
Чудно. Если же мы оставляем эту работу более высокоуровневому коду, то ему надо откуда-то узнать, что именно случилось. Или же все кончается методом
bool SaveChangesToDbAndSendNotifications()

В случае возврата false надо отправить письмо — и пусть админ гадает, что же там упало. То ли с базой связаться не удалось, то ли нотификации не уехали.
Вообще, вас уже отправили читать Страуструпа — не упрямьтесь, поверьте — он про все это лучше меня написал. И уже давно.

Второй момент — вы предлагаете трактовать все, оговоренное в ТЗ как штатную ситуацию. Оставим пока за бортом вопрос полноты ТЗ. Решим пока, что все неописанные случаи могут приводить к undefined behavior (вообще в наши дни софт с UB — это моветон, если что).

С вашей точки зрения, если проектировщик догадался спросить, не нужна ли реакция софта на падение метеорита, и ему сказали что нужна, то код должен быть устроен так:
if(метеорит_упал)
{
  выполняем_запасные_действия();
}
else
{
  идем_по_основной_ветке();
}

Во-первых, такой код тяжело читать. Он намекает на 50% вероятность попадания метеорита; он содержит ветку основной логики как редкий частный случай и затрудняет понимание собственно решаемой задачи.
Кроме того, зачастую реакция на очень большое количество разнообразных ситуаций более-менее одна. К примеру, асп.нет банально перезапускает повисшее приложение, не вдаваясь в детали — метеорит там, деление на ноль, бесконечный цикл или моль дырку проела. В коде, который действует по методу блондинки, надо предусмотреть реакцию как на отсутствие динозавра, так и на его присутствие.

Во-вторых, это банально влияет на производительность. Если у нас есть частая ветка, то она должна исполняться максимально быстро. Особенно это характерно для исключений — если произошел какой-то сбой, не так уж важно быстро его обработать. Тут бы не совсем не упасть — и то хорошо. Вот, к примеру, процессоры так и делают — предсказывают ветвления и стараются ускорить выполнение частой ветки, в ущерб выполнению редкой, которое приводит к дорогостоящему сбросу конвеера. Но у процессора близорукость сильная, его предсказалка в пределах махоньких циклов хорошо работает. А для более крупных блоков он не поможет.
Код, работающий пессимистично, должен, к примеру, перед снятием денег со счета проверить, а хватит ли их там. Ну и пойти либо снимать деньги, либо писать пользователю отмазку. А поскольку стоимость проверки количества денег примерно такая же, что и стоимость съема денег, мы получаем просад производительности минимум в два раза только за счет пессимизма. (На самом деле все еще намного хуже из-за блокировок и прочих эффектов второго порядка). А вот оптимистичный код пытается выполнить все, как будто все хорошо. И только если вдруг оказалось, что что-то не вышло, выполняется дорогой код раскрутки стека, отката транзакции и т.п.

Вот вам и отличие штатной от нештатной — нештатная ситуация редка, и не позволяет довести начатое до конца. Академизм здесь вреден — не все ситуации равноправны.
Да, использовать исключения для штатной работы — глупо:
// Бросает исключение OopsItsTailsAgainException в 50% случаев
void ThrowCoinAndCheckHeads() 

enum CoinSides { Heads, Tails};
...

CoinSides ThrowCoin()
{
  try
    {
       ThrowCOinAndCheckHeads();
         return CoinSides.Heads;
    catch(OopsItsTailsAgainException)
    {
        return CoinSides.Tails;
    }
}

Но это никак не подрывает саму идею исключений как механизма отделения логики обработки нештатных ситуаций от основной логики.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 19.11.05 20:14
Оценка: 6 (1) -18 :))) :))) :))
Здравствуйте, Nickolay Ch, Вы писали:

http://www.rsdn.ru/Forum/Message.aspx?mid=1496415&only=1
Автор: Nickolay Ch
Дата: 19.11.05


NC>А вот очень бы хотелось услышать, что вы предлагаете на замену эксепшенов, только мб в новой теме. Они много чем не нравятся, но пока не видно лучших механизмов обработки ошибок.


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

Ошибки категори (1) легко обрабатывается без механизма exceptions, так надо проектировать просто.
Ошибки категории (2) фатальные, тут программу надо завершать — в программе ошибка, т.е. программа не правильная. Использовать exception только для того чтобы правильно завершить работу программы (ну там закрыть открытые ресурсы), только для этого чтоли? Закрыть открытое можно и другими способами.
Re[2]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 19.11.05 22:12
Оценка: 9 (2) +1 :))) :))) :))) :))) :))) :))) :))) :))
Здравствуйте, psg, Вы писали:

psg>А собственно, чем вам не нравятся exceptions?...


Видимо они отсутствуют в Обероне.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[27]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 30.11.05 03:51
Оценка: 264 (19) +1
Здравствуйте, Сергей Губанов, Вы писали:

IT>>Сейчас чего-нибудь изобразим.


СГ>Написали Вы много,


А ты думал ты в сказку попал. Хватит в солдатиков в песочнице играться, welcome to the real world.

СГ>но принципиальной разницы с предыдущим примером нет.


А вот это мы сейчас и узнаем

Непонятно почему ты пропустил целый лэйер, но да бог с ним. Даже и с ним твой код рабочим назвать нельзя. Точнее он будет работать, но только в чистом, глубоком вакууме, т.к. увлёкшись бесконечными if'ами и &'ми ты совсем забыл сделать Rollback транзакции в случае ошибки. Ошибки двух методов StealSomeXXX ты тоже почему-то решил не обрабатывать. Отговорки типа ну я мол только идею продемонстрировал не принимаются. Впрочем, как раз её ты и "продемонстрировал" — сам понатыкал сосен и сам же в них запутался.

А теперь давай перепишем твой код на C# так чтобы он по идее был рабочим и можно было хоть что-то хоть как-то сравнивать. На строчки скупиться не будем (я же в своём примере не экономил). Я буду писать в своём стиле, но придерживаясь твоей идее. Любые замечания по существу принимаются.

Итак, первый слой — UI. Мой код из предыдущего примера.

void WithdrawalAndGetBalance()
{
    try
    {
        decimal newBalance = AccountManager.WithdrawalAndGetBalance("12345", 100m);
        Console.WriteLine("New balance is: {0}", bewBalance);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Oops: " + ex.Message);
    }
}

Твой вариант (по твоей идее).

void WithdrawalAndGetBalance()
{
  decimal newBalance;
  Errors  err = null;

  if (AccountManager.WithdrawalAndGetBalance("12345", 100m, out newBalance, ref list))
    Console.WriteLine("New balance is: {0}", bewBalance);
  else
  {
    if (err != null)
      Console.WriteLine("Oops: " + err.Message);
    else
      Console.WriteLine("Just oops :xz:");
  }
}

Счёт:
lines: 7:12
if/else/&: 0:4

AccountManager. Мой пример.

public static decimal WithdrawalAndGetBalance(string accountNumber, decimal amount)
{
  Validate(accountNumber);
  Validate(amount);

  return new AccountService().WithdrawalAndGetBalance(accountNumber, amount);
}

Твой вариант.

public static bool WithdrawalAndGetBalance(string accountNumber, decimal amount, out decimal newBalance, ref Errors err)
{
  return Validate(accountNumber, ref err) &&
         Validate(amount, ref err) &&
         new AccountService().WithdrawalAndGetBalance(accountNumber, amount, out newBalance, ref err);
}

Здесь я для наглядности перенёс вызовы на разные строчки, иначе текст не помещался на экран. В общем, далее слишком длинные строки я буду переносить.

lines: 4:3
if/else/&: 0:3
params: 2:4 (output: 0:2)

Но это всё цветочки. Вот они ягодки.

AccountService. Мой пример.

public decimal WithdrawalAndGetBalance(string accountNumber, decimal amount)
{
  Validate(accountNumber);
  Validate(amount);

  using (AccountDataAccessor dataAccessor = new AccountDataAccessor())
  {
    dataAccessor.BeginTransaction();

    decimal balance = dataAccessor.GetBalance(accountNumber);

    if (balance < amount)
      throw new BalanceException("You are freaking bankrupt!");

    balance -= amount;

    dataAccessor.SetNewBalance(accountNumber, balance);

    if (balance > 1000000m)
      dataAccessor.StealSomeForMe(accountNumber, 1.15m);

    balance -= 1.15m;

    if (balance > 10000000m)
      dataAccessor.StealSomeForHomelessPeople(accountNumber, 0.15m);

    balance -= 0.15m;

    dataAccessor.ChargeForService(accountNumber, 10m);
 
    balance -= 10m;

    dataAccessor.CommitTransaction();
 
    return balance;
  }
}

Твой вариант.

delegate bool Do();

public bool WithdrawalAndGetBalance(string accountNumber, decimal amount, out decimal newBalance, ref Errors err)
{
  newBalance = 0m;

  if (Validate(accountNumber, err) && Validate(amount, ref err))
  {
    AccountDataAccessor dataAccessor = new AccountDataAccessor();

    if (dataAccessor.Open(ref err))
    {
      if (dataAccessor.BeginTransaction(ref err))
      {
        if (new Do(delegate()
        {
          if (dataAccessor.GetBalance(accountNumber, out newBalance, ref err))
          {
            if (newBalance < amount)
            {
              err := Errors.NewList(Errors.NewError("You are freaking bankrupt!"), err); // Вот такое вот "кидание исключения"
              return false;
            }
            else
            {
              newBalance -= amount;

              if (dataAccessor.SetNewBalance(accountNumber, newBalance, ref err))
              {
                if (balance > 1000000m)
                {
                  if (dataAccessor.StealSomeForMe(accountNumber, 1.15m, ref err) == false)
                    return false;

                  balance -= 1.15m;
                }

                if (balance > 10000000m)
                {
                  if (dataAccessor.StealSomeForHomelessPeople(accountNumber, 0.15m, ref err) == false)
                    return false

                  balance -= 0.15m;
                  }

                if (dataAccessor.ChargeForService(accountNumber, 10m, ref err))
                  {
                    balance -= 10m;
                    return true;
                }
              }
            }
          }
          }())
        {
          if (dataAccessor.CommitTransaction(ref err))
          {
            dataAccessor.Close();
            return true;
          }
          else
          {
            dataAccessor.Close();
            return false;
          }
        }

        dataAccessor.RollbaсkTransaction();
      }

      dataAccessor.Close();
    }

    return false;
  }
}

lines: 35:71
if/else/&: 3:16 (9 уровней вложенности)
params: 2:4 (output: 0:2)

Нормально, да? Мало того что я на него потратил примерно на порядок больше времени, так ещё после того как я его закончил мне захотелось плакать

Итого имеем. Увеличение количество строк кода в два раза. Усложнение логики за счёт ветвления кода в 5 раз. В принципе, это и есть реальные, даже несколько заниженные цифры. Код начинает ветвиться и разрастаться с ужасающей быстротой, так же быстро теряется наглядность и появляются повторяющиеся фрагменты типа dataAccessor.Close() в примере. Уж извини, старался держаться в рамках твоей идеи. Для того, чтобы это хоть как-то контролировать в реальной жизни (а не в песочнице), некоторые проверки начинают пропускаться или просто забываться делаться с соответствующими последствиями. При внесении изменений в такой, уже казалось бы отлаженный код, внести новый баг — это обычное дело. Чтобы этого избежать, нужно тщательнейшим образом разобраться в этом бреде и делать всё максимально аккуратно, а это время, много времени.

Код с исключениями, как нетрудно заметить, имеет линейную структуру, прост и нагляден. Сделать ошибку в нём трудно, вносить изменения просто.

Некоторые, особенно одарённые товарищи, додумываются вообще до просто таки гениальной идеи. Если мы уже всё равно передаём структуру err, то почему бы в неё не затолкать какой-нибудь код, который можно было бы проверить на клиенте и сделать что-нибудь этакое. Т.е. коды результата уже начинают использоваться не только по своему прямому назначению, но и для других, внебрачных целей. Понять потом логику таких программ можно только "поднявшись" до уровня таких гениев.

Но это ещё не всё.

AccountDataAccessor. Мой код.

public decimal GetBalance(string accountNumber)
{
  return (decimal)ExecuteScalarSp("GetBalance", accountNumber);
}
  
public void SetNewBalance(string accountNumber, decimal amount)
{
  ExecuteNonQuerySp("SetBalance", accountNumber, amount);
}
  
public void StealSomeForMe(string accountNumber, decimal amount)
{
  ExecuteNonQuerySp("StealSomeForMe", accountNumber, amount);
}
  
public void StealSomeForHomelessPeople(string accountNumber, decimal amount)
{
  ExecuteNonQuerySp("StealSomeForHomelessPeople", accountNumber, amount);
}

public void ChargeForService(string accountNumber, decimal amount)
{
  ExecuteNonQuerySp("ChargeForService", accountNumber, amount);
}

Твой вариант.

public bool GetBalance(string accountNumber, out newBalance, ref Errors err)
{
  // oops!!! А ExecuteScalarSp параметра Errors не поддерживает.
  // Ну дятлы её какие-то писали, не додумались до такой классной идее.
  //
  ///////////return (decimal)ExecuteScalarSp("GetBalance", accountNumber);
}

// остальные упсы поскипаны.

В случае со "стандартной" ExecuteScalarSp, чтобы сохранить лицо, тебе скорее всего придётся написать длиннючий switch на все возможные коды возврата и подобрать к ним более менее вменяемые сообщения.

Да, кстати, использование ref и out параметров считается признаком плохого дизайна. FxCop на это заявляет "Consider a design that does not require that 'parameter_name' be an out parameter".
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re: Что вы предлагаете на замену эксепшенов?
От: Павел Кузнецов  
Дата: 19.11.05 20:27
Оценка: 1 (1) +10
Сергей,

> http://www.rsdn.ru/Forum/Message.aspx?mid=1496415&amp;only=1
Автор: Nickolay Ch
Дата: 19.11.05

>
> NC>А вот очень бы хотелось услышать, что вы предлагаете на замену эксепшенов, только мб в новой теме. Они много чем не нравятся, но пока не видно лучших механизмов обработки ошибок.
>
> Я делю ошибки на две категории:
> 1) ошибки в данных (программа на вход получила неправильные данные);
> 2) ошибки в программе (программист ошибся: а) просто ошибся; б) сложно ошибся — в дизайне/архитектуре).
>
> Ошибки категори (1) легко обрабатывается без механизма exceptions, так надо проектировать просто.

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

> Использовать exception только для того чтобы правильно завершить работу программы (ну там закрыть открытые ресурсы), только для этого чтоли?


Исключения в первую очередь предназначены именно для (1).
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
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[31]: Что вы предлагаете на замену эксепшенов?
От: Пацак Россия  
Дата: 01.12.05 08:38
Оценка: 18 (1) :))) :))) :)
Здравствуйте, Сергей Губанов, Вы писали:

IT>>Может посчитать количество строчек.

СГ>Фигнёй страдаете, однако .

Сергей, и это говорите Вы?
Ку...
Re[11]: Вот подумалось
От: Belsen  
Дата: 28.11.05 03:51
Оценка: 15 (1) :))) :)))
Здравствуйте, IT, Вы писали:

IT>...переписать вот такой код без returns?


public class ResultException<T> : ApplicationException
{
    public T Result;

    public ResultException(T result)
    {
        Result = result;
    }
}

public class UndefinedResultException : ApplicationException 
{
}

private static MemberMapper GetNullableMemberMapper(MapMemberInfo mi)
{
    try
    {
        Type type = mi.MemberAccessor.Type;
        
        if (type.IsGenericType == false || mi.MapValues != null)
            throw new ResultException<MemberMapper>(null);
        
        Type underlyingType = Nullable.GetUnderlyingType(type);
        
        if (underlyingType == null)
            throw new ResultException<MemberMapper>(null);
        
        if (underlyingType.IsEnum)
        {
            underlyingType = Enum.GetUnderlyingType(underlyingType);
        
            if (underlyingType == typeof(SByte))    throw new ResultException<MemberMapper>(new NullableSByteMapper. Enum());
            if (underlyingType == typeof(Int16))    throw new ResultException<MemberMapper>(new NullableInt16Mapper. Enum());
            if (underlyingType == typeof(Int32))    throw new ResultException<MemberMapper>(new NullableInt32Mapper. Enum());
            if (underlyingType == typeof(Int64))    throw new ResultException<MemberMapper>(new NullableInt64Mapper. Enum());
            if (underlyingType == typeof(Byte))     throw new ResultException<MemberMapper>(new NullableByteMapper.  Enum());
            if (underlyingType == typeof(UInt16))   throw new ResultException<MemberMapper>(new NullableUInt16Mapper.Enum());
            if (underlyingType == typeof(UInt32))   throw new ResultException<MemberMapper>(new NullableUInt32Mapper.Enum());
            if (underlyingType == typeof(UInt64))   throw new ResultException<MemberMapper>(new NullableUInt64Mapper.Enum());
        }
        else
        {
            if (underlyingType == typeof(SByte))    throw new ResultException<MemberMapper>(new NullableSByteMapper());
            if (underlyingType == typeof(Int16))    throw new ResultException<MemberMapper>(new NullableInt16Mapper());
            if (underlyingType == typeof(Int32))    throw new ResultException<MemberMapper>(new NullableInt32Mapper());
            if (underlyingType == typeof(Int64))    throw new ResultException<MemberMapper>(new NullableInt64Mapper());
            if (underlyingType == typeof(Byte))     throw new ResultException<MemberMapper>(new NullableByteMapper());
            if (underlyingType == typeof(UInt16))   throw new ResultException<MemberMapper>(new NullableUInt16Mapper());
            if (underlyingType == typeof(UInt32))   throw new ResultException<MemberMapper>(new NullableUInt32Mapper());
            if (underlyingType == typeof(UInt64))   throw new ResultException<MemberMapper>(new NullableUInt64Mapper());
            if (underlyingType == typeof(Char))     throw new ResultException<MemberMapper>(new NullableCharMapper());
            if (underlyingType == typeof(Single))   throw new ResultException<MemberMapper>(new NullableSingleMapper());
            if (underlyingType == typeof(Boolean))  throw new ResultException<MemberMapper>(new NullableBooleanMapper());
            if (underlyingType == typeof(Double))   throw new ResultException<MemberMapper>(new NullableDoubleMapper());
            if (underlyingType == typeof(DateTime)) throw new ResultException<MemberMapper>(new NullableDateTimeMapper());
            if (underlyingType == typeof(Decimal))  throw new ResultException<MemberMapper>(new NullableDecimalMapper());
            if (underlyingType == typeof(Guid))     throw new ResultException<MemberMapper>(new NullableGuidMapper());
        }
    
        throw new ResultException<MemberMapper>(null);
    }
    catch (ResultException<MemberMapper> re)
    {    
        return re.Result;
    }
    throw new UndefinedResultException();
}
I might be wrong...
Re[13]: Что вы предлагаете на замену эксепшенов?
От: mrozov  
Дата: 23.11.05 12:48
Оценка: 7 (2) +2 :)))
Здравствуйте, Сергей Губанов, Вы писали:

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

Вот в приведенном примере — что делать, если журнал не смог записать успешную запись в файл? О да, в данном случае он отправит письмо "внутри". Потому, что он инкапсулирует как запись протокола, так и сообщения об ошибках. А если бы мы разделили эту функциональность (что, в общем-то, более правильно, т.к. она ортогональная), то в коде пришлось бы отдельно проверять, удалось ли в провести запись в файл.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[19]: Что вы предлагаете на замену эксепшенов?
От: CrystaX Россия https://crystax.me/
Дата: 23.11.05 16:56
Оценка: 51 (5) +1
Здравствуйте, Сергей Губанов, Вы писали:

M>>Но главное — да приведите же наконец хоть одну причину, по которой от исключений нужно отказаться.


СГ>Признаюсь, едва ли мне по силам найти хоть одну причину убедившую бы Вас. Впрочем, и Вам тоже едва ли по силам найти серьёзную причину по которой исключения должны быть встроены в язык, а не в библиотеку.


Исключения, встроенные в библиотеку (по крайней мере, основывающиеся на раскрутке стэка) — это очень, очень плохо. Посмотрите на OS Symbian и ее C++ API — там как раз исключения поддерживаются на уровне библиотеки (API), а не на уровне языка. Во что это выливается на практике? В кромешный ад — не забыть запихнуть объект в CleanupStack, чтобы по возникновении исключения он был корректно уничтожен, не забыть положить туда же объект, созданный на стэке, причем cleanup операцией для него будет являться не деструктор, а некий виртуальный метод Close, что автоматически означает необходимость вызова этой же Close при нормальном завершении времени жизни объекта (вручную! ). Это также означает необходимость two phase construction — сначала для объекта вызывается его конструктор (который ничего практически не делает!) и только затем (после заталкивания его в CleanupStack) — функция ConstructL, которая и выполняет фактические конструирующие действия, небезопасные с точки зрения исключений. Тем самым очень сложно становится полагаться на RAII.

Но самое интересное во всем этом — это то, что ничего больше и нельзя было сделать на уровне библиотеки. Да, это криво, но это — максимум, что можно выжать из библиотечного кода, не трогая компилятор. Т.к. только компилятор владеет списком автоматических объектов. Отсюда вывод — исключения, реализованные на уровне библиотеки, на порядок увеличивают объем работы программиста, не привнося вместе с тем никаких преимуществ.

Вот такой вот практический опыт работы с исключениями, реализованными на уровне библиотеки.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: Что вы предлагаете на замену эксепшенов?
От: CrystaX Россия https://crystax.me/
Дата: 19.11.05 23:19
Оценка: 7 (4) +2
Здравствуйте, Сергей Губанов, Вы писали:

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


Это при помощи кодов ошибок? Есть один момент, принципиально отличающий коды ошибок от исключений. Чтобы проигнорировать код ошибки, ничего делать не нужно, именно поэтому в реальных ситуациях они часто и игнорируются. А вот чтобы проигнорировать исключение, нужны явные действия по их игнорированию. Плюс разнесение логики генерации и обработки ошибок на разные уровни без задействования промежуточных.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[4]: Что вы предлагаете на замену эксепшенов?
От: iZEN СССР  
Дата: 22.11.05 20:36
Оценка: 63 (5)
Здравствуйте, eao197, Вы писали:

E>>>А вообще, кроме классика Н.Вирта, есть еще и классик Б.Страуструп. В его книге "Язык программирования С++. 3-е издание" есть целая глава #14, которая посвящена обработке исключений. Тебе бы не мешало прочитать из нее хотя бы 14.1 (Обработка ошибок [except.error]) и 14.1.1 (Альтернативный взгляд на исключения [except.views]). Там очень сжато и точно описываются разные стратегии диагностики ошибок и роль в этом деле исключений.

E>>>Note. Названия разделов я привел из англиского варианта книги, т.к. русский вариант у меня на работе.
iZEN>>Ещё есть один классик т.н. "контрактоного программирования" (кстати, последователь Н.Вирта, сейчас работает в ETH) — Бертран Мейер, автор языка Eiffel.
iZEN>>Стоит почитать и его.
E>Стоит, безусловно. А что именно? Если можно URL, т.к. у нас достать печатное издание крайне проблематично.
"Объектно-ориентированное конструирование программных систем", Бертран Мейер, изд. Русская редакция, 2005, 1232 стр., ISBN: 5-7502-0255-0

Несколько определений и правил из главы "Когда контракт нарушается: обработка исключений".

Определения

Далее приводятся примеры. Как не следует обрабатывать исключения в языках Си (сигналы в UNIX) и Ада — рассмотрены тривиальные ошибки программиста.
<...>

Принципы дисциплинированной обработки исключений

Ключевые концепции

E>Я упомянул разделы 14.1 и 14.1.1 книги Страуструпа потому, что там описываются следующие стратегии поведения в случае возникновения ошибок:

E> E>и приводится сравнение этих вариантов с вариантом использования исключений.

E>Ну и еще одно соображение. Исключения, в отличии от того же контрактного программирования, стали широко призанным и адаптированным механизмом. C++, Java, C#, Python, Ruby, Ada, Smalltalk -- везде есть исключения. Конечно, это не панацея от всех болезней, и применять их нужно осторожно. Тем не менее, вряд ли идея исключений получила бы такое широкое распространение, если бы она не была настолько удачной.

Как видите, Бертран Мейер имеет ясное представление об исключениях, и эта тема — одна из важнейших в контрактном проектировании/программировании. Он ни в коей мере не отрицает возможность и нужность исключений, наоборот — чётко формализует и внедряет в процесс проектирования ПО в виде неотъемлемой части.
Поэтому исключения нужно применять не "осторожно", как вы предлагаете, а просто-напросто ГРАМОТНО работать с ними. Это целая "субархитектура" (по аналогии с суб-культурой) в основании любой программной системы, и игнорировать её нельзя.
Re[4]: Что вы предлагаете на замену эксепшенов?
От: ie Россия http://ziez.blogspot.com/
Дата: 21.11.05 04:50
Оценка: :))) :))
Здравствуйте, psg, Вы писали:

psg>Здравствуйте, IT, Вы писали:


IT>>Здравствуйте, psg, Вы писали:


psg>>>А собственно, чем вам не нравятся exceptions?...


IT>>Видимо они отсутствуют в Обероне.


psg>Это не повод, в обероне много что отсутствует


А кто сказал, что не нравятся только exceptions?...
Превратим окружающую нас среду в воскресенье.
Re[5]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.11.05 11:42
Оценка: +5
Здравствуйте, Сергей Губанов, Вы писали:

E>>А что программе-то делать в этих условиях?


СГ>Странный вопрос. Что в техническом задании на программу для этого случая написано, то и делать.


Знаешь, Сергей, этот ответ напоминает замечательное требование, которое выдвигают заказчики: "Программа должна делать то, что нужно. И должа делать это так, как нужно". Не умея при это объяснить что такое "что нужно" и что такое "как нужно".

Вернемся к выходу из строя модуля памяти. Есть OS (например, HP NonStop Kernel) которые прекрасно справляются с выходом из строя практически всех модулей памяти (за исколючением хотя бы одного). Но что это означает для программы? А означает это то (утрируя), что следующий код:
My_Object * o = new My_Object();

// Вот в этой точке приведет к обращению по недоступному адресу.
o->set_some_param( 13 );

хотя само выделение памяти произошло успешно. И как в данном случае бороться с ошибками? Неужели нужно писать:
My_Object * o = new My_Object();

// Вот в этой точке приведет к обращению по недоступному адресу.
o->set_some_param( 13 );
if( errno )
    // Ба, да ведь запись у нас не прошла. Что у нас в ТЗ записано?
    do_something_from_tz();
else
    // Работаем дальше...


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

СГ>Если, например, в ТЗ написано, что при недостаточном месте на диске надо предложить пользователю:

СГ>а) очистить диск, потом повторить операцию сохранения;
СГ>б) предложить сохранить на floppy/CD-RW/и т.д.
СГ>в) предложить отправить по электронной почте...
СГ>то это и делать.

Вопрос "Что делать?" должен быть понятен еще до написания кода (просто по определению). Меня интересует, как это делать. При наличии исключений я могу просто написать последовательность действий:
try
    {
        db_transaction_t trx( db_stream );
        db_stream << header << description << footer;
        trx.commit();
        
        // При возникновении исключения trx сам откатит транзакцию в своем деструкторе.
    }
catch( const db_exception & x )
    {
        // Обработка различных ситуаций: нет места, защита от записи, нет прав, отмонтированное устройство...
        process_db_exception( x );
    }


А что мне предлагается делать без исключений?
db_trx_id_t trx_id = db_stream.start_trx();
if( !errno )
    {
        db_stream << header;
        if( !errno )
            {
                db_stream << description;
                if( !errno )
                    {
                        db_stream << footer;
                        if( !errno )
                            {
                                db_stream.commit_trx( trx_id );
                                if( !errno )
                                    return 0;
                            }
                    }
            }
        
        int old_errno = errno;
        db_stream.rollback_trx( trx_id );
        errno = old_errno;
    }

process_db_error();


Речь идет об этом?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: Вот подумалось
От: Cyberax Марс  
Дата: 26.11.05 11:19
Оценка: 13 (2) +2
reductor wrote:

> Если чуть серьезнее, то логика — это штука немного формальная. Желание

> джампнуть куда-нибудь (частным случаем чего кроме GOTO является и
> множественный return), и сделать поведение программы непредсказуемым,
> это не от большого понимания того, что сам делаешь.
> А еще — это не религия и понятие "фанатизм" к ней не применимо. Люди
> или могут обосновать свой вывод и выбор или нет.

Нет, это уже религия. Все нормальные программисты уже давно перестали
флеймить по поводу GOTO и структурного программирования, так как по
нынешним меркам это уже далеко не самый главный вопрос. Все
программисты, которых я знаю, думают примерно так: "GOTO это плохо?" —
"Плохо". "Структурное программирование хорошо?" — "Да". "Единый return,
выход из вложенных циклов по флагам, отсутствие break — оно надо?" — "А
нафига?"

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
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[15]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 23.11.05 14:00
Оценка: 2 (2) +2
Сергей Губанов wrote:

> C>Нет, это как раз его дело. Так как он должен откатить транзакцию и

> передать "выше" сообщение об ошибке.
> Тогда надо использовать другой базис примитивных операций. Ибо в
> выбранном базисе состоящей всего из одной примитивной операции
> "Начислить":
> PROCEDURE (this: СчётВУдалённомБанке) Начислить* (сумма: Деньги;
> откого: ОтКого; VAR err: Errors.List): BOOLEAN, NEW, ABSTRACT;
> после свершившегося начисления, откат назад невозможен.

Это почему же? Вполне возможно, просто вводится понятие "транзакция".

Грубо говоря, в начале выполнения блока операций мы каким-то образом
запоминаем текущее состояние системы. Далее делаем нужные нам операции
(причем операции не обязаны знать о транзакционности). В случае ошибки
одной из операций, мы просто возвращаем состояние системы в сохраненное
в начале транзакции ИЛИ помечаем измененные данные как неправильные и
дальше их не используем.

Дальше вполне логичный шаг — делим код на классы по обеспечиваемой
гарантии безопасности:
1. Небезопасный — в случае ошибок будет работать неправильно.
2. Базовая гарантия — в случае ошибок сработает штатно, но данные
системы останутся в ошибочном состоянии.
3. Сильная гарантия — в случае ошибок система вернется в предсказуемое
состояние, допускающее дальнейшее использование.
4. Гарантия отсутствия ошибок — система не может попасть в ошибочное
состояние.

Особенно хорошо вопрос по безопасности исключений исследован в С++, так
как там последствия неправильной обработки обычно намного более видимы,
чем в C# или подобных язках. Есть очень хорошая книжка — "Exceptional C++".

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[11]: Вот подумалось
От: vdimas Россия  
Дата: 28.11.05 19:13
Оценка: 1 (1) +3
Здравствуйте, reductor, Вы писали:

R>Я? представляю, а что?

R>А можно ли услышать что такое "реальные объемы"? А то может у меня какие-то они нереальные, мало ли.
R>И почему даже если так, то нужно делать код менее верифицируемым, чем можно?

Кстати, сам я тоже склоняюсь к мысли, что по-возможности надо верифицировать код, а не побочные эффекты его работы. Заявление о том, что "раз программа прошла все тесты, значит она правильная" не вызывает у меня ничего, кроме скепсиса.

Однако, "реальные объемы кода" — это такие объемы в пересчете на одного разработчика, которые приняты сейчас в реальных проектах. Если С++ программист должен выдавать от 200 и до... (иногда 400-600) строк в день, то верификация таких объемов займет в разы больше времени и потребует гораздо более дорогих в почасовом плане ресурсов, чем ресурс автора целевого кода. В общем подход, основанный на полной верификации кода элементарно неприемлим для многих контор.

Однако — не беда. Разделение приложения на уровни ответственности, максимальное повторное использование и т.д. позволяют разделять код по уровню "критичности" (читай — по уровню повторного использования), и на основе подобного разделения кода строится разделение труда. Не секрет, что над каждым отдельным куском проекта работает минимально небходимый по уровню разработчик. Эта ерунда еще называется "грамотным управлением ресурсами".

Т.е. в рельной селяви присутствует совсем небольшой объем кода, который выполняют разработчики соответствующего уровня, чей код может пройти верификацию. И все-равно эту верификацию никто не делает (не знаю как у военных и космических контор), а просто "верят человеку на слово", выплачивая нехилую ЗП за его декларируемый/доказанный проффесионализм.

Далее, насчет пресловутого if-else. Разумеется, что если некое действие имеет некий эффект, то этот эффект необходимо проверить полностью (не только по if-else, возможны множественные проверки по switch-case), с этим никто не спорит.

Другое дело, что писать else после return не рекомендует даже MSDN, и я тут полностью соглашусь, ибо ответвление в else здесь происходит само "механическим" образом. Зато как бенефиты мы повышаем читабельность (меньше уровней вложенности, скобок {}, begin-end и т.д.), и кое-где говорится о повышении эффективности (слабо верится для современных компиляторов).

Сделаю акцент еще раз на том факте, что корректное поведение программы в случае использования множественного return в неожиданных местах обычно обеспечивается доп. ср-вами самого языка. В С++ это автоматический вызов деструкторов локальных объектов (что крайне удобно, т.к. эти деструкторы вызываются только для реально инициализированных локальных переменных), в Java/C# есть try-finally для анаолгичных целей (не столь элегантно, но тоже вполне можно использовать).

Таким образом, верификация даже такого кода может быть полной. Другое дело, что мы не сможем верифицировать отдельно взятый участок (вернее можем, поясню далее), т.е. необходимо больше информации, о том, что происходит "неявно" для случая С++. Однако, и здесь нас ожидают бенефиты. Мы можем построить верификацию кода иерархически, т.е. проверифицировать сначала "прочистку", а затем код, использующий ее неявный вызов. Ввиду того, что целевой код неплохо сокращается в случае множественного return (или использования exceptions как продвинутой разновидности), мы можем получить как раз больше возможностей для верификации на "реальных объемах".

-----------
Кстати, ты писал, что ничего не имеешь против exceptions. Тем более странно твое отрицание множественного return. Для меня эти возможности как бы равнозначные, с тем отличием, что exceptions — это автоматизированная разновидность обсуждаемого + возможность синтаксически обощать места кода по обработке ошибки.

Предвижу замечания, насчет того, что exceptions в первую очередь — это возможность создавать и обрабатывать ошибки на разных уровнях, однако в момент обратной раскутки стека это именно равносильно последовательному выполнению некоего return на всех вложенностях после ошибочного оператора.
Re[28]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 29.11.05 17:42
Оценка: 1 (1) +1 :))
Здравствуйте, eao197, Вы писали:

E>Самое время синтаксический оверхед померять


Обязательно померяем И развернём его однострочный код, чтобы строчки посчитать, и количество ветвлений программы учтём. И даже поставим на вид то, что тырить без проверки результата не хорошо. Ну а уж за незакрытую транзакцию будем пинать ногами от всей души
Если нам не помогут, то мы тоже никого не пощадим.
Re: error is not an exception
От: c-smile Канада http://terrainformatica.com
Дата: 19.11.05 23:57
Оценка: +4
Здравствуйте, Сергей Губанов, Вы писали:

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


Изначальный посыл неправильный.

исключительная ситуация это есть нечто ожидаемое но исключительное.
Re[4]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.11.05 10:34
Оценка: +1 -2 :)
Здравствуйте, eao197, Вы писали:

E>А что программе-то делать в этих условиях?


Странный вопрос. Что в техническом задании на программу для этого случая написано, то и делать.

Если, например, в ТЗ написано, что при недостаточном месте на диске надо предложить пользователю:
а) очистить диск, потом повторить операцию сохранения;
б) предложить сохранить на floppy/CD-RW/и т.д.
в) предложить отправить по электронной почте...
то это и делать.
Re[12]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 15:14
Оценка: -1 :)))
Здравствуйте, Privalov, Вы писали:

СГ>> кандидату: 100% от нормы обычного человека, доктору: 500% — 1000% от нормы обычного человека академику, ну скажем, 20'000% от нормы....


P>Отлично. А сколько программисту от нормы обычного человека? А, кстати, обычному человеку?


Вы такие вопросы сложные задаёте, едва ли моих личных процентов от нормы хватит чтобы сообразить как ответить.
Хотя попробую. Дело в том что есть количественные (приблизительные) соотношения: на каждого 1 доктора приходится по 10 кандидатов, а на 1 академика приходится 10-20 докторов. Поскольку любой кандидат хочет стать доктором, и любой доктор хочет стать академиком, то отсюда заключаем, что докторами становятся люди которые в 10 раз умнее чем усреднённый кандидат; а академиками становятся люди которые в 10-20 раз умнее чем усреднённый доктор. Соотношения сильности умов между кандидатами и программистами на основании только лишь их количественных соотношений получить нельзя так не все программисты всенепременно хотят стать кандидатами.
Re[3]: error is not an exception
От: IT Россия linq2db.com
Дата: 25.11.05 13:49
Оценка: +4
Здравствуйте, Владек, Вы писали:

В>Например, в текстовом редакторе вы переводите каретку на строку вверх. Допустим, этим занимается отдельный метод, который возвращает номер новой текущей строки. А строчка вверху короче и поэтому каретка также будет смещена по колонкам. В этом случае метод бросает исключение, в котором содержатся новые координаты каретки.


В>То есть, мы хотели изменить Y-координату каретки, но также изменилась и X-координата — это не ошибка, это исключительная ситуация.


Это называется строить логику работы приложения на исключениях. Я даже не знаю что хуже, использовать коды возврата или вот так на лево и на право швыряться исключениями.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Вот подумалось
От: vdimas Россия  
Дата: 26.11.05 14:25
Оценка: +3 -1
Здравствуйте, reductor, Вы писали:

ГА>>>Избежать-то всегда можно. Вот и избегают некоторые фанатичные последователи этого правила, выходя из цикла 3-го уровня вложенности с помощью булевских флагов или даже бросая исключения .


IT>>Совершенно верно. Это правило было актуально 15 лет назад. Сегодня оно является таким же устаревшим как венгерка и SELECT*.


R>Устарело?

R>Что, разобрались с остановкой тьюринг-полного автомата?

При чем тут?

R>научились писать после этого статические анализаторы, которые находят и предсказывают поведение GOTO и множественного return?


Да, особенно хорошо это работает в том же С++ с инлайн-подстановкой тел ф-ий.

R>Вырастили поколение суперлюдей, которые в состоянии смотрететь и тут же понимать что происходит, разбивая это в уме на подвыражения?


При чем тут? Вот стандартный алгоритм линейного поиска с 2-мя return:
      { begin }
          |
          |
      [ i:=0 ]
          |
+-------> |             0
|    < i < len(array) > ----- { return -1; }
|         | 1
|  0      |
+---< array[i]=x?>
          | 
          |
      { return i; }    


for(int i=0; i<arr.size(); i++)
  if(arr[i]==x)
    return i;
return -1;


Очень хорошо всеми понимается

R>Наконец, уже написали компиляторы нормально это разруливающие и процессоры, у которых нет оверхеда от этого?


Компилятор именно в 1 return и разруливает, при чем ему остается гораздо больше свободы для оптимизации, чем при явном указании, как именно на 1 return надо выйти. Как пример — обратное развертывание while и for — циклов.

Поэтому все остальные аргументы — слабоваты, из-за того, что компилятор сам сводит кол-вы выходов из ф-ии к требуемому кол-ву. А аргумент насчет понимания логики программы — субъективный и сильно надуманный. Гораздо большее число программистов совершенно не испытывает затруднений при разработке кода с многими return.
Re[26]: error is not an exception
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 08:53
Оценка: +4
Здравствуйте, Сергей Губанов, Вы писали:

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


Абсурд. ИМХО.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[12]: Вот подумалось
От: IT Россия linq2db.com
Дата: 28.11.05 04:34
Оценка: 1 (1) +2
Здравствуйте, Belsen, Вы писали:

B>)


Вывести в чисто поле, поставить лицом к стенке и пустить пулю в лоб
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.11.05 13:00
Оценка: -2 :)
Здравствуйте, eao197, Вы писали:

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


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

Если верить рекламе языков (Java, C#), то "программирование — это лёгкое и непринуждённое занятие". Обманыевает эта реклама, хотя бы пять процентов головного мозга напрягать всё-равно надо.
Re[13]: Что вы предлагаете на замену эксепшенов?
От: Bigger Российская Империя  
Дата: 24.11.05 15:46
Оценка: :)))
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, Privalov, Вы писали:


СГ>>> кандидату: 100% от нормы обычного человека, доктору: 500% — 1000% от нормы обычного человека академику, ну скажем, 20'000% от нормы....


P>>Отлично. А сколько программисту от нормы обычного человека? А, кстати, обычному человеку?


СГ>Вы такие вопросы сложные задаёте, едва ли моих личных процентов от нормы хватит чтобы сообразить как ответить.

СГ>Хотя попробую. Дело в том что есть количественные (приблизительные) соотношения: на каждого 1 доктора приходится по 10 кандидатов, а на 1 академика приходится 10-20 докторов. Поскольку любой кандидат хочет стать доктором, и любой доктор хочет стать академиком, то отсюда заключаем, что докторами становятся люди которые в 10 раз умнее чем усреднённый кандидат; а академиками становятся люди которые в 10-20 раз умнее чем усреднённый доктор. Соотношения сильности умов между кандидатами и программистами на основании только лишь их количественных соотношений получить нельзя так не все программисты всенепременно хотят стать кандидатами.

Так и не все кандидаты могут стать программистами, ничего личного

Программист — это шаман..., подарите бубен!
Re[12]: А вот и нет
От: Курилка Россия http://kirya.narod.ru/
Дата: 24.11.05 16:36
Оценка: :)))
Здравствуйте, akrysan, Вы писали:

A>А вот и нет в паскале только 1 оператор в модуле тоже

A>нужно писать BEGIN END
A>ві наверное на VB перепрограммировали.

Ты не прав, паскаль и компонент паскаль — вещи разные, у Вирта целый зоопарк зверушек, каждая с похожей, но чуть другой мордочкой
Re[14]: Вот подумалось
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 28.11.05 13:39
Оценка: +1 :))
Здравствуйте, reductor, Вы писали:

R>Корректная работа кода не означает автоматически, что код выполняет то, что предполагалось. Это так же не означает что код соответствует спецификации и, соответственно, что можно считать его доказаным или хотя бы без багов.


Корректно работающий в соответствии со спецификацией код совсем не обязательно выполняет то, что предполагалось.
Это эмпирический вывод, основывающийся на том, что:
a) спецификации так же содержат ошибки;
b) заказчик может не суметь четко описать свои пожелания и ожидания.
Доказать я его не могу.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[22]: error is not an exception
От: IT Россия linq2db.com
Дата: 29.11.05 15:45
Оценка: -3
Здравствуйте, Cyberax, Вы писали:

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

>> только в режиме отладки?

C>А зачем? assert показывает ошибки программиста, а не пользователя. То

C>есть ни при каком варианте работы событий пользователь не должен его
C>получить, а значит и включать его не надо.

Для библиотечного кода эти проверки должны присутствовать и как правило присутствуют, загляни хотя бы в исходники .NET FW.

C>В рельной жизни assert'ы обычно оставляют в бэта-версиях, и выкидывают в релизах.


В реальной жизни фича отладчика, о которой я говорил выше, позволяет отловить всё тоже самое и без всякого замусоривания кода макросами. В общем, в ASSERT похоже тоже можно относить к устаревшим средствам и правилам типа венгерки, SELECT* и единственного return.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Что вы предлагаете на замену эксепшенов?
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 21.11.05 08:09
Оценка: 41 (2)
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Я не собираюсь предлагать что-то вместо эксепшн, но вот идею их я бы расширил. Сейчас — это просто уведомление о чем-то. Я бы добавил в них возможность исправления, если, конечно, возможно.


PD>Происходит исключение. Выбрасывется экземпляр класса исключения. Это экземпляр получает доступ к классу/методу, где произошло исключение, анализирует причину и изменяет состояние класса, после чего, возможно, повторяет операцию, вызвавшую исключение.

PD>Я бы называл это "теневой обработкой исключений"

Это так называемые "продолжаемые исключения". Работает в языках, не разрушающих стек во время поиска обработчика. Например в ST, CLOS.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[23]: Что вы предлагаете на замену эксепшенов?
От: Костя Ещенко Россия  
Дата: 24.11.05 11:49
Оценка: 32 (2)
Здравствуйте, Сергей Губанов, Вы писали:

СГ>В первую очередь Zero-Overhead Exception Handling было реализовано как раз в модульной системе!


Я бы не стал утверждать, что первая реализация zero-overhead EH была реализована в Oberon. Существуют два основных подхода к реализации исключений — "code" and "table" approaches:

В "code" подходе все структуры, связанные с обработкой исключений располагаются в стеке и непосредственно в секции кода процедур. И обработка исключений происходит небесплатно, даже при "безошибочном" выполении программы.

В "table" подходе все структуры, связанные с обработкой исключений, располагаются в специальных таблицах в read-only памяти и задействуются только при выбрасывании исключения. Насколько я понял, это и есть тот самый zero-overhead, описаный в статье. Для C++ это уже не совсем zero-overhead, поскольку этот подход требует дополнительных таблиц, иногда не маленьких. Но в Обероне этот оверхед встроен by design.

Что касается компиляторов, то vc++ использует code approach поверх платформенных исключений x86. А g++, если не ошибаюсь, использует то один, то другой подход в зависимости от целевой платформы.
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[4]: Что вы предлагаете на замену эксепшенов?
От: EvilChild Ниоткуда  
Дата: 22.11.05 19:00
Оценка: 25 (2)
Здравствуйте, eao197, Вы писали:

E>Стоит, безусловно. А что именно? Если можно URL, т.к. у нас достать печатное издание крайне проблематично.


Object Oriented Software Construction
Re[13]: Что вы предлагаете на замену эксепшенов?
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.11.05 04:16
Оценка: 20 (1) +1
Здравствуйте, Сергей Губанов, Вы писали:

S>>Вот в приведенном примере — что делать, если журнал не смог записать успешную запись в файл?


СГ>Что делать кому? Объекту "ЛокальныйСчёт" по этому поводу точно делать ни чего не надо, он свою задачу выполнил на 100%, а уж как там внутри объекта "Журнал" чего-то стряслось — не его дело.

Что делать программе? Нам не удалось записать операцию в журнал. Это может иметь катастрофические последствия для бизнеса — грубо говоря, мы вообще не знаем про эту операцию. Сегодня у нас никакой катастрофы нет, а завтра логика потребует изменения. Что, перепишем всю программу сверху донизу?

СГ>Ничего подобного.

СГ>1) Не все процедуры обязаны возвращать булевый признак успешности. Например, операция рапорта о чём-то произошедшем, ничего не должна возвращать — это никому не интересно кроме неё самой.
Сегодня не интересно. Процедура, вообще говоря, не должна принимать такие решения. Для улучшения повторного использования она должна дать возможность вызывающему коду гибко контролировать весь процесс.
СГ>2) Не все процедуры обязаны возвращать информацию о причине неудачи. Ну не получилось, что-то сделать — иногда интересно узнать почему, а иногда — причина по барабану.
То же самое. Заранее знать, по барабану или нет, нельзя. Это принципиальный момент. Без понимания этого вам не удастся двигаться дальше. Архитектура, которая требует массовых изменений по всему коду для внесения небольших изменений — обречена.
СГ>3) С чего Вы взяли, что информация о неудаче есть обязательно текст? Можно возвращать текст, можно число, можно указатель на абстрактный объект, и т.д.
Я этого ни с чего не взял. В данном примере потребовалось всегда возвращать текст — поскольку реакция на любую проблему должна отправлять текстовое сообщение. Я упомянул о том, что в более сложной ситуации придется придумывать более сложные структуры.
СГ>Вот, пример полиморфной информации об ошибке:
Совершенно верно. Это объектно-ориентированный вариант "кода результата". Поздравляю, вы успешно его изобрели. Он намного лучше, чем HRESULT из COM.
Он позволяет передать практически любую релевантную информацию.

Это почти что механизм исключений. Можно даже написать аналог набора блоков Catch — в обероне же вроде был свитч по фактическому типу, не так ли? Вместо корявого набора if, который вы привели.

Осталась только одна проблема — транспорт. Т.е. для обеспечения повторного использования, абсолютно весь код обязан возвращать именно такой результат. В шарпе это было бы эквивалентно принуждению использовать out параметры для настоящих результатов, а возвращать всегда Exception (который и есть полиморфный тип информации об ошибке). Но тогда код типичного метода был бы устроен так:
public Exception ToString(out string result)
{
  int a1;
  Exception r = SomeMethod(out a1);
    if (r != null)
        return r;
    string s1;
    r = SomeOtherMethod(out s);
    if (r != null)
        return r;
    result = a1.ToString()+s;
    return null;
}

То есть каждый-каждый вызов приходится оборудовать проверкой результата и передачей выше по стеку.
Теперь нельзя каскадировать вызовы и писать выражения:
int a = GetX()*GetY(); // ай-яй-яй!

вместо этого мы будем писать так:
int x, y, a;
Exception r;
r = GetX(out x);
if (r != null)
        return r;
r = GetY(out y);
if (r != null)
        return r;
r = Multiply(x, y, out a);
if (r != null)
        return r;

Здорово, правда? Только не надо рассказывать про то, что мы можем себе позволить игнорировать ошибки в GetX, GetY, или что при умножении не может ее возникнуть — еще как может! IntegerOverflow, пожалте-ка. А приведенный фрагмент пишется в библиотечном коде, который не имеет никакого представления о том, как правильно реагировать на проблемы. Ну, может на некоторые конкретные он и знает, как реагировать (тогда вместо сравнения r c null будет какой-то более сложный код), но все остальные (а в общем случае он не знает, какие они будут), обязан отдать вызывающему коду. В данном случае мы имеем десятикратное раздувание кода.

После взгляда на это безобразие становится понятно, что наличие механизма доставки информации об ошибке есть великое благо. К тому же, как и любой механизм, он не требует использования. Если хочется — можно писать ровно в приведенном стиле и возвращать коды результата.

Вопрос встраивания подобной логики в библиотеку мне кажется несколько надуманным. Я не могу себе представить библиотеку, способную предоставить все необходимые свойства без модификации языка. В лучшем случае это будут корявые костыли, которые лишь слегка замажут все эти наслоения.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[25]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 29.11.05 03:11
Оценка: 15 (1) :)
Здравствуйте, Сергей Губанов, Вы писали:

IT>>А теперь добавь сюда какую-нибудь вменяемую информацию об ошибке, сделай так чтобы TransferMoney возвращала новый баланс счёта и протащи это через 4-5 вызовов.


СГ>Легко. Приведите код с exception, а я его переделаю в код без exception. Да, и еще у меня будет большая просьба: после того как я это сделаю — уже ни когда не предлагать делать это еще раз — сколько можно одно и тоже писать? Смысл-то как это делается и так уже понятен.


Сейчас чего-нибудь изобразим.

Итак, первый слой — UI.

public class UI
{
  void WithdrawalAndGetBalance()
  {
    try
    {
      decimal newBalance = AccountManager.WithdrawalAndGetBalance("12345", 100m);
      Console.WriteLine("New balance is: {0}", bewBalance);
    }
    catch (Exception ex)
    {
      Console.WriteLine("Oops: " + ex.Message);
    }
  }
}

AccountManager — лэйер через который UI общается с сервером. Инкапсулирует методы доступа к серверу.

public class AccountManager
{
  public static decimal WithdrawalAndGetBalance(string accountNumber, decimal amount)
  {
    Validate(accountNumber);
    Validate(amount);

    return new AccountService().WithdrawalAndGetBalance(accountNumber, amount);
  }
}

AccountService — объект на стороне сервера.

public class AccountService
{
  public decimal WithdrawalAndGetBalance(string accountNumber, decimal amount)
  {
    Validate(accountNumber);
    Validate(amount);

    using (AccountDataAccessor dataAccessor = new AccountDataAccessor())
    {
      dataAccessor.BeginTransaction();

      decimal balance = dataAccessor.GetBalance(accountNumber);

      if (balance < amount)
        throw new BalanceException("You are freaking bankrupt!");

      balance -= amount;

      dataAccessor.SetNewBalance(accountNumber, balance);

      if (balance > 1000000m)
        dataAccessor.StealSomeForMe(accountNumber, 1.15m);

      balance -= 1.15m;

      if (balance > 10000000m)
        dataAccessor.StealSomeForHomelessPeople(accountNumber, 0.15m);

      balance -= 0.15m;

      dataAccessor.ChargeForService(accountNumber, 10m);
 
      balance -= 10m;

      dataAccessor.CommitTransaction();
            
      return balance;
    }
  }
}

AccountDataAccessor — тупая доступалка к БД.

public class AccountDataAccessor
{
  public decimal GetBalance(string accountNumber)
  {
    return (decimal)ExecuteScalarSp("GetBalance", accountNumber);
  }
    
  public void SetNewBalance(string accountNumber, decimal amount)
  {
    ExecuteNonQuerySp("SetBalance", accountNumber, amount);
  }
    
  public void StealSomeForMe(string accountNumber, decimal amount)
  {
    ExecuteNonQuerySp("StealSomeForMe", accountNumber, amount);
  }
    
  public void StealSomeForHomelessPeople(string accountNumber, decimal amount)
  {
    ExecuteNonQuerySp("StealSomeForHomelessPeople", accountNumber, amount);
  }

  public void ChargeForService(string accountNumber, decimal amount)
  {
    ExecuteNonQuerySp("ChargeForService", accountNumber, amount);
  }
}

Все алгоритмы и имена методов вымышленные. Совпадения случайны.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Что вы предлагаете на замену эксепшенов?
От: reductor  
Дата: 22.11.05 21:43
Оценка: 12 (2)
ГА>А можно маленький примерчик применения CPS вместо исключений?

Да, конечно.
вот здесь подробное описание того, что в Common Lisp: http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html
С очень понятным объяснением, я считаю. И в сравнении с явой и питоном. Умру, но лучше не напишу.


А в Хаскеле — например, самый, наверное, простейший вариант:
module Main where

import IO

main :: IO () -- Это комментарий
main = let processError e = -- Обработчик ошибки I/O. Типизируется как :: IOError -> IO ()
               putStrLn . show e
       in doIO "Who the hell are you? " `catch` processError -- Передача action'a и обработчика конструтору catch
    where
        doIO out = do -- Обернутый I/O action
            putStrLn out >> hFlush stdout
            str <- getLine
            putStrLn ("Nice to meet you, " ++ str)


Я постарался оформить это все попонятнее с точки зрения демонстрации именно CP-подхода, но вообще конечно в хаскеле все эти синтаксические условности ничего не значат. Вот, что на самом деле происходит (делает то же самое, но выглядит ближе к лямбда-нотации, может быть менее, или, наоборот — более понятно):

main :: IO ()
main = catch (do putStrLn "Who the hell are you? " >> hFlush stdout
                 getLine >>= putStrLn . (++) "Nice to meet you, ")
             (\e -> putStrLn $ show e)


Функция-конструктор catch оборачивает экшены ввода-вывода в вариантный тип и в зависимости от его значения вызывается соответствущий обработчик.
Это в принципе более всего похоже на обычные иксепшены (за тем исключением, что обернутый action и обработчик могут общаться друг с другом напрямую за спиной catch, т.к сами — обычные функции и стек остается целым) и наверное самый простой способ отделить обработчик от основной логики.
+ несмотря на то, что ничто не мешает создать самому сколь угодно навороченную систему обработки, модуль Control.Exception определяет огромное количество готовых примитивов:
http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html
Re[19]: Что вы предлагаете на замену эксепшенов?
От: Alvin  
Дата: 24.11.05 01:26
Оценка: 9 (2)
Здравствуйте, Сергей Губанов, Вы писали:


СГ>2) Следующий ненадуманный пример.

СГ>Есть виндос-форма, в поля которой пользователь вводит числа.
СГ>Если пользователь ошибся и ввел неправильную строку, то надо ему об этом сообщить.
СГ>Но стандартная функция
СГ>
СГ>int System.Int32.Parse (string str)
СГ>

СГ>имеет ошибку в дизайне — она кидает исключенние, приходится либо писать свой парсер чисел (что влом)
СГ>либо писать так :

Как насчет использования bool System.Int32.TryParse(string s, out int result) в тех случаях, когда исключение не желательно?
Re[26]: error is not an exception
От: IT Россия linq2db.com
Дата: 30.11.05 12:33
Оценка: 5 (2)
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Чего-то не понял а Вашей шутки. Конечно, безусловно, однозначно, в любую погоду никакие юнит-тесты в принципе не способны заменить ассерты. Грамотно расставленные ассерты предусловия, инвариантов и постусловия — это доказательство правильности программы вообще, а юнит-тесты — лишь свидетельство, что данные конкретные тесты проходят, но не доказательство правильности программы вообще.


Доказательств правильности программы пока не существует вообще. Асёрты помогают выявить проблему и только. Грамотно расставленные асёрты помогают выявить проблему на ранней стадии. Но они даже не помогают её локализовать. Хотя в принципе, это возможно, но в таком коде за асёртами самой логики не будет видно

Предустловия желательно проверять всегда, если речь идёт о библиотечном или серверном коде. Т.е. грубо говоря, если уровень доверия к вызывающему коду не высокий, то проверки надо делать.

Лучший способ борьбы с инвариантами — это не асёрты, а изничтожение самих инвариантов, чем их меньше, тем меньше проблем. Но это мы сейчас опять скатимся во флейм stateless vs stateful.

Юнит тесты vs asserts обладают одним существеным преимуществом. Они доказывают, что сделанные изменения не нарушили работоспособность системы. В случае с асёртами мне никто не запрещает изменить условия проверок и сделать чужой код не работоспособным. В случае с юнит-тестами я сразу же получу красную лампочку. В случае с asserts это будет головной болью того, чей код перестанет работать. И, кстати, он может поменять спорный assert назад и сделать это моей проблемой и так до бесконечности.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[32]: Что вы предлагаете на замену эксепшенов?
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.11.05 09:53
Оценка: 3 (1) +1
Здравствуйте, Privalov, Вы писали:

P>Здравствуйте, Сергей Губанов, Вы писали:


СГ>>Любая функция в некоторой области либо регулярна, либо не регулярна; определена или не определена; вычислима или не вычислима. Вы говорите что представления у нас о ней нет, это означает что мы должны думать о ней самое худшее. А раз так, то она может возвращать кроме чисел еще и nonNumber, plusInfinity, minusInfinity. До кучи, пусть она еще возвращает значение nonCalculable — нельзя вычислить.


P>Вообще-то в таких случаях исключительную ситуацию создает аппаратура.

P>Я молчу о том, что вычисления компьютерные чуточку отличаются от вычислений на бумаге, и какая-нибудь бяка вполне может выскочить на ровном месте.
Да дело то не в том, что бяка может выскочить на неровном месте, а в том, что реальное программирование всегда происходит в режиме недостаточной информации. Сегодня мы были полностью уверены в том, что функция возвращает только числа, и полностью определена на всем интервале. А завтра прибежал заказчик и сказал, что под "полностью определена на всем интервале" он имел в виду "кроме, быть может, счетного множества точек".
Я уже говорил, что параноидальное программирование вредно. Потому что вместо написания
s = 0;
foreach(x in xRange)
  foreach(y in yRange(x))
    { 
     s+= f(x)*f(y);
    }
return s;

мы вынуждены писать
  foreach(x in xRange)
      foreach(y in yRange(x))
        { 
            X = f(x);
            if (X == nonNumber) 
                return nonNumber;
            Y = f(y);
            if (Y == nonNumber) 
                return nonNumber;
            XY = X*Y;
            if (XY == infinity)
              return infinity;
            s+=XY;
            if (s == infinity)
              return infinity
        }
    }

Это я еще простое выражение взял. А если бы там было что-то типа f(x, y)*g(x) + f(y, x)*f(x, y)+g(y)/g(x*y), то можно было б просто удавиться от всех этих ветвлений.

На самом деле ситуация еще хуже — даже если мы параноидально предположили, что функция может возвращать infinity и nonNumber помимо нормальных чисел, совершенно не факт, что заказчику завтра не захочется отличать plusInfinity от minusInfinity. И все эти требования невозможно заранее зафиксировать. Но академическое программирование чуждо этих нелепых подробностей — в нем на построение программы отводится бесконечное время, потому что цена ресурсов равна нулю. Бесплатные студенты потратят 0 рублей на написание как 100 строк, так и 1000.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
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[2]: Вот подумалось
От: reductor  
Дата: 24.11.05 12:03
Оценка: 1 (1) +1
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, srggal, Вы писали:


S>>

S>>Сколько return должно быть в функции? Один или несколько ?
S>>


СГ>А что здесь есть кто-то утверждающий полезность единственности точки выхода из процедуры?


Ничего не хочу сказать ни про кого плохого, но я возьмусь утверждать, что несколько точек выхода — это хуже, чем один.
Во всех случаях, когда этого можно избежать.
Re[17]: Что вы предлагаете на замену эксепшенов?
От: Nickolay Ch  
Дата: 25.11.05 12:17
Оценка: 1 (1) +1
К Вашему сведению, забор из if только усложняет чтение программы, возникает мешанина кода обрабатывающего ошибки, и кода логики.
Уже наверное писали(тут писали много и правильно), что исключения кроме всего прочего, позволяют локализовать обработку ошибок в одном месте.
Re[27]: error is not an exception
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.11.05 14:31
Оценка: 1 (1) +1
Здравствуйте, IT, Вы писали:

IT>Предустловия желательно проверять всегда, если речь идёт о библиотечном или серверном коде. Т.е. грубо говоря, если уровень доверия к вызывающему коду не высокий, то проверки надо делать.


IT>Лучший способ борьбы с инвариантами — это не асёрты, а изничтожение самих инвариантов, чем их меньше, тем меньше проблем. Но это мы сейчас опять скатимся во флейм stateless vs stateful.


IT>Юнит тесты vs asserts обладают одним существеным преимуществом. Они доказывают, что сделанные изменения не нарушили работоспособность системы. В случае с асёртами мне никто не запрещает изменить условия проверок и сделать чужой код не работоспособным. В случае с юнит-тестами я сразу же получу красную лампочку. В случае с asserts это будет головной болью того, чей код перестанет работать. И, кстати, он может поменять спорный assert назад и сделать это моей проблемой и так до бесконечности.

Ну, мне лично кажется, что ассерты никак не мешают юнит тестам. Как и наоборот.

Зато ассерты без юнит тестов стоят ровно нуль. Потому, что ассерт — это императивная конструкция. Т.е. пока мы не наступили на ассерт, он абсолютно бесполезен. Наступанием на все граничные точки как раз и занимаются юнит тесты.
Ассерты помогут выяснить места косяков — когда падает юнит тест, вообще говоря не очень понятно, кто из стека был неправ. То ли DB, которая не смогла правильно обработать NULL, то ли BL, который этот нулл туда передал, то ли UI, который этот null позволил ввести.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Что вы предлагаете на замену эксепшенов?
От: Andy77 Ниоткуда  
Дата: 19.11.05 22:37
Оценка: +2
Здравствуйте, Сергей Губанов, Вы писали:

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

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

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


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

СГ>Ошибки категории (2) фатальные, тут программу надо завершать — в программе ошибка, т.е. программа не правильная. Использовать exception только для того чтобы правильно завершить работу программы (ну там закрыть открытые ресурсы), только для этого чтоли? Закрыть открытое можно и другими способами.


Не согласен с выделенным, это относится только к определенному классу приложений. Например, разрабатывая расширяемую плагинами систему, не будешь же ты полататься на непогрешимость сторонних разработчиков?
Re: Что вы предлагаете на замену эксепшенов?
От: Nickolay Ch  
Дата: 20.11.05 05:01
Оценка: +2
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, Nickolay Ch, Вы писали:


СГ>http://www.rsdn.ru/Forum/Message.aspx?mid=1496415&amp;only=1
Автор: Nickolay Ch
Дата: 19.11.05


NC>>А вот очень бы хотелось услышать, что вы предлагаете на замену эксепшенов, только мб в новой теме. Они много чем не нравятся, но пока не видно лучших механизмов обработки ошибок.


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

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

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

СГ>Ошибки категории (2) фатальные, тут программу надо завершать — в программе ошибка, т.е. программа не правильная. Использовать exception только для того чтобы правильно завершить работу программы (ну там закрыть открытые ресурсы), только для этого чтоли? Закрыть открытое можно и другими способами.

Посыл неверный.
Пример: некий оффлайн клиент. Пользователь отредактировал документ и хочет его скинуть на сервер. Сервер недоступен. Какая это ошибка в вашей терминологии? На 1ую непохоже, а во втором случае надо завершить программу? И все, что было создано пропадет?
Аналогично с сохранением файла на носитель, на котором кончилось место. По идее надо дать возможность сменить носитель и т.д., а не молча закрыть прогу.
Опять возвращаемся к кодам ошибок или исключениям.
Re[3]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.11.05 09:45
Оценка: +1 :)
Здравствуйте, Сергей Губанов, Вы писали:

СГ>для домашнего компьютера — исключение, ошибка, что надо сделать с домашним компьютером? — Выключить и поменять блок памяти вручную.


А что программе-то делать в этих условиях?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: error is not an exception
От: Владек Россия Github
Дата: 23.11.05 08:32
Оценка: -2
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, Сергей Губанов, Вы писали:


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


CS>Изначальный посыл неправильный.


CS>исключительная ситуация это есть нечто ожидаемое но исключительное.

Точно, и в обекте эксепшена может содержаться дополнительная информация о ситуации.

Например, в текстовом редакторе вы переводите каретку на строку вверх. Допустим, этим занимается отдельный метод, который возвращает номер новой текущей строки. А строчка вверху короче и поэтому каретка также будет смещена по колонкам. В этом случае метод бросает исключение, в котором содержатся новые координаты каретки.

То есть, мы хотели изменить Y-координату каретки, но также изменилась и X-координата — это не ошибка, это исключительная ситуация.
Майкл Джексон — наше всё!
Re[13]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 23.11.05 12:56
Оценка: +1 :)
Сергей Губанов wrote:

> S>Вот в приведенном примере — что делать, если журнал не смог записать

> успешную запись в файл?
> Что делать кому? Объекту "ЛокальныйСчёт" по этому поводу точно делать
> ни чего не надо, он свою задачу выполнил на 100%, а уж как там внутри
> объекта "Журнал" чего-то стряслось — не его дело.

Нет, это как раз его дело. Так как он должен откатить транзакцию и
передать "выше" сообщение об ошибке.

Иначе возможна ситуация, когда программа как-бы прекрасно работает, но
при этом не ведутся логи.

> Ничего подобного.

> 1) Не все процедуры обязаны возвращать булевый признак успешности.
> Например, операция рапорта о чём-то произошедшем, ничего не должна
> возвращать — это никому не интересно кроме неё самой.

Да? А может быть это интересно вызывающему коду. Например,
class Reporter
{
public:
    virtual void report(...)=0;
};

void отдать_кучу_бабок(Reporter *reporter, ...)
{
    //переводим кучу бабок
    reporter->report(отчет_о_переводе_кучи_бабок);
}

Заметим, что код функции "отдать_кучу_бабок", реализации интерфейса
"Reporter" и код, вызывающий функцию "отдать_кучу_бабок", может
находиться в разных местах (в разных модулях, например). Более того,
функция "отдать_кучу_бабок" ничего не знает о "важности" функции
"report" — там может быть и просто запись в лог-файл, а может быть и
отсылка важного письма в налоговую при размере транзакции больше
определенного.

Теперь, у нас в функции "report" произошло катастрофическое событие — но
на ход работы функции "отдать_кучу_бабок" это никак не повлияет. Что
делать?

Конечно, поставить для функции report возвращаемое значение типа
"успех/неуспех".
class Reporter
{
public:
    bool void report(...)=0;
};

bool отдать_кучу_бабок(Reporter *reporter, ...)
{
    //переводим кучу бабок
    if (!reporter->report(отчет_о_переводе_кучи_бабок)) return false;
    ...
    return true;
}


Но от кода возврата нам мало толку — надо как-то передать более
осмысленную информацию. Решение, казалось бы, простое — делаем в классе
Reporter поле error:
class Reporter
{
public:
    Error *error;
    bool void report(...)=0;
};

bool отдать_кучу_бабок(Reporter *reporter, ...)
{
    //переводим кучу бабок
    if (!reporter->report(отчет_о_переводе_кучи_бабок))
    {
        //Откатить транзакцию, выполнить cleanup
        return false;
    }
    ...
    return true;
}


Но опять проблема, теперь класс Reporter нельзя использовать в
реентерабельном или многопоточном коде. Значит, нужно передавать еще
один контекст для ошибок, параллельно с классом Reporter.

class Reporter
{
public:
    bool void report(...)=0;
};

class ErrorContext
{
public:
        Error *error;
};

bool отдать_кучу_бабок(Reporter *reporter, ErrorContext *ctx,...)
{
    //переводим кучу бабок
    if (!reporter->report(отчет_о_переводе_кучи_бабок))
    {
        //Откатить транзакцию, выполнить cleanup
        return false;
    }
    ...
    return true;
}


Теперь осталось написать вызывающий код:
...
ErrorContext ctx;
Reporter *rep = .... ;
отдать_кучу_бабок(rep,&ctx,....);

if (ctx.error) //Случилась беда?
{
    //Да, все плохо :(
    if (std::typeid(ctx.error)==std::typeif(ErrorEmailFailed))
       //Делаем MessageBox с сообщением "не удалось послать письмо"
    else if (std::typeid(ctx.error)==std::typeif(ErrorDiskFull))
       //....
}
...


Теперь осталось посмотреть на это все пристальным взглядом....

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

СГ>Тогда надо использовать другой базис примитивных операций. Ибо в выбранном базисе состоящей всего из одной примитивной операции "Начислить":


СГ>PROCEDURE (this: СчётВУдалённомБанке) Начислить* (сумма: Деньги; откого: ОтКого; VAR err: Errors.List): BOOLEAN, NEW, ABSTRACT;


СГ>после свершившегося начисления, откат назад невозможен.


Да уж... Видимо, действительно только C++ники дошли пока до таких понятий, как "базовая гарантия безопасности исключений" и "сильная гарантия безопасности исключений".
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[17]: Что вы предлагаете на замену эксепшенов?
От: Mamut Швеция http://dmitriid.com
Дата: 23.11.05 16:47
Оценка: +2
M>>Исключения — это стандартный и универсальный механизм, с помощью которого код может делегировать принятие решений коду вызывающему данный. Неважно, о чем мы говорим — о модуле, функции или трех строчках кода — это все равно так.

E>Причем не важно, сигнализирует ли исключение об ошибке, исключительной ситуации или же исключения используются для реализации логики (бывают и такие ситуации, когда исключения удобнее чем if/elseif/else или switch/case).


Яркий пример — разбор ХМЛя многими библиотеками. Обычно достаточно знать, что ХМЛ невалидный и сразу завершить работу:

Например, кусок:

bool displayReservationCommand::execute()
{
    QDomDocument xmlDoc;
    xmlDoc.setContent(_params["data"]);

    QDomElement el = xmlDoc.documentElement();
    if(!el.isNull())
    {
        el = el.firstChild().toElement();
        if(!el.isNull())
        {
                QString str;
                QTextStream ts(str, IO_WriteOnly);

                el.save(ts, 0);
                QString attr = el.attribute("guid", "-1");
                iqAdrReservationApplicationForm::displayReservation(attr, str);
                
                return true;
        }
        
        return false;
    }

    return false;
}


В процессе эксплуатации оказалось, что ХМЛ в 99% случаев приходит валидный (так как я сам его и отсылаю ). Вопрос. Нафига мне там столько if-ов? Когда документ начинает расти, код читать становится неприятно.

int displayReservationCommand::execute()
{
    QDomDocument xmlDoc;
    xmlDoc.setContent(_params["data"]);
    
    try{
        QDomElement el = xmlDoc.documentElement();
        el = el.firstChild().toElement();
        
        QString str;
        QTextStream ts(str, IO_WriteOnly);
        el.save(ts, 0);
        
        QString attr = el.attribute("guid", "-1");
        iqAdrReservationApplicationForm::displayReservation(attr, str);
        
    }catch(... /*на самом деле здесь надо что-нить типа XMLTagError, но мне все равно.*/){
        return false; 
    }

    return true;
}


Сама функция возвращает application-specific error-code.
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Вот подумалось
От: srggal Украина  
Дата: 24.11.05 11:32
Оценка: :))
Здравствуйте, Сергей Губанов, Вы писали:

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

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

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

СГ>Ошибки категории (2) фатальные, тут программу надо завершать — в программе ошибка, т.е. программа не правильная. Использовать exception только для того чтобы правильно завершить работу программы (ну там закрыть открытые ресурсы), только для этого чтоли? Закрыть открытое можно и другими способами.

Дело в том, что при применении Вашего подходя, вызвавшего такую бурную дискуссию, разработчи сталкивается со следующим известным вопросом:


Сколько return должно быть в функции? Один или несколько ?


А этот вопрос Гораздо старей Вашего. Следовательно можно предположить что исключения полезны, как минимум, потому, что позволяет в большинстве случаев абстрагироваться от проблемы колва точек выхода из функции.


... << RSDN@Home 1.1.4 stable rev. 510>>
Re[11]: А вот и нет
От: akrysan  
Дата: 24.11.05 16:25
Оценка: -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


А вот и нет в паскале только 1 оператор в модуле тоже
нужно писать BEGIN END
ві наверное на VB перепрограммировали.
Re[18]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 27.11.05 17:56
Оценка: +1 :)
Здравствуйте, Mamut, Вы писали:

M>Яркий пример — разбор ХМЛя многими библиотеками. Обычно достаточно знать, что ХМЛ невалидный и сразу завершить работу:


M>Например, кусок:


А если так?

bool displayReservationCommand::execute()
{
    QDomDocument xmlDoc;
    xmlDoc.setContent(_params["data"]);

    QDomElement el = xmlDoc.documentElement();
    if(el.isNull()) return false;

    el = el.firstChild().toElement();
    if(el.isNull()) return false;

    QString str;
    QTextStream ts(str, IO_WriteOnly);

    el.save(ts, 0);
    QString attr = el.attribute("guid", "-1");
    iqAdrReservationApplicationForm::displayReservation(attr, str);
    
    return true;
}

Исключений нет, а кода даже на две строчки меньше чем у тебя
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[10]: Вот подумалось
От: Костя Ещенко Россия  
Дата: 28.11.05 09:23
Оценка: +2
Здравствуйте, reductor, Вы писали:

[]

R>Все гораздо проще. Есть, предположим, спецификация, вида:


R>
R>       | Positive if x > 0
R>f(x) = | Negative if x < 0
R>       | Zero otherwise 
R>


R>Не может быть спецификации без _полной_ проверки возможных значений.

R>И, строго говоря, код вида:
R>
R>int f (int x) {
R>    if (x > 0) return 1;
R>    if (x < 0) return -1;
R>    return 0;
R>}
R>

R>Ей формально не соответствует. И главное, что проверить это очень сложно. В общем виде такое вообще не проверяется.

Если этот код формально не соответствует той спецификации, то видимо он формально соответствует некой другой спецификации. Можно взглянуть на нее?

R>А когда таких вариантов много, то непредсказуемость растет очень быстро.

R>тогда как код вида:
R>
R>int f (int x) {
R>    if (x > 0) return 1;
R>    else if (x < 0) return -1;
R>    else return 0;
R>}
R>

R>Вполне соответствует. Проверяются все значения и для любого варианта есть выход. То есть можно показать, что эта функция соответствует спецификации. Речь формально уже не идет о множественном выходе.

Почти уверен, что на языке промежуточного представления, которым пользуется нормальный компилятор (SSA или чего там еще), оба эти варианта выглядят одинаково.

[]
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[13]: Вот подумалось
От: Павел Кузнецов  
Дата: 28.11.05 16:09
Оценка: +2
reductor,

> V> Например, в С++, опять ресурсы и коды возвратов:


> Ну если дело только в этом конкретном коде, то:

>
>      if (error( openRes1() )) return ERR_RESOURCE1;
> else if (error( openRes2() )) return ERR_RESOURCE2;
> else if (error( openRes3() )) return ERR_RESOURCE3;
> else return ERR_SUCCESS;
>

> формальнее некуда
>

Здесь упущена существенная деталь, присутствовавшая в оригинальном варианте: освобождение ресурсов в каждом из случаев (в оригинале это делали деструкторы).
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: Что вы предлагаете на замену эксепшенов?
От: vdimas Россия  
Дата: 29.11.05 01:05
Оценка: +2
Здравствуйте, Сергей Губанов, Вы писали:

СГ>На самом деле, применительно к доводам использования exception, я привёл (мою) классификацию ошибок: (1) ошибка в данных, и (2) ошибка в программе. Сказал что для обработки ошибок в данных exception не нужны, а для обработки ошибок в программе довольно ASSERT + system trap, так что опять exception не нужны. Вы против этого что-то имеете конструктивно возразить?


Да нет такого разделения. Простой пример "в лоб".

Процедура А подразумевает, что ей никто не передаст null в качестве аргумента. Согласно твоей классификации, если мы подали туда null, то это — ошибка программы.

Процедура B читает некие данные в определенном формате. В процессе работы вызвает процедуру C для преобразования данных. Результат преобразования данных помещает как аргумент вызова процедуры A. Известно, что процедура С не возвращает null (достаточно оттестирована).

Однако, в формате данных произошел сбой, процедура С в нештатной ситуации (отсутствующей в тест-кейсах) выдала null, результат поместили как аргумент в А.

Какому классу принадлежит ошибка?


----------
ИМХО, ошибки могут принадлежать только одному классу — ошибки программы. Ошибка данных — это нонсенс. Входные данные по определению могут быть произвольными. Если кто-то считает и пишет свое ПО для работы "в специальных условиях", в расчете на "специальные данные", то он нарушает самые основы, и регулярно получает по голове обычно.


----------
Re[21]: error is not an exception
От: Глеб Алексеев  
Дата: 29.11.05 12:33
Оценка: -1 :)
Здравствуйте, IT, Вы писали:

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

Зачем, если они срабатывают только при наличии ошибки в программе (и теоретически в окончательной версии их быть не должно) и могут снижать производительность?
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[21]: error is not an exception
От: Cyberax Марс  
Дата: 29.11.05 15:07
Оценка: +1 :)
IT wrote:

> C>Или, например, вот такой код (спас часы отладки):

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

А зачем? assert показывает ошибки программиста, а не пользователя. То
есть ни при каком варианте работы событий пользователь не должен его
получить, а значит и включать его не надо.

В рельной жизни assert'ы обычно оставляют в бэта-версиях, и выкидывают в
релизах.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[12]: Вот подумалось
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 29.11.05 16:47
Оценка: +2
Здравствуйте, vdimas, Вы писали:

V>Сделаю акцент еще раз на том факте, что корректное поведение программы в случае использования множественного return в неожиданных местах обычно обеспечивается доп. ср-вами самого языка. В С++ это автоматический вызов деструкторов локальных объектов (что крайне удобно, т.к. эти деструкторы вызываются только для реально инициализированных локальных переменных), в Java/C# есть try-finally для анаолгичных целей (не столь элегантно, но тоже вполне можно использовать).


V>Таким образом, верификация даже такого кода может быть полной.

Погоди, верификация и корректность работы компилятора — не одно и то же. Язык просто даёт нам некие автоматически работающие механизмы и не более того. И там и там есть оговорки использования и т.п. Можно и в деструкторе RAII исключение пульнуть.

Другое дело, что верификация невозможна без спецификации, которой должна соответствовать программа. Нет спецификации — верификация невозможна. Вывал AV в некоторых ситуациях может расцениваться как штатное и запланированное поведение. То есть, сначала нужна полная спецификация: что можно, чего нельзя и т.п. Но такая спецификация по сложности сопоставима с самой программой, то есть, получим ту же проблему, но в профиль: языки спецификации, наследование спецификаций (множественное vs одиночное), синтаксический оверхед при специфицировании поведения и т.п.

V> Другое дело, что мы не сможем верифицировать отдельно взятый участок (вернее можем, поясню далее), т.е. необходимо больше информации, о том, что происходит "неявно" для случая С++.


Да ну? А что, в случае Java/C# работа GC уже стала 100% детерминированной? А полиморфный код тоже 100% сможем верифицировать?

V>Однако, и здесь нас ожидают бенефиты. Мы можем построить верификацию кода иерархически, т.е. проверифицировать сначала "прочистку", а затем код, использующий ее неявный вызов. Ввиду того, что целевой код неплохо сокращается в случае множественного return (или использования exceptions как продвинутой разновидности), мы можем получить как раз больше возможностей для верификации на "реальных объемах".


Не, гиблая затея на любых объёмах. Примерно такое же ожидание панацеи, как её в своё время ожидали от перехода к языкам высокого уровня. Просто проблемы сместятся с одного уровня на другой. Всё равно задач адекватного учёта внешних условий и построения точных формулировок никто не снимет.
<<RSDN@Home 1.1.4 stable SR1 rev. 568>>
Music: Mike Oldfield — Moonlight Shadow

Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[27]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 29.11.05 17:05
Оценка: +1 :)
Здравствуйте, Сергей Губанов

Самое время синтаксический оверхед померять
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[23]: error is not an exception
От: Cyberax Марс  
Дата: 29.11.05 17:59
Оценка: +2
IT wrote:

> C>А зачем? assert показывает ошибки программиста, а не пользователя. То

> C>есть ни при каком варианте работы событий пользователь не должен его
> C>получить, а значит и включать его не надо.
> Для библиотечного кода эти проверки должны присутствовать и как
> правило присутствуют, загляни хотя бы в исходники .NET FW.

Стоп. В FW куча проверок пост/пред-условий — это вполне нормально, если
клинет может передать неправильное значение. В случае FW клинетом
является пользовательское приложение.

Assertы нужны для проверки "невозможных" случаев, типа:
string str="adfhjadkjf";
string str2="adsfkjds";
string str3=str+str2;
assert(str3.size()!=0);

При нормальной работе оператора "+" срабатывание assert'а невозможно,
соответственно заменять его на exception — нет смысла.

Или так:
class fast_string
{
    void append(const string_base &_other)
    {
       assert(_begin!=_end); //Check invariant.
       ....
    }
};

В данном случае проверяется инвариант класса — существование хотя бы
одного символа (с кодом 0). Если он нарушен — то это уже ошибка
программиста библиотечного класса или побочный эффект какой-нибудь
глобальной ошибки.

> C>В рельной жизни assert'ы обычно оставляют в бэта-версиях, и

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

Ну да, просто заменить на замусоривание исключениями.

> В общем, в ASSERT похоже тоже можно относить к устаревшим средствам и

> правилам типа венгерки, SELECT* и единственного return.

НЕТ! Тогда стоит к устаревшим правилам отнести и хороший стиль
программирования. В конце концов, он в .NET не нужен....

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[11]: Вот подумалось
От: reductor  
Дата: 27.11.05 21:53
Оценка: 40 (1)
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, reductor, Вы писали:


R>>Компиляторы конечно пусть выполняют свою работу, но есть все же некоторое соответствие между количеством их работы и нашим пониманием того, что мы делаем.


IT>Ага, компиляторы оставлены в покое, это уже прогресс


R>>А так же между количеством их работы и умственным напряжением того человека, который будет читать наш код.


IT>Не хочешь переписать вот такой код без returns?


Ок. Только сразу предупреждаю, я вообще не знаю C# (как и .NET), потому пришлось msdn почитать.
Могут быть ошибки (как в оптимальности реализации, так и в понимании логики того, что здесь происходит), но в общем вроде все так.
private static MemberMapper MapperFromTC (TypeCode tc) {
    MemberMapper value;
    switch (tc) {
        case TypeCode.SByte: value = new NullableSByteMapper(); break;
        case TypeCode.Int16: value = new NullableInt16Mapper(); break;
        case TypeCode.Int32: value = new NullableInt32Mapper(); break;
        case TypeCode.Int64: value = new NullableInt64Mapper(); break;
        case TypeCode.Byte: value = new NullableByteMapper(); break;
        case TypeCode.UInt16: value = new NullableUInt16Mapper(); break;
        case TypeCode.UInt32: value = new NullableUInt32Mapper(); break;
        case TypeCode.UInt64: value = new NullableUInt64Mapper(); break;
        case TypeCode.Char: value = new NullableCharMapper(); break;
        case TypeCode.Single: value = new NullableSingleMapper(); break;
        case TypeCode.Boolean: value = new NullableBooleanMapper(); break;
        case TypeCode.Double: value = new NullableDoubleMapper(); break;
        case TypeCode.DateTime: value = new NullableDateTimeMapper(); break;
        case TypeCode.Decimal: value = new NullableDecimalMapper(); break;
        case TypeCode.Guid: value = new NullableGuidMapper(); break;
        default: value = null; break;
    }
    return value;
}

private static MemberMapper GetNullableMemberMapper(MapMemberInfo mi) {
    Type type = mi.MemberAccessor.Type;
    MemberMapper value;
    
    if (type.IsGenericType == true && mi.MapValues == null) {
        Type underlyingType = Nullable.GetUnderlyingType(type);
        if (underlyingType != null) {
            value = MapperFromTC(underlyingType.IsEnum
                    ? underlyingType.GetTypeCode()
                    : Type.GetTypeCode(underlyingType)); 
        } else {
            value = null;
        }
    } else {
        value = null;
    }
    return value;
}


Если интересен был proof-of-concept, то вот. Ничего, что я добавил "лишнюю" функцию? а то читать было сложновато.
В общем-то в case-ах и if'ах можно было и return'ы оставить (вариантов без них не остается), но чтобы лишнего флейма избежать, я сделал с переменной.
Хотя идеально бы конечно было, если бы switch возвращал значение. Но так зато можно дополнительно в выводить в лог mm перед каждым возвратом. и то хлеб. Надеюсь, больше на C# ничего делать не придется.
Re[14]: Вот подумалось
От: vdimas Россия  
Дата: 30.11.05 15:13
Оценка: 21 (1)
Здравствуйте, _Winnie, Вы писали:

Вот у тебя очень показательная ошибка. Надо писать так:
goto ошибка_снять;
...
goto ошибка_положить;
...
goto ошибка_журналировать;


а последний кусок вообще надо в обратном порядке:
ошибка_журналировать:
    rollback(&бо_журнализовать);
ошибка_положить:
    rollback(&бо_положить);
ошибка_снять:
    rollback(&бо_снять);
    return false;



Т.е. самому вручную раскручивать стек в правильном порядке. Если бы ты использовал исключения, то тебе правильный порядок был бы гарантирован.


----------
Сам я всячески отстаиваю свое право на использование goto по собственному усмотрению, но тут такой неожиданный пример с граблями во всей красе... мне надо было внимательней прислушиваться к оппонентам
Re[5]: Вот подумалось
От: reductor  
Дата: 26.11.05 04:19
Оценка: 15 (1)
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, Глеб Алексеев, Вы писали:


ГА>>Избежать-то всегда можно. Вот и избегают некоторые фанатичные последователи этого правила, выходя из цикла 3-го уровня вложенности с помощью булевских флагов или даже бросая исключения .


IT>Совершенно верно. Это правило было актуально 15 лет назад. Сегодня оно является таким же устаревшим как венгерка и SELECT*.


Устарело?
Что, разобрались с остановкой тьюринг-полного автомата?
научились писать после этого статические анализаторы, которые находят и предсказывают поведение GOTO и множественного return?
Вырастили поколение суперлюдей, которые в состоянии смотрететь и тут же понимать что происходит, разбивая это в уме на подвыражения?
Наконец, уже написали компиляторы нормально это разруливающие и процессоры, у которых нет оверхеда от этого?

Хочу ссылки, выкладки и доказательства.
Re[13]: Вот подумалось
От: reductor  
Дата: 30.11.05 14:51
Оценка: 9 (1)
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, reductor, Вы писали:


R>>Но конечно основной смысл в том, что если у нас есть

R>>
R>>// некий абстрактный код
R>>int y = 5;
R>>if (x == 1) return y;
R>>y++;
R>>if (x == 2) return y;
R>>return y + 5
R>>

R>>То понять что здесь происходит невозможно ни компилятору (та самая проблема с автоматами) ни человеку.

V>Я в очередной раз ловлю себя на ступоре после прочтения подобной фразы. Может я чего-то не понимаю? Откуда у компилятора или у человека сложности с прочтением? Насчет обязательности соответствия y<=f(x) мне понятно, насчет каких-то затруднений компиляции — нет. Хочешь, прямо здесь и сейчас граф детерминриованного автомата нарисую по этому куску кода? Не знаю, как другие программисты трассируют исходники в голове, но я, когда трассирую куски алгоритмов именно думаю как автомат — т.е. перехожу из состояние в состояние (состояние — множество значений всех локальных/глобальных переменных и проч. ячеек данных быстрой и медленной памяти, прямо или коссвено принимающих участие в алгоритме) в ответ на некие действия над этими переменными.


http://en.wikipedia.org/wiki/Halting_problem

Нужна функция, которая возьмет код другой функции и даст ответ — даст ли функция ответ в заданном диапазоне значений

Первое пришедшее в голову решение с построением графа (запуском, фактически) проблему не решает, функция может и не завершить свою работу — потому не завершит свою работу и наш анализатор — потому ответ мы так и не получим.
Анализировать построенный граф статически — тут для начала полезно вспомнить про поиск Hamilton Path и следующую из него NP-полноту

Причем, конечно, нет доказательства самого существования как проблемы остановки автомата, так и существования NP-полноты, причем, есть основания утверждать, что существование такого доказательства невозможно, так как его наличие автоматически означает решение самой проблемы остановки, что автоматически приводит нас к доказательству обратного. Корни этого тесно переплетаются с парадоксом Рассела и теоремой Геделя о неполноте, если вы знакомы с ними, то уже сами заметили это сходство парой строк раньше

V>Где фишка? Если можно построить детерминированный автомат, то можно проверифицировать что угодно.


Выше показано почему это не так
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[4]: Что вы предлагаете на замену эксепшенов?
От: Глеб Алексеев  
Дата: 21.11.05 12:08
Оценка: 4 (1)
Здравствуйте, eao197, Вы писали:

E>Спецификация исключений -- это только одна сторона медали.

E>Другая сторона -- это catch(...) или catch( const std::exception & ), ибо в противном случае игнорирования не получится -- исполнение прервется.
Исполнение прервется, если исключение будет брошено. В этом случае непойманные исключения действительно проявляются заметнее проигнорированных кодов возврата. Проблема в тех исключениях, которые не будут брошены при тестировании.

Я, видимо, недостаточно ясно сформулировал. Имелось в виду следующее:


///foo.cpp
void foo() {
  if ( judgement_day_has_come() ) {
    throw std::runtime_error("Приехали...");
  }
}

///bar.cpp
void bar() {
  foo(); // автор bar() плохо читал документацию/документации не было/забыл/ваш вариант,
         // но обработки исключения нет. Код компилируется и будет работать до самого Судного дня.
         // Как видим, игнорировать исключения очень даже можно, по-крайней мере, в С++
}

// а теперь то же самое с кодами возврата
enum status {
  status_ok,
  status_failure
};
status foo() {
  if ( judgement_day_has_come() ) {
    return status_failure;
  }
  return status_ok;
}

///bar.cpp
void bar() {
  foo(); // чем отличается клиентский код в случае игнорирования ошибки? ничем. 
}


К чему я веду? Что исключения очень полезны для отделения "нормального" кода от кода обработки ошибок, а также для передачи управления на несколько уровней выше при невозможности обработать ошибку в точке возникновения, но никак не заменитель головы программиста. Внимательность никто не отменял и видимо еще долго не отменит.
Re[26]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 28.11.05 14:06
Оценка: 4 (1)
Здравствуйте, Sergey J. A., Вы писали:

E>>Я думаю, тебе интересно будет почитать мнение Бертрана Мейера про исключения: Re[4]: Что вы предлагаете на замену эксепшенов?
Автор: iZEN
Дата: 22.11.05
Так вот Мейер в качестве одной из дисциплин обработки исключений определяет "Повторение" (Retrying), но об этом чуть ниже.

SJA>Жаль, но там нет ссылки на онлайн версию... В наших магазинах я такой книги не видал.

Re[4]: Что вы предлагаете на замену эксепшенов?
Автор: EvilChild
Дата: 22.11.05


Единственно, что Мейер об исключениях говорит со своей колокольни, поэтому мне показалось, что у Страуструпа про исключения лучше написано. Лаконичнее, практичнее и ближе к мейнстримовым языкам (C++, Java, C#).
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[8]: error is not an exception
От: IT Россия linq2db.com
Дата: 26.11.05 15:15
Оценка: 3 (1)
Здравствуйте, reductor, Вы писали:

R>Вообще непонятно почему все так против использования иксепшенов для описания логики, когда в большинстве рассматриваемых тут языков это самый быстрый и простой способ эмуляции pattern matching (не знаю как это по-русски), (чего о тех же классах с коллбеками по ним не скажешь).


У меня есть как минимум две причины.
Первая — эксепшены довольно тормозная вещь. В данном примере при перемещении коретки пользователем это вряд ли будет заметно. Но программист использующий подобный паттерн легко напишет и серверную логику на эксепшинах. А чё?
Вторая. Современные средства отладки сегодня позволяют практически отказаться от пошагового брождения по программе с целью локализации места ошибки. При возникновении исключения — отладчик автоматически останавливается в нужном месте. Время фикса багов в таком случае возрастает на порядки. Использование исключений где попало, особенно в циклически повторяющемся коде убивает всю идею. И приходится опять отлаживать код по старинке, с точками останова, бесконечными заходами и выходами во все возможные методы в программе.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
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[25]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 27.11.05 21:35
Оценка: 1 (1)
Здравствуйте, Cyberax, Вы писали:

C>так как приложение в ответ на него

C>может удалить часть данных (почистить кэши, например)

Сдаётся мне, что нужно такие объекты держать как Weak Reference, а не чистить по исключению.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[4]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.11.05 08:42
Оценка: 1 (1)
Здравствуйте, vdimas, Вы писали:

V>Процедура А подразумевает, что ей никто не передаст null в качестве аргумента. Согласно твоей классификации, если мы подали туда null, то это — ошибка программы.


Да, именно так.

V>Процедура B читает некие данные в определенном формате. В процессе работы вызвает процедуру C для преобразования данных. Результат преобразования данных помещает как аргумент вызова процедуры A. Известно, что процедура С не возвращает null (достаточно оттестирована).


V>Однако, в формате данных произошел сбой, процедура С в нештатной ситуации (отсутствующей в тест-кейсах) выдала null, результат поместили как аргумент в А.


V>Какому классу принадлежит ошибка?


Вы же сами написали, что "в формате данных произошел сбой" значит, во-первых, есть ошибка во входных данных. Во-вторых, если процедура B этого не поняла, значит в процедуре B есть програмная ошибка. Итого, здесь присутствуют оба типа ошибок.

V>ИМХО, ошибки могут принадлежать только одному классу — ошибки программы. Ошибка данных — это нонсенс.


Не ошибка данных, а ошибка в данных. Пользователь вводит число с клавиатуры и нажал не на ту кнопку, ввел строку не представляющую число. Эта строка пошла на вход процедуры В. Процедура В поняла, что в данных поступивших к ней на вход есть ошибка и не стала вызывать процедуру-форматтер С, а вместо этого инициализировала процесс, в результате которого пользователь был ткнут носом в неправильно введённую им строку. То есть в программе ошибок нет, ошибка была в данных.
Re[25]: error is not an exception
От: Cyberax Марс  
Дата: 30.11.05 12:40
Оценка: 1 (1)
IT wrote:

> C>Assertы нужны для проверки "невозможных" случаев, типа:

> Это всё легко покрывается юнит-тестами. Или ты их заменяешь асёртами?

Уберите слово "легко"

> C>Ну да, просто заменить на замусоривание исключениями.

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

У багов есть такая вещь, что проявиться они могут далеко не сразу. И
через обычное тестирование могут пройти, так что как раз в тестировании
ассерты незаменимы. Они помогают обнаруживать нарушения инвариантов как
можно раньше.

> C>НЕТ! Тогда стоит к устаревшим правилам отнести и хороший стиль

> программирования. В конце концов, он в .NET не нужен....
> Зачем передёргивать? Или ты хочешь сказать, что хороший стиль и асёрты
> — это синонимы?

Это реакция на слово "устаревший"

> ЗЫ. Не хочу с тобой продолжать бодаться, всё равно ни мне тебя, ни

> тебе меня похоже не переубедить. Скажу только, что лично я, никакой
> практической пользы от асёртов сегодня не вижу. Речь идёт о .NET/C#.
> Такое моё сугуболичное ИМХО.

В .NET сильно помогает то, что бибилиотека делает очень много проверок.
То есть то, что в С++ могло проскочить незамеченным здесь вызовет
исключение. Но это не отменяет ценности ассертов в своем коде

> Пойду лучше Серёгу за забытый ролбэк отстегаю


Бей его, бей

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

E>>А вообще, кроме классика Н.Вирта, есть еще и классик Б.Страуструп. В его книге "Язык программирования С++. 3-е издание" есть целая глава #14, которая посвящена обработке исключений. Тебе бы не мешало прочитать из нее хотя бы 14.1 (Обработка ошибок [except.error]) и 14.1.1 (Альтернативный взгляд на исключения [except.views]). Там очень сжато и точно описываются разные стратегии диагностики ошибок и роль в этом деле исключений.

E>>Note. Названия разделов я привел из англиского варианта книги, т.к. русский вариант у меня на работе.

ZEN>Ещё есть один классик т.н. "контрактоного программирования" (кстати, последователь Н.Вирта, сейчас работает в ETH) — Бертран Мейер, автор языка Eiffel.

ZEN>Стоит почитать и его.

Стоит, безусловно. А что именно? Если можно URL, т.к. у нас достать печатное издание крайне проблематично.

Я упомянул разделы 14.1 и 14.1.1 книги Страуструпа потому, что там описываются следующие стратегии поведения в случае возникновения ошибок:
и приводится сравнение этих вариантов с вариантом использования исключений.

Во многих случаях в C++ (да и не только), исключения являются единственным способом информирования приложения об ошибках. Например, при перегрузке операторов. Например, оператора << или +. На самом деле, как использовать коды ошибок вот в таком выражении:
db_stream << header << description << footer;

а ошибка возникает из-за отсутствия достаточного места на диске?

Ну и еще одно соображение. Исключения, в отличии от того же контрактного программирования, стали широко призанным и адаптированным механизмом. C++, Java, C#, Python, Ruby, Ada, Smalltalk -- везде есть исключения. Конечно, это не панацея от всех болезней, и применять их нужно осторожно. Тем не менее, вряд ли идея исключений получила бы такое широкое распространение, если бы она не была настолько удачной.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Что вы предлагаете на замену эксепшенов?
От: reductor  
Дата: 20.11.05 14:49
Оценка: +1
Существует множество вариантов

например, обработка через continuation passing — см. например, conditions в Common Lisp. И этот подход, нужно сказать, кроме того, что быстрее, чем иксепшены, еще и дает возможность поправить ошибку на месте — без раскрутки стека — и продолжить делать то же самое как ни в чем не бывало.
Так же, в строго-типизированых языках это могут контейнерные (higher order aka kinds) типы
еще довольно уникальный случай — в хаскеле некоторые библиотечные типы для обработки ошибок определены еще и как монады. например, Maybe. Хотя некоторые виды ошибок в хаскеле по-умолчанию предлагается отлавливать через некоторую симуляцию иксепшенов, которая впрочем чистой воды те же continuations + контейнерные типы.

Так что по обстоятельствам
Re[2]: Плагины = компоненты системы
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.11.05 10:47
Оценка: :)
Здравствуйте, Andy77, Вы писали:

A>Например, разрабатывая расширяемую плагинами систему, не будешь же ты полататься на непогрешимость сторонних разработчиков?


Да, Вы правы. Я упустил этот вариант. Прошу прощения. Разумеется в этом случае системные ловушки (trap) обязательны.

Попытаюсь объяснить почему я упустил этот вариант из виду. Дело в том, что программирование в компонентных системах (скажем, таких как Оберон-системы) это уже есть де-факто написание плагинов для уже готовой системы времени исполнения. Каждый модуль (компонент системы) — фактически и есть плагин. Разумеется, если цель состоит в написании своей собственной системы времени исполнения, то, повторяюсь, системные ловушки обязательны. Но даже это еще не повод включать механизм исключений в язык. Проблема решается на уровне библиотек. Прекрасный пример — BlackBox, там системные trap-ы есть (на уровне модуля Kernel), но в самом языке Component Pascal, на котором написано ядро = система времени исполнения, механизма исключений нет.
Re[3]: Что вы предлагаете на замену эксепшенов?
От: GlebZ Россия  
Дата: 21.11.05 10:53
Оценка: +1
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Это так называемые "продолжаемые исключения". Работает в языках, не разрушающих стек во время поиска обработчика. Например в ST, CLOS.

Честно говоря такое есть и в C. Только не везде реализовано, зависит от платформы и очень тормозно. Но благодаря таким возвратам можно управлять виртуальными страницами.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
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]: Что вы предлагаете на замену эксепшенов?
От: 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[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[14]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 12:19
Оценка: -1
Здравствуйте, Privalov, Вы писали:

P>Так ведь если запись в журнал транзакций не прошла, состояние объекта "ЛокальныйСчет" восстановить требуется. Кто этим займется?


Ага, а удалённый банк надо попросить: "Пожалуйста, верните деньги обратно"...

P>Кстати, в действительности там все намного сложнее.


Ясное дело.
Re[15]: Что вы предлагаете на замену эксепшенов?
От: mrozov  
Дата: 23.11.05 14:14
Оценка: +1
Здравствуйте, Сергей Губанов, Вы писали:


СГ>Совершенно верно — не знает. Процедура чего-то сделала, о результатах сообщила. А при чём тут exception? Или exception — это единственный или лучший способ сообщить о результатах? Нет, не единственный и не лучший. Тогда при чём тут они...


Что не единственный — это да. А вот что не лучший — уже категорически нет.

Хотя бы потому, что с точки зрения ООД, функция должна возвращать результат своего выполнения. Например, строку. Что ей делать, столкнувшись с проблемой, не дающей ей вернуть строку?

Вообще, у вас фатальный баг в понятийном аппарате. Вы почему-то думаете, что исключения преднозначены для сообщений об ошибках. А это всего лишь побочный эффект от главного предназначения исключений. А именно:

Исключения — это стандартный и универсальный механизм, с помощью которого код может делегировать принятие решений коду вызывающему данный. Неважно, о чем мы говорим — о модуле, функции или трех строчках кода — это все равно так.

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

А в тех случаях, когда требуется продолжение работы того же блока кода после сбоя — можно и нужно применять те же события. Никто этому не припятствует. Таким образом мы доказали, что исключения есть полезный и даже необходимый интсрумент при разработке программ.
Re[16]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 14:41
Оценка: -1
Здравствуйте, mrozov, Вы писали:

M>Хотя бы потому, что с точки зрения ООД, функция должна возвращать результат своего выполнения. Например, строку. Что ей делать, столкнувшись с проблемой, не дающей ей вернуть строку?


Если заранее известно, что функция может сталкиваться с подобными проблемами, то это однозначно говорит о том, что функция не должна возвращать строку вовсе:

PROCEDURE TryReturnString (OUT s: String): BOOLEAN;

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


Прикольное доказательство

Мой понятийный аппарат, говорит мне, что лучше писать так:
  IF TryReturnString(str) THEN 
    ... 
  ELSE 
    ... 
  END

чем вот так:
  bool valid = false;
  try
  {
    str = ReturnString();
    valid = true;
  }
  catch
  {
    ......
  }
  if (valid)
  {
     ........
  }

и я рассматриваю второй вариант как фатальный баг в понятийном аппарате.
Re[12]: Что вы предлагаете на замену эксепшенов?
От: vitaly_spb Россия  
Дата: 23.11.05 15:21
Оценка: +1
S>1. Все функции обязаны возвращать булевый признак успешности выполнения.
S>2. Все функции обязаны передавать информацию о причине неудачи.
S>3. Если нам надо что-то большее, чем текст, в качестве информации о причине неудачи, то мы встряли. Потому что сигнатуры всех функций, имевших несчастье попасть в стек вызовов между тем местом, где мы обрабатываем ситуацию, и тем местом, где она произошла, должны быть модифицированы для передачи этой информации. Что-то более-менее общее мы использовать не сможем.

Мне это напоминает паскаль или COM с его HRESULT ;(
...Ei incumbit probatio, qui dicit, non qui negat...
Re[3]: Что вы предлагаете на замену эксепшенов?
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.11.05 05:16
Оценка: :)
Здравствуйте, Joker6413, Вы писали:

J>Это будет круче множественного наследования! Имхо повысит энтропию системы не в разы, а на порядки!


Ага, если обработчик:
1. Меняет состояние объектов, участвовавших в выполнении сбойнувшего фрагмента
2. Подшаманивает стек, чтобы все выглядело так, как будто все и было нормально с самого начала
3. Подправляет код методов в стеке, чтобы обеспечить более корректное исполнение.
4. Передает управление временно сгенерированному thunk, который модифицирует сам первоначальный обработчик, заканчивает очистку и продолжает выполнение в нормальном режиме.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[20]: Что вы предлагаете на замену эксепшенов?
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 24.11.05 07:50
Оценка: +1
Здравствуйте, CrystaX, Вы писали:

CX>Вот такой вот практический опыт работы с исключениями, реализованными на уровне библиотеки.


Нужно добавить "... в С++".
Никто и не сомневался
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[21]: Что вы предлагаете на замену эксепшенов?
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.11.05 10:17
Оценка: +1
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Посмотрите пожалуйста следующую статью (потрясающую воображение):

Ничего особенно потрясающего. Да, такую штуку можно реализовать для любого языка, который
а) поддерживает вложенные процедуры
б) поддерживает RTTI
в) разрешает библиотеке играть со стеком.
Кстати, вопрос с finally остался в статье неосвещенным, а очень зря. Дело в том, что на технике finally построено детерминистическое освобождение ресурсов (необходимое в системе без автоматических объектов).

Рассуждения по поводу таблиц и ресурсов на самом деле, мягко говоря, надуманны. Дело в том, что реализация опирается на метаданные, которые сами по себе тоже тратят место (по сравнению с чистым нативным кодом). Да, замечательно, что удалось обойтись без дублирования этих таблиц. Но сравнивать надо честно.

В целом — неплохая техника для обхода ограничения компилятора, неспособного предоставить достаточно удобный механизм.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 11:46
Оценка: :)
Здравствуйте, Privalov, Вы писали:

P>Здравствуйте, Сергей Губанов, Вы писали:


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


P>Тогда вопрос: сколько процентов головного мозга приходится напрягать физику-теоретику в повседневной деятельности? В каком угодно смысле. Просто для сравнения.


кандидату: 100% от нормы обычного человека, доктору: 500% — 1000% от нормы обычного человека академику, ну скажем, 20'000% от нормы....
Re[23]: Что вы предлагаете на замену эксепшенов?
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.11.05 12:00
Оценка: +1
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Необычно то, что:

СГ>1) Zero-overhead;
это маркетинг булшит. Никаким зеро там и не пахнет. Во-первых, для работы используются метаданные, которые конечно зеро по сравнению с "обычным обероном", т.к. встроены намертво, но вовсе не зеро по сравнению с полным отсутствием метаданных. Во-вторых, приведенные цифры по скорости раскрутки стека мягко говоря, далеки от зеро. Интуитивно мне кажется, что легендарно медленная раскрутка в плюсах порвет этот код как тузик грелку — потому что reflection да еще и с анализом стека на халяву не дается.
СГ>2) не требуется вносить изменения в синтаксис языка Оберон.
Это да. Удачное совпадение.
Кстати, нельзя ли поподробнее рассказать о том, каким именно способом эта библиотека подправляет stack pointer? Это основная фича данной техники, которая, к слову, никакого отношения к метапрограммированию не имеет — скорее к хакерству, а стало быть, под большим вопросом в средах, ориентированных на надежность.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[14]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 24.11.05 16:06
Оценка: :)
Здравствуйте, Bigger, Вы писали:

B>Так и не все кандидаты могут стать программистами, ничего личного

Эт потому, что у мозгов кроме количественной характеристики есть ещё и тип. Тут приведение с трудом работает.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[20]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.11.05 12:07
Оценка: +1
Здравствуйте, Bigger, Вы писали:

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


B>А вот это не есть хорошо, мухи от котлет должны быть отдельно, логика работы и логика обработки ошибок не одно и тоже.


"Исключение == ошибка" -- это догма, иногда вредная. Исключение -- это факт того, что что-то в программе идет не так, как ожидалось, но не обязательно из-за ошибки. Например, есть обработка транзакций от клиента. Одновременно может обрабатываться не более N транзакций, причем N довольно большое число и поросто так его не достичь (это возможно, например, в "часы пик" или когда транзакции начинают валиться после восстановления разрыва связи). Поэтому N+1 транзакции нужно корректно отказать со специфическим кодом возврата. Так же возможна ситуация, когда клиент повторяет транзакцию, не дождавшись от нас результата (не выдержал тайм-аут на своей стороне). Это так же не ошибка и повторый запрос нужно просто проигнорировать. И делается это приблизительно так:
try
    {
        // Нормальная обработка транзакции, расчитанная на обычные условия.
        ...
    }
catch( const too_much_trx_t & x )
    {
        // Обработка N+1 транзакции.
        ...
    }
catch( const repeated_trx_t & x )
    {
        // Обработка повторной транзакции.
        ...
    }
catch( const std::exception & x )
    {
        // А вот это уже действительно плохо!
        cleanup();
        initiate_shutdown();
    }


Ситуации, когда порождаются too_much_trx_t и repeated_trx_t -- это не ошибки, просто это исключительные ситуации для обычной обработки транзакций. Случаются они редко. А писать из-за них код в виде вложенных if-ов (как в первоначальном примере Mamut-а) -- получается плохочитабельно.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: Вот подумалось
От: IT Россия linq2db.com
Дата: 25.11.05 17:17
Оценка: +1
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Избежать-то всегда можно. Вот и избегают некоторые фанатичные последователи этого правила, выходя из цикла 3-го уровня вложенности с помощью булевских флагов или даже бросая исключения .


Совершенно верно. Это правило было актуально 15 лет назад. Сегодня оно является таким же устаревшим как венгерка и SELECT*.
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: error is not an exception
От: reductor  
Дата: 26.11.05 02:14
Оценка: +1
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Глеб Алексеев, Вы писали:


ГА>>Возвращаясь к исходному примеру, верхняя строчка будет короче в половине случаев, какое же это исключение?


ГА>>Использовать исключения не для обработки ошибок — это совершенно исключительная ситуация, должна продумываться и документироваться очень тщательно.


E>Не спорю. Но я здесь и сам примеры приводил:

E>Re[18]: Что вы предлагаете на замену эксепшенов?
Автор: eao197
Дата: 25.11.05
(это гипотетический пример),

E>Re[20]: Что вы предлагаете на замену эксепшенов?
Автор: eao197
Дата: 25.11.05
(это из реальной жизни, хотя и схематично, а не точно).



Пример с парсером вовсе не гипотетический. Более того, он еще давно имеет свое название в Computer Science — это Parser Combinators. Несколько ограниченный случай, но тем не менее, все равно очень мощное средство.

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

Вообще непонятно почему все так против использования иксепшенов для описания логики, когда в большинстве рассматриваемых тут языков это самый быстрый и простой способ эмуляции pattern matching (не знаю как это по-русски), (чего о тех же классах с коллбеками по ним не скажешь).

Все так на название чтоли остро реагируют...
Re[22]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.11.05 06:39
Оценка: +1
Здравствуйте, Sergey J. A., Вы писали:

SJA>Не ошибки ? Ну, в таком случае отказ записи файла из за недостаточности места тоже не ошибка, а "исключительная ситуация для обычной обработки" файлов.


В некоторых ситуациях это может быть совсем не ошибка. Например, в системах со сборкой мусора недостаток памяти для размещения нового объекта -- это еще не ошибка, а повод к запуску GC. И только если после работы GC памяти не окажется, то это становится ошибкой.

Так же и с файлами.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[24]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.11.05 13:12
Оценка: +1
Здравствуйте, Sergey J. A.

Сдается мне, что мы сейчас говорим об одном и том же, но разными словами.

Я думаю, тебе интересно будет почитать мнение Бертрана Мейера про исключения: Re[4]: Что вы предлагаете на замену эксепшенов?
Автор: iZEN
Дата: 22.11.05
Так вот Мейер в качестве одной из дисциплин обработки исключений определяет "Повторение" (Retrying), но об этом чуть ниже.

E>>Так же и с файлами.

SJA>Что то-же ? Не совсем понял...
SJA>С файлами представляю это так:
SJA>Если нет места на диске, но алгоритм расчитан так, что ищет место на других дисках и пробует сохранится туда — исключение не требуется (всё обрабатывается на одном уровне). Если уже нигде места нет — бросаем исключение — пусть кто знает обрабатывает.

Вот смотри, как я вижу себе это на примере log-файлов. Есть подсистема ведения логов, которая циклически использует, скажем, пять файлов для сохранения информации. При выполнении очередной операции записи может обнаружена нехватка места на диске. Тогда следует попробовать удалить один из старых файлов и попробовать произвести запись еще раз. Выглядеть это может так (на C++):
void store_log_record( const log_record_t & r )
    {
        while( true ) // Цикл вместо Мейеровского retry.
            {
                try
                    {
                        // Пытаемся сохранить запись.
                        try_store_record( r );
                        
                        // Т.к. исключений нет, то завершаем работу.
                        return;
                    }
                catch( const no_enough_space_t & x )
                    {
                        // Нет места, пытаемся освободить.
                        // Если процедура освобождения окажется неудачной, то она
                        // породит свое исключение, по которому мы вылетим из
                        // store_log_record.
                        try_free_space( x.spaced_needed() );
                    }
            }
    }


Т.е. получается, что исключение no_enough_space_t является фатальным для try_store_record() всегда, но не всегда является таковым для store_log_record(). А метод store_log_record() как раз использует мейеровскую дисциплину "Повторение".

SJA>Отсюда моё ИМХО: Исключение нужно бросать в том случае, если на данном логическом уровне (в данном модуле) неизвестен алгоритм работы с некоторой ситуацией. Которая и является исключительной на данном уровне.


Так ведь и я о том же. Но вот вернемся к моему исходному примеру.
void process_trx( const some_trx_t & trx )
    {
        try
            {
                // Нормальная обработка транзакции, расчитанная на обычные условия.
                // В этой функции неизвестно, как обрабатывать лишние и повторные
                // транзакции, поэтому там порождаются исключения.
                ordinal_processing( trx );
            }
        catch( const too_much_trx_t & x )
            {
                // Обработка N+1 транзакции.
                send_negative_response( trx, error_reason::too_much_trx );
            }
        catch( const repeated_trx_t & x )
            {
                // Обработка повторной транзакции.
                ignore_repeated_trx( trx );
            }
        catch( const std::exception & x )
            {
                // А вот это уже действительно плохо!
                cleanup();
                initiate_shutdown();
            }
    }

Т.е. уровень ordinal_processing() не может справится с ошибками too_much_trx и repeated_trx, поэтому он и порождает исключения. Но вот уровен process_trx как раз знает, как с этими ошибками бороться, и именно он инициирует их обработку. Т.е. в точности то, что ты и сказал (имхо).

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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[9]: error is not an exception
От: Ракот  
Дата: 26.11.05 17:26
Оценка: +1
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, reductor, Вы писали:


R>>Вообще непонятно почему все так против использования иксепшенов для описания логики, когда в большинстве рассматриваемых тут языков это самый быстрый и простой способ эмуляции pattern matching (не знаю как это по-русски), (чего о тех же классах с коллбеками по ним не скажешь).


IT>У меня есть как минимум две причины.

IT>Первая — эксепшены довольно тормозная вещь. В данном примере при перемещении коретки пользователем это вряд ли будет заметно. Но программист использующий подобный паттерн легко напишет и серверную логику на эксепшинах. А чё?
IT>Вторая. Современные средства отладки сегодня позволяют практически отказаться от пошагового брождения по программе с целью локализации места ошибки. При возникновении исключения — отладчик автоматически останавливается в нужном месте. Время фикса багов в таком случае возрастает на порядки. Использование исключений где попало, особенно в циклически повторяющемся коде убивает всю идею. И приходится опять отлаживать код по старинке, с точками останова, бесконечными заходами и выходами во все возможные методы в программе.

Третье. Средство профилирования, способные перехватывать любые ошибки в коде, засыплят команду тестеров сообщениями, содержищие подчас бесполезную информацию.
Re[6]: Вот подумалось
От: reductor  
Дата: 27.11.05 10:05
Оценка: -1
Здравствуйте, Cyberax, Вы писали:

C>reductor wrote:


>> Если чуть серьезнее, то логика — это штука немного формальная. Желание

>> джампнуть куда-нибудь (частным случаем чего кроме GOTO является и
>> множественный return), и сделать поведение программы непредсказуемым,
>> это не от большого понимания того, что сам делаешь.
>> А еще — это не религия и понятие "фанатизм" к ней не применимо. Люди
>> или могут обосновать свой вывод и выбор или нет.

C>Нет, это уже религия. Все нормальные программисты уже давно перестали

C>флеймить по поводу GOTO и структурного программирования, так как по
C>нынешним меркам это уже далеко не самый главный вопрос. Все
C>программисты, которых я знаю, думают примерно так: "GOTO это плохо?" —
C>"Плохо". "Структурное программирование хорошо?" — "Да". "Единый return,
C>выход из вложенных циклов по флагам, отсутствие break — оно надо?" — "А
C>нафига?"

Я не знаю что такое "нормальные программисты". Тем более что такое "все нормальные программисты".
Я знаю, что такое формальная логика и изоморфизм Карри-Говарда. А так же как я могу и как не могу обосновать, что мой модуль выполняет именно то, что он него ожидается при всех условиях.

Что касается выхода из циклов по флагам и отсутствия break, то вообще не понимаю в чем проблема — что мешает вынести цикл в отдельную функцию и выходить исключительно из цикла, делая код более предсказуемым?
return в цикле и множественный return — это вовсе не то же самое.

Я не очень хочу продолжать переливать из пустого в порожнее еще 1000 писем в мейлбоксе. Если у кого-то есть код и он может показать, что с множественным выходом (не путать с выходом из цикла и несколькими _условиями_ выхода) будет проще и обосновать и отладить и оно будет быстрее работать — прекрасно. А пока что это разговоры в пользу бедных. И шарлатанство.
Re[10]: Вот подумалось
От: IT Россия linq2db.com
Дата: 27.11.05 17:21
Оценка: :)
Здравствуйте, reductor, Вы писали:

R>Компиляторы конечно пусть выполняют свою работу, но есть все же некоторое соответствие между количеством их работы и нашим пониманием того, что мы делаем.


Ага, компиляторы оставлены в покое, это уже прогресс

R>А так же между количеством их работы и умственным напряжением того человека, который будет читать наш код.


Не хочешь переписать вот такой код без returns?

private static MemberMapper GetNullableMemberMapper(MapMemberInfo mi)
{
    Type type = mi.MemberAccessor.Type;

    if (type.IsGenericType == false || mi.MapValues != null)
        return null;

    Type underlyingType = Nullable.GetUnderlyingType(type);

    if (underlyingType == null)
        return null;

    if (underlyingType.IsEnum)
    {
        underlyingType = Enum.GetUnderlyingType(underlyingType);

        if (underlyingType == typeof(SByte))    return new NullableSByteMapper. Enum();
        if (underlyingType == typeof(Int16))    return new NullableInt16Mapper. Enum();
        if (underlyingType == typeof(Int32))    return new NullableInt32Mapper. Enum();
        if (underlyingType == typeof(Int64))    return new NullableInt64Mapper. Enum();
        if (underlyingType == typeof(Byte))     return new NullableByteMapper.  Enum();
        if (underlyingType == typeof(UInt16))   return new NullableUInt16Mapper.Enum();
        if (underlyingType == typeof(UInt32))   return new NullableUInt32Mapper.Enum();
        if (underlyingType == typeof(UInt64))   return new NullableUInt64Mapper.Enum();
    }
    else
    {
        if (underlyingType == typeof(SByte))    return new NullableSByteMapper();
        if (underlyingType == typeof(Int16))    return new NullableInt16Mapper();
        if (underlyingType == typeof(Int32))    return new NullableInt32Mapper();
        if (underlyingType == typeof(Int64))    return new NullableInt64Mapper();
        if (underlyingType == typeof(Byte))     return new NullableByteMapper();
        if (underlyingType == typeof(UInt16))   return new NullableUInt16Mapper();
        if (underlyingType == typeof(UInt32))   return new NullableUInt32Mapper();
        if (underlyingType == typeof(UInt64))   return new NullableUInt64Mapper();
        if (underlyingType == typeof(Char))     return new NullableCharMapper();
        if (underlyingType == typeof(Single))   return new NullableSingleMapper();
        if (underlyingType == typeof(Boolean))  return new NullableBooleanMapper();
        if (underlyingType == typeof(Double))   return new NullableDoubleMapper();
        if (underlyingType == typeof(DateTime)) return new NullableDateTimeMapper();
        if (underlyingType == typeof(Decimal))  return new NullableDecimalMapper();
        if (underlyingType == typeof(Guid))     return new NullableGuidMapper();
    }

    return null;
}
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[20]: error is not an exception
От: IT Россия linq2db.com
Дата: 27.11.05 20:23
Оценка: +1
Здравствуйте, GlebZ, Вы писали:

IT>>На плюсах и я таким частенько грешил На шарпе пока как-то надобности не было.

GZ>При отладке windows сервисов вставлял в код даже не assert, а прямой вызов дебаггера.

Это другой случай. При разработке UI иногда даже два монитора не помогают, если надо с фокусом повозиться, который постоянно уходит в отладчик. Приходится по старинке выводить всё что нужно в лог. Но это всё 5-10% случаев.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[14]: Вот подумалось
От: IT Россия linq2db.com
Дата: 27.11.05 23:03
Оценка: :)
Здравствуйте, reductor, Вы писали:

R>Создать свой Enum с необходимым набором?


Ну переедут if'ы в другое место. А в том месте делать return или через переменную?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[11]: Вот подумалось
От: vdimas Россия  
Дата: 28.11.05 00:33
Оценка: +1
Здравствуйте, reductor, Вы писали:


R>Или я говорил, что код с несколькими стейтментами return не может работать корректно?

R>или что его нельзя в AST трансформировать во что-то там? Или что его нельзя скомпилировать?
R>Я утверждал, что без явной обработки всех условий вероятность ошибки и последующая с этим возня могут возрасти многократно.

Все с точностью до наоборот. В сочетании с RAII это помогает писать очень простой код. А надежность ПО достигается косвенным путем, а именно — чем проще код, тем сложнее ошибиться, тем легче сопровождать/исправлять и верифицировать.

Например, в С++, опять ресурсы и коды возвратов:

Resource1 res1 = openRes1();
if(error(res1)) return ERR_RESOURCE1;

Resource2 res2 = openRes2();
if(error(res2)) return ERR_RESOURCE2;

Resource3 res3 = openRes3();
if(error(res3)) return ERR_RESOURCE3;

return ERR_SUCCESS;



Теперь представь себе гору кода, если бы мы делал все через if-else и явное управление ресурсами... бррр... Вероятность ошибки возрасла бы многократно. Т.е., дело в том, что некое ELSE все равно выполняется. И разработчик, размеется, прекрасно знает — что именно (вызов деструкторов локальных объектов). И он это использует на всю катушку, для однократного программирования кода этих ELSE и затем многократного повторного использования (да и еще автоматического). Это тебе как бы затравка на другие способы повышения надежности (читабельность, максимальное повторное использование)

А с использованием exceptions, код выглядит еще читабельнее:

Resource1 res1 = openRes1();
Resource2 res2 = openRes2();
Resource3 res3 = openRes3();


Re[13]: Вот подумалось
От: CrystaX Россия https://crystax.me/
Дата: 28.11.05 13:01
Оценка: :)
Здравствуйте, IT, Вы писали:

IT>Вывести в чисто поле, поставить лицом к стенке и пустить пулю в лоб


... тремя очередями, чтоб всю жизнь помнил.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[16]: Вот подумалось
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 28.11.05 14:06
Оценка: :)
Здравствуйте, reductor, Вы писали:

E>>Корректно работающий в соответствии со спецификацией код совсем не обязательно выполняет то, что предполагалось.


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

R>Если есть данные или другой аппарат, позволяющие это оспорить и доказать, что наоборот — буду рад услышать.

К счастью, мне не приходилось вообще заниматься формальным доказательством корректности работы программы. Читали нам в универе какой-то спецкурс по этому поводу, но это было уже очень давно. Единственное, что помню, так это скептическое отношение самого преподавателя к данной теме. И еще он вспоминал какую-то программу, на одну страничку объемом, для которой на пяти страницах текста было формально доказана правильность ее работы. К сожалению, программа работала не правильно.

E>>Это эмпирический вывод, основывающийся на том, что:

E>>a) спецификации так же содержат ошибки;
E>>b) заказчик может не суметь четко описать свои пожелания и ожидания.
E>>Доказать я его не могу.

R>А вот это уже лирика, к делу не относящаяся. Методов, чтобы определить в каком состоянии писал заказчик спецификацию и писал ли вообще, а не сгенерировал генератором матерных слов, я не знаю. Себе спецификации я стараюсь писать сам. Формальные и без противоречий (это очень просто).


Еще как относится. Поскольку платят не за то, насколько полно программа соответствует спецификации, а насколько полно делает то, что от нее требовал заказчик.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[18]: error is not an exception
От: IT Россия linq2db.com
Дата: 29.11.05 02:19
Оценка: -1
Здравствуйте, Cyberax, Вы писали:

C>Не совсем так, но близко.


Т.е. на 10 строчек полезного кода столько же, если не больше, мусора. Найс.

C>Заодно помогает прояснять контракты использования.


У тебя же исходники есть, чего там прояснять.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[19]: error is not an exception
От: Cyberax Марс  
Дата: 29.11.05 08:34
Оценка: +1
IT wrote:

> C>Не совсем так, но близко.

> Т.е. на 10 строчек полезного кода столько же, если не больше, мусора.
> Найс.

ASSERT'ы — это НЕ мусор. Это чрезвычайно удобное средство отладки.

> C>Заодно помогает прояснять контракты использования.

> У тебя же исходники есть, чего там прояснять.

Вот, например, кусок функции:
    static void move_overlapped(pointer _first, pointer _last, pointer 
_dest, AllocatorT& _alloc)
    {
        assert(_dest!=_first);
        size_t count=_last-_first;
        pointer dest_begin=_dest;
        pointer dest_end=dest_begin+count;

        if (dest_begin<_first)
        {
             //...
        }
       //...
    }

assert тут помогает иллюстрировать предусловие функции. И если он
сработает — то может сэкономить кучу времени на отладку.

Или, например, вот такой код (спас часы отладки):
    void deallocate_data(pointer _ptr, size_type _sz)
    {
        storage_allocator alloc(get_allocator_inst());
        assert(*get_counter(_ptr)==0); //Check if refcount if zero.
        get_counter(_ptr)->~counter_type(); //Destroy reference counter...
        alloc.deallocate(get_storage_ptr(_ptr),adjust_size(_sz)); //and 
deallocate storage.
    }

Пишется пару секунд, а экономит кучу времени.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[7]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 29.11.05 15:58
Оценка: :)
Здравствуйте, Сергей Губанов, Вы писали:

Вариант с исключениями:

PROCEDURE Proc (param: Param): BOOLEAN;
BEGIN
  ...
  DoSmth(param);
    ...
  IF b # TRUE THEN
        THROW NEW NewMyError('Proc: что-то не так с B');
    END
END Proc;


У вашего варианта оверхед — 16/9*100 = 177% !!!
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[29]: Что вы предлагаете на замену эксепшенов?
От: AndrewJD США  
Дата: 30.11.05 10:51
Оценка: +1
Здравствуйте, dshe, Вы писали:


D>Насколько я понимаю, проблемы возникаеют когда встречаются два взаимоисключающий подхода (обработки исключений, в данном случае). Если бы стиль ref-out был общепринятым, то и ExecuteЧего-То-ТамSp его бы тоже поддерживал. И в этом случае пришлось бы написать длиннючий switch для того, чтобы Errors err преобразовать в исключения.


Не всегда. Например стороняя либа возвращает какие-то свои ошибки, а нам необходимо преобразовать их в коды ошибок/исключения которые используются в приложении
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re[12]: Вот подумалось
От: vdimas Россия  
Дата: 30.11.05 13:27
Оценка: :)
Здравствуйте, Belsen, Вы писали:

[...]

я провел лениво взглядом не вдаваясь в подробности, дошел до конца... где-то в мозжечке что-то засвербило... заставил себя навести резкость и... чуть не свалился со стула!
Я несколько раз слышал о таком коде, но увидел впервые.

В общем, послеобеденный сон на рабочем месте был безвозратно испорчен.
Re[30]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 01.12.05 08:19
Оценка: :)
Здравствуйте, IT, Вы писали:

IT>Может посчитать количество строчек. Выигрышь более чем в два раза при гораздо более высокой наглядности (если слово наглядность вообще уместно при таком стиле).


Фигнёй страдаете, однако .


---------

Кстати, символ "~" в Modula/Oberon-ах обозначает инструкцию логического отрицания, т.е. то же что в Си-образных языках обозначается символом "!".

if ( ! b) { ... }

эквивалентно:

IF ~b THEN ... END
Re[30]: error is not an exception
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 01.12.05 10:44
Оценка: :)
Здравствуйте, Cyberax, Вы писали:

C>У вас просто сместится сложность с проверки программного кода на

C>соответствие с требованиями задачи на проверку мат. модели на
C>соответствие требованиям задачи.

Кстати, о птичках:

Формальная верификация — конструирование некорректного доказательства, изоморфного по отношению к некорректной программе.

Escape-cловарь терминов программной инженерии
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Фильтрация исключений
От: Ignoramus  
Дата: 02.12.05 07:23
Оценка: +1
Господа философы, хватит спорить о пользе исключений! Хотел бы затронуть более практическую сторону использования исключений, а именно — фильтрацию. Я уже описывал проблему в форуме С/С++, здесь
Автор: Ignoramus
Дата: 23.11.05
.

Кратко повторюсь. Exception-safe и exception-neutral код действительно очень выигрывает по сравнению с использованием возврата (кода) ошибок.

Однако в программе где-то должны быть (хотя бы один) try/catch, и тут начинаются проблемы. Прежде всего — фильтрация исключений. Исключения могут возникать на разных логических уровнях и смешивать их в кучу нельзя. Например, с нижнего уровня пришло исключение "ошибка переполнения буфера", тогда как пользователю следовало бы показать (да и в лог записать): "не удалось открыть документ, т.к. он открыт другим приложением" (пример чисто условный). Т.е. нужно как бы раскрутить стек в обратную сторону, сверху вниз, чтобы узнать, в какой функции, в какой подфункции и т.д. произошел сбой.

Но стек раскручивается в направлении снизу вверх. Чтобы добиться фильтрации исключений, т.е. подавления исключений нижнего уровня и переизлучения исключений более высокого уровня, необходимо на каждом уровне ставить ловушки try/catch. Например, оборачивать публичные методы классов и конструкторы. Однако при этом код становится менее читабельным и уже больше напоминает проверку кода возврата, т.е. теряет преимущества прозрачности и нейтральности.

Как обычно осуществляют фильтрацию исключений? Может существует какой-то хитрый способ автоматического "оборачивания" исключений на промежуточных уровнях, о котором я не знаю?
Re[23]: error is not an exception
От: _Winnie Россия C++.freerun
Дата: 03.12.05 12:12
Оценка: +1
Здравствуйте, любители ret-кодов, Вы писали:
HRESULT h(bool *out);
HRESULT f(int *out);
HRESULT h(int in, int *out);

HRESULT k(int *out)
{
  bool h_res;
  if (FAILED(h(&h_res)))
    return E_FAIL;

  if (h_res)
  {
    int f_res;
    if (FAILED(f(&f_res)))
      return E_FAIL;

    int g_res;
    if (FAILED(g(f_res, &g_res))
      return E_FAIL;

    *out = g_res;
     return S_OK;
  }
  else
  {
    *out = 0;
    return S_OK;
   }
}


int k()
{
  return h()        ?        g(f()) : 0;
}



Еще какие-то вопросы есть?
Правильно работающая программа — просто частный случай Undefined Behavior
Re[30]: error is not an exception
От: OnThink Россия http://vassilsanych.livejournal.com
Дата: 06.12.05 11:50
Оценка: :)
E>нужно взять генератор волн с такой же частотой, но противоположной фазой, разместить рядом больным и все -- больные клетки разрушатся в результате частотного резонанса.

Раковая опухоль ещё и зудит —
Побочные явления — зудовый шок, щекотливый шок
А если цероз печени, то она отвалится в натуральном смысле.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re: Что вы предлагаете на замену эксепшенов?
От: psg  
Дата: 19.11.05 21:38
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

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

СГ>Ошибки категории (2) фатальные, тут программу надо завершать — в программе ошибка, т.е. программа не правильная. Использовать exception только для того чтобы правильно завершить работу программы (ну там закрыть открытые ресурсы), только для этого чтоли? Закрыть открытое можно и другими способами.

А собственно, чем вам не нравятся exceptions?...
Re[3]: Что вы предлагаете на замену эксепшенов?
От: psg  
Дата: 19.11.05 23:40
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, psg, Вы писали:


psg>>А собственно, чем вам не нравятся exceptions?...


IT>Видимо они отсутствуют в Обероне.


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

СГ>http://www.rsdn.ru/Forum/Message.aspx?mid=1496415&amp;only=1
Автор: Nickolay Ch
Дата: 19.11.05


NC>>А вот очень бы хотелось услышать, что вы предлагаете на замену эксепшенов, только мб в новой теме. Они много чем не нравятся, но пока не видно лучших механизмов обработки ошибок.


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

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

Ключевой момент -- это большое и жирное "Я" в твоем утверждении.

А вообще, кроме классика Н.Вирта, есть еще и классик Б.Страуструп. В его книге "Язык программирования С++. 3-е издание" есть целая глава #14, которая посвящена обработке исключений. Тебе бы не мешало прочитать из нее хотя бы 14.1 (Обработка ошибок [except.error]) и 14.1.1 (Альтернативный взгляд на исключения [except.views]). Там очень сжато и точно описываются разные стратегии диагностики ошибок и роль в этом деле исключений.

Note. Названия разделов я привел из англиского варианта книги, т.к. русский вариант у меня на работе.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: А есть ли замена?
От: gear nuke  
Дата: 20.11.05 09:27
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>http://www.rsdn.ru/Forum/Message.aspx?mid=1496415&amp;only=1
Автор: Nickolay Ch
Дата: 19.11.05


NC>>А вот очень бы хотелось услышать, что вы предлагаете на замену эксепшенов, только мб в новой теме. Они много чем не нравятся, но пока не видно лучших механизмов обработки ошибок.


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

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

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


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

СГ>Ошибки категории (2) фатальные, тут программу надо завершать — в программе ошибка, т.е. программа не правильная. Использовать exception только для того чтобы правильно завершить работу программы (ну там закрыть открытые ресурсы), только для этого чтоли? Закрыть открытое можно и другими способами.


Может быть и можно, но в системах использующих аппаратные механизмы защиты — это наиболее простой (а не только быстрый) способ.
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[2]: Что вы предлагаете на замену эксепшенов?
От: iZEN СССР  
Дата: 20.11.05 12:55
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Сергей Губанов, Вы писали:


СГ>>http://www.rsdn.ru/Forum/Message.aspx?mid=1496415&amp;only=1
Автор: Nickolay Ch
Дата: 19.11.05


NC>>>А вот очень бы хотелось услышать, что вы предлагаете на замену эксепшенов, только мб в новой теме. Они много чем не нравятся, но пока не видно лучших механизмов обработки ошибок.


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

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

E>Ключевой момент -- это большое и жирное "Я" в твоем утверждении.


E>А вообще, кроме классика Н.Вирта, есть еще и классик Б.Страуструп. В его книге "Язык программирования С++. 3-е издание" есть целая глава #14, которая посвящена обработке исключений. Тебе бы не мешало прочитать из нее хотя бы 14.1 (Обработка ошибок [except.error]) и 14.1.1 (Альтернативный взгляд на исключения [except.views]). Там очень сжато и точно описываются разные стратегии диагностики ошибок и роль в этом деле исключений.

E>Note. Названия разделов я привел из англиского варианта книги, т.к. русский вариант у меня на работе.

Ещё есть один классик т.н. "контрактоного программирования" (кстати, последователь Н.Вирта, сейчас работает в ETH) — Бертран Мейер, автор языка Eiffel.
Стоит почитать и его.
Re[3]: Что вы предлагаете на замену эксепшенов?
От: iZEN СССР  
Дата: 20.11.05 12:56
Оценка:
"контрактного программирования"
Re: Что вы предлагаете на замену эксепшенов?
От: Pavel Dvorkin Россия  
Дата: 21.11.05 07:08
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

Я не собираюсь предлагать что-то вместо эксепшн, но вот идею их я бы расширил. Сейчас — это просто уведомление о чем-то. Я бы добавил в них возможность исправления, если, конечно, возможно.

Происходит исключение. Выбрасывется экземпляр класса исключения. Это экземпляр получает доступ к классу/методу, где произошло исключение, анализирует причину и изменяет состояние класса, после чего, возможно, повторяет операцию, вызвавшую исключение.
Я бы называл это "теневой обработкой исключений"

При этом мы будем иметь "автоматизированную обработку исключений" — можно будет писать код, который в самом исключении пытается исправить ситуацию. Можно будет писать код, который не будет содержать try-catch. Просто если этот код выбросит исключение, то экземпляр исключения появится сам, исправит что надо и сам же исчезнет.

Разумеется, это не везде и всегда возможно. Поэтому если не может исправить — перевыбрасывает исключение на более высокий уровень.

В свое время такое в примитивном виде было в Фортране IBM/360. Там можно было задать "корректирующее действие". Например, при переполнении стандартное корректирующее действие заключалось в засылке MAXFLOAT в ячейку ответа. Т.е. происходило "исключение" (ovarflow в процессоре), автоматом запускался некий код, который и обрабатывал это исключение, так что я даже не знал, что оно произошло. Можно было задать свое действие.

Понимаю, что технических проблем здесь хватит, и вряд ли нынешние языки это потянут, но самам идея, ИМХО, имеет право на существование.
With best regards
Pavel Dvorkin
Re: Что вы предлагаете на замену эксепшенов?
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 21.11.05 08:09
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Использовать exception только для того чтобы правильно завершить работу программы (ну там закрыть открытые ресурсы), только для этого чтоли? Закрыть открытое можно и другими способами.


afaik, так Erlang работает — тред с исключением прибивается. Нормальная система, имхо.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[2]: Что вы предлагаете на замену эксепшенов?
От: reductor  
Дата: 21.11.05 08:11
Оценка:
<i>Я бы называл это "теневой обработкой исключений"</i>

А чем старое название — "conditions" не устраивает?

Или более общее — continuations?

Правда для последних еще бы хорошо помнить лексический контекст приемника.
Re[2]: Что вы предлагаете на замену эксепшенов?
От: c-smile Канада http://terrainformatica.com
Дата: 21.11.05 08:12
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Понимаю, что технических проблем здесь хватит, и вряд ли нынешние языки это потянут, но самам идея, ИМХО, имеет право на существование.


В VB есть нечто подобное

On Error Resume [Next]

http://www.magictree.com/vbcourse/11design/errors.htm
Re[2]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 21.11.05 08:30
Оценка:
Pavel Dvorkin wrote:

> Происходит исключение. Выбрасывется экземпляр класса исключения. Это

> экземпляр получает доступ к классу/методу, где произошло исключение,
> анализирует причину и изменяет состояние класса, после чего, возможно,
> повторяет операцию, вызвавшую исключение.

Такие идеи пробовались в 70-80х годах. Оказалось, что корректно
обрабатывать retry'и достаточно сложно, и почти никогда не нужно. А
когда все же действительно нужно, то проще явный while поставить.

У Страуструпа где-то об этом было неплохо написано.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[2]: Что вы предлагаете на замену эксепшенов?
От: Глеб Алексеев  
Дата: 21.11.05 08:39
Оценка:
Здравствуйте, CrystaX, Вы писали:

CX> Чтобы проигнорировать код ошибки, ничего делать не нужно, именно поэтому в реальных ситуациях они часто и игнорируются. А вот чтобы проигнорировать исключение, нужны явные действия по их игнорированию.


Явные действия по игнорированию? Это вроде только в Java нужно, AFAIK. Во многих языках, и в С++ в том числе, спецификации исключений необязательны, и вызов функции, потенциально бросающей исключение, не генерирует ошибку компиляции. Так что этот аргумент принимается только в том случае, если coverage (степень покрытия?) тестов достаточный(ая).
Re[3]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.11.05 08:43
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

CX>> Чтобы проигнорировать код ошибки, ничего делать не нужно, именно поэтому в реальных ситуациях они часто и игнорируются. А вот чтобы проигнорировать исключение, нужны явные действия по их игнорированию.


ГА>Явные действия по игнорированию? Это вроде только в Java нужно, AFAIK. Во многих языках, и в С++ в том числе, спецификации исключений необязательны, и вызов функции, потенциально бросающей исключение, не генерирует ошибку компиляции. Так что этот аргумент принимается только в том случае, если coverage (степень покрытия?) тестов достаточный(ая).


Спецификация исключений -- это только одна сторона медали.
Другая сторона -- это catch(...) или catch( const std::exception & ), ибо в противном случае игнорирования не получится -- исполнение прервется.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Что вы предлагаете на замену эксепшенов?
От: CrystaX Россия https://crystax.me/
Дата: 21.11.05 08:43
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

CX>> Чтобы проигнорировать код ошибки, ничего делать не нужно, именно поэтому в реальных ситуациях они часто и игнорируются. А вот чтобы проигнорировать исключение, нужны явные действия по их игнорированию.


ГА>Явные действия по игнорированию? Это вроде только в Java нужно, AFAIK. Во многих языках, и в С++ в том числе, спецификации исключений необязательны, и вызов функции, потенциально бросающей исключение, не генерирует ошибку компиляции. Так что этот аргумент принимается только в том случае, если coverage (степень покрытия?) тестов достаточный(ая).


Нет, я говорил вот о чем:
try
{
    do_something();
}
catch(some_specific_exception &)
{
    // Ignore it
}


Для того, чтобы проигнорировать some_specific_exception, понадобилось писать блок try/catch. В ином случае оно обязательно вылетело бы где-нибудь выше. А вот с кодами ошибок ситуация другая — чтобы не забыть ее обработать, нужен доп. код.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.11.05 09:39
Оценка:
Здравствуйте, Nickolay Ch, Вы писали:

NC>Посыл неверный.


Не верный относительно чего?

NC>Пример: некий оффлайн клиент. Пользователь отредактировал документ и хочет его скинуть на сервер. Сервер недоступен. Какая это ошибка в вашей терминологии? На 1ую непохоже, а во втором случае надо завершить программу? И все, что было создано пропадет?

NC>Аналогично с сохранением файла на носитель, на котором кончилось место. По идее надо дать возможность сменить носитель и т.д., а не молча закрыть прогу.
NC>Опять возвращаемся к кодам ошибок или исключениям.

Сервер недоступен или место на жестком диске кончилось — это не ошибки вовсе. Программист с самого начала проектирования программы знает, что серверы могут быть не доступными, а жесткие диски не резиновые. Программа должна уметь корректно работать и в этих случаях. Это не то что не ошибки, это даже не исключительные ситуации, а самые обычные рядовые — штатные варианты работы.

То же мне выдумали, этот вариант работы значит штатный, а вот этот вариант работы уже значит не штатный. Да любой известный заранее вариант работы — штатный. Прилетел из космоса микрометеорит и пробил в блоке памяти дырку — исключительная ситуация? Для космических кораблей — не исключительная, а рядовая, штатная; для домашнего компьютера — исключение, ошибка, что надо сделать с домашним компьютером? — Выключить и поменять блок памяти вручную.
Re[4]: Что вы предлагаете на замену эксепшенов?
От: Глеб Алексеев  
Дата: 21.11.05 12:21
Оценка:
Здравствуйте, CrystaX, Вы писали:

CX>Нет, я говорил вот о чем:

А я — вот
Автор: Глеб Алексеев
Дата: 21.11.05
о чем .
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Что вы предлагаете на замену эксепшенов?
От: CrystaX Россия https://crystax.me/
Дата: 21.11.05 12:31
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

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


Мы говорим, похоже, о разных вещах. Ты можешь игнорировать и исключение, и код ошибки, но только до того момента, пока она (ошибка) не произойдет. Но если ошибка все-таки произошла, то исключение ты "случайно" не пропустишь — только предприняв для этого явные действия. А вот код ошибки — запросто.

ГА>К чему я веду? Что исключения очень полезны для отделения "нормального" кода от кода обработки ошибок, а также для передачи управления на несколько уровней выше при невозможности обработать ошибку в точке возникновения, но никак не заменитель головы программиста. Внимательность никто не отменял и видимо еще долго не отменит.


Я с этим и не спорил.

На этом, думаю, взаимные объяснения можно считать завершенными.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[5]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.11.05 12:37
Оценка:
Здравствуйте, Глеб Алексеев

Теперь твоя точка зрения стала понятна. В Java как раз попытались побороться с игнорированием исключений, но, имхо, получили не меньше проблем, чем от которых избавились. Серьезное обсуждение этой темы здесь было: Checked exceptions... зло или добро?
Автор: mishaa
Дата: 16.07.05
.

ГА>К чему я веду? Что исключения очень полезны для отделения "нормального" кода от кода обработки ошибок, а также для передачи управления на несколько уровней выше при невозможности обработать ошибку в точке возникновения, но никак не заменитель головы программиста. Внимательность никто не отменял и видимо еще долго не отменит.


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

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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[6]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.11.05 12:56
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Что значит "неожиданная ситуация"? Это выражение означает "невозможно выполнить запрошенное действие".


Ничего неожиданного в этом нет. С самого начала известно, что соединение может разорваться в любой момент, да и денег на счете может быть меньше чем запрошено.
Re[6]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.11.05 13:07
Оценка:
Здравствуйте, eao197, Вы писали:

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


Единственное правильное использование ловли исключений — это чтобы в случае чего грамотно прибрать за собой.
При наличии автоматической сборки мусора, прибрать за собой — гораздо менее актуальная задача.
Re[2]: Что вы предлагаете на замену эксепшенов?
От: Шахтер Интернет  
Дата: 21.11.05 13:08
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Сергей Губанов, Вы писали:


PD>Я не собираюсь предлагать что-то вместо эксепшн, но вот идею их я бы расширил. Сейчас — это просто уведомление о чем-то. Я бы добавил в них возможность исправления, если, конечно, возможно.


Это возможно на SEH-овских исключениях.
SEH поддерживает возобновление исполнения для некоторых типов исключений.
Весьма редко используемая фича.
Можно разреженные контейнеры делать, например, в которых память выделяется только по обращению к соотвествующей странице памяти.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
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[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[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[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[2]: Что вы предлагаете на замену эксепшенов?
От: Глеб Алексеев  
Дата: 22.11.05 10:31
Оценка:
Здравствуйте, reductor, Вы писали:

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


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


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

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


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

Такими, которые обеспечивают ACID. Т.е. снятие/положение денег — некая сложная, но атомарная операция. Не обязательно приводить их полный код. Можно пользоваться ими как черными ящиками.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[11]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.11.05 14:29
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

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


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


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

E>Здравствуйте, Сергей Губанов, Вы писали:


E>Т.е. вот этот вызов:

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


E>гарантированно завершается успешно? Всегда, при любых условиях?


Да считаю. Это монитор — вход в эксклюзивный блок кода, обычная блокировка. Например, на C# было бы написано:
lock (this)
{
  ...
}

эквивалентное:
try
{
  System.Threading.Monitor.Enter(this); // this.НачалоЭксклюзивнойОперации;
  ...
}
finally
{
  System.Threading.Monitor.Exit(this) // this.КонецЭксклюзивнойОперации;
}
Re[11]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 22.11.05 15:04
Оценка:
Сергей Губанов wrote:

> S>Такими, которые обеспечивают ACID. Т.е. снятие/положение денег —

> некая сложная, но атомарная операция. Не обязательно приводить их
> полный код. Можно пользоваться ими как черными ящиками.
> Программа, я так понимаю, работает в банке со счета которого деньги
> снимаются.
>
> this.журнал.РапортОбУдачномОсуществленииДенежногоПеревода(this, счёт, сумма);
>
>
А если в этот момент выдернут сетевой кабель, и email не отправится? Или
запись в журнал из-за переполненого диска не произойдет?

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[3]: Что вы предлагаете на замену эксепшенов?
От: Дарней Россия  
Дата: 23.11.05 04:04
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Такие идеи пробовались в 70-80х годах. Оказалось, что корректно

C>обрабатывать retry'и достаточно сложно, и почти никогда не нужно. А
C>когда все же действительно нужно, то проще явный while поставить.

например, у меня несколько раз возникала такая необходимость: если операция не удалась, то вызвать функцию, которая запрашивает юзера "retry, abort, skip?". Ну и далее действовать по результатам ответа.
Действительно — в С++ остается только завернуть операцию в цикл, который прерывается по ответу "skip" и по благополучному завершению операции, или кидается исключением по ответу "abort".
Проблема в том, что таких мест в программе десятки, а код цикла с проверками получается довольно-таки объемистый — нужно каким-то образом использовать его повторно. Вопрос только, как?
Делегатов в С++ нет, а каждой операции нужно передавать набор аргументов, и получать обратно результат. Использовать boost по некоторым причинам низзя.
Ваши варианты, как решить эту проблему? (лучшее, до чего я тогда додумался — это написать большой страшнючий макрос, которому нужная операция передается как аргумент)
... << RSDN@Home 1.1.4 stable rev. 510>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[4]: Что вы предлагаете на замену эксепшенов?
От: Павел Кузнецов  
Дата: 23.11.05 04:08
Оценка:
Дарней,

> Делегатов в С++ нет, а каждой операции нужно передавать набор аргументов, и получать обратно результат. Использовать boost по некоторым причинам низзя. Ваши варианты, как решить эту проблему?


Boost -- не единственное, и даже не первое место, где предоставлена функциональность аналогов boost::function на C++. Более того, для этой частной задачи реализовать это добро "ручками" совершенно несложно и недолго.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: Что вы предлагаете на замену эксепшенов?
От: Дарней Россия  
Дата: 23.11.05 05:16
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Более того, для этой частной задачи реализовать это добро "ручками" совершенно несложно и недолго.


несложно и недолго — если компилятор нормальный
... << RSDN@Home 1.1.4 stable rev. 510>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[5]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.11.05 05:53
Оценка:
Здравствуйте, iZEN, Вы писали:

E>>Стоит, безусловно. А что именно? Если можно URL, т.к. у нас достать печатное издание крайне проблематично.

ZEN>"Объектно-ориентированное конструирование программных систем", Бертран Мейер, изд. Русская редакция, 2005, 1232 стр., ISBN: 5-7502-0255-0

ZEN>Несколько определений и правил из главы "Когда контракт нарушается: обработка исключений".


Бегло просмотрел эту главу. Мне показалось, что у Страуструпа про исключения написано более лаконично и практично.

E>>Ну и еще одно соображение. Исключения, в отличии от того же контрактного программирования, стали широко призанным и адаптированным механизмом. C++, Java, C#, Python, Ruby, Ada, Smalltalk -- везде есть исключения. Конечно, это не панацея от всех болезней, и применять их нужно осторожно. Тем не менее, вряд ли идея исключений получила бы такое широкое распространение, если бы она не была настолько удачной.

ZEN>Как видите, Бертран Мейер имеет ясное представление об исключениях,

и, как мне видится, собственное представление. Которое он и выразил в Eiffel

ZEN> и эта тема — одна из важнейших в контрактном проектировании/программировании. Он ни в коей мере не отрицает возможность и нужность исключений, наоборот — чётко формализует и внедряет в процесс проектирования ПО в виде неотъемлемой части.

ZEN>Поэтому исключения нужно применять не "осторожно", как вы предлагаете, а просто-напросто ГРАМОТНО работать с ними. Это целая "субархитектура" (по аналогии с суб-культурой) в основании любой программной системы, и игнорировать её нельзя.

Грамотно, по отношению к исключениям, имхо, это и есть осторожно. При проектировании библиотек во многих случаях есть выбор: как реализовать информирование пользователя библиотеки об ошибках -- с помощью исключений или кодов возврата. Иногда использование исключений может привести к сильнейшему геморрою при использовании библиотеки, т.к. придется каждый вызов заворачивать в try...catch (begin...rescue, do...requie...rescue и пр.). Иногда -- наоборот. Здесь важнейшую роль играют опыт, здравый смысл, интуиция и чувство меры проектировщика. ИМХО, конечно.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: Что вы предлагаете на замену эксепшенов?
От: Joker6413  
Дата: 23.11.05 08:16
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Сергей Губанов, Вы писали:


PD>Я не собираюсь предлагать что-то вместо эксепшн, но вот идею их я бы расширил. Сейчас — это просто уведомление о чем-то. Я бы добавил в них возможность исправления, если, конечно, возможно.


PD>Происходит исключение. Выбрасывется экземпляр класса исключения. Это экземпляр получает доступ к классу/методу, где произошло исключение, анализирует причину и изменяет состояние класса, после чего, возможно, повторяет операцию, вызвавшую исключение.


Это будет круче множественного наследования! Имхо повысит энтропию системы не в разы, а на порядки!
Re[4]: Что вы предлагаете на замену эксепшенов?
От: Joker6413  
Дата: 23.11.05 08:19
Оценка:
Здравствуйте, Дарней, Вы писали:

Д>Здравствуйте, Cyberax, Вы писали:


C>>Такие идеи пробовались в 70-80х годах. Оказалось, что корректно

C>>обрабатывать retry'и достаточно сложно, и почти никогда не нужно. А
C>>когда все же действительно нужно, то проще явный while поставить.

Д>например, у меня несколько раз возникала такая необходимость: если операция не удалась, то вызвать функцию, которая запрашивает юзера "retry, abort, skip?". Ну и далее действовать по результатам ответа.

Д>Действительно — в С++ остается только завернуть операцию в цикл, который прерывается по ответу "skip" и по благополучному завершению операции, или кидается исключением по ответу "abort".
Д>Проблема в том, что таких мест в программе десятки, а код цикла с проверками получается довольно-таки объемистый — нужно каким-то образом использовать его повторно. Вопрос только, как?

С помощью декомпозиции и какой-то матери...

Д>Делегатов в С++ нет, а каждой операции нужно передавать набор аргументов, и получать обратно результат. Использовать boost по некоторым причинам низзя.


Делегат — это ведь тот же самый callback.
Re[5]: Что вы предлагаете на замену эксепшенов?
От: Дарней Россия  
Дата: 23.11.05 08:29
Оценка:
Здравствуйте, Joker6413, Вы писали:

J>С помощью декомпозиции и какой-то матери...


точно. особенно с помощью второго пункта

J>Делегат — это ведь тот же самый callback.


верно. просто в данном случае неизвестно заранее количество и тип аргументов, которые нужно передавать
можно конечно использовать функтор, но это большой гемор с дополнительным кодированием

В общем, что я хотел сказать? Сама идея continuations кажется мне вполне интересной, хотя с помощью такой-то матери можно обойтись и без них
... << RSDN@Home 1.1.4 stable rev. 510>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[4]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 23.11.05 08:35
Оценка:
Здравствуйте, Дарней, Вы писали:

Д>например, у меня несколько раз возникала такая необходимость: если операция не удалась, то вызвать функцию, которая запрашивает юзера "retry, abort, skip?". Ну и далее действовать по результатам ответа.

Д>Действительно — в С++ остается только завернуть операцию в цикл, который прерывается по ответу "skip" и по благополучному завершению операции, или кидается исключением по ответу "abort".
Д>Проблема в том, что таких мест в программе десятки, а код цикла с проверками получается довольно-таки объемистый — нужно каким-то образом использовать его повторно. Вопрос только, как?
Примерно как у меня:
typedef boost::function<SomeResultType ()> SomeResultFunctor;
...

//Обернем функтор в графическую оболочку
SomeResultFunctor res = wrap_with_gui<SomeResultType>(m_hWnd,boost::bind(&MyClass::func,this),std_exception_translator();

SomeResultType val = res(); //Вызовет появление окна если все будет плохо

У меня такой же подход используется для организации future-переменных.

Д>Делегатов в С++ нет, а каждой операции нужно передавать набор аргументов, и получать обратно результат. Использовать boost по некоторым причинам низзя.

Ну так в простом варианте делегаты за вечер пишутся. Я бы просто взял Boost и художественно спер бы оттуда код
Sapienti sat!
Re[12]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 11:38
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>А если в этот момент выдернут сетевой кабель, и email не отправится? Или

C>запись в журнал из-за переполненого диска не произойдет?

Объекту "ЛокальныйСчёт" нет до этого ни какого дела, он свою задачу выполнил на 100%. Всё остальное находится в компетенции объекта "Журнал".
Re[13]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 23.11.05 11:44
Оценка:
Сергей Губанов wrote:

> C>А если в этот момент выдернут сетевой кабель, и email не отправится?

> Или
> C>запись в журнал из-за переполненого диска не произойдет?
> Объекту "ЛокальныйСчёт" нет до этого ни какого дела, он свою задачу
> выполнил на 100%. Всё остальное находится в компетенции объекта "Журнал".

А как тогда реагировать на его ошибки? А они вполне воможны в данном случае.

Ваше решение — просто на них плюнуть, так как функиця
"РапортОбУдачномОсуществленииДенежногоПеревода" никак не может повлять
(кроме полного останова программы) на ход вызывающей функции.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[13]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 23.11.05 11:53
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:


СГ>Объекту "ЛокальныйСчёт" нет до этого ни какого дела, он свою задачу выполнил на 100%. Всё остальное находится в компетенции объекта "Журнал".


Так ведь если запись в журнал транзакций не прошла, состояние объекта "ЛокальныйСчет" восстановить требуется. Кто этим займется? Кстати, в действительности там все намного сложнее.
Re[12]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 12:09
Оценка:
Здравствуйте, Sinclair, Вы писали:

Отвечу в обратном порядке.

S>Вот в приведенном примере — что делать, если журнал не смог записать успешную запись в файл?


Что делать кому? Объекту "ЛокальныйСчёт" по этому поводу точно делать ни чего не надо, он свою задачу выполнил на 100%, а уж как там внутри объекта "Журнал" чего-то стряслось — не его дело.

S>Прекрасно. Великолепный пример. Что мы из него видим?

S>1. Все функции обязаны возвращать булевый признак успешности выполнения.
S>2. Все функции обязаны передавать информацию о причине неудачи.
S>3. Если нам надо что-то большее, чем текст, в качестве информации о причине неудачи, то мы встряли. Потому что сигнатуры всех функций, имевших несчастье попасть в стек вызовов между тем местом, где мы обрабатываем ситуацию, и тем местом, где она произошла, должны быть модифицированы для передачи этой информации. Что-то более-менее общее мы использовать не сможем.
S>Более того, у нас нет никакого способа комбинировать обработку, и с ростом количества потенциальных неудач у нас нарастает объем кода, посвященного обработке. Если бы мы обрабатывали исключения, то все было бы сделано одной строчкой.

Ничего подобного.
1) Не все процедуры обязаны возвращать булевый признак успешности. Например, операция рапорта о чём-то произошедшем, ничего не должна возвращать — это никому не интересно кроме неё самой.
2) Не все процедуры обязаны возвращать информацию о причине неудачи. Ну не получилось, что-то сделать — иногда интересно узнать почему, а иногда — причина по барабану.
3) С чего Вы взяли, что информация о неудаче есть обязательно текст? Можно возвращать текст, можно число, можно указатель на абстрактный объект, и т.д.

Вот, пример полиморфной информации об ошибке:
MODULE Errors;

  TYPE
    Error* = POINTER TO EXTENSIBLE RECORD
      msg*: ARRAY 256 OF CHAR;
    END;
  
    List* = POINTER TO RECORD
      head-: Error;
      tail-: List
    END;

  PROCEDURE NewError* (msg: ARRAY OF CHAR): Error;
    VAR e: Error;
  BEGIN 
    NEW(e); 
    e.msg := msg$; 
    RETURN e
  END NewError;

  PROCEDURE NewList* (head: Error; tail: List): List;
    VAR list: List;
  BEGIN 
    NEW(list); 
    list.head := head; 
    list.tail := tail;
    RETURN list
  END NewList;

END Errors.


Пользовательский модуль:
MODULE MyModule;

  IMPORT Errors;

  TYPE
    MyError* = POINTER TO EXTENSIBLE RECORD (Errors.Error)
      extendedParam: MyExtendedParam;
    END;

  PROCEDURE NewMyError* (s: ARRAY OF CHAR; p: MyExtendedParam): Error;
    VAR e: MyError;
  BEGIN 
    NEW(e); 
    e.msg := s$; 
    e.extendedParam := p;
    RETURN e
  END NewError;

  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

  PROCEDURE TryDoSmth* (...params.., VAR err: Errors.List): BOOLEAN;
  BEGIN

    ...

    IF обычнаяХерняСлучилась THEN
      err := Errors.NewList(Errors.NewError("обычнаяХерняСлучилась"), err);
      RETURN FALSE
    END;

    ...

    IF мояХерняСлучилась THEN
      err := Errors.NewList(NewMyError("мояХерняСлучилась"), err);
      RETURN FALSE
    END;

    ...

    RETURN TRUE
  END TryDoSmth;

  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

END MyModule.
Re[15]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 23.11.05 12:34
Оценка:
Сергей Губанов wrote:

> P>Так ведь если запись в журнал транзакций не прошла, состояние

> объекта "ЛокальныйСчет" восстановить требуется. Кто этим займется?
> Ага, а удалённый банк надо попросить: "Пожалуйста, верните деньги
> обратно"...

Да, как ни странно. Это буква "A"(Atomicity) в слове ACID.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[14]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 13:36
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Нет, это как раз его дело. Так как он должен откатить транзакцию и передать "выше" сообщение об ошибке.


Тогда надо использовать другой базис примитивных операций. Ибо в выбранном базисе состоящей всего из одной примитивной операции "Начислить":

PROCEDURE (this: СчётВУдалённомБанке) Начислить* (сумма: Деньги; откого: ОтКого; VAR err: Errors.List): BOOLEAN, NEW, ABSTRACT;

после свершившегося начисления, откат назад невозможен. К сожалению, я не знаком с устройством банковских систем и не знаю какой базис примитивных операций там используется.
Re[14]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 13:44
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Гениально! Эдак вы скоро и до exception-ов додумаетесь, колллега!

M>Как только осознаете, наконец, что служебный код как правило не знает, является ли неудача его выполнения критическим багом или нет для данного случая.

Совершенно верно — не знает. Процедура чего-то сделала, о результатах сообщила. А при чём тут exception? Или exception — это единственный или лучший способ сообщить о результатах? Нет, не единственный и не лучший. Тогда при чём тут они...
Re[15]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 23.11.05 13:52
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Ага, а удалённый банк надо попросить: "Пожалуйста, верните деньги обратно"...


Именно. А как иначе? Дисбаланс получится со всеми вытекающими, если не думать о таких вещах.

P>>Кстати, в действительности там все намного сложнее.


СГ>Ясное дело.


Настолько, что в близких к реальным условиях Ваш пример
Автор: Сергей Губанов
Дата: 22.11.05
неработоспособен.
Re[16]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.11.05 14:23
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Исключения — это стандартный и универсальный механизм, с помощью которого код может делегировать принятие решений коду вызывающему данный. Неважно, о чем мы говорим — о модуле, функции или трех строчках кода — это все равно так.


Причем не важно, сигнализирует ли исключение об ошибке, исключительной ситуации или же исключения используются для реализации логики (бывают и такие ситуации, когда исключения удобнее чем if/elseif/else или switch/case).
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[6]: Что вы предлагаете на замену эксепшенов?
От: Павел Кузнецов  
Дата: 23.11.05 14:28
Оценка:
Дарней,

> ПК>Более того, для этой частной задачи реализовать это добро "ручками" совершенно несложно и недолго.

>
> несложно и недолго — если компилятор нормальный

Несложно и недолго начиная с VC++ 6 SP4 или GCC 2.95. Вы используете что-нибудь более старое?
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[16]: Что вы предлагаете на замену эксепшенов?
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 23.11.05 14:33
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Исключения — это стандартный и универсальный механизм, с помощью которого код может делегировать принятие решений коду вызывающему данный. Неважно, о чем мы говорим — о модуле, функции или трех строчках кода — это все равно так.


M>Можно ли делигировать принятие решения другим способом?


Можно. Самый распространённый механизм — это возврат некого значения.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[17]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.11.05 14:47
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:


СГ>вот так:

СГ>
СГ>  bool valid = false;
СГ>  try
СГ>  {
СГ>    str = ReturnString();
СГ>    valid = true;
СГ>  }
СГ>  catch
СГ>  {
СГ>    ......
СГ>  }
СГ>  if (valid)
СГ>  {
СГ>     ........
СГ>  }
СГ>


Это уж действительно баг в понятийном аппарате
Поскольку проще написать так:
try
    {
        str = ReturnString();
        useStringAsYouWant();
    }
catch( const std::exception & x )
    {
        allGoingToForest();
    }
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[17]: Что вы предлагаете на замену эксепшенов?
От: mrozov  
Дата: 23.11.05 14:51
Оценка:
Ну, во-первых, еще раз — есть понятие функции. Оно не предусматривает иных возвращаемых значений, помимо retval. И это удобно. Точно также, как и использование свойства.

Т.е. если вы предлагаете отказаться от конструкций вида:
funct1().func2(someParam).Doit()
то я спрашиваю — а ради чего? Где эта святая цель? Она должна быть дьявольски велика, чтобы я ее принял.

А во-вторых, пример надуманный. Т.е. да, так бывает. Но гораздо чаще бывает так:

try
{
делаем что-то
делаем еще что-то
вообще, нам тут много чего нужно делать
}
catch(Exception1)
{
Делаем что-то полезное при возникновении проблемы №1
}
catch(Exception2)
{
Делаем что-то полезное при возникновении проблемы №2
}

И если вы предлагаете везде проверять статусы и плодить доп. проверки... ну... очень плохо — для вас и вашего работодателя.

Замечу — не использовать исключение, если они доступны, легко. А вот эмулировать их там, где их нет — намного сложнее.

Но главное — да приведите же наконец хоть одну причину, по которой от исключений нужно отказаться. Пока я вижу только ... ну не очень впечатляющие доводы в пользу того, что без них можно обойтись, если все делать через одно место.
Re[16]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 14:54
Оценка:
Здравствуйте, Cyberax, Вы писали:

>> Тогда надо использовать другой базис примитивных операций. Ибо в

>> выбранном базисе состоящей всего из одной примитивной операции
>> "Начислить":
>> PROCEDURE (this: СчётВУдалённомБанке) Начислить* (сумма: Деньги; откого: ОтКого; VAR err: Errors.List): BOOLEAN, NEW, ABSTRACT;
>> после свершившегося начисления, откат назад невозможен.

C>Это почему же?


Деньги уже начисленные на счёт в другом банке??????????
По той же самой причине, что:
1) "Фарш невозможно провернуть назад" (с) С. Лукьяненко.
2) Нельзя распечатать на принтере документ обратно (в зад, так сказать — в чистый лист, и в краску в картиридже).
3) Поезд уже ушел.

Чтобы был возможен откат, базис примитивных операций должен быть другой, ибо операция "Начислить" — необратима.
Re[18]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 14:59
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Но главное — да приведите же наконец хоть одну причину, по которой от исключений нужно отказаться.


Признаюсь, едва ли мне по силам найти хоть одну причину убедившую бы Вас. Впрочем, и Вам тоже едва ли по силам найти серьёзную причину по которой исключения должны быть встроены в язык, а не в библиотеку.
Re[17]: Что вы предлагаете на замену эксепшенов?
От: mrozov  
Дата: 23.11.05 15:02
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, Cyberax, Вы писали:


>>> Тогда надо использовать другой базис примитивных операций. Ибо в

>>> выбранном базисе состоящей всего из одной примитивной операции
>>> "Начислить":
>>> PROCEDURE (this: СчётВУдалённомБанке) Начислить* (сумма: Деньги; откого: ОтКого; VAR err: Errors.List): BOOLEAN, NEW, ABSTRACT;
>>> после свершившегося начисления, откат назад невозможен.

C>>Это почему же?


СГ>Деньги уже начисленные на счёт в другом банке??????????

СГ>По той же самой причине, что:
СГ>1) "Фарш невозможно провернуть назад" (с) С. Лукьяненко.
СГ>2) Нельзя распечатать на принтере документ обратно (в зад, так сказать — в чистый лист, и в краску в картиридже).
СГ>3) Поезд уже ушел.

СГ>Чтобы был возможен откат, базис примитивных операций должен быть другой, ибо операция "Начислить" — необратима.


Простите. вы вообще имели когда-нибудь дело с платежными системами? Я вот да.
Re[17]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.11.05 15:03
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Деньги уже начисленные на счёт в другом банке??????????

СГ>По той же самой причине, что:
СГ>1) "Фарш невозможно провернуть назад" (с) С. Лукьяненко.
СГ>2) Нельзя распечатать на принтере документ обратно (в зад, так сказать — в чистый лист, и в краску в картиридже).
СГ>3) Поезд уже ушел.

В исходном задании не было сказано про удаленный банк: Re[7]: Что вы предлагаете на замену эксепшенов?
Автор: Sinclair
Дата: 22.11.05
.

СГ>Чтобы был возможен откат, базис примитивных операций должен быть другой, ибо операция "Начислить" — необратима.


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


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

СГ>Здравствуйте, Cyberax, Вы писали:


>>> Тогда надо использовать другой базис примитивных операций. Ибо в

>>> выбранном базисе состоящей всего из одной примитивной операции
>>> "Начислить":
>>> PROCEDURE (this: СчётВУдалённомБанке) Начислить* (сумма: Деньги; откого: ОтКого; VAR err: Errors.List): BOOLEAN, NEW, ABSTRACT;
>>> после свершившегося начисления, откат назад невозможен.

C>>Это почему же?


СГ>Деньги уже начисленные на счёт в другом банке??????????

СГ>По той же самой причине, что:
СГ>1) "Фарш невозможно провернуть назад" (с) С. Лукьяненко.
СГ>2) Нельзя распечатать на принтере документ обратно (в зад, так сказать — в чистый лист, и в краску в картиридже).
СГ>3) Поезд уже ушел.

СГ>Чтобы был возможен откат, базис примитивных операций должен быть другой, ибо операция "Начислить" — необратима.

Обратима.
Операция "начислить" — это транзакция, которая в случае успеха фиксируется (commit), а в случае неудачи откатывается (rollback). Только после фиксации деньги фактически зачислены на счёт. И этот принцип называется ACID (см. предыдущие сообщения) и на нём строится вся банковская система со времён не то что бы изобретения первых ЭВМ, а с ранних времён ростовщичества в доверенностях и записях купли/продажи.
Re[17]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 23.11.05 15:15
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Чтобы был возможен откат, базис примитивных операций должен быть другой, ибо операция "Начислить" — необратима.


Она, может, и необратима, но это не значит, что она всегда завершается успешно. Так вот в случае неудачи состояние обоих счетов (отправителя и получателя) должно остаться в точности таким же, как до начала операции.

Один из возможных сценариев (упрощенный, естественно).

1. Видимая владельцу счета-отправителя сумма уменьшается на величину перевода.
2. Сумма перевода заносится в специальный журнал, ей присваивается статус "ожидание".
3. Отправляется запрос получателю.
4. Принимается подтверждение от получателя о приеме.
5. Сумма списывается со счета.
6. Операция получает статус "выполнена".

На каждом из шагов может произойти что угодно. Например, кто-нибудь оборвал сетевой кабель на одном из серверов на маршруте. Функция, ожидающая ответа, вернет банальный time-out, ничего не говорящий о том, как завершилась операция.

Вот вариант обработки исключений в случае серьезного обрыва связи: подтверждение шлется по телефону/факсу и все обновления данных выполняются вручную на обоих концах линии.
Re[19]: Что вы предлагаете на замену эксепшенов?
От: mrozov  
Дата: 23.11.05 15:17
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, mrozov, Вы писали:


M>>Но главное — да приведите же наконец хоть одну причину, по которой от исключений нужно отказаться.


СГ>Признаюсь, едва ли мне по силам найти хоть одну причину убедившую бы Вас. Впрочем, и Вам тоже едва ли по силам найти серьёзную причину по которой исключения должны быть встроены в язык, а не в библиотеку.


Да, это будет сложно. Но не нужно. Да пускай хоть в подсознание. Хоть тушкой, хоть чучелом — но ехать надо.
Re[18]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 15:22
Оценка:
Здравствуйте, mrozov, Вы писали:

M>А во-вторых, пример надуманный.


1) Вот, не надуманный пример.

Есть диапазон портов: minPort, maxPort (чётные)
использовать из них можно порты начиная от minPort с шагом incPort

minPort, minPort + incPort, minPort + 2*incPort, ... <= maxPort

Создайте сокет и забиндите его на любой из портов в этом диапазоне (но некоторые порты уже могут быть заняты).
Трабл в том, что процедура socket.Bind(this.point) кидает исключение если порт уже занят,
хотя в миллион раз было бы логичнее, чтобы это была булевская функция.
namespace MeraSystems.Net
{
    public sealed class StdSocketFactory: MeraSystems.Net.ISocketFactory
    {
        private readonly System.Net.IPAddress localIP;
        private readonly int minPort, maxPort, incPort, cntPort;
        private readonly System.Net.IPEndPoint point;

        private static int CalculatePortsCount (int min, int max, int inc)
        {
            int count = 0;
            for (int i = min; i <= max; i += inc)
            {
                count++;
            }
            return count;
        }

        public StdSocketFactory (System.Net.IPAddress ThisLocalIP, int ThisMinPort, int ThisMaxPort, int ThisIncPort)
        {
            ASSERT.PRE(ThisLocalIP != null, "{ThisLocalIP is null}");
            if (ThisMinPort % 2 == 1) ThisMinPort++;
            if (ThisMaxPort % 2 == 1) ThisMaxPort--;
            if (ThisIncPort < 1) ThisIncPort = 1;
            ASSERT.PRE(ThisMinPort <= ThisMaxPort, "{ThisMinPort > ThisMaxPort}");
            //  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
            this.localIP = ThisLocalIP;
            this.minPort = ThisMinPort;
            this.maxPort = ThisMaxPort;
            this.incPort = ThisIncPort;
            this.cntPort = CalculatePortsCount(ThisMinPort, ThisMaxPort, ThisIncPort);
            this.point = new System.Net.IPEndPoint(ThisLocalIP, ThisMinPort);
        }

        private void SetNextPort ()
        {
            this.point.Port += this.incPort;
            if (this.point.Port > this.maxPort) this.point.Port = this.minPort;
        }

        private bool TryBindNextPort (System.Net.Sockets.Socket socket)
        {
            bool result = false;
            try
            {
                socket.Bind(this.point); result = true;
            }
            catch
            {
            }
            this.SetNextPort();
            return result;
        }

        public System.Net.Sockets.Socket NewSocket (System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType)
        {
            lock(this)
            {
                System.Net.Sockets.Socket s = new System.Net.Sockets.Socket(this.point.AddressFamily, socketType, protocolType);
                for (int n = 0; n < this.cntPort; n++)
                {
                    if (this.TryBindNextPort(s)) return s;
                }
                return null;
            }
        }
    }
}


Вот она, красавица наша :
        private bool TryBindNextPort (System.Net.Sockets.Socket socket)
        {
            bool result = false;
            try
            {
                socket.Bind(this.point); result = true;
            }
            catch
            {
            }
            this.SetNextPort();
            return result;
        }


2) Следующий ненадуманный пример.
Есть виндос-форма, в поля которой пользователь вводит числа.
Если пользователь ошибся и ввел неправильную строку, то надо ему об этом сообщить.
Но стандартная функция
int System.Int32.Parse (string str)

имеет ошибку в дизайне — она кидает исключенние, приходится либо писать свой парсер чисел (что влом)
либо писать так :
bool TryGetNumber (string str, out int number)
{
  try
  { 
     number = System.Int32.Parse(str);
     return true;
  }
  catch
  {
     number = 0;
     return false;
  }
}
Re[17]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 23.11.05 15:23
Оценка:
Сергей Губанов wrote:

>>> после свершившегося начисления, откат назад невозможен.

> C>Это почему же?
> Деньги *уже начисленные* на счёт в другом банке??????????

Ни одна серьезная система так не работает. Для таких переводов всегда
используется расперделенные транзакции (как они работают объяснять лень
— поищите по словам "distributed transactions" и "two-phase commit").

> Чтобы был возможен откат, базис примитивных операций должен быть

> другой, ибо операция "Начислить" — необратима.

Операция "начислить" — необратима. Однако можно отменить совершенные ей
изменения.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[18]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 15:31
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Один из возможных сценариев (упрощенный, естественно).


P>1. Видимая владельцу счета-отправителя сумма уменьшается на величину перевода.

P>2. Сумма перевода заносится в специальный журнал, ей присваивается статус "ожидание".
P>3. Отправляется запрос получателю.
P>4. Принимается подтверждение от получателя о приеме.
P>5. Сумма списывается со счета.
P>6. Операция получает статус "выполнена".

В том коде который я привёл именно этот сценарий и реализован (в упрощенном варианте конечно).
После этого меня спросили, а что если при выполнении пункта (6) произошла ошибка записи информации в локальный журнал работы — как я буду откатывать всё взад?
Я и говорю, что на момент выполнения пункта (6) деньги уже перечислены (от получателя уже пришло подтверждение о получении им денег — он их уже может быть даже успел истратить ). Так что на шаге (6) взад уже ничего не вернёшь.
Re[18]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 15:38
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Ни одна серьезная система так не работает. Для таких переводов всегда

C>используется расперделенные транзакции (как они работают объяснять лень
C>- поищите по словам "distributed transactions" и "two-phase commit").

Я это прекрасно понимаю.

Однако тут речь не о том как это по настоящему работает,
а о реализации вымышленного механизма денежного перевода
основанного на единственном примитиве "Начислить"
причём без использования exceptions.
Меня просили так сделать — я так и сделал.
Re[18]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 15:41
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Простите. вы вообще имели когда-нибудь дело с платежными системами? Я вот да.


Отродясь не имел. Но мы тут спорим о платежах или об exceptions? Если не нравится пример с платежами, давайте рассмотрим какой-нибудь другой пример, я его берусь написать без использования exceptions.
Re[19]: Что вы предлагаете на замену эксепшенов?
От: iZEN СССР  
Дата: 23.11.05 15:46
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, Privalov, Вы писали:


P>>Один из возможных сценариев (упрощенный, естественно).


P>>1. Видимая владельцу счета-отправителя сумма уменьшается на величину перевода.

P>>2. Сумма перевода заносится в специальный журнал, ей присваивается статус "ожидание".
P>>3. Отправляется запрос получателю.
P>>4. Принимается подтверждение от получателя о приеме.
P>>5. Сумма списывается со счета.
P>>6. Операция получает статус "выполнена".

СГ>В том коде который я привёл именно этот сценарий и реализован (в упрощенном варианте конечно).

СГ>После этого меня спросили, а что если при выполнении пункта (6) произошла ошибка записи информации в локальный журнал работы — как я буду откатывать всё взад?
СГ>Я и говорю, что на момент выполнения пункта (6) деньги уже перечислены (от получателя уже пришло подтверждение о получении им денег — он их уже может быть даже успел истратить ). Так что на шаге (6) взад уже ничего не вернёшь.
Ошибаетесь.
До выполнения п.6 опрерации перечисления не существует в природе. Ни для отправителя, ни тем более для получателя операция не существует — она существует только в воспалённом мозгу компьютера, в котором работают "какие-то" программы. И только после п.6 всем вдруг становится ясно, что "операция по переводу денег совершилась". В этом и суть транзакции.
Re[19]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 23.11.05 15:49
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>В том коде который я привёл именно этот сценарий и реализован (в упрощенном варианте конечно).

СГ>После этого меня спросили, а что если при выполнении пункта (6) произошла ошибка записи информации в локальный журнал работы — как я буду откатывать всё взад?

Этот вопрос разве не был Вами проигнорирован?

СГ>Я и говорю, что на момент выполнения пункта (6) деньги уже перечислены (от получателя уже пришло подтверждение о получении им денег — он их уже может быть даже успел истратить ). Так что на шаге (6) взад уже ничего не вернёшь.


Вернешь, вернешь. До завершения шага 6 переводимая сумма заморожена на обоих счетах. Фактическое начисление/списание происходит только после получения подтверждения об успешном переводе. До этого получатель сумму не увидит, не говоря уже об истратить.
Re[19]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 23.11.05 15:51
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Однако тут речь не о том как это по настоящему работает,

СГ>а о реализации вымышленного механизма денежного перевода
СГ>основанного на единственном примитиве "Начислить"
СГ>причём без использования exceptions.
СГ>Меня просили так сделать — я так и сделал.

Ключевое слово — вымышленный.
Re[20]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 23.11.05 16:01
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Вернешь, вернешь. До завершения шага 6 переводимая сумма заморожена на обоих счетах. Фактическое начисление/списание происходит только после получения подтверждения об успешном переводе. До этого получатель сумму не увидит, не говоря уже об истратить.


Значит Вы пользуетесь другим базисом примитивных операций. А вот в базисе состоящем всего из одной примитивной операции "Начислить" — откат после начисления невозможен. О чём я в сотый раз уже повторил. И exceptions тут совсем не при чём. Ёмоё сколько можно, всё надоело, хватит....
Re[7]: Что вы предлагаете на замену эксепшенов?
От: Дарней Россия  
Дата: 23.11.05 17:27
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Несложно и недолго начиная с VC++ 6 SP4 или GCC 2.95. Вы используете что-нибудь более старое?


это давно уже было, да и компилятор — специально заточенная под девайс версия GCC
в общем, с шаблонами там проблематично было
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[19]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 23.11.05 18:51
Оценка:
Сергей Губанов wrote:

> M>Простите. вы вообще имели когда-нибудь дело с платежными системами?

> Я вот да.
> Отродясь не имел. Но мы тут спорим о платежах или об exceptions? Если
> не нравится пример с платежами, давайте рассмотрим какой-нибудь другой
> пример, я его берусь написать без использования exceptions.

На самом деле, пример с платежами — очень хороший. Он заодно помогает
проиллюстрировать понятие транзакций и их симбиоз с исключениями.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[20]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 07:44
Оценка:
Здравствуйте, CrystaX, Вы писали:

CX>Вот такой вот практический опыт работы с исключениями, реализованными на уровне библиотеки.


Посмотрите пожалуйста следующую статью (потрясающую воображение):

http://www.oberon2005.ru/paper/p_ex.pdf

Zero-Overhead Exception Handling Using Metaprogramming
Markus Hof, Hanspeter Mössenböck, Peter Pirkelbauer

We present a novel approach to exception handling which is based on metaprogramming.
Our mechanism does not require language support, imposes no run time overhead to errorfree
programs, and is easy to implement. Exception handlers are implemented as ordinary
procedures. When an exception occurs, the corresponding handler is searched dynamically
using the type of the exception as a search criterion. Our implementation was done in the
Oberon System but it could be ported to most other systems that support metaprogramming.

Re[20]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 07:47
Оценка:
Здравствуйте, Alvin, Вы писали:

A>Как насчет использования bool System.Int32.TryParse(string s, out int result) в тех случаях, когда исключение не желательно?


В библиотеке .NET Framework version 1.1. такой процедуры нет. Во второй версии значит появилась? Хорошо, очень оперативно работают, молодцы.
Re[20]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 07:51
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>На самом деле, пример с платежами — очень хороший. Он заодно помогает проиллюстрировать понятие транзакций и их симбиоз с исключениями.


Так покажите код. Я на него посмотрю, и по образу и подобию перепишу его без exceptions. Ведь вся проблема (с моей стороны) в предметной области, а не в кодировании.
Re[14]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 08:23
Оценка:
Здравствуйте, Sinclair, Вы писали:

S> механизма доставки информации об ошибке есть великое благо


Я начинаю понимать причину того почему Вы меня не понимаете.
Вы думаете, что если в языке (возьмем тот же Oberon или Component Pascal) нет встроенного (на синтаксическом уровне) транспорта доставки информации об ошибке, то этого транспорта нет вообще и в системах (возьмём тот же BlackBox). Однако, механизм доставки сообщения об ошибке есть всегда. Есть транспорт — просто он синтаксически не выражаем. (В конце-концов это просто некая архитектурная особенность процессора, а не синтаксическая особенность языка.) Вопрос лишь в том — куда доставляется эта информация? Кто ловит исключение? Её ловит сама система. Команда под BlackBox создав исключительную ситуацию (например по ASSERT, или NIL dereference, или деление на 0, и т.д.) не убивает саму систему BlackBox, а происходит лишь останов выполнения команды породившей исключение. BlackBox ловит порождённое исключение.

Программируя на языке Component Pascal в системе BlackBox я могу порождать исключительные ситуации сам. Только для этого я использую вовсе не аналог вот такого кода:
if ( ! condition) throw new Exception("error");

а вот такой код:
ASSERT(condition, err_no);

ASSERT — это служебное слово языка (ASSERT-ы Оберона отличаются от ассертов в других языках тем, что не игнорируются в релиз-версии). Порождённое таким образом исключение ловится system trap-ом которым снабжается каждая команда. Так что выполнение команды прекращается.

Короче, в Component Pascal в системе BlackBox исключения есть (равно как они есть всегда в силу архитектуры x86), просто их нет на синтаксическом уровне языка.


S> Я не могу себе представить библиотеку, способную предоставить все необходимые свойства без модификации языка. В лучшем случае это будут корявые костыли, которые лишь слегка замажут все эти наслоения.


Вы сможете это себе представить прочитав это:
http://www.rsdn.ru/Forum/Message.aspx?mid=1503575&amp;only=1
Автор: Сергей Губанов
Дата: 24.11.05

Оберон как Оберон, только с exceptions, а в самом языке не добавлено ни одного служебного слова.
Re[8]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 08:41
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Не очень хотелось высказываться здесь, но, похоже, у нас разные подходы к получению значения 5 процентов.


Пять процентов головного мозга — это конечно шутка. Понимать надо не в биологическом смысле, а в переносном
Re[21]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 24.11.05 08:43
Оценка:
Сергей Губанов wrote:

> CX>Вот такой вот *практический* опыт работы с исключениями,

> реализованными на уровне библиотеки.
> Посмотрите пожалуйста следующую статью (потрясающую воображение):
> http://www.oberon2005.ru/paper/p_ex.pdf
> *Zero-Overhead Exception Handling Using Metaprogramming*

И что тут необычного? Особенно если учесть, что оно не будет работать в
модульных системах.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[21]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 24.11.05 08:55
Оценка:
Сергей Губанов wrote:

> C>На самом деле, пример с платежами — очень хороший. Он заодно

> помогает проиллюстрировать понятие транзакций и их симбиоз с исключениями.
> Так покажите код.

Вариант 1 (с транзакциями):
void transfer_money(Account *from, Account *to, Money money)
{
    transaction transaction(...); //Создаем транзакцию
   
    //Вводим объекты в контекст транзакции
    LockedAccount *from_locked=from->enroll(transaction);
    LockedAccount *to_locked=to->enroll(transaction);

    //Перечисляем деньги
    Transfer  t(from_locked->get_money(money));
    to_locked->add_money(t.get_money());

    //Коммитим транзакцию
    transaction.commit();
}


Или второй вариант, без транзакций и на Java для простоты:
void transfer_money(Account from, Account to, Money money)
{
    Transfer t=from.get_money();
    try
    {
       to.add_money(t);
       t=null;
    } finally
    {
       if (t!=null) t.cancel_transfer();
    }
}


--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[21]: Что вы предлагаете на замену эксепшенов?
От: CrystaX Россия https://crystax.me/
Дата: 24.11.05 09:44
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

CX>>Вот такой вот практический опыт работы с исключениями, реализованными на уровне библиотеки.


ANS>Нужно добавить "... в С++".

ANS>Никто и не сомневался

Да причем тут C++? Если бы это был стандартный C++, проблем бы не было. Но в том-то и беда, что это "улучшенный" C++. Вот так бывает, когда "улучшают", не подумав толком.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[22]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 10:36
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>И что тут необычного?


Необычно то, что:
1) Zero-overhead;
2) не требуется вносить изменения в синтаксис языка Оберон.

C>Особенно если учесть, что оно не будет работать в модульных системах.


Так ведь уже работает:

...Our implementation was done in the Oberon System...

В первую очередь Zero-Overhead Exception Handling было реализовано как раз в модульной системе!
Re[9]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 24.11.05 10:36
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

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


Тогда вопрос: сколько процентов головного мозга приходится напрягать физику-теоретику в повседневной деятельности? В каком угодно смысле. Просто для сравнения.
Re[23]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 24.11.05 10:52
Оценка:
Сергей Губанов wrote:

> C>Особенно если учесть, что оно не будет работать в модульных системах.

> Так ведь уже работает:
> ...Our implementation was done in the *Oberon System*...
> В первую очередь Zero-Overhead Exception Handling было реализовано как
> раз в модульной системе!

Нет, Rider должен видеть полный код моулей для своей работы.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[18]: Что вы предлагаете на замену эксепшенов?
От: srggal Украина  
Дата: 24.11.05 11:39
Оценка:
Здравствуйте, Mamut, Вы писали:


M>В процессе эксплуатации оказалось, что ХМЛ в 99% случаев приходит валидный (так как я сам его и отсылаю ). Вопрос. Нафига мне там столько if-ов? Когда документ начинает расти, код читать становится неприятно.


Дык и зачем сразу использовать исключения ????

Все гараздо проще

M>
M>void displayReservationCommand::execute()
M>{
M>    QDomDocument xmlDoc;
M>    xmlDoc.setContent(_params["data"]);
    
M>//    try{
M>        QDomElement el = xmlDoc.documentElement();
M>        el = el.firstChild().toElement();
        
M>        QString str;
M>        QTextStream ts(str, IO_WriteOnly);
M>        el.save(ts, 0);
        
M>        QString attr = el.attribute("guid", "-1");
M>        iqAdrReservationApplicationForm::displayReservation(attr, str);
        
/*
M>    }catch(... /*на самом деле здесь надо что-нить типа XMLTagError, но мне все равно.*/){
M>        return false; 
M>    }

M>    return true;
*/
M>}
M>


И тогда все свалится в каком-то другом месте, неважно в каком потому как информация о месте и характере ошибки не важна Автору топика.

Кстати, подобный подход, исходя из предпосылок ГОРАЗДО эффективней исключений, функция без них будет работать быстрей и что немаловажно, в 98% случаев — правильно.



Ещё одна мысль здесь
Автор: srggal
Дата: 24.11.05
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[24]: Zero-Overhead Exception Handling Using Metaprogrammi
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 11:42
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Нет, Rider должен видеть полный код моулей для своей работы.


Так ведь подразумевается наличие возможности Metaprogramming-а, т.е. всё что ему нужно видеть он видит.
Re[22]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 11:51
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Вариант 1 (с транзакциями):

C>
void transfer_money(Account *from, Account *to, Money money)
{
    transaction transaction(...); //Создаем транзакцию
   
    //Вводим объекты в контекст транзакции
    LockedAccount *from_locked=from->enroll(transaction);
    LockedAccount *to_locked=to->enroll(transaction);

    //Перечисляем деньги
    Transfer  t(from_locked->get_money(money));
    to_locked->add_money(t.get_money());

    //Коммитим транзакцию
    transaction.commit();
}


Ну, значит, вот так:
PROCEDURE TransferMoney (src, dst: Account; m: Money; log: Log): BOOLEAN;
  VAR r: BOOLEAN; t: Transaction; s, d: LockedAccount; x: Transfer;

   PROCEDURE BeginTransfer;
   BEGIN (*...*)
   END BeginTransfer;

   PROCEDURE GetMoney (): BOOLEAN;
   BEGIN (*...*)
   END GetMoney;

   PROCEDURE AddMoney (): BOOLEAN;
   BEGIN (*...*)
   END AddMoney;

   PROCEDURE Enroll (a: Account; OUT b: LockedAccount): BOOLEAN;
   BEGIN (*...*)
   END Enroll;

   PROCEDURE Commit (): BOOLEAN;
   BEGIN (*...*)
   END Commit;

   PROCEDURE EndTransfer;
   BEGIN (*...*)
   END EndTransfer;

BEGIN r := (src # NIL) & (dst # NIL) & (m > 0);
  IF r THEN
    BeginTransfer;
    r := Enroll(src, s) & Enroll(dst, d) & GetMoney() & AddMoney() & Commit();
    EndTransfer
  END;
  RETURN r
END TransferMoney;
Re[21]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 24.11.05 11:52
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Посмотрите пожалуйста следующую статью (потрясающую воображение):


For system exceptions, which are triggered automatically, the system will generate a call to the
procedure Raise as if they were user exceptions.


Не совсем понял, system это что ? Операционная стистема ? Значит ли это, что операционная система должна знать о каждой библиотечной схеме исключений, что-бы вызвать соответствующий Rise ?
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re: Вот подумалось
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 11:55
Оценка:
Здравствуйте, srggal, Вы писали:

S>

S>Сколько return должно быть в функции? Один или несколько ?
S>


А что здесь есть кто-то утверждающий полезность единственности точки выхода из процедуры?
Re[2]: Вот подумалось
От: mrozov  
Дата: 24.11.05 12:00
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, srggal, Вы писали:


S>>

S>>Сколько return должно быть в функции? Один или несколько ?
S>>


СГ>А что здесь есть кто-то утверждающий полезность единственности точки выхода из процедуры?


Ну кто-то утверждающий бесполезность exception-ов же нашелся
А вообще-то множественные точки выхода — это оверхед + мешает некоторым приемам нормально работать.
Re[2]: Вот подумалось
От: srggal Украина  
Дата: 24.11.05 12:00
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

S>>

S>>Сколько return должно быть в функции? Один или несколько ?
S>>


СГ>А что здесь есть кто-то утверждающий полезность единственности точки выхода из процедуры?


Речь идет о том, что

полезность единственности точки выхода из процедуры


Впрос еще более философский чем принятие/непринятие исключений
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[22]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 12:01
Оценка:
Здравствуйте, Sergey J. A., Вы писали:

SJA>Не совсем понял, system это что ? Операционная стистема ? Значит ли это, что операционная система должна знать о каждой библиотечной схеме исключений, что-бы вызвать соответствующий Rise ?


Имеется в виду run-time system. Скажем, run-time system-а языка Java или run-time system-а .Net или run-time system-а Oberon... Run-time system может работать как поверх операционной системы так и наоборот.
Re[11]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 24.11.05 12:16
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

P>>Тогда вопрос: сколько процентов головного мозга приходится напрягать физику-теоретику в повседневной деятельности? В каком угодно смысле. Просто для сравнения.


СГ> кандидату: 100% от нормы обычного человека, доктору: 500% — 1000% от нормы обычного человека академику, ну скажем, 20'000% от нормы....


Отлично. А сколько программисту от нормы обычного человека? А, кстати, обычному человеку?
Re[23]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 24.11.05 12:16
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

SJA>>Не совсем понял, system это что ? Операционная стистема ? Значит ли это, что операционная система должна знать о каждой библиотечной схеме исключений, что-бы вызвать соответствующий Rise ?


СГ>Имеется в виду run-time system. Скажем, run-time system-а языка Java или run-time system-а .Net или run-time system-а Oberon... Run-time system может работать как поверх операционной системы так и наоборот.


Ну значит обработка исключений должна быть встроена в рантайм (чтоб он знал как транслировать системные исключения), не в отдельную библиотеку ? Я так понял ?
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[19]: Что вы предлагаете на замену эксепшенов?
От: Mamut Швеция http://dmitriid.com
Дата: 24.11.05 13:38
Оценка:
S>Дык и зачем сразу использовать исключения ????
S>Все гараздо проще

[поскипано]

S>И тогда все свалится в каком-то другом месте, неважно в каком потому как информация о месте и характере ошибки не важна Автору топика.


S>Кстати, подобный подход, исходя из предпосылок ГОРАЗДО эффективней исключений, функция без них будет работать быстрей и что немаловажно, в 98% случаев — правильно.


S>


Это тоже мысля. Просто у меня метод execute должон был возвращать код ошибки (кстати, в приведенном коде у меня ошибка — возвращается не код, а true/false ) если что не так — требование общего интерфейса iqCommand.

А так — да, можно было

S> Ещё одна мысль здесь
Автор: srggal
Дата: 24.11.05


ыыыы Хотя, по Дейкстре, выход должен быть только один. "Из любой ситуации есть выход. В крайнем случае, можно выйти из себя" (с) не помню кто
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re[24]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 24.11.05 14:54
Оценка:
Здравствуйте, Sergey J. A., Вы писали:

SJA>Ну значит обработка исключений должна быть встроена в рантайм (чтоб он знал как транслировать системные исключения), не в отдельную библиотеку ? Я так понял ?


Предлагаемая в статье библиотека ловли исключений расширяет среду времени исполнения. Так что, новая (расширенная) среда исполнения теперь умеет вызывать пользовательские обработчики исключений. Вообще, среда времени исполнения по любому умеет ловить системные (на машинном уровне) исключения не зависимо от того предоставляет ли она эту услугу тем программам которые поверх неё работают. То есть раньше она поймав исключение обрабатывала его сама, а теперь, благодаря библиотеке, вызывает пользовательские обработчики.
Re[25]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 24.11.05 16:01
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Предлагаемая в статье библиотека ловли исключений расширяет среду времени исполнения. Так что, новая (расширенная) среда исполнения теперь умеет вызывать пользовательские обработчики исключений. Вообще, среда времени исполнения по любому умеет ловить системные (на машинном уровне) исключения не зависимо от того предоставляет ли она эту услугу тем программам которые поверх неё работают. То есть раньше она поймав исключение обрабатывала его сама, а теперь, благодаря библиотеке, вызывает пользовательские обработчики.


Ну вот и отлично. В рантайме поддержка исключений, а в язык введём синтаксические конструкции для удобства и что бы не было (подумайте только !!!) синтаксического оверхеда.

По сути, чем различается использование ф-ий рантайма и синтаксических конструкция языка ?
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[18]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.11.05 10:49
Оценка:
Здравствуйте, Mamut, Вы писали:

M>>>Исключения — это стандартный и универсальный механизм, с помощью которого код может делегировать принятие решений коду вызывающему данный. Неважно, о чем мы говорим — о модуле, функции или трех строчках кода — это все равно так.


E>>Причем не важно, сигнализирует ли исключение об ошибке, исключительной ситуации или же исключения используются для реализации логики (бывают и такие ситуации, когда исключения удобнее чем if/elseif/else или switch/case).


M>Яркий пример — разбор ХМЛя многими библиотеками. Обычно достаточно знать, что ХМЛ невалидный и сразу завершить работу

M>В процессе эксплуатации оказалось, что ХМЛ в 99% случаев приходит валидный (так как я сам его и отсылаю ). Вопрос. Нафига мне там столько if-ов? Когда документ начинает расти, код читать становится неприятно.

Так то же можно, но я подразумевал другой вариант.
Вот попробую пофантазировать. Пусть, к примеру, есть функция для лексического анализа, которая возвращает токены CHAR, INTEGER, REAL, STRING и т.д. С некоторыми токенами должны быть связаны данные. Скажем, с CHAR -- символ, с INTEGER и REAL -- числовое значение, с STRING -- значение строки и т.д. Можно сделать это без исключений с помощью полиморфных классов:
class Token { public: int token() const = 0; ... };
class Char_Token : public Token { ... };
class Integer_Token : public Token { ... };
...

std::auto_ptr< Token >
get_token() { ... }

void
process()
    {
        while( true )
            {
                std::auto_ptr< Token > t = get_token();
                if( Char_Token::id == t->token() )
                    process_char( dynamic_cast< const Char_Token & >( *t ) );
                else if( Integer_Token::id == t->token() )
                    process_integer( dynamic_cast< const Integer_Token & >( *t ) );
                ...
            }
    }


А можно сделать так, чтобы get_token порождал исключения, где тип исключения был бы типом токена:
class Token : public std::exception { ... };
class Char_Token : public Token { ... };
class Integer_Token : public Token { ... };
...

void
get_token() { ... }

void
process()
    {
        while( true )
            {
                try { get_token(); }
                catch( const Char_Token & t ) { process_char( t ); }
                catch( const Integer_Token & t ) { process_integer( t ); }
                ...
            }
    }


Disclaimer. Сам именно таких приемов никогда не применял, но по жизни пару раз сталкивался с моментами, когда исключение выбрасывалось для изменения логики работы программы.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Что вы предлагаете на замену эксепшенов?
От: Bigger Российская Империя  
Дата: 25.11.05 11:54
Оценка:
Здравствуйте, eao197, Вы писали:
skip

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


А вот это не есть хорошо, мухи от котлет должны быть отдельно, логика работы и логика обработки ошибок не одно и тоже.

Программист — это шаман..., подарите бубен!
Re[18]: Что вы предлагаете на замену эксепшенов?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.11.05 12:22
Оценка:
Здравствуйте, Nickolay Ch, Вы писали:

NC>К Вашему сведению, забор из if только усложняет чтение программы, возникает мешанина кода обрабатывающего ошибки, и кода логики.

NC>Уже наверное писали(тут писали много и правильно), что исключения кроме всего прочего, позволяют локализовать обработку ошибок в одном месте.

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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Вот подумалось
От: IT Россия linq2db.com
Дата: 25.11.05 14:22
Оценка:
Здравствуйте, reductor, Вы писали:

СГ>>А что здесь есть кто-то утверждающий полезность единственности точки выхода из процедуры?


R>Ничего не хочу сказать ни про кого плохого, но я возьмусь утверждать, что несколько точек выхода — это хуже, чем один.

R>Во всех случаях, когда этого можно избежать.

Почему? Можно аргументировать?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: error is not an exception
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.11.05 15:15
Оценка:
Здравствуйте, IT, Вы писали:

В>>То есть, мы хотели изменить Y-координату каретки, но также изменилась и X-координата — это не ошибка, это исключительная ситуация.


IT>Это называется строить логику работы приложения на исключениях. Я даже не знаю что хуже, использовать коды возврата или вот так на лево и на право швыряться исключениями.


Если налево или направо, то, разумеется, исключения гораздо хуже.
А если в одном-двух местах и одним-двумя исключениями, то может быть и лучше.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: error is not an exception
От: Глеб Алексеев  
Дата: 25.11.05 15:43
Оценка:
Здравствуйте, eao197, Вы писали:

E>Если налево или направо, то, разумеется, исключения гораздо хуже.

E>А если в одном-двух местах и одним-двумя исключениями, то может быть и лучше.

Возвращаясь к исходному примеру, верхняя строчка будет короче в половине случаев, какое же это исключение?

Использовать исключения не для обработки ошибок — это совершенно исключительная ситуация, должна продумываться и документироваться очень тщательно.
Пример из буста:
http://boost.org/libs/graph/doc/faq.html

# How do I perform an early exit from an algorithm such as BFS?

Create a visitor that throws an exception when you want to cut off the search, then put your call to breadth_first_search inside of an appropriate try/catch block. This strikes many programmers as a misuse of exceptions, however, much thought was put into the decision to have exceptions has the preferred way to exit early. See boost email discussions for more details.

... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[3]: Вот подумалось
От: Глеб Алексеев  
Дата: 25.11.05 15:46
Оценка:
Здравствуйте, reductor, Вы писали:

R>Ничего не хочу сказать ни про кого плохого, но я возьмусь утверждать, что несколько точек выхода — это хуже, чем один.

R>Во всех случаях, когда этого можно избежать.
Избежать-то всегда можно. Вот и избегают некоторые фанатичные последователи этого правила, выходя из цикла 3-го уровня вложенности с помощью булевских флагов или даже бросая исключения .
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[6]: error is not an exception
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.11.05 17:23
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Возвращаясь к исходному примеру, верхняя строчка будет короче в половине случаев, какое же это исключение?


ГА>Использовать исключения не для обработки ошибок — это совершенно исключительная ситуация, должна продумываться и документироваться очень тщательно.


Не спорю. Но я здесь и сам примеры приводил:
Re[18]: Что вы предлагаете на замену эксепшенов?
Автор: eao197
Дата: 25.11.05
(это гипотетический пример),
Re[20]: Что вы предлагаете на замену эксепшенов?
Автор: eao197
Дата: 25.11.05
(это из реальной жизни, хотя и схематично, а не точно).
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[21]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 25.11.05 18:05
Оценка:
Здравствуйте, eao197, Вы писали:

E>Ситуации, когда порождаются too_much_trx_t и repeated_trx_t -- это не ошибки, просто это исключительные ситуации для обычной обработки транзакций. Случаются они редко.


Не ошибки ? Ну, в таком случае отказ записи файла из за недостаточности места тоже не ошибка, а "исключительная ситуация для обычной обработки" файлов.

Сдаётся мне это вполне ошибки.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[4]: Вот подумалось
От: reductor  
Дата: 26.11.05 03:57
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА>Здравствуйте, reductor, Вы писали:


R>>Ничего не хочу сказать ни про кого плохого, но я возьмусь утверждать, что несколько точек выхода — это хуже, чем один.

R>>Во всех случаях, когда этого можно избежать.
ГА>Избежать-то всегда можно. Вот и избегают некоторые фанатичные последователи этого правила, выходя из цикла 3-го уровня вложенности с помощью булевских флагов или даже бросая исключения .

Да-да, исключения — это кошмар. Да и return — для слабаков. Лучше вычисляемое фортрановское GOTO.
Чтобы ни одна тварь не поняла, что происходит.

Если чуть серьезнее, то логика — это штука немного формальная. Желание джампнуть куда-нибудь (частным случаем чего кроме GOTO является и множественный return), и сделать поведение программы непредсказуемым, это не от большого понимания того, что сам делаешь.
А еще — это не религия и понятие "фанатизм" к ней не применимо. Люди или могут обосновать свой вывод и выбор или нет.

На всякий случай заранее и воизбежание бессмысленных еще на 500 сообщений флеймов на эту тему хочу сказать, что
а) осознаю в некоторых случаях необходимость того же GOTO (в очень низкоуровневом коде на, например, Си или коде на плохо спроектированном языке).
б) в подавляющем большинстве прикладных случаев, что я видел (а это много), множественный выход был обусловлен или раздолбайством и нежеланием думать и отвечать за то, что делаешь или плохим пониманием проблемы и соответственно жутким дизайном с расчетом на последующий рефакторинг.

Что не отменяет, еще раз повторюсь варианта, где это может потребоваться. Правда встречается такое очень редко.
Re[4]: Вот подумалось
От: reductor  
Дата: 26.11.05 04:27
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, reductor, Вы писали:


СГ>>>А что здесь есть кто-то утверждающий полезность единственности точки выхода из процедуры?


R>>Ничего не хочу сказать ни про кого плохого, но я возьмусь утверждать, что несколько точек выхода — это хуже, чем один.

R>>Во всех случаях, когда этого можно избежать.

IT>Почему? Можно аргументировать?


Потому что эти вещи очень сложно или вообще не поддаются анализу.
Потому что усложняют отладку, багов при этом попрождая больше.
Сильно усложняют понимание того, что программа делает.
Компилятору такое сложно или вообще невозможно оптимизировать.
Re[6]: Вот подумалось
От: IT Россия linq2db.com
Дата: 26.11.05 04:32
Оценка:
Здравствуйте, reductor, Вы писали:

R>Хочу ссылки, выкладки и доказательства.


Во-первых, calm down, во-вторых, аргументы я попросил
Автор: IT
Дата: 25.11.05
предоставить первый.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: Вот подумалось
От: IT Россия linq2db.com
Дата: 26.11.05 04:36
Оценка:
Здравствуйте, reductor, Вы писали:

IT>>Почему? Можно аргументировать?


R>Потому что эти вещи очень сложно или вообще не поддаются анализу.

R>Потому что усложняют отладку, багов при этом попрождая больше.
R>Сильно усложняют понимание того, что программа делает.
R>Компилятору такое сложно или вообще невозможно оптимизировать.

Это ты не про плюсы случаем?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: Вот подумалось
От: reductor  
Дата: 26.11.05 04:39
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, reductor, Вы писали:


R>>Хочу ссылки, выкладки и доказательства.


IT>Во-первых, calm down, во-вторых, аргументы я попросил
Автор: IT
Дата: 25.11.05
предоставить первый.



Не поймите меня правильно, но мне казалось, что я это сделал.
И тут и там.
Re[6]: Вот подумалось
От: reductor  
Дата: 26.11.05 05:02
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, reductor, Вы писали:


IT>>>Почему? Можно аргументировать?


R>>Потому что эти вещи очень сложно или вообще не поддаются анализу.

R>>Потому что усложняют отладку, багов при этом попрождая больше.
R>>Сильно усложняют понимание того, что программа делает.
R>>Компилятору такое сложно или вообще невозможно оптимизировать.

IT>Это ты не про плюсы случаем?


про HTML
Re[23]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 26.11.05 11:42
Оценка:
Здравствуйте, eao197, Вы писали:

E>В некоторых ситуациях это может быть совсем не ошибка. Например, в системах со сборкой мусора недостаток памяти для размещения нового объекта -- это еще не ошибка, а повод к запуску GC.

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

E> И только если после работы GC памяти не окажется, то это становится ошибкой.

Да, эта исключительная ситуация, и должна порождать исключение, что-бы верхние уровни (тут неизвесно кто конкретно) могли принять какое-либо решение — убить программу, сохранить дамп, спросить пользователя ...

E>Так же и с файлами.

Что то-же ? Не совсем понял...
С файлами представляю это так:
Если нет места на диске, но алгоритм расчитан так, что ищет место на других дисках и пробует сохранится туда — исключение не требуется (всё обрабатывается на одном уровне). Если уже нигде места нет — бросаем исключение — пусть кто знает обрабатывает.

Отсюда моё ИМХО: Исключение нужно бросать в том случае, если на данном логическом уровне (в данном модуле) неизвестен алгоритм работы с некоторой ситуацией. Которая и является исключительной на данном уровне.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re: Что вы предлагаете на замену эксепшенов?
От: vdimas Россия  
Дата: 26.11.05 12:51
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

На самом деле, применительно к доводам использования exception используется другое разделение:
1. Ошибка обрабатывается там же обнаруживается, или есть возможность построить иерархию обслуживания ошибочных ситуаций
2. в случае обработки ошибки прямо в месте обнаружения, так же анализируется возможность игнорирования ошибки, структурирование программы (if после каждой строки неудобен), ожидаемая частота ошибочных ситуаций (т.е. является ли ситуация "штатной" или действительно исключительной).
3. Кодами ошибок очень трудно централизовано управлять (знаю о чем говорю, науправлялись достаточно кодом HRESULT в COM-системе из около 50 проектов), иерархии исключений могут быть совершенно независимы или наоборот, зависимы при необходимости.
Re[24]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 26.11.05 13:47
Оценка:
Sergey J. A. wrote:

> Именно. Это не ошибка, а часть алгоритма. Совершенно точно извесно как

> она будет обрабатыватся, причём самим сборщиком мусора. Поэтому нет
> никакой нужды передавать эту ситуацию в верхние уровни. Следовательно
> это и не должно считатся исключительной ситуацией и не должно вызывать
> исключение.

Да, напомните мне, плиз, почему в Java/C# есть OutOfMemoryException

Кстати, даже с GC вполне может быть, что памяти просто не хватает
физически (то есть она занята живыми объектами, а не мусором). Тогда
исключение по OOM — вполне логично, так как приложение в ответ на него
может удалить часть данных (почистить кэши, например) и освободить
достаточно памяти для дальнейшей работы.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[8]: Вот подумалось
От: IT Россия linq2db.com
Дата: 26.11.05 14:58
Оценка:
Здравствуйте, reductor, Вы писали:

IT>>Во-первых, calm down, во-вторых, аргументы я попросил
Автор: IT
Дата: 25.11.05
предоставить первый.


R>Не поймите меня правильно, но мне казалось, что я это сделал.

R>И тут и там.

Сделал, на секунд позже чем я здесь ответил. Ну да фиг с ним.

В общем, как я понял, ты очень сильно переживаешь не перенапрягуться ли компиляторы Не поверишь, но мне это по барабану. Пусть напрягаются, это их работа. Тем более что в том же C# return — это банальный jmp в конец метода, никаких деструкторов раскручивать не надо. К тому же, проблемы о которых ты говоришь возникают не только при return, есть ещё break, continue, try/cathc/finally. От этого всего тоже надо отказаться?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[9]: error is not an exception
От: Cyberax Марс  
Дата: 26.11.05 16:02
Оценка:
IT wrote:

> Вторая. Современные средства отладки сегодня позволяют практически

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

Используйте assert'ы

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[4]: Вот подумалось
От: Ракот  
Дата: 26.11.05 17:23
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, reductor, Вы писали:


СГ>>>А что здесь есть кто-то утверждающий полезность единственности точки выхода из процедуры?


R>>Ничего не хочу сказать ни про кого плохого, но я возьмусь утверждать, что несколько точек выхода — это хуже, чем один.

R>>Во всех случаях, когда этого можно избежать.

IT>Почему? Можно аргументировать?


Плодятся временные переменные. Особенно, когда размыты логические границы метода, т.е. действие метода можно разбить на несколько отдельных. Мне нужно получить лишь информацию под номером 0, но компилятор вежливо просит создать переменную для получения и информации под номером 1.
Re[10]: error is not an exception
От: IT Россия linq2db.com
Дата: 26.11.05 18:44
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Используйте assert'ы


Как assert'ы помогут мне избавиться от логики на ексепшинах?
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: Вот подумалось
От: IT Россия linq2db.com
Дата: 26.11.05 18:46
Оценка:
Здравствуйте, Ракот, Вы писали:

Р>Плодятся временные переменные. Особенно, когда размыты логические границы метода, т.е. действие метода можно разбить на несколько отдельных. Мне нужно получить лишь информацию под номером 0, но компилятор вежливо просит создать переменную для получения и информации под номером 1.


Избавиться от лишних локальных переменных — задача оптимизатора.
Если нам не помогут, то мы тоже никого не пощадим.
Re[11]: error is not an exception
От: Cyberax Марс  
Дата: 26.11.05 19:07
Оценка:
IT wrote:

> C>Используйте assert'ы

> Как assert'ы помогут мне избавиться от логики на ексепшинах?

Для отладки их используйте, а не исключения

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[12]: error is not an exception
От: IT Россия linq2db.com
Дата: 26.11.05 19:19
Оценка:
Здравствуйте, Cyberax, Вы писали:

>> Как assert'ы помогут мне избавиться от логики на ексепшинах?


C>Для отладки их используйте, а не исключения


OK, поставим вопрос по другому. Как они мне помогут локализовать место ошибки?
Если нам не помогут, то мы тоже никого не пощадим.
Re[13]: error is not an exception
От: Cyberax Марс  
Дата: 26.11.05 19:42
Оценка:
IT wrote:

>>> Как assert'ы помогут мне избавиться от логики на ексепшинах?

> C>Для отладки их используйте, а не исключения
> OK, поставим вопрос по другому. Как они мне помогут локализовать место
> ошибки?

Вообще-то, когда срабатывает assert, то у меня появляется окошечко
"Assertion failed in file .... line ..." с предложением запустить
отладчик. Если работает под отладкой — сразу вываливается в отладчик.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[6]: Вот подумалось
От: Ракот  
Дата: 26.11.05 19:55
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, Ракот, Вы писали:


Р>>Плодятся временные переменные. Особенно, когда размыты логические границы метода, т.е. действие метода можно разбить на несколько отдельных. Мне нужно получить лишь информацию под номером 0, но компилятор вежливо просит создать переменную для получения и информации под номером 1.


IT>Избавиться от лишних локальных переменных — задача оптимизатора.


Все, конечно, верно. Только в коде это не уберешь — теряется чистота.
Re[14]: error is not an exception
От: IT Россия linq2db.com
Дата: 26.11.05 19:55
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Вообще-то, когда срабатывает assert, то у меня появляется окошечко

C>"Assertion failed in file .... line ..." с предложением запустить
C>отладчик. Если работает под отладкой — сразу вываливается в отладчик.

У меня тоже самое появляется при необработанных исключениях. А вот если их затрайкечить... Насколько мне известно, assert тоже кидает исключение, так что поймать его и придушить нет никаких проблем.
Если нам не помогут, то мы тоже никого не пощадим.
Re[15]: error is not an exception
От: Cyberax Марс  
Дата: 26.11.05 19:59
Оценка:
IT wrote:

> C>Вообще-то, когда срабатывает assert, то у меня появляется окошечко

> C>"Assertion failed in file .... line ..." с предложением запустить
> C>отладчик. Если работает под отладкой — сразу вываливается в отладчик.
> У меня тоже самое появляется при необработанных исключениях. А вот
> если их затрайкечить... Насколько мне известно, assert тоже кидает
> исключение, так что поймать его и придушить нет никаких проблем.

В С++ сработавший assert вызывает функцию DebugBreak, так что поймать ее
сложно будет. Ну а в С# можно поставить, чтобы отладчик срабатывал на
вылетевшее AssertionFailedException. Ну или вызвать DebugBreak через
interop.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[9]: Вот подумалось
От: reductor  
Дата: 27.11.05 10:43
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, reductor, Вы писали:


IT>>>Во-первых, calm down, во-вторых, аргументы я попросил
Автор: IT
Дата: 25.11.05
предоставить первый.


R>>Не поймите меня правильно, но мне казалось, что я это сделал.

R>>И тут и там.

IT>Сделал, на секунд позже чем я здесь ответил. Ну да фиг с ним.


IT>В общем, как я понял, ты очень сильно переживаешь не перенапрягуться ли компиляторы Не поверишь, но мне это по барабану. Пусть напрягаются, это их работа. Тем более что в том же C# return — это банальный jmp в конец метода, никаких деструкторов раскручивать не надо. К тому же, проблемы о которых ты говоришь возникают не только при return, есть ещё break, continue, try/cathc/finally. От этого всего тоже надо отказаться?


Компиляторы конечно пусть выполняют свою работу, но есть все же некоторое соответствие между количеством их работы и нашим пониманием того, что мы делаем. А так же между количеством их работы и умственным напряжением того человека, который будет читать наш код. Функция со множественным выходом изоморфна нескольким с одним. break внутри цикла изоморфен функции с единственным выходом из тела цикла, continue уже становится понятно изоморфен чему, ага? try/catch/finally — это, извините, просто continuation. то есть по сути, это не выход, а _вход_. Понимая это, можно сразу увидеть, где нужно несколько функций, а где нет и потому и несколько return лишние. Понимая это, начинаешь писать код и понятнее и короче, чем писал до того.
И главное — себе любиомому потом время экономишь на отладке.

И отказываться я никого ни от чего не убеждаю. Это занятие бессмысленное.
Re[7]: Вот подумалось
От: reductor  
Дата: 27.11.05 11:17
Оценка:
Здравствуйте, vdimas, Вы писали:

V>for(int i=0; i<arr.size(); i++)

V> if(arr[i]==x)
V> return i;
V>return -1;
V>[/ccode]

V>Очень хорошо всеми понимается


Вы, мне кажется, путаете две близкие вещи.
Посмотрим, вот ваша функция на Haskell, где вообще нет оператора выхода:
contains _ [] = False
contains y (x:xs) | x == y = True
                  | otherwise = contains y xs

1-в-1, То же самое.
А вот функция, которая пытается сделать сразу 10 вещей закрывая дыры в логике преждевременным выходом так легко формальным образом не выразится. Можно делать выводы.

Несколько выходов — это всегда повод к тому, чтобы задать себе вопрос — не создаю ли я тут эмуляцию вложеных функций. И ответить на этот вопрос или утвердительно или отрицательно.
А все остальное уже из этого следует.
Re[7]: Вот подумалось
От: Cyberax Марс  
Дата: 27.11.05 12:58
Оценка:
reductor wrote:

> Я не знаю что такое "нормальные программисты". Тем более что такое

> "все нормальные программисты".
> Я знаю, что такое формальная логика и изоморфизм Карри-Говарда. А так
> же как я могу и как не могу обосновать, что мой модуль выполняет
> именно то, что он него ожидается при всех условиях.

И что? Чем этому мешает break и goto? Прекрасно можно доказывать
кооректность программ и с ними.

> Что касается выхода из циклов по флагам и отсутствия break, то вообще

> не понимаю в чем проблема — что мешает вынести цикл в отдельную
> функцию и выходить исключительно из цикла, делая код более предсказуемым?

Слишком много переменных может потребоваться передавать в виде параметров.

> Я не очень хочу продолжать переливать из пустого в порожнее еще 1000

> писем в мейлбоксе. Если у кого-то есть код и он может показать, что с
> множественным выходом (не путать с выходом из цикла и несколькими
> _условиями_ выхода) будет проще и обосновать и отладить и оно будет
> быстрее работать — прекрасно. А пока что это разговоры в пользу
> бедных. И шарлатанство.

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

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[8]: Вот подумалось
От: reductor  
Дата: 27.11.05 16:06
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>И что? Чем этому мешает break и goto? Прекрасно можно доказывать

C>кооректность программ и с ними.

Можно, но без "прекрасно".
Я даже не хочу повторять за Edsger W. Dijkstra почему так.


>> Что касается выхода из циклов по флагам и отсутствия break, то вообще

>> не понимаю в чем проблема — что мешает вынести цикл в отдельную
>> функцию и выходить исключительно из цикла, делая код более предсказуемым?

C>Слишком много переменных может потребоваться передавать в виде параметров.


Ну наверное может. А может и нет. Или наоборот. О чем вообще мы?

C>Нет уж, сами затеяли спор — сами и показывайте код, который

C>множественный выход делает недоказуемым и вообще отстойным.

Извините, это вы говорите, что у вас есть такой код. Что он есть у меня, я не говорил.
А я такого кода не пишу.

Будем продолжать беседы о том сколько ангелов уместится на острие иголки?
Re[16]: error is not an exception
От: IT Россия linq2db.com
Дата: 27.11.05 16:41
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>В С++ сработавший assert вызывает функцию DebugBreak, так что поймать ее

C>сложно будет.

Not big deal.

#include "stdafx.h"
#include <windows.h>

void main()
{
    __try
    {
        DebugBreak();
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
    }
}


Все asserts идут лесом. Но дело даже не в этом. Ты собираешься на любую возможную ситуацию в программе писать assert? Этак у тебя на 10 строчек кода должно быть 20 asserts.
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: Вот подумалось
От: IT Россия linq2db.com
Дата: 27.11.05 17:51
Оценка:
Здравствуйте, Ракот, Вы писали:

IT>>Избавиться от лишних локальных переменных — задача оптимизатора.


Р>Все, конечно, верно. Только в коде это не уберешь — теряется чистота.


Что-то я начал терять ход мыслей О каких локальных переменных идёт речь?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[19]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 27.11.05 18:11
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>1) Вот, не надуманный пример.

СГ>2) Следующий ненадуманный пример.

Не надо обобщать косяки в реализации конкретных методов криворукими девелоперами на весь механизм исключений. Этак я могу специально для тебя написать какого-нибудь уродца на Обероне, тем самым дав твоим аппонентам в руки очень "весомые" аргументы поносить его налево и направо.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[9]: Вот подумалось
От: Cyberax Марс  
Дата: 27.11.05 18:23
Оценка:
reductor wrote:

> C>И что? Чем этому мешает break и goto? Прекрасно можно доказывать

> C>кооректность программ и с ними.
> Можно, но без "прекрасно".

Замечательно. Теперь рассказать как можно преобразовать AST с multiple
returns в AST с single returns?

> C>Слишком много переменных может потребоваться передавать в виде

> параметров.
> Ну наверное может. А может и нет. Или наоборот. О чем вообще мы?

Не знаю. Кто-то пытается мне зубы заговорить, кажется.

> C>Нет уж, сами затеяли спор — сами и показывайте код, который

> C>множественный выход делает недоказуемым и вообще отстойным.
> Извините, это вы говорите, что у вас есть такой код. Что он есть у
> меня, я не говорил.
> А я такого кода не пишу.

И судите о сложности чтения multiple returns?

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[6]: Вот подумалось
От: GlebZ Россия  
Дата: 27.11.05 19:48
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Нет, это уже религия. Все нормальные программисты уже давно перестали

C>флеймить по поводу GOTO и структурного программирования, так как по
C>нынешним меркам это уже далеко не самый главный вопрос. Все
C>программисты, которых я знаю, думают примерно так: "GOTO это плохо?" —
C>"Плохо". "Структурное программирование хорошо?" — "Да". "Единый return,
C>выход из вложенных циклов по флагам, отсутствие break — оно надо?" — "А
C>нафига?"
Честно говоря кроме структурного программирования есть еще куча стилей где goto не является противоречием. Например — автоматное программирование, на чем он и построен. Или например лисповские continuation.
Что касается множественного выхода, то противоречий я здесь не вижу. В отличие от goto его всегда можно трансформировать в классическую структурную схему.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[17]: error is not an exception
От: GlebZ Россия  
Дата: 27.11.05 19:48
Оценка:
Здравствуйте, IT, Вы писали:

IT>Все asserts идут лесом. Но дело даже не в этом. Ты собираешься на любую возможную ситуацию в программе писать assert? Этак у тебя на 10 строчек кода должно быть 20 asserts.

В некоторых особо жарких местах у меня бывало и такое. И иногда даже помогало.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[18]: error is not an exception
От: IT Россия linq2db.com
Дата: 27.11.05 19:58
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>В некоторых особо жарких местах у меня бывало и такое. И иногда даже помогало.


На плюсах и я таким частенько грешил На шарпе пока как-то надобности не было.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[19]: error is not an exception
От: GlebZ Россия  
Дата: 27.11.05 20:13
Оценка:
Здравствуйте, IT, Вы писали:

IT>На плюсах и я таким частенько грешил На шарпе пока как-то надобности не было.

При отладке windows сервисов вставлял в код даже не assert, а прямой вызов дебаггера.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[23]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 27.11.05 21:12
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Ну, значит, вот так:


А теперь добавь сюда какую-нибудь вменяемую информацию об ошибке, сделай так чтобы TransferMoney возвращала новый баланс счёта и протащи это через 4-5 вызовов.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[12]: Вот подумалось
От: IT Россия linq2db.com
Дата: 27.11.05 22:23
Оценка:
Здравствуйте, reductor, Вы писали:

R>Ок. Только сразу предупреждаю, я вообще не знаю C# (как и .NET), потому пришлось msdn почитать.


Совсем не плохо для начала, хотя я просил повторить в точности то что есть, а не самовольничать

R>Могут быть ошибки (как в оптимальности реализации, так и в понимании логики того, что здесь происходит), но в общем вроде все так.


Тут две проблемы.
1. Для типа Guid не существует TypeCode.
2. Для перечислений создаются другие мапперы, т.е. нужна будет ещё одна функция.

Но даже и в таком виде очень хорошо видно, что наглядность кода не возрасла. К тому же можно было бы предложить вариант для SqlTypes: SqlInt16, SqlInt32 и т.п. для которых нет TypeCodes.

R>Если интересен был proof-of-concept, то вот. Ничего, что я добавил "лишнюю" функцию? а то читать было сложновато.


То-то и оно.

R>Надеюсь, больше на C# ничего делать не придется.


... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[10]: Вот подумалось
От: reductor  
Дата: 27.11.05 22:49
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>reductor wrote:


>> C>И что? Чем этому мешает break и goto? Прекрасно можно доказывать

>> C>кооректность программ и с ними.
>> Можно, но без "прекрасно".

C>Замечательно. Теперь рассказать как можно преобразовать AST с multiple

C>returns в AST с single returns?

при чем здесь AST?
по вашему, исходя из этого:
if (cond) return 1
return 0

можно утверждать, что имелось в виду это:
if (cond) return 1
else return 0
?
а под этим:
if (cond1) 
   if (cond2) return 2
return 0

подразумевалось без сомнения это:
if (cond1)
   if (cond2) return 2
   else return 0
else return 0

?

Или я говорил, что код с несколькими стейтментами return не может работать корректно?
или что его нельзя в AST трансформировать во что-то там? Или что его нельзя скомпилировать?
Я утверждал, что без явной обработки всех условий вероятность ошибки и последующая с этим возня могут возрасти многократно.
Без нее где-нибудь код будет ждать вариант, который функция никогда не возвращает, потому что кто-то написал красивый трансформер для AST, который тем не менее вряд ли умеет еще и проверять возвращает ли функция все возможные значения или только половину из них.


>> C>Слишком много переменных может потребоваться передавать в виде

>> параметров.
>> Ну наверное может. А может и нет. Или наоборот. О чем вообще мы?

C>Не знаю. Кто-то пытается мне зубы заговорить, кажется.


По-моему кто-то не держит себя в руках. Код со многими переменными можно глянуть?.

>> C>Нет уж, сами затеяли спор — сами и показывайте код, который

>> C>множественный выход делает недоказуемым и вообще отстойным.
>> Извините, это вы говорите, что у вас есть такой код. Что он есть у
>> меня, я не говорил.
>> А я такого кода не пишу.

C>И судите о сложности чтения multiple returns?


Да, переубедите меня. Покажите обратное.
Re[13]: Вот подумалось
От: reductor  
Дата: 27.11.05 22:58
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, reductor, Вы писали:


R>>Ок. Только сразу предупреждаю, я вообще не знаю C# (как и .NET), потому пришлось msdn почитать.


IT>Совсем не плохо для начала, хотя я просил повторить в точности то что есть, а не самовольничать


R>>Могут быть ошибки (как в оптимальности реализации, так и в понимании логики того, что здесь происходит), но в общем вроде все так.


IT>Тут две проблемы.

IT>1. Для типа Guid не существует TypeCode.

ну можно в default там добавить проверку на Guid дополнительно, вроде

IT>2. Для перечислений создаются другие мапперы, т.е. нужна будет ещё одна функция.

А.. точно, я не заметил вызовы .Enum()
Можно передавать вторым параметром флаг и перед возвратом, если true и != null, то вернуть value.Enum()
Или что-нибудь такое. Наверняка есть миллион способов не дублировать кучу кода

IT>Но даже и в таком виде очень хорошо видно, что наглядность кода не возрасла. К тому же можно было бы предложить вариант для SqlTypes: SqlInt16, SqlInt32 и т.п. для которых нет TypeCodes.


Создать свой Enum с необходимым набором?
Re[15]: Вот подумалось
От: reductor  
Дата: 27.11.05 23:11
Оценка:
Здравствуйте, IT, Вы писали:

как-то так. ну или сделать уже свой Enum, чтобы без костылей.

Блин, хотел подредактировать форматирование, а получилось как всегда . IT.
Re[16]: Вот подумалось
От: IT Россия linq2db.com
Дата: 27.11.05 23:17
Оценка:
Здравствуйте, reductor, Вы писали:

R>как-то так. ну или сделать уже свой Enum, чтобы без костылей.


Ну понятно. В общем, оценочку за волю к победе я тебе двумя постами выше поставил
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: Вот подумалось
От: vdimas Россия  
Дата: 28.11.05 00:11
Оценка:
Здравствуйте, reductor, Вы писали:

R>Вы, мне кажется, путаете две близкие вещи.

R>Посмотрим, вот ваша функция на Haskell, где вообще нет оператора выхода:
R>
R>contains _ [] = False
R>contains y (x:xs) | x == y = True
R>                  | otherwise = contains y xs
R>

R>1-в-1, То же самое.
R>А вот функция, которая пытается сделать сразу 10 вещей закрывая дыры в логике преждевременным выходом так легко формальным образом не выразится. Можно делать выводы.

R>Несколько выходов — это всегда повод к тому, чтобы задать себе вопрос — не создаю ли я тут эмуляцию вложеных функций. И ответить на этот вопрос или утвердительно или отрицательно.

R>А все остальное уже из этого следует.

Я, как раз, ничего не путаю. Чтобы адекватно обмениваться мнениями, немного терминологии:
goto, continue, break, return — суть операторы безусловного перехода. return — это, грубо, безусловный переход на метку конца подпрограммы.

На блок-диаграммах алгоритмов все операторы безусловного перехода обозначаются одинаково и имеют один и тот же смысл. В приведенной мною блок-диаграмме нехватает блока {конец}, куда я должен был привести алгоритм после присвоения выходного значения.

Такие разновидности goto как continue, break, return позволяют банально обходится без меток, используя границы блоков в структурном программировании.

И кстати, то о чем говоришь ты, легко достигается и без множественного return, и причина в этом другая/другие. Ты намекал на кашу в построении алгоритма конкретной процедуры. Для каши в голове может быть миллион причин, и оно не лечится сведением ретурнов к единственности. Да и вообще, с т.з. структурного программирования это не принципиально. Гораздо принципиальней внешний интерфейс самой процедуры и спецификация ее семантики. Дай бог обойтись без каши на этом уровне.

---------
Да, и что там насчет останова автомата Тьюринга, что не так? Мы же не перепрыгиваем через уровни во время return, более того, return стоит именно рассматривать как оператор безусловного перехода на том же уровне вложенности. В отличие от exceptions... Вот уж где Тьюринг отдыхает... ИМХО, другие модели нынче требуются, малость посложнее, для формального описания сути происходящего в современном ПО.

---------
И еще, насчет твоего примера на Haskell. А что, в этом ЯП есть оператор goto?
Я когда-то возился с Прологом, поэтому примерно понял, о чем речь в твоем отрезке (с Haskell не знаком). Однако, в том же Прологе, такая частоиспользуемая штука, как отсекающие условия — что как не разновидность return?

В твоем примере вот это оно: "x == y = True", самый что ни на есть немедленный return из алгоритма, как только попали в подходящую для return ситуацию.
Re[9]: Вот подумалось
От: vdimas Россия  
Дата: 28.11.05 00:17
Оценка:
Здравствуйте, reductor, Вы писали:

>>> Что касается выхода из циклов по флагам и отсутствия break, то вообще

>>> не понимаю в чем проблема — что мешает вынести цикл в отдельную
>>> функцию и выходить исключительно из цикла, делая код более предсказуемым?

C>>Слишком много переменных может потребоваться передавать в виде параметров.


R>Ну наверное может. А может и нет. Или наоборот. О чем вообще мы?


О том, что ты вот только сейчас начинаешь более-менее четко определять свою позицию. Насчет выхода из цикла или из "всей" подпрограммы — ты сделал правильное замечание. И тебя тоже весьма правильно поправили насчет целесообразности в случае сильной связанности кода цикла с окружающим кодом.

C>>Нет уж, сами затеяли спор — сами и показывайте код, который

C>>множественный выход делает недоказуемым и вообще отстойным.

R>Извините, это вы говорите, что у вас есть такой код. Что он есть у меня, я не говорил.

R>А я такого кода не пишу.

R>Будем продолжать беседы о том сколько ангелов уместится на острие иголки?


Нет, лучше сместиться в сторону верифицирования современного ПО. Ты хоть представляешь, КАК ИМЕННО оно происходит сейчас? В общем, твоя точка зрения понятна, но она неприменима на "реальных объемах".
Re[9]: Вот подумалось
От: reductor  
Дата: 28.11.05 01:30
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, reductor, Вы писали:


R>>Вы, мне кажется, путаете две близкие вещи.

R>>Посмотрим, вот ваша функция на Haskell, где вообще нет оператора выхода:
R>>
R>>contains _ [] = False
R>>contains y (x:xs) | x == y = True
R>>                  | otherwise = contains y xs
R>>

R>>1-в-1, То же самое.
R>>А вот функция, которая пытается сделать сразу 10 вещей закрывая дыры в логике преждевременным выходом так легко формальным образом не выразится. Можно делать выводы.

R>>Несколько выходов — это всегда повод к тому, чтобы задать себе вопрос — не создаю ли я тут эмуляцию вложеных функций. И ответить на этот вопрос или утвердительно или отрицательно.

R>>А все остальное уже из этого следует.

V>Я, как раз, ничего не путаю. Чтобы адекватно обмениваться мнениями, немного терминологии:

V>goto, continue, break, return — суть операторы безусловного перехода. return — это, грубо, безусловный переход на метку конца подпрограммы.

V>На блок-диаграммах алгоритмов все операторы безусловного перехода обозначаются одинаково и имеют один и тот же смысл. В приведенной мною блок-диаграмме нехватает блока {конец}, куда я должен был привести алгоритм после присвоения выходного значения.


V>Такие разновидности goto как continue, break, return позволяют банально обходится без меток, используя границы блоков в структурном программировании.


Все гораздо проще. Есть, предположим, спецификация, вида:

       | Positive if x > 0
f(x) = | Negative if x < 0
       | Zero otherwise


Не может быть спецификации без _полной_ проверки возможных значений.
И, строго говоря, код вида:
int f (int x) {
    if (x > 0) return 1;
    if (x < 0) return -1;
    return 0;
}

Ей формально не соответствует. И главное, что проверить это очень сложно. В общем виде такое вообще не проверяется.
А когда таких вариантов много, то непредсказуемость растет очень быстро.
тогда как код вида:
int f (int x) {
    if (x > 0) return 1;
    else if (x < 0) return -1;
    else return 0;
}

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


V>---------

V>Да, и что там насчет останова автомата Тьюринга, что не так? Мы же не перепрыгиваем через уровни во время return, более того, return стоит именно рассматривать как оператор безусловного перехода на том же уровне вложенности. В отличие от exceptions... Вот уж где Тьюринг отдыхает... ИМХО, другие модели нынче требуются, малость посложнее, для формального описания сути происходящего в современном ПО.

Проблема с тьюринг-полным автоматом в том, что мы не можем определить свойства программы, у которой есть внешний вход.
Потому, мы вынуждены так или иначе с одной стороны определять то, что можем и с другой ограничивать используемые конструкции.
Именно потому go to statements considered harmful.
Что касается отдыхает тьюринг или нет, то вообще Машина Тьюриннга может вычислить _любую_ вычислимую функцию.
И все остальные выч. модели, которые могут эмулировать МТ ей равномощны.
Но дело не в этом. Для формализации и доказательств действительно используется типизированное лямбда-исчисление и изоморфизм Карри-Говарда. http://en.wikipedia.org/wiki/Curry-Howard_isomorphism
Которое, являсь само по себе формальной математической моделью проще отображается в регулярную математику и обратно.
К слову что я Хаскель вспомнил.

V>---------

V>И еще, насчет твоего примера на Haskell. А что, в этом ЯП есть оператор goto?

Нет конечно. И return нет. И циклов нет. И присваиваний нет. Переменных нет.
Потому очень показателен пример на нем. Я вообще часто, когда что-то сложное пишу на любом языке, сначала на хаскеле спецификацию-прототип составляю (Это если нельзя по каким-то причинам сразу на хаскеле написать.

V>Я когда-то возился с Прологом, поэтому примерно понял, о чем речь в твоем отрезке (с Haskell не знаком). Однако, в том же Прологе, такая частоиспользуемая штука, как отсекающие условия — что как не разновидность return?


Тем, что задается соответсвие между входом и выходом. скажем так, справедливо сказать, что этот _выразим_ с помощью return. Как и return с помощью джампа куда-нибудь. Но не оставляет вариантов для размышления.

V>В твоем примере вот это оно: "x == y = True", самый что ни на есть немедленный return из алгоритма, как только попали в подходящую для return ситуацию.


Нет конечно. Это именно что задание соответствия между выходом и выходом. Чего в функции на Си может и не быть явным (определяемым анализатором) образом.
Re[10]: Вот подумалось
От: reductor  
Дата: 28.11.05 01:38
Оценка:
Здравствуйте, vdimas, Вы писали:

R>>Ну наверное может. А может и нет. Или наоборот. О чем вообще мы?


V>О том, что ты вот только сейчас начинаешь более-менее четко определять свою позицию. Насчет выхода из цикла или из "всей" подпрограммы — ты сделал правильное замечание. И тебя тоже весьма правильно поправили насчет целесообразности в случае сильной связанности кода цикла с окружающим кодом.


Ну лично я о том, что без примеров это как беседа о марсианах.

V>Нет, лучше сместиться в сторону верифицирования современного ПО. Ты хоть представляешь, КАК ИМЕННО оно происходит сейчас? В общем, твоя точка зрения понятна, но она неприменима на "реальных объемах".


Я? представляю, а что?
А можно ли услышать что такое "реальные объемы"? А то может у меня какие-то они нереальные, мало ли.
И почему даже если так, то нужно делать код менее верифицируемым, чем можно?
Re[12]: Вот подумалось
От: reductor  
Дата: 28.11.05 02:36
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, reductor, Вы писали:



R>>Или я говорил, что код с несколькими стейтментами return не может работать корректно?

R>>или что его нельзя в AST трансформировать во что-то там? Или что его нельзя скомпилировать?
R>>Я утверждал, что без явной обработки всех условий вероятность ошибки и последующая с этим возня могут возрасти многократно.

V>Все с точностью до наоборот. В сочетании с RAII это помогает писать очень простой код. А надежность ПО достигается косвенным путем, а именно — чем проще код, тем сложнее ошибиться, тем легче сопровождать/исправлять и верифицировать.


V>Например, в С++, опять ресурсы и коды возвратов:


Ну если дело только в этом конкретном коде, то:
     if (error( openRes1() )) return ERR_RESOURCE1;
else if (error( openRes2() )) return ERR_RESOURCE2;
else if (error( openRes3() )) return ERR_RESOURCE3;
else return ERR_SUCCESS;

формальнее некуда


V>Теперь представь себе гору кода, если бы мы делал все через if-else и явное управление ресурсами... бррр... Вероятность ошибки возрасла бы многократно. Т.е., дело в том, что некое ELSE все равно выполняется. И разработчик, размеется, прекрасно знает — что именно (вызов деструкторов локальных объектов). И он это использует на всю катушку, для однократного программирования кода этих ELSE и затем многократного повторного использования (да и еще автоматического). Это тебе как бы затравка на другие способы повышения надежности (читабельность, максимальное повторное использование)


если else есть, а он есть всегда, когда мы имеем любое соответствие между входом и выходом, то явное его присутствие хуже не сделает. а наоборот — может сделать еще и заметными свои ошибки в понимании того, как эта функция должна себя вести.
когда вдруг понимаешь, что в else нечего писать, порой настоящее просветление получаешь.

V>А с использованием exceptions, код выглядит еще читабельнее:


А вот на иксепшены я и не гнал. Тут где-то даже валяется постинг от меня в их защиту.
правда их я люблю не в варианте с++, но это уже детали.
Re[23]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 28.11.05 06:09
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:


СГ>Ну, значит, вот так:

СГ>
СГ>PROCEDURE TransferMoney (src, dst: Account; m: Money; log: Log): BOOLEAN;
СГ>  VAR r: BOOLEAN; t: Transaction; s, d: LockedAccount; x: Transfer;

СГ>   PROCEDURE BeginTransfer;
СГ>   BEGIN (*...*)
СГ>   END BeginTransfer;

СГ>   PROCEDURE GetMoney (): BOOLEAN;
СГ>   BEGIN (*...*)
СГ>   END GetMoney;

СГ>   PROCEDURE AddMoney (): BOOLEAN;
СГ>   BEGIN (*...*)
СГ>   END AddMoney;

СГ>   PROCEDURE Enroll (a: Account; OUT b: LockedAccount): BOOLEAN;
СГ>   BEGIN (*...*)
СГ>   END Enroll;

СГ>   PROCEDURE Commit (): BOOLEAN;
СГ>   BEGIN (*...*)
СГ>   END Commit;

СГ>   PROCEDURE EndTransfer;
СГ>   BEGIN (*...*)
СГ>   END EndTransfer;

СГ>BEGIN r := (src # NIL) & (dst # NIL) & (m > 0);
СГ>  IF r THEN
СГ>    BeginTransfer;
СГ>    r := Enroll(src, s) & Enroll(dst, d) & GetMoney() & AddMoney() & Commit();
СГ>    EndTransfer
СГ>  END;
СГ>  RETURN r
СГ>END TransferMoney;
СГ>


Данные у нас правильные по определению, функция enroll на заблокированную базу данных нарваться не может опять же по определению. Rollback не бывает. Об остальном я, пожалуй, промолчу.
Re[25]: Что вы предлагаете на замену эксепшенов?
От: xBlackCat Россия  
Дата: 28.11.05 09:15
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Да, напомните мне, плиз, почему в Java/C# есть OutOfMemoryException


Не знаю, как с C#, а в Java есть только OutOfMemoryError. По документации, исключения(?) типа Error приложения не должны перехватывать и, если перехватывают, должны передавать наверх.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Rojac &mdash; Rsdn Offline JAva Client
Анонсы и обсуждение здесь
Автор: xBlackCat
Дата: 08.02.10
Re[11]: Вот подумалось
От: reductor  
Дата: 28.11.05 11:49
Оценка:
Здравствуйте, Костя Ещенко, Вы писали:

КЕ>Здравствуйте, reductor, Вы писали:


КЕ>[]



КЕ>Если этот код формально не соответствует той спецификации, то видимо он формально соответствует некой другой спецификации. Можно взглянуть на нее?


Не понял. Какой еще спецификации?
А вообще я бы тоже глянул на ту спецификацию, которая заставляет писать такой код.


КЕ>Почти уверен, что на языке промежуточного представления, которым пользуется нормальный компилятор (SSA или чего там еще), оба эти варианта выглядят одинаково.


Скорее всего, с этим простым примером так и будет. Что с того? Да и какая вообще разница во что это потом превратится?


КЕ>[]
Re[26]: Что вы предлагаете на замену эксепшенов?
От: Cyberax Марс  
Дата: 28.11.05 13:10
Оценка:
xBlackCat wrote:

> C>Да, напомните мне, плиз, почему в Java/C# есть OutOfMemoryException

> Не знаю, как с C#, а в Java есть только OutOfMemory*Error*. По
> документации, исключения(?) типа Error приложения не должны
> перехватывать и, если перехватывают, должны передавать наверх.

Перехватить его можно, но опасно — при любом new оно может вылететь
снова. Хотя я видел системы, где OOM успешно обрабатывался.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[12]: Вот подумалось
От: Костя Ещенко Россия  
Дата: 28.11.05 13:11
Оценка:
Здравствуйте, reductor, Вы писали:

КЕ>>Если этот код формально не соответствует той спецификации, то видимо он формально соответствует некой другой спецификации. Можно взглянуть на нее?


R>Не понял. Какой еще спецификации?

ты приводил эту:
       | Positive if x > 0
f(x) = | Negative if x < 0
       | Zero otherwise

R>А вообще я бы тоже глянул на ту спецификацию, которая заставляет писать такой код.

Вот и мне интересно — если код соответствует спецификации, только являясь ее достаточно точной калькой — то как может выглядеть спецификация "некрасивого" варианта? Есть варианты?

КЕ>>Почти уверен, что на языке промежуточного представления, которым пользуется нормальный компилятор (SSA или чего там еще), оба эти варианта выглядят одинаково.


R>Скорее всего, с этим простым примером так и будет. Что с того?


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

R>Да и какая вообще разница во что это потом превратится?


Никакой
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[13]: Вот подумалось
От: reductor  
Дата: 28.11.05 13:31
Оценка:
Здравствуйте, Костя Ещенко, Вы писали:

КЕ>Вот и мне интересно — если код соответствует спецификации, только являясь ее достаточно точной калькой — то как может выглядеть спецификация "некрасивого" варианта? Есть варианты?


Нет, у меня вариантов нет. И вообще пример был для описания различий между формальной реализацией и неформальной.


КЕ>>>Почти уверен, что на языке промежуточного представления, которым пользуется нормальный компилятор (SSA или чего там еще), оба эти варианта выглядят одинаково.


R>>Скорее всего, с этим простым примером так и будет. Что с того?


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



Я скоро это внесу себе в сигнатуру:
Корректная работа кода не означает автоматически, что код выполняет то, что предполагалось. Это так же не означает что код соответствует спецификации и, соответственно, что можно считать его доказаным или хотя бы без багов.
Ошибки в софте, написанном десятилетия назад и обнаруженные только сейчас это непосредственным образом подтверждают. Код с явной обработкой всех условий будет с меньшей вероятностью подвержен глупым ошибкам, чем код без таковой.

Что еще?

P.S
Еще у меня есть все основания предполагать, что код, написанный формальным образом читается и понимается гораздо легче, чем наоборот. По крайней мере человеком, у которого все в порядке с логикой. Это эмпирический вывод. Доказать я это не могу.

P.P.S
иксепшенов это не касается, они — совершенно другая тема.
Re[25]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 28.11.05 13:47
Оценка:
Здравствуйте, eao197, Вы писали:

E>Я думаю, тебе интересно будет почитать мнение Бертрана Мейера про исключения: Re[4]: Что вы предлагаете на замену эксепшенов?
Автор: iZEN
Дата: 22.11.05
Так вот Мейер в качестве одной из дисциплин обработки исключений определяет "Повторение" (Retrying), но об этом чуть ниже.

Жаль, но там нет ссылки на онлайн версию... В наших магазинах я такой книги не видал.

E>Сдается мне, что мы сейчас говорим об одном и том же, но разными словами.


Да. Точно, мы говорим об одном и том-же.
Просто в начале, я решил, что ты предлагаеш иногда использовать исключения на одном логическом уровне для передачи информации/контроля (как тот пример с курсором и короткой строкой).
Теперь всё ясно.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[15]: Вот подумалось
От: reductor  
Дата: 28.11.05 13:56
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, reductor, Вы писали:


R>>Корректная работа кода не означает автоматически, что код выполняет то, что предполагалось. Это так же не означает что код соответствует спецификации и, соответственно, что можно считать его доказаным или хотя бы без багов.


E>Корректно работающий в соответствии со спецификацией код совсем не обязательно выполняет то, что предполагалось.


Корректно работающий в соответствии со спецификацией код, делает то, что предполагалось в спецификации с несколько большей вероятностью, чем код, который ей не соответствует. И есть формальный аппарат, позволяющий это проверить.
Если есть данные или другой аппарат, позволяющие это оспорить и доказать, что наоборот — буду рад услышать.

E>Это эмпирический вывод, основывающийся на том, что:

E>a) спецификации так же содержат ошибки;
E>b) заказчик может не суметь четко описать свои пожелания и ожидания.
E>Доказать я его не могу.

А вот это уже лирика, к делу не относящаяся. Методов, чтобы определить в каком состоянии писал заказчик спецификацию и писал ли вообще, а не сгенерировал генератором матерных слов, я не знаю. Себе спецификации я стараюсь писать сам. Формальные и без противоречий (это очень просто).
Re[24]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 28.11.05 14:24
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Данные у нас правильные по определению, функция enroll на заблокированную базу данных нарваться не может опять же по определению. Rollback не бывает. Об остальном я, пожалуй, промолчу.


Всё учтено в процедурах: BeginTransfer, EndTransfer; а так же в процедурах-функциях: Enroll, GetMoney, AddMoney, Commit.
Re[24]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 28.11.05 14:29
Оценка:
Здравствуйте, IT, Вы писали:

IT>А теперь добавь сюда какую-нибудь вменяемую информацию об ошибке, сделай так чтобы TransferMoney возвращала новый баланс счёта и протащи это через 4-5 вызовов.


Легко. Приведите код с exception, а я его переделаю в код без exception. Да, и еще у меня будет большая просьба: после того как я это сделаю — уже ни когда не предлагать делать это еще раз — сколько можно одно и тоже писать? Смысл-то как это делается и так уже понятен.
Re[17]: Вот подумалось
От: reductor  
Дата: 28.11.05 14:36
Оценка:
E>К счастью, мне не приходилось вообще заниматься формальным доказательством корректности работы программы. Читали нам в универе какой-то спецкурс по этому поводу, но это было уже очень давно. Единственное, что помню, так это скептическое отношение самого преподавателя к данной теме. И еще он вспоминал какую-то программу, на одну страничку объемом, для которой на пяти страницах текста было формально доказана правильность ее работы. К сожалению, программа работала не правильно.

Ок. Вы правы


R>>А вот это уже лирика, к делу не относящаяся. Методов, чтобы определить в каком состоянии писал заказчик спецификацию и писал ли вообще, а не сгенерировал генератором матерных слов, я не знаю. Себе спецификации я стараюсь писать сам. Формальные и без противоречий (это очень просто).


E>Еще как относится. Поскольку платят не за то, насколько полно программа соответствует спецификации, а насколько полно делает то, что от нее требовал заказчик.


Ок. Вы правы.
Во всем. Больше мне добавить или прокомментировать нечего.
Re[2]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 28.11.05 14:45
Оценка:
Здравствуйте, vdimas, Вы писали:

V>На самом деле, применительно к доводам использования exception используется другое разделение:


На самом деле, применительно к доводам использования exception, я привёл (мою) классификацию ошибок: (1) ошибка в данных, и (2) ошибка в программе. Сказал что для обработки ошибок в данных exception не нужны, а для обработки ошибок в программе довольно ASSERT + system trap, так что опять exception не нужны. Вы против этого что-то имеете конструктивно возразить?
Re[17]: error is not an exception
От: Cyberax Марс  
Дата: 28.11.05 15:00
Оценка:
IT wrote:

> C>В С++ сработавший assert вызывает функцию DebugBreak, так что

> поймать ее
> C>сложно будет.
> Not big deal.

Если постараться, то и на Луну можно слетать.

> Все asserts идут лесом.


Тогда можно написать функцию, которая будет писать в лог stacktrace, а
потом кидать исключение.

> Но дело даже не в этом. Ты собираешься на любую возможную ситуацию в

> программе писать assert? Этак у тебя на 10 строчек кода должно быть 20
> asserts.

Не совсем так, но близко. Заодно помогает прояснять контракты использования.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[12]: Вот подумалось
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 28.11.05 15:01
Оценка:
Здравствуйте, Belsen, Вы писали:

B>
B>    }
B>    catch (ResultException<MemberMapper> re)
B>    {    
B>        return re.Result;
B>    }
B>    throw new UndefinedResultException();
B>}
B>


Дай пожму твою мужественную руку!
Re[25]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 28.11.05 15:17
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Всё учтено в процедурах: BeginTransfer, EndTransfer; а так же в процедурах-функциях: Enroll, GetMoney, AddMoney, Commit.


Я не знаю, насколько этот код верен с точки зрения исключений. Смущает меня, однако, что функции, работающие с удаленным счетом:
1) блокируют всю работу с нашим счетом;
2) держат открытым канал связи в течение всего времени работы;
3) не дают вразумительного ответа, почему транзакция не прошла.

При переводе денег куда-нибудь в Уругвай, при таком подходе, связь будет клиенту не по карману.
Re[25]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 28.11.05 15:18
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Легко. Приведите код с exception, а я его переделаю в код без exception. Да, и еще у меня будет большая просьба: после того как я это сделаю — уже ни когда не предлагать делать это еще раз — сколько можно одно и тоже писать? Смысл-то как это делается и так уже понятен.


А переделать Ваш, уже существующий, код сложно?
Re[26]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 28.11.05 15:21
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Я не знаю, насколько этот код верен с точки зрения исключений. Смущает меня, однако, что функции, работающие с удаленным счетом:

P>1) блокируют всю работу с нашим счетом;
P>2) держат открытым канал связи в течение всего времени работы;
P>3) не дают вразумительного ответа, почему транзакция не прошла.
P>При переводе денег куда-нибудь в Уругвай, при таком подходе, связь будет клиенту не по карману.

Эти вопросы не ко мне, а к автору кода. Я всего лишь переписал предложенный код содержащий exceptions в аналогичный мой код их не содержащий.
Re[25]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 28.11.05 15:29
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Легко. Приведите код с exception, а я его переделаю в код без exception. Да, и еще у меня будет большая просьба: после того как я это сделаю — уже ни когда не предлагать делать это еще раз — сколько можно одно и тоже писать? Смысл-то как это делается и так уже понятен.


Если хотите, можем оставить банковскую тему. Вот еще вопрос: Вы пишете программу, вычисляющую значения функции y=f(x) на интервале [a, b]. Программа не знает, какую функцию ей предстоит вычислять. Что она должна делать, если знаменатель (если он есть) обращается в 0? Или если в какой-нибудь точке функция не определена?
Re[25]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 28.11.05 16:01
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Легко. Приведите код с exception, а я его переделаю в код без exception.


Ок. Напишите маленький кусочек кода, который инициирует перевод денег и отображает ошибку пользователю.
С исключениями:

// Информация об ошибке.
class TransactionException
{
    char * Description;
}

// попытаемся....
try
{
    transfer_money(from, to, modey);
}
catch(TransactionException &e)
{
    ShowMessage("Trans error. Reason: " + e.Description);
}


При появлении ошибки в ф-иях GetMoney, AddModey ... генерируется исключение, заполняется поле Description.

Ваш ход конём! Тобиш обероном.

СГ> Да, и еще у меня будет большая просьба: после того как я это сделаю — уже ни когда не предлагать делать это еще раз — сколько можно одно и тоже писать? Смысл-то как это делается и так уже понятен.

Одно и тоже не будем. Будем "развивать" систему.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[27]: Что вы предлагаете на замену эксепшенов?
От: Sergey J. A. Беларусь  
Дата: 28.11.05 16:02
Оценка:
Здравствуйте, eao197, Вы писали:

SJA>>Жаль, но там нет ссылки на онлайн версию... В наших магазинах я такой книги не видал.


E>Re[4]: Что вы предлагаете на замену эксепшенов?
Автор: EvilChild
Дата: 22.11.05

Thx. Проморгал....
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[26]: Что вы предлагаете на замену эксепшенов?
От: GlebZ Россия  
Дата: 28.11.05 16:36
Оценка:
Здравствуйте, Sergey J. A., Вы писали:

Не так.
using (TransactionScope scope=new TransactionScope())
{
//здесь код, любой который может быть использующий данную транзакцию
.......
scope.Complete();//подтверждение транзакции.
}

public class TransactionScope:IDisposable
{
  private DBTransaction _trans;
    private bool _commited=false;
  public TransactionScope(){_trans=new DBTransaction();};
    public Complete(){_trans.Commit();_commited=true;};
    public void Dispose()//для сишников - это аналог деструктора
    {
      if (!_commited)_trans.Rollback();
    }
}

Транзакции наплевать, что было — ошибка бизнес-логики или OutOfMemory.
С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[27]: Что вы предлагаете на замену эксепшенов?
От: GlebZ Россия  
Дата: 28.11.05 16:40
Оценка:
Здравствуйте, GlebZ, Вы писали:

Oops. Баян. Re[21]: Что вы предлагаете на замену эксепшенов?
Автор: Cyberax
Дата: 24.11.05
Не заметил.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Что вы предлагаете на замену эксепшенов?
От: Павел Кузнецов  
Дата: 28.11.05 16:44
Оценка:
Сергей,

> я привёл (мою) классификацию ошибок: (1) ошибка в данных, и (2) ошибка в программе. Сказал что для обработки ошибок в данных exception не нужны


И? Обоснование этого пункта будет? (С учетом последовавших реплик о проблемах с зависимостями промежуточных уровней от исключительных ситуаций, возникающих на нижних уровнях, и обрабатывающихся на верхних.)
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: Что вы предлагаете на замену эксепшенов?
От: Владик Россия  
Дата: 28.11.05 16:57
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>И? Обоснование этого пункта будет? (С учетом последовавших реплик о проблемах с зависимостями промежуточных уровней от исключительных ситуаций, возникающих на нижних уровнях, и обрабатывающихся на верхних.)


Я так понял, что все свелось к идее протаскивания абстрактного Exception в виде возвращаемого значения, которое проверяется на каждом уровне. Как эта идея согласуется с отсутствием "синтаксического оверхеда" — я не понял
Как все запущенно...
Re[12]: Вот подумалось
От: reductor  
Дата: 28.11.05 21:33
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, reductor, Вы писали:


R>>Я? представляю, а что?

R>>А можно ли услышать что такое "реальные объемы"? А то может у меня какие-то они нереальные, мало ли.
R>>И почему даже если так, то нужно делать код менее верифицируемым, чем можно?

V>Кстати, сам я тоже склоняюсь к мысли, что по-возможности надо верифицировать код, а не побочные эффекты его работы. Заявление о том, что "раз программа прошла все тесты, значит она правильная" не вызывает у меня ничего, кроме скепсиса.


V>Однако, "реальные объемы кода" — это такие объемы в пересчете на одного разработчика, которые приняты сейчас в реальных проектах. Если С++ программист должен выдавать от 200 и до... (иногда 400-600) строк в день, то верификация таких объемов займет в разы больше времени и потребует гораздо более дорогих в почасовом плане ресурсов, чем ресурс автора целевого кода. В общем подход, основанный на полной верификации кода элементарно неприемлим для многих контор.




По-поводу теоретических размышлений на тему верификации, bug preventing и MSDN, хочу просто рассказать несколько фактов:
1. Сначала посчитаем количество строк:
$ cd ghc-6.4.1
*@desktop ghc-6.4.1
$ find . -name "*.hs" -exec cat {} \;|wc -l
265870

+ 138287 на си

Это директория с исходниками компилятора GHC. Который развивают и поддерживают в основном 2(два) человека и несколько мелких контрибьютеров. Их зовут Simon Peyton Jones и Simon Marlow. По поводу каждого крупного изменения, они как правило делают публикацию с формальным обоснованием. Компилятор работает на windows, linux, macos, нескольких других юниксах и нескольких процессорах и охват платформ только расширяется.
2. С недавних пор они оба работают в Microsoft Research. (там же с ними и Tony Hoare)
3. http://lists.seas.upenn.edu/pipermail/types-list/2005/000903.html
4. http://research.microsoft.com/projects/ilx/fsharp.aspx
5. По поводу количества строк, я ничего не скажу, для меня это несколько странный критерий. Но использование формальных методов на Java (Статический анализ, правила кодирования) в моем случачае показали увеличение производительности раза в 2-3. В основном за счет значительно сократившегося потока багрепортов и возможности на ранней стадии обнаружить огрехи в архитектуре и дизайне приложения.
6. Я не утверждал, а) что следует повсеместно внедрять конструкции с полной проверкой. даже в паре мест специально отметил, что этого не утверждаю. б) во всяком промежуточном и интерфейсном коде я сам частенько пишу абы как. контекст позволяет — там часто достаточно протестировать, чтобы быть уверенным, что все работает.
7. Однозначно не утверждал, что это единственная возможность и самое главное условие для получения корректного кода. Просто речь зашла именно об этом.
8. Формальный подход — это следствие, а не причина.
8. Хотел тут написать про языки изначально максимально верифицируемые и формальные (такие как хаскель), но как-то слишком громко выходит. Косвенные выводы см. пункт 1 :)



V>-----------

V>Кстати, ты писал, что ничего не имеешь против exceptions. Тем более странно твое отрицание множественного return. Для меня эти возможности как бы равнозначные, с тем отличием, что exceptions — это автоматизированная разновидность обсуждаемого + возможность синтаксически обощать места кода по обработке ошибки.

Иксепшены запросто формализуются как частный случай continuations. Коими они, нужно сказать, в большом количестве языков и являются (Common Lisp, Scheme, Smalltalk, O'Caml, Haskell). И уж точно почти везде они лишь добавляют формальности (можно попробовать в Java не отловить нужный иксепшен и посмотреть что на это скажет компилятор).


V>Предвижу замечания, насчет того, что exceptions в первую очередь — это возможность создавать и обрабатывать ошибки на разных уровнях, однако в момент обратной раскутки стека это именно равносильно последовательному выполнению некоего return на всех вложенностях после ошибочного оператора.


Да. вот и формализация подоспела.
else return(ehandler.catch(createNiftyExepction())); // просто пример.
// не пройбуйте запустить это дома.

В случае с continuations все еще красивее.
А что там где раскручивается, уже никого не волнует.


У меня все.
На такую банальщину столько времени тратится.
Re[26]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.11.05 08:28
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Если хотите, можем оставить банковскую тему. Вот еще вопрос: Вы пишете программу, вычисляющую значения функции y=f(x) на интервале [a, b]. Программа не знает, какую функцию ей предстоит вычислять. Что она должна делать, если знаменатель (если он есть) обращается в 0? Или если в какой-нибудь точке функция не определена?


Под вопросом "что должна делать программа?" замаскирован вопрос "что должен написать программист?". А чтобы ответить на этот вопрос нужно понять смысл решаемой задачи. Итак, в чем смысл?
Re[19]: Что вы предлагаете на замену эксепшенов?
От: Mamut Швеция http://dmitriid.com
Дата: 29.11.05 08:41
Оценка:
M>>Яркий пример — разбор ХМЛя многими библиотеками. Обычно достаточно знать, что ХМЛ невалидный и сразу завершить работу:

M>>Например, кусок:


IT>А если так?


Ну тормоз я, тормоз *Ушел посыпать голову пеплом*
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re[5]: Что вы предлагаете на замену эксепшенов?
От: vdimas Россия  
Дата: 29.11.05 09:47
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Не ошибка данных, а ошибка в данных. Пользователь вводит число с клавиатуры и нажал не на ту кнопку, ввел строку не представляющую число. Эта строка пошла на вход процедуры В. Процедура В поняла, что в данных поступивших к ней на вход есть ошибка и не стала вызывать процедуру-форматтер С, а вместо этого инициализировала процесс, в результате которого пользователь был ткнут носом в неправильно введённую им строку. То есть в программе ошибок нет, ошибка была в данных.


Ok, продолжим. Добавим в твой пример сохранение введенных данных на диск. Предположим, что у нас не получилось сохранить данные на диск, это возможно по следующим причинам:
— пользователь ввел несуществующей путь для сохранения
— путь существующий, но мало места на диске, или же путь существует, но сетевой диск по этому пути именно в этот момент стал недоступным.

Последнюю причину мне как-то сложно отнести к ошибкам в данных, тем не менее я хочу обрабатывать ее именно одинаково, а лучше — одними и теми же строчками кода, как и первую причину.

Собственно, как и обработку неверного формата из твоего примера.

Понимаешь, exceptions разносят на уровни и группируют ошибочные ситуации. Т.е., если я хочу во время возникновения ошибочной ситуации выполнить одинаковую последовательность действий (неважно какую), то я группирую целевой код вложенностью try-catch. Сам код внутри блока try-catch весьма чист, и не содержит проверяющие if-else на каждой второй строке. Помнится, ты как-то сетовал на синтаксический оверхед.

------------
Вот сравни (некий код по нашей ситуации):
err_no B() {
  string str = InputSomeString();
  int i;
  err_no err = C(str, &i);
  if(err!=0) {
    ShowError("Can not convert value \"%s\" to integer", str);
    return err_invalidformat;
  }
  
  string path = InputSomePath();
  File f;
  err = OpenWrite(&f, path);
  if(err!=0) {
    string reason;
    switch(err) {
      case err_pathnotexists: reason = "path not exists";
      case err_accessdenied: reason = ...
      case ...
    }

    ShowError("Can not open file %s due the error: %s", path, reason);
    return err;
  }

  err = WriteInteger(f, i);
  if(err!=0) {
    string reason;
    switch(err) {
      // СНОВА 100 НЕНУЖНЫХ СТРОК
      case : 
    }

    ShowError("Can not write to file %s due the error: %s", path, reason);
    return err;
  }
}


и это:
void B() {
  int i= C(InputSomeString()); 
  File f = OpenWrite(InputSomePath());
  WriteInteger(f, i);
}


И где-то на верхнем уровне:

while(!quit()) {
  try {
    ...
    DispatchEvents();
  } catch(ApplicationException ex) {
    ShowWarning(ex);
  } catch(FatalException ex) {
    ShowFatalErorWriteDumpSendBugReport(ex);
    return;
  } catch(Exception ex) {
    ShowError(ex);
  }
}
Re[27]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 29.11.05 09:50
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Под вопросом "что должна делать программа?" замаскирован вопрос "что должен написать программист?". А чтобы ответить на этот вопрос нужно понять смысл решаемой задачи. Итак, в чем смысл?


Необходимо получить 2 массива, первый из которых содержит значения аргумента, а второй — значения функции от этого аргумента

 double arg[200], fun[200];

 void g(double (*f)(double), double a, double b)
 {
    double step = (b - a) / 200;
    for (int i = 0; i < 200; i++)
    {
       arg[i] = a + step * i
       fun[i] = f(x);
    }
 }


В реальной программе я, разумеется, так не писал бы, но для иллюстрации, imho, достаточно.
У программиста нет ни малейшего представления о функции f. Вот что будет с программой, если эта функция определена не на всем интервале [a, b]?
Re[10]: Вот подумалось
От: vdimas Россия  
Дата: 29.11.05 09:53
Оценка:
Здравствуйте, reductor, Вы писали:

R>Нет конечно. Это именно что задание соответствия между выходом и выходом. Чего в функции на Си может и не быть явным (определяемым анализатором) образом.


Насчет Си — есть такое, и то, компиляторы выдают предупреждение. Но в том же C# ты уже не можешь написать ветку кода без return, если ф-ия возвращает не void. Т.е. компилятор верифицирует этот момент и просто не пропускает такой код. Соответственно, ты просто вынужден поставить некое соответствие м/у входом и выходом по-молчанию. (как раз последний return в твоих примерах). При чем, это ограничение не обойти даже с помощью goto. Такое положение вещей исправляет ситуацию?
Re[11]: Вот подумалось
От: reductor  
Дата: 29.11.05 10:27
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, reductor, Вы писали:


R>>Нет конечно. Это именно что задание соответствия между выходом и выходом. Чего в функции на Си может и не быть явным (определяемым анализатором) образом.


V>Насчет Си — есть такое, и то, компиляторы выдают предупреждение. Но в том же C# ты уже не можешь написать ветку кода без return, если ф-ия возвращает не void. Т.е. компилятор верифицирует этот момент и просто не пропускает такой код. Соответственно, ты просто вынужден поставить некое соответствие м/у входом и выходом по-молчанию. (как раз последний return в твоих примерах). При чем, это ограничение не обойти даже с помощью goto. Такое положение вещей исправляет ситуацию?


Частично. В С# вообще много чего (по сравнению с другими супермайнстримными языками) появляется формального со временем.
3.0 вот уже начинает быть похожим на ML (lambda expressions, type inference, tuples).
Но конечно основной смысл в том, что если у нас есть
// некий абстрактный код
int y = 5;
if (x == 1) return y;
y++;
if (x == 2) return y;
return y + 5

То понять что здесь происходит невозможно ни компилятору (та самая проблема с автоматами) ни человеку.
Re[20]: error is not an exception
От: IT Россия linq2db.com
Дата: 29.11.05 12:25
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Или, например, вот такой код (спас часы отладки):


Так может такие проверки должны быть штатными и использоваться не только в режиме отладки?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[28]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.11.05 12:58
Оценка:
Здравствуйте, Privalov, Вы писали:

P>У программиста нет ни малейшего представления о функции f. Вот что будет с программой, если эта функция определена не на всем интервале [a, b]?


Тогда будет нарушено предусловие процедуры g. Предусловие заключается в том, что процедура-функция f(x) должна быть определена на интервале a..b. Нарушение предусловия — это ошибка в программе.

Если заранее известно, что процедура-функция f(x) может быть не определена (или бесконечна) в некоторой области, то с самого начала надо расширить тип возвращаемого значения дополнительными значениями: nonNumber, plusInfinity, minusInfinity.
Re[29]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 29.11.05 13:24
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, Privalov, Вы писали:


P>>У программиста нет ни малейшего представления о функции f. Вот что будет с программой, если эта функция определена не на всем интервале [a, b]?


СГ>Тогда будет нарушено предусловие процедуры g. Предусловие заключается в том, что процедура-функция f(x) должна быть определена на интервале a..b. Нарушение предусловия — это ошибка в программе.


Еще раз: у нас нет ни малейшего представления о функции f(x). Поэтому если функция не определена в какой-то точке интервала — это исключительная ситуация.

СГ>Если заранее известно, что процедура-функция f(x) может быть не определена ...


Не известно.
Re[6]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.11.05 13:31
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Последнюю причину мне как-то сложно отнести к ошибкам в данных


Перечитайте пожалуйста эту ветку форума — я на подобный вопрос уже отвечал. С самого начала известно, что жесткий диск не резиновый, памяти может не хватить, пути может не быть, сеть может пропасть и т.д. Ошибка в программе — это когда она не знает что надо делать в таких случаях. Если программа справляется с такими случаями, то ошибки в ней нет. Если внешний мир отказался выполнить услугу о которой просила программа, то это не ошибка программы. Ошибкой программы будет лишь ее неадекватное поведение в случае отказа внешнего мира выполнить услугу.

V>Вот сравни (некий код по нашей ситуации):

V>
V>  err_no err = C(str, &i);
V>  if(err!=0) {
V>


И на подобный вопрос я тоже уже отвечал. Откуда такая жесткая ассоциация: если нет exception, то обязательно должен быть номер кода ошибки? Это ложная ассоциация. Ни что не запрещает работать с полиморфными сообщениями об ошибках, даже если в языке нет exceptions!
PROCEDURE Proc (param: Param; VAR errList: Errors.List): BOOLEAN;
BEGIN
  ...
  IF DoSmth(param, errList) THEN
    ...
    IF b THEN
      ...
      RETURN TRUE
    ELSE
      errList := Errors.NewList(NewMyError('Proc: что-то не так с B'), errList)
    END
  ELSE
    errList := Errors.NewList(Errors.NewError('Proc: процедура DoSmth обломалась!'), errList)
  END;
  RETURN FALSE
END Proc;

Здесь errList: Errors.List — список полиморфных сообщений об ошибках.
Re[30]: Что вы предлагаете на замену эксепшенов?
От: Трурль  
Дата: 29.11.05 14:37
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Еще раз: у нас нет ни малейшего представления о функции f(x).


То есть, вполне возможно, что для некоторых x f(x) = exit(x)?
Re[31]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 29.11.05 14:52
Оценка:
Здравствуйте, Трурль, Вы писали:

Т>То есть, вполне возможно, что для некоторых x f(x) = exit(x)?


Нет, зачем. Немного раньше я дал ее объявление: double f(double). exit вроде бы объявлена по-другому в process.h.
Re[26]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.11.05 15:56
Оценка:
Здравствуйте, IT, Вы писали:

IT>Сейчас чего-нибудь изобразим.


Написали Вы много, но принципиальной разницы с предыдущим примером нет.

MODULE RsdnUI;

  IMPORT StdLog, Errors := RsdnErrors, AccountManager := RsdnAccountManager;
  
  PROCEDURE WithdrawalAndGetBalance*;
    VAR newBalance: REAL; err: Errors.List;
  BEGIN
    IF AccountManager.WithdrawalAndGetBalance("12345", 1.0E2, newBalance, err) THEN
      StdLog.String("New balance is: "); StdLog.Real(newBalance); StdLog.Ln
    ELSE
      StdLog.String("Oops: "); StdLog.Ln;
      Errors.Print(err)
    END
  END WithdrawalAndGetBalance;

END RsdnUI.


MODULE RsdnAccountManager;

  IMPORT Errors := RsdnErrors;
  
  TYPE
    AccountService = RECORD
      (*...*)
    END;

    AccountDataAccessor = RECORD
      (*...*)
    END;

  ...

  PROCEDURE (VAR this: AccountService) WithdrawalAndGetBalance (accountNumber: ARRAY OF CHAR; amount: REAL; OUT rest: REAL; VAR err: Errors.List): BOOLEAN, NEW;
    VAR r: BOOLEAN; accessor: AccountDataAccessor;
    (*...*)
    PROCEDURE Do (): BOOLEAN;
      VAR ignored: Errors.List; (* ignored errors for steal-methods *)
    BEGIN
      IF accessor.GetBalance(accountNumber, rest, err) THEN
        IF rest >= amount THEN
          IF accessor.ChargeForService(accountNumber, 10, err) THEN
            rest := rest - amount - 10;
            IF (rest > 1.0E6) & accessor.StealSomeForMe(accountNumber, 1.15, ignored) THEN rest := rest - 1.15 END;
            IF (rest > 1.0E7) & accessor.StealSomeForHomelessPeople(accountNumber, 1.15, ignored) THEN rest := rest - 1.15 END;      
            RETURN accessor.SetBalance(accountNumber, rest, err)
          END
        ELSE
          err := Errors.NewList(Errors.NewError("You are freaking bankrupt!"), err); (* Вот такое вот "кидание исключения" *)
        END
      END;
      RETURN FALSE
    END Do;
    (*...*)
  BEGIN r := ValidateAccountNumber(accountNumber, err) & ValidateAmount(amount, err);
    IF r THEN
      accessor.Init;
      r := accessor.BeginTransaction(err) & Do() & accessor.CommitTransaction(err);
      accessor.Close
    END;
    RETURN r
  END WithdrawalAndGetBalance;

  ...
  
  PROCEDURE WithdrawalAndGetBalance* (accountNumber: ARRAY OF CHAR; amount: REAL; OUT rest: REAL; VAR err: Errors.List): BOOLEAN;
    VAR r: BOOLEAN; service: AccountService;
  BEGIN r := ValidateAccountNumber(accountNumber, err) & ValidateAmount(amount, err);
    IF r THEN
      service.Init;
      r := service.WithdrawalAndGetBalance(accountNumber, amount, rest, err);
      service.Close
    END;
    RETURN r
  END WithdrawalAndGetBalance;

  ...
  
END RsdnAccountManager.


MODULE RsdnErrors;

  IMPORT StdLog;
  
  CONST
    max = 256;
    
  TYPE
    Error* = POINTER TO EXTENSIBLE RECORD
      desc*: ARRAY max OF CHAR;
    END;
    
    List* = POINTER TO RECORD
      head-: Error; 
      tail-: List
    END;

  PROCEDURE NewError* (desc: ARRAY OF CHAR): Error;
    VAR e: Error;
  BEGIN ASSERT(LEN(desc) < max, 20);
    NEW(e); e.desc := desc$; RETURN e
  END NewError;

  PROCEDURE NewList* (head: Error; tail: List): List;
    VAR u: List; 
  BEGIN ASSERT(head # NIL, 20);
    NEW(u); u.head := head; u.tail := tail; RETURN u
  END NewList;
  
  PROCEDURE Print* (err: List);
  BEGIN
    WHILE err # NIL DO 
      StdLog.String(err.head.desc); StdLog.Ln; err := err.tail
    END
  END Print;
  
END RsdnErrors.
Re[30]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.11.05 16:17
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Еще раз: у нас нет ни малейшего представления о функции f(x). Поэтому если функция не определена в какой-то точке интервала — это исключительная ситуация.


Любая функция в некоторой области либо регулярна, либо не регулярна; определена или не определена; вычислима или не вычислима. Вы говорите что представления у нас о ней нет, это означает что мы должны думать о ней самое худшее. А раз так, то она может возвращать кроме чисел еще и nonNumber, plusInfinity, minusInfinity. До кучи, пусть она еще возвращает значение nonCalculable — нельзя вычислить.

СГ>>Если заранее известно, что процедура-функция f(x) может быть не определена ...


P>Не известно.


А мне, например, это известно.
Re[24]: error is not an exception
От: IT Россия linq2db.com
Дата: 30.11.05 01:32
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Assertы нужны для проверки "невозможных" случаев, типа:


Это всё легко покрывается юнит-тестами. Или ты их заменяешь асёртами?

>> В реальной жизни фича отладчика, о которой я говорил выше, позволяет отловить всё тоже самое и без всякого замусоривания кода макросами.


C>Ну да, просто заменить на замусоривание исключениями.


Зачем? Предусловия в библиотечном или, например, в серверном коде проверять всё равно надо. А прикладной код нужно просто не лениться тестировать. В независимости от того используются асёрты или нет.

>> В общем, в ASSERT похоже тоже можно относить к устаревшим средствам и

>> правилам типа венгерки, SELECT* и единственного return.

C>НЕТ! Тогда стоит к устаревшим правилам отнести и хороший стиль программирования. В конце концов, он в .NET не нужен....


Зачем передёргивать? Или ты хочешь сказать, что хороший стиль и асёрты — это синонимы?

ЗЫ. Не хочу с тобой продолжать бодаться, всё равно ни мне тебя, ни тебе меня похоже не переубедить. Скажу только, что лично я, никакой практической пользы от асёртов сегодня не вижу. Речь идёт о .NET/C#. Такое моё сугуболичное ИМХО. Пойду лучше Серёгу за забытый ролбэк отстегаю
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[28]: Что вы предлагаете на замену эксепшенов?
От: dshe  
Дата: 30.11.05 08:16
Оценка:
Здравствуйте, IT, Вы писали:

В целом согласен, однако последний аргумент не совсем удачен.

IT>Но это ещё не всё.


IT>AccountDataAccessor. Мой код.


IT>
IT>public decimal GetBalance(string accountNumber)
IT>{
IT>  return (decimal)ExecuteScalarSp("GetBalance", accountNumber);
IT>}
  
IT>

IT>Твой вариант.

IT>
IT>public bool GetBalance(string accountNumber, out newBalance, ref Errors err)
IT>{
IT>  // oops!!! А ExecuteScalarSp параметра Errors не поддерживает.
IT>  // Ну дятлы её какие-то писали, не додумались до такой классной идее.
IT>  //
IT>  ///////////return (decimal)ExecuteScalarSp("GetBalance", accountNumber);
IT>}

IT>// остальные упсы поскипаны.
IT>

IT>В случае со "стандартной" ExecuteScalarSp, чтобы сохранить лицо, тебе скорее всего придётся написать длиннючий switch на все возможные коды возврата и подобрать к ним более менее вменяемые сообщения.

Насколько я понимаю, проблемы возникаеют когда встречаются два взаимоисключающий подхода (обработки исключений, в данном случае). Если бы стиль ref-out был общепринятым, то и ExecuteЧего-То-ТамSp его бы тоже поддерживал. И в этом случае пришлось бы написать длиннючий switch для того, чтобы Errors err преобразовать в исключения.

IT>Да, кстати, использование ref и out параметров считается признаком плохого дизайна. FxCop на это заявляет "Consider a design that does not require that 'parameter_name' be an out parameter".


Полагаю, FxCop не знает об использования стиля ref-out как альтернативы исключениям. И если ref-out плох, то отнюдь не потому, что FxCop его не понимает. Если бы более удобного подхода обработки исключений не было, чем ref-out, то и FxCop на него бы не ругался.
--
Дмитро
Re[25]: error is not an exception
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 30.11.05 08:49
Оценка:
Здравствуйте, IT, Вы писали:

IT>Это всё легко покрывается юнит-тестами. Или ты их заменяешь асёртами?


Чего-то не понял а Вашей шутки. Конечно, безусловно, однозначно, в любую погоду никакие юнит-тесты в принципе не способны заменить ассерты. Грамотно расставленные ассерты предусловия, инвариантов и постусловия — это доказательство правильности программы вообще, а юнит-тесты — лишь свидетельство, что данные конкретные тесты проходят, но не доказательство правильности программы вообще.
Re[31]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 30.11.05 08:58
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Любая функция в некоторой области либо регулярна, либо не регулярна; определена или не определена; вычислима или не вычислима. Вы говорите что представления у нас о ней нет, это означает что мы должны думать о ней самое худшее. А раз так, то она может возвращать кроме чисел еще и nonNumber, plusInfinity, minusInfinity. До кучи, пусть она еще возвращает значение nonCalculable — нельзя вычислить.


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

СГ>>>Если заранее известно, что процедура-функция f(x) может быть не определена ...


P>>Не известно.


СГ>А мне, например, это известно.


Откуда?
Re[33]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 30.11.05 10:30
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Да дело то не в том, что бяка может выскочить на неровном месте, а в том, что реальное программирование всегда происходит в режиме недостаточной информации.


[...]

Мне-то это понятно. Я, правда, не всегда могу нормально объяснять. За что мне время от времени еще в институте снижали оценки на экзаменах. Да и сейчас на всяких там совещаниях я мало разговариваю.
Re[34]: Что вы предлагаете на замену эксепшенов?
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.11.05 11:13
Оценка:
Здравствуйте, Privalov, Вы писали:
P>Мне-то это понятно. Я, правда, не всегда могу нормально объяснять. За что мне время от времени еще в институте снижали оценки на экзаменах. Да и сейчас на всяких там совещаниях я мало разговариваю.
А ты в форумы пиши
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[35]: Что вы предлагаете на замену эксепшенов?
От: Privalov  
Дата: 30.11.05 11:55
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>А ты в форумы пиши


Вот, пытаюсь.
Re[29]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 30.11.05 12:12
Оценка:
Здравствуйте, dshe, Вы писали:

D>Насколько я понимаю, проблемы возникаеют когда встречаются два взаимоисключающий подхода (обработки исключений, в данном случае). Если бы стиль ref-out был общепринятым, то и ExecuteЧего-То-ТамSp его бы тоже поддерживал. И в этом случае пришлось бы написать длиннючий switch для того, чтобы Errors err преобразовать в исключения.


В принципе, AndrewJD уже ответил. В дополнении могу сказать, что в случае с исключениями нам делать ничего не надо, т.к. они просто пролетят выше. Если мы их хотим сконвертировать в коды возврата, то достаточно их отловить, выковырять из них сообщение и вернуть даже один код возврата на все случаи жизни, мол не шмагла. Если же метод будет возвращать тоже коды возврата, да ещё и без сообщений, то придётся обрабатывать их все, что-то можно забыть, что-то может быть добавлено разработчиками метода позже.

D>Полагаю, FxCop не знает об использования стиля ref-out как альтернативы исключениям. И если ref-out плох, то отнюдь не потому, что FxCop его не понимает. Если бы более удобного подхода обработки исключений не было, чем ref-out, то и FxCop на него бы не ругался.


Это просто более громоздкая конструкция. В том же примере можно было создать err в вызывающем методе и передавать его обычным способом. Т.е. out/ref параметров практически всегда можно избежать и их наличие очень точный индикатор проблем в дизайне.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[30]: Что вы предлагаете на замену эксепшенов?
От: vdimas Россия  
Дата: 30.11.05 13:15
Оценка:
Здравствуйте, IT, Вы писали:

IT>Это просто более громоздкая конструкция. В том же примере можно было создать err в вызывающем методе и передавать его обычным способом. Т.е. out/ref параметров практически всегда можно избежать и их наличие очень точный индикатор проблем в дизайне.


Оффтоп, надеюсь на громоздкие value-типы этот принцип не распространяется?
Re[12]: Вот подумалось
От: vdimas Россия  
Дата: 30.11.05 13:38
Оценка:
Здравствуйте, reductor, Вы писали:

R>Но конечно основной смысл в том, что если у нас есть

R>
R>// некий абстрактный код
R>int y = 5;
R>if (x == 1) return y;
R>y++;
R>if (x == 2) return y;
R>return y + 5
R>

R>То понять что здесь происходит невозможно ни компилятору (та самая проблема с автоматами) ни человеку.

Я в очередной раз ловлю себя на ступоре после прочтения подобной фразы. Может я чего-то не понимаю? Откуда у компилятора или у человека сложности с прочтением? Насчет обязательности соответствия y<=f(x) мне понятно, насчет каких-то затруднений компиляции — нет. Хочешь, прямо здесь и сейчас граф детерминриованного автомата нарисую по этому куску кода? Не знаю, как другие программисты трассируют исходники в голове, но я, когда трассирую куски алгоритмов именно думаю как автомат — т.е. перехожу из состояние в состояние (состояние — множество значений всех локальных/глобальных переменных и проч. ячеек данных быстрой и медленной памяти, прямо или коссвено принимающих участие в алгоритме) в ответ на некие действия над этими переменными.

Где фишка? Если можно построить детерминированный автомат, то можно проверифицировать что угодно.
Re[13]: Вот подумалось
От: _Winnie Россия C++.freerun
Дата: 30.11.05 13:45
Оценка:
В банковских операциях разбираюсь, как кот в желудях, так что где-то мог и ошибиться.
О rollback-commit относительно них узнал, читая эту тему.

Вот решение на pure C.
Если можно использовать С++ RAII c автоматическим rollback в деструкторе, то всё еще красивше.
И причём тут исключения?

#include <stddef.h>

typedef struct банковская_операция_tag
{
    void *handle;
    /*...*/
} банковская_операция_t;

typedef struct банк_tag
{
    void *handle;
} банк_t;

typedef struct аккаунт_tag
{
    void *handle;
} аккаунт_t;

typedef struct кол_денег_tag
{
    long long m_количество_в_копейках;
} кол_денег_t;

void rollback(банковская_операция_t *банковская_операция);
void commit(банковская_операция_t *банковская_операция);

_Bool снять_деньги(банк_t *банк, аккаунт_t *откуда, кол_денег_t сколько, банковская_операция_t *банковская_операция);
_Bool положить_деньги(банк_t *банк, аккаунт_t *откуда, кол_денег_t сколько, банковская_операция_t *банковская_операция);
_Bool журнализовать(банк_t *банк, банковская_операция_t *банковская_операция, wchar_t *фоматирование, ...);



_Bool снять_положить_записать_на_C(банк_t *банк, аккаунт_t *откуда, аккаунт_t *куда, кол_денег_t сколько) 
{
    банковская_операция_t бо_снять = { 0 };
    банковская_операция_t бо_положить = { 0 };
    банковская_операция_t бо_журнализовать = { 0 };

    if (!снять_деньги(банк, откуда, сколько, &бо_снять)) goto ошибка;
    if (!положить_деньги(банк, куда, сколько, &бо_положить)) goto ошибка;
    if (!журнализовать(
        банк, &бо_журнализовать, локал_строка("TRANSER_MONEY_FROM_TO"), 
        аккунт_имя(откуда), аккунт_имя(куда), сколько.m_количество_в_копейках)) goto ошибка;
    
    commit(&бо_снять);
    commit(&бо_положить);
    commit(&бо_журнализовать);
    return true;
ошибка:
    rollback(&бо_снять);
    rollback(&бо_положить);
    rollback(&бо_журнализовать);
    return false;
}
Правильно работающая программа — просто частный случай Undefined Behavior
Re[31]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 30.11.05 14:19
Оценка:
Здравствуйте, vdimas, Вы писали:

IT>>Это просто более громоздкая конструкция. В том же примере можно было создать err в вызывающем методе и передавать его обычным способом. Т.е. out/ref параметров практически всегда можно избежать и их наличие очень точный индикатор проблем в дизайне.


V>Оффтоп, надеюсь на громоздкие value-типы этот принцип не распространяется?


По поводу value типов FxCop скромно молчит Но громоздкости это не убавляет всё равно.
Если нам не помогут, то мы тоже никого не пощадим.
Re[14]: Вот подумалось
От: Sergey J. A. Беларусь  
Дата: 30.11.05 14:23
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Вот решение на pure C.

_W>Если можно использовать С++ RAII c автоматическим rollback в деструкторе, то всё еще красивше.
А, если использовать и исключения, то "всё еще красивше" в ещё большей степени.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[14]: Вот подумалось
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 14:41
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>
_W>_Bool снять_положить_записать_на_C(банк_t *банк, аккаунт_t *откуда, аккаунт_t *куда, кол_денег_t сколько) 
_W>{
_W>    банковская_операция_t бо_снять = { 0 };
_W>    банковская_операция_t бо_положить = { 0 };
_W>    банковская_операция_t бо_журнализовать = { 0 };

_W>    if (!снять_деньги(банк, откуда, сколько, &бо_снять)) goto ошибка;
_W>    if (!положить_деньги(банк, куда, сколько, &бо_положить)) goto ошибка;
_W>    if (!журнализовать(
_W>        банк, &бо_журнализовать, локал_строка("TRANSER_MONEY_FROM_TO"), 
_W>        аккунт_имя(откуда), аккунт_имя(куда), сколько.m_количество_в_копейках)) goto ошибка;
    
_W>    commit(&бо_снять);
_W>    commit(&бо_положить);
_W>    commit(&бо_журнализовать);
_W>    return true;
_W>ошибка:
_W>    rollback(&бо_снять);
_W>    rollback(&бо_положить);
_W>    rollback(&бо_журнализовать);
_W>    return false;
_W>}
_W>


Может это нужно было вот в эту ветку: Goto's are evil?
Автор: Cyberax
Дата: 28.11.05
?

Хотя я бы написал что-нибудь подобное без goto:
int commit_transfer_money( transfer_money_trx_state_t * state )
    {
        commit( state->put_trx() );
        commit( state->get_trx() );
        commit( state->log_trx() );

        return 0;
    }
    
int rollback_transfer_money( transfer_money_trx_state_t * state )
    {
        rollback( state->put_trx() );
        rollback( state->get_trx() );
        rollback( state->log_trx() );
        return -1;
    }
    
int transfer_money( bank_t * bank, account_t * from, account_t * to, money_t amount )
    {
        transfer_money_trx_state_t state;
        int (*finisher)( transfer_money_trx_state_t ) = &rollback_transfer_money;
        
        if( 0 == log_transfer( bank, from, amount, &state ) &&
            0 == get_money( bank, from, amount, &state ) &&
            0 == put_money( bank, to, amount, &state ) )
            finisher = &commit_transfer_money;
            
        return (*finisher)( &state );
    }
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[13]: Вот подумалось
От: vdimas Россия  
Дата: 30.11.05 14:59
Оценка:
Здравствуйте, Геннадий Васильев, Вы писали:

ГВ>Здравствуйте, vdimas, Вы писали:


V>>Сделаю акцент еще раз на том факте, что корректное поведение программы в случае использования множественного return в неожиданных местах обычно обеспечивается доп. ср-вами самого языка. В С++ это автоматический вызов деструкторов локальных объектов (что крайне удобно, т.к. эти деструкторы вызываются только для реально инициализированных локальных переменных), в Java/C# есть try-finally для анаолгичных целей (не столь элегантно, но тоже вполне можно использовать).


V>>Таким образом, верификация даже такого кода может быть полной.

ГВ>Погоди, верификация и корректность работы компилятора — не одно и то же. Язык просто даёт нам некие автоматически работающие механизмы и не более того. И там и там есть оговорки использования и т.п. Можно и в деструкторе RAII исключение пульнуть.

Да, не точно выразился в выделенном, следовало так: язык предоставляет ср-ва для построения детерминированных программ (участков кода). Ничего, он размеется не обеспечивает, кроме перевода всего того, что мы накодили — в машинное представление.

ГВ>Другое дело, что верификация невозможна без спецификации, которой должна соответствовать программа. Нет спецификации — верификация невозможна. Вывал AV в некоторых ситуациях может расцениваться как штатное и запланированное поведение. То есть, сначала нужна полная спецификация: что можно, чего нельзя и т.п. Но такая спецификация по сложности сопоставима с самой программой, то есть, получим ту же проблему, но в профиль: языки спецификации, наследование спецификаций (множественное vs одиночное), синтаксический оверхед при специфицировании поведения и т.п.


V>> Другое дело, что мы не сможем верифицировать отдельно взятый участок (вернее можем, поясню далее), т.е. необходимо больше информации, о том, что происходит "неявно" для случая С++.


ГВ>Да ну? А что, в случае Java/C# работа GC уже стала 100% детерминированной?


Речь шла о "невидимом" вызове неких методов (деструкторов). Т.е. я намекал на неявность, хотя эта неявность очень четко специфицирована стандартом, и на нее можно смело опираться (детерминированный момент вызова деструкторов и детерминированный порядок их вызова).

В Java/C#, в отличие от, НЕ ПРИНЯТО логику помещать в финалайзеры. В стандартном Dispose-паттерне финалайзер вызывается только если есть ошибка в программе (т.е. программист забыл вызвать Dispose), как раз хорошо применимо для того, чтобы все-таки вернуть кисть оконной системе или отпустить COM-объект на все 4 стороны (лучше уж поздно, чем никогда). При работе паттерна в штатной ситуации в теле метда Dispose() происходит следующее: GC.SupressFinalize(this). Это означает, что финализатор у объекта вызван не будет, ибо не за чем.

ГВ>А полиморфный код тоже 100% сможем верифицировать?


Да, если полиморфные методы в свою очередь отвечают спецификациям.

В общем, попытаюсь обощить свою мысль. Для того, чтобы само верифицирование стало возможным, необходимо сделать программу детерминированной, т.е. иметь возможность в явном виде описать ее поведение на всем допустимом множестве входных данных. Reductor утверждал (причем, для Си/С++ — небезосновательно), что в некоторых приемах кроется опасность написания недетерминированного кода. Я в ответ показывал, как этот код приводить к детерминированному.


V>>Однако, и здесь нас ожидают бенефиты. Мы можем построить верификацию кода иерархически, т.е. проверифицировать сначала "прочистку", а затем код, использующий ее неявный вызов. Ввиду того, что целевой код неплохо сокращается в случае множественного return (или использования exceptions как продвинутой разновидности), мы можем получить как раз больше возможностей для верификации на "реальных объемах".


ГВ>Не, гиблая затея на любых объёмах. Примерно такое же ожидание панацеи, как её в своё время ожидали от перехода к языкам высокого уровня. Просто проблемы сместятся с одного уровня на другой. Всё равно задач адекватного учёта внешних условий и построения точных формулировок никто не снимет.


Где-то 10-тью постами выше я высказвал мысль о том, что верифицировать весь код просто нереально (лень даже обосновывать ) Вывод был такой, что чем выше повторное использование некоего куска кода, тем больше внимания нужно уделять этому куску. Кое-какие вещи я все же трассирую "пальчиком по экрану" полностью в некоторые моменты разработки, по всем возможным веткам. Заодно хочешь не хочешь, вынужден эти участки писать как можно проще, иначе подобное занятие станет невозможным.

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


------------
Конкретно в нашем проекте, тот участок, где я собираю метаинформацию, которая комбинируется из типов самих полей, типов соотв. полей в базе с учетом ограничений (длина + nullable), с последующим наложением других аттрибутов (в описании полей в C#), вычислением значений по-молчанию и т.д. и т.п. Чтобы обложить это дело юнит-тестами полностью, это нужна весьма длинная простыня кода самих тестов с различными тестовыми комбинациями, которые по объему далеко перепрыгнут нашу предметную модель. Поэтому юнит-тесты написаны на самые "популярные" сочетания, дополнительно довольно много внимания уделил именно этому куску, и в сочетании с первым делаю предположение, что все остальные всевозможные сочетания (их число конечно, просто очень большое) будут работать корректно.

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

Подход вполне имеет право на жизнь. Мне только претит когда народ оголтело бросается в юнит тесты "потому что так надо и рулез", бросаются писать нешуточные тест-кейзы, когда тестировать еще тольком нечего, и потом тонны труда пропадают в момент выкидывания этих тестов или серьезной переделки. В общем, несмотря на родителя XP, сами юнит тесты необходимо очень даже планировать

-------------
Описанный полуэмпирический подход до того популярен, что его уже используют в академических кругах. Ту ОС на .Net, которую разрабатывают пара PhD для Microsoft, они впихнули в единое физическое адресное пространство (!!!), т.е. соседние процессы легко могут наступить друг-другу на лапы... Но это теоретически. А практически, создается некое ядро, компилятор, JIT + верификатор. Эти блоки образуют "пояс целомудрия", тот самый базис доверия, в которую они будут аккуратно запускать пользовательские приложения, нещадно их верифицируя по чем зря. Т.е., они считают, что разработчики ПО все-таки смогут выполнять свою работу не хуже разработчиков железа, и поддержка железки им уже не требуется.

(Раньше этот пояс целомудрия висел на уровне аппаратной реализации защиты памяти. Блин, народ, обидно же... Взрослые дядьки отвели детишкам песочницу, играйтесь, только не поцарапайтесь. И все в ответ: "да-да-да, поцарапаться можно так легко и незаметно, давайте-ка там делайте нам безопасные песочницы для игр".)

В общем посмотрим на эту Сингулярити. Мне пока кажется, что слова "теоретически" и "практически" запросто можно менять местами на данном этапе
Re[28]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 30.11.05 15:31
Оценка:
Здравствуйте, IT, Вы писали:

IT> Непонятно почему ты пропустил целый лэйер, но да бог с ним.


Прости, пропустил потому что там я написал бы тоже самое.

IT> ты совсем забыл сделать Rollback транзакции в случае ошибки.


Нет, не забыл. RollBack спрятан внутри accessor.Close и срабатывает автоматически если не было Commit

IT> Ошибки двух методов StealSomeXXX ты тоже почему-то решил не обрабатывать.


Инициатива наказуема... Хорошо, вот буквальный перевод Вашего кода:
  PROCEDURE (VAR this: AccountService) WithdrawalAndGetBalance (accountNumber: ARRAY OF CHAR; amount: REAL; OUT balance: REAL; VAR err: Errors.List): BOOLEAN, NEW;
    VAR r: BOOLEAN; accessor: AccountDataAccessor;

    PROCEDURE TransAction (): BOOLEAN;
    BEGIN
      IF ~accessor.GetBalance(accountNumber, balance, err) THEN RETURN FALSE END;
      IF balance < amount THEN 
        err := Errors.NewList(Errors.NewError('You are freaking bankrupt!'), err);
        RETURN FALSE
      END;
      balance := balance - amount;
      IF ~accessor.SetBalance(accountNumber, rest, err) THEN RETURN FALSE END;
      IF balance > 1.0E6 THEN
        IF ~accessor.StealSomeForMe(accountNumber, 1.15, err) THEN RETURN FALSE END;
        balance := balance - 1.15
      END;
      IF balance > 1.0E7 THEN
        IF ~accessor.StealSomeForHomelessPeople(accountNumber, 1.15, err) THEN RETURN FALSE END;
        balance := balance - 1.15
      END;
      IF ~accessor.ChargeForService(accountNumber, 10.0, err) THEN RETURN FALSE END;
      balance := balance - 10.0;
      RETURN TRUE
    END TransAction;

  BEGIN r := ValidateAccountNumber(accountNumber, err) & ValidateAmount(amount, err);
    IF r THEN
      accessor.Init;
      r := accessor.BeginTransaction(err) & TransAction() & accessor.CommitTransaction(err);
      accessor.Close  (* <------ RollBack спрятан здесь внутри accessor.Close и срабатывает автоматически если не было Commit *)
    END;
    RETURN r
  END WithdrawalAndGetBalance;
Re[28]: error is not an exception
От: IT Россия linq2db.com
Дата: 30.11.05 15:33
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Ну, мне лично кажется, что ассерты никак не мешают юнит тестам. Как и наоборот.


Подветка у нас началась вообще-то с того, что асёрты могут быть использованы вместо некоторых фич отладчика. О мешают/не мешают никто и не говорил. Я лишь пытаюсь утверждать, что, так как любое решение имеет как свои достоинства так и недостатки, то на сегодняшний день, при наличии современных средств отладки и тестирования, важность и достоинства асёртов легко ими покрываются. При этом вместе с асёртами уходят и их недостатки — замусоривание кода и спец. эффекты от использования макросов.

Вот и всё, что я хотел сказать. Надеюсь, я высказался достаточно осторожно, чтобы не дать повод к очередному флейму
Если нам не помогут, то мы тоже никого не пощадим.
Re[26]: error is not an exception
От: reductor  
Дата: 30.11.05 16:25
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:


СГ>Чего-то не понял а Вашей шутки. Конечно, безусловно, однозначно, в любую погоду никакие юнит-тесты в принципе не способны заменить ассерты. Грамотно расставленные ассерты предусловия, инвариантов и постусловия — это доказательство правильности программы вообще, а юнит-тесты — лишь свидетельство, что данные конкретные тесты проходят, но не доказательство правильности программы вообще.


Это персональное сообщения и вовсе не для флейма.

Я конечно понимаю полную бесперспективность этого совета, но
Вам, совершенно очевидно, просто необходимо познакомиться с язками, произведенными от ML и ISWIM — Haskell или на худой конец SML — хотя бы чтобы потом уметь тут же доказать вот это ваше утверждение (а доказательство этому существует уже лет 50 вообще и 40 в программировании)
Опять же, в Хаскеле вы, как теорфизик (если я ничего не путаю), найдете там немало знакомого.

Прошу прощения, я не смог не сказать этого :)
Re[27]: error is not an exception
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 16:34
Оценка:
Здравствуйте, reductor, Вы писали:

R>Вам, совершенно очевидно, просто необходимо познакомиться с язками, произведенными от ML и ISWIM — Haskell или на худой конец SML — хотя бы чтобы потом уметь тут же доказать вот это ваше утверждение (а доказательство этому существует уже лет 50 вообще и 40 в программировании)


Не совсем понял... Из этого следует, что уже 40 лет есть способ писать безошибочные программы?
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[29]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 30.11.05 16:51
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

IT>> ты совсем забыл сделать Rollback транзакции в случае ошибки.


СГ>Нет, не забыл. RollBack спрятан внутри accessor.Close и срабатывает автоматически если не было Commit


Ах, ну да, как я мог об этом не подумать, это же так очевидно из твоего кода

СГ>Инициатива наказуема... Хорошо, вот буквальный перевод Вашего кода:


Давай его ещё раз переведём, на этот раз твой код в твоём стиле, но с исключениями (синтаксиса исключений паскаля не знаю, поэтому буду сочинять).

PROCEDURE (VAR this: AccountService) WithdrawalAndGetBalance (accountNumber: ARRAY OF CHAR; amount: REAL): REAL, NEW;
  VAR balance: REAL; accessor: AccountDataAccessor;
BEGIN ValidateAccountNumber(accountNumber); ValidateAmount(amount); accessor.Init; accessor.BeginTransaction;
  balance := ~accessor.GetBalance(accountNumber);
  IF balance < amount THEN throw Errors.NewList(Errors.NewError('You are freaking bankrupt!')); END;
  balance := balance - amount;
  ~accessor.SetBalance(accountNumber, balance);
  IF balance > 1.0E6 THEN ~accessor.StealSomeForMe(accountNumber, 1.15); balance := balance - 1.15 END;
  IF balance > 1.0E7 THEN ~accessor.StealSomeForHomelessPeople(accountNumber, 1.15); balance := balance - 1.15 END;
  ~accessor.ChargeForService(accountNumber, 10.0);
  balance := balance - 10.0;
  accessor.CommitTransaction;
  RETURN balance;
END WithdrawalAndGetBalance;

Может посчитать количество строчек. Выигрышь более чем в два раза при гораздо более высокой наглядности (если слово наглядность вообще уместно при таком стиле).
Если нам не помогут, то мы тоже никого не пощадим.
Re[28]: error is not an exception
От: reductor  
Дата: 30.11.05 17:13
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, reductor, Вы писали:


R>>Вам, совершенно очевидно, просто необходимо познакомиться с язками, произведенными от ML и ISWIM — Haskell или на худой конец SML — хотя бы чтобы потом уметь тут же доказать вот это ваше утверждение (а доказательство этому существует уже лет 50 вообще и 40 в программировании)


E>Не совсем понял... Из этого следует, что уже 40 лет есть способ писать безошибочные программы?



Да.
Насколько это возможно в условиях существования основного ограничения теории автоматов и теоремы геделя о неполноте.
Но для большинства случаев (А вариантов ошибок и того что считать таковыми несколько больше, чем просто ошибка в программе и ошибка в данных) ответ — Да. 40 лет и последние лет 15 еще и очень практичный способ (аппарат расширили).

Но, заренее хочу сказать, здесь и сейчас доказывать это и спорить по этому поводу я не буду. Нет интереса.
Re[29]: error is not an exception
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 17:28
Оценка:
Здравствуйте, reductor, Вы писали:

E>>Не совсем понял... Из этого следует, что уже 40 лет есть способ писать безошибочные программы?


R>Да.


А мужики-то и не знают...


R>Насколько это возможно в условиях существования основного ограничения теории автоматов и теоремы геделя о неполноте.

R>Но для большинства случаев (А вариантов ошибок и того что считать таковыми несколько больше, чем просто ошибка в программе и ошибка в данных) ответ — Да. 40 лет и последние лет 15 еще и очень практичный способ (аппарат расширили).

R>Но, заренее хочу сказать, здесь и сейчас доказывать это и спорить по этому поводу я не буду. Нет интереса.


Лично со мной на эту тему спорить бесполезно. Разве что опубликовать этот способ.

Вспоминается, как на одной научной конференции довелось послушать одну тетеньку, которая продвигала какой-то частотный резонатор, как панацею от всех болезней. Типа того, что у всех клеток есть своя частота колебаний. И все больные или болезнетворные клетки (вирусы там всякие) находятся в других диапазонах, чем колебания здоровых клеток. Отсюда простое решение -- нужно взять генератор волн с такой же частотой, но противоположной фазой, разместить рядом больным и все -- больные клетки разрушатся в результате частотного резонанса. Эту тетеньку еще по НТВ в какой-то передаче показывали, с такими же росказнями.

Чей-то мне она вспомнилась.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[30]: error is not an exception
От: reductor  
Дата: 30.11.05 17:45
Оценка:
Здравствуйте, eao197, Вы писали:


E>>>Не совсем понял... Из этого следует, что уже 40 лет есть способ писать безошибочные программы?


R>>Да.


E>

E>А мужики-то и не знают...


счастье — в неведении.


E>Лично со мной на эту тему спорить бесполезно. Разве что опубликовать этот способ.


Все значимые публикации по теории типов, лямбда-исчислению, комбинаторной логике, SKI-исчислению, изоморфизму Карри-Говарда и теории категорий лежат в свободном доступе и находятся через любой поисковик.


E>Чей-то мне она вспомнилась. :xz:


Замечательный и важный для темы случай.
Очень интересная, наверное, конференция была. И очень научная.


На этом позвольте прекратить свое участие в этой теме.
Re[31]: error is not an exception
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 17:51
Оценка:
Здравствуйте, reductor, Вы писали:

R>счастье — в неведении.


Причем неведают все. Ладно сообщество Linux-оидов никак баги из ядра вычистить не могут. Но вот MS-то чего глюкавый софт пишет? Уж они-то могли себе позволить лучшие наработки в этой области на службу поставить.

R>Замечательный и важный для темы случай.

R>Очень интересная, наверное, конференция была. И очень научная.

Конференция-то нормальная была. Просто на открытии в президиуме сидел какой-то мужик, замминистра какого-то, вот он ее и выдвинул на трибуну, вместо какого-то профессора, который должен был свой доклад прочитать. Любят во власти такого рода шарлатанов.

А в науке, похоже, верят, что программы можно писать без ошибок.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[28]: error is not an exception
От: GlebZ Россия  
Дата: 30.11.05 18:22
Оценка:
Здравствуйте, eao197, Вы писали:

E>Не совсем понял... Из этого следует, что уже 40 лет есть способ писать безошибочные программы?

Вообще-то reductor в отношении функциональных языков прав. С помощью редуцирования лямбда функций можно построить глобальную мат. модель вычислений и математически проверить ее на соответвие. В отношении императивных языков, в большинстве случаев, такое не пройдет. Слишком сложная структура чтобы ее можно было автоматически описать. До некоторой степени можно проверить простейшие случаи опытным путем с помощью unit-тестов. Но тут есть одна проблемка. Все это работает до тех пор, пока мы можем доказанно описать входные и выходные параметры. Ну например, у нас на входе есть некоторая грамматика, допустим состоящая из 20 лексем. Тогда всего количество цепочек лексем у нас будет 20^20, считай что неисчеслимо. В результате, проверить все мы физически не сможем. Если мы сможем из этих лексем построить вполне понятную мат. модель соответсвия к результатам, то добавив полученную мат. модель вычислений из функционального языка вполне возможно.
Для доведения до некоторого уровня надежности, обычно применяют свои методики(коих дост. много). Ну например, у нас входной параметр находится на некоторой числовой прямой. Мы берем минимальное значение, максимальное значение и некоторое значение из середины. После unit теста с некоторой эвристической вероятностью мы можем утверждать что функция работает.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[15]: Вот подумалось
От: _Winnie Россия C++.freerun
Дата: 30.11.05 18:26
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, _Winnie, Вы писали:


V>Вот у тебя очень показательная ошибка. Надо писать так:

V>
V>goto ошибка_снять;
V>goto ошибка_положить;
V>goto ошибка_журналировать;
V>


V>а последний кусок вообще надо в обратном порядке:

V>
V>ошибка_журналировать:
V>    rollback(&бо_журнализовать);
V>ошибка_положить:
V>    rollback(&бо_положить);
V>ошибка_снять:
V>    rollback(&бо_снять);
V>    return false;
V>



V>Т.е. самому вручную раскручивать стек в правильном порядке. Если бы ты использовал исключения, то тебе правильный порядок был бы гарантирован.



Не-не-не.

Я не написал, но подразумевал, что объект, который инициализирован по-умолчанию — можно безопасно убить.
банковская_операция_t бо_снять = { 0 };


Товарищ, вы мало программировали на C

Вот такой же безопасный код:

void f()
{
    FILE *file = NULL;
    char *name = NULL;
    char *last_name = NULL;

    file = fopen("data.txt", "rb");
    if (!file)  goto error;

    name = (char*)malloc(name_len + 1);
    if (!name)  goto error;

    last_name = (char*)malloc(last_name_len + 1);
    if (!last_name)  goto error;

    /* работаем с файлом и памятью */
error:
    if (file)
        fclose(file);
    free(name);
    free(last_name);
}


это общеизвестный goto cleanup паттерн.

Ну хорошо.
То, что это на С, это я выпендрился.


Кстати, у меня в коде настоящая ошибка, которую вы не заметили.
локал_строка("TRANSER_MONEY_FROM_TO") 
локал_строка("TRANSFER_MONEY_FROM_TO")




bool снять_положить_записать_на_C_plus_plus(банк_t *банк, аккаунт_t *откуда, аккаунт_t *куда, кол_денег_t сколько) 
{
    банковская_операция_t снять = банк->снять_деньги(откуда, сколько);
    if (!снять) return false;
    банковская_операция_t положить = банк->положить_деньги(куда, сколько);
    if (!положить) return false;
    std::string формат_мессаги;
    if (!локал_строка("TRANSER_MONEY_FROM_TO", формат_мессаги))
        return false;
    банковская_операция_t журнализовать = банк->записать(формат_мессаги, откуда->имя(), куда->имя(), сколько.m_количество_в_копейках);
    if (!журнализовать) return false;

    commit(снять, положить, журнализовать);
    
    return true;
}


Мда. Всё-таки с исключениями проще...
Придётся согласиться.

#define CHECK(x) if (!x) return false;

void снять_положить_записать_на_C_plus_plus(банк_t *банк, аккаунт_t *откуда, аккаунт_t *куда, кол_денег_t сколько) 
{
    банковская_операция_t снять = банк->снять_деньги(откуда, сколько);
    банковская_операция_t положить = банк->положить_деньги(куда, сколько);
    банковская_операция_t журнализовать = 
        банк->записать(
            локал_строка("TRANSFER_MONEY_FROM_TO", формат_мессаги), 
            откуда->имя(), куда->имя(), сколько.m_количество_в_копейках);
    commit(снять, положить, журнализовать);
}
Правильно работающая программа — просто частный случай Undefined Behavior
Re[9]: error is not an exception
От: GlebZ Россия  
Дата: 30.11.05 19:44
Оценка:
Здравствуйте, IT, Вы писали:

IT>У меня есть как минимум две причины.

[...skipped]
Занятно. Только что нашел на блоге Tess Ferrandes Are you aware that you have thrown over 40,000 exceptions in the last 3 hours?
Оттуда:

So why are they so bad? If they are handled and the end users don’t see them are they really harmful?
I can think of 3 reasons off the top of my head.
Exceptions are expensive.
Exceptions can take you into unnecessary code paths.
Exceptions are generally thrown when something went wrong.


С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[29]: error is not an exception
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 30.11.05 23:55
Оценка:
Здравствуйте, GlebZ, Вы писали:

E>>Не совсем понял... Из этого следует, что уже 40 лет есть способ писать безошибочные программы?

GZ>Вообще-то reductor в отношении функциональных языков прав. С помощью редуцирования лямбда функций можно построить глобальную мат. модель вычислений и математически проверить ее на соответвие. В отношении императивных языков, в большинстве случаев, такое не пройдет. Слишком сложная структура чтобы ее можно было автоматически описать.

Ребята, ни в моем вопросе, ни в утверждениях Губанова или reductor-а не было ограничений на функциональные языки или объемы программ.
Поэтому все это отговорки, мол где-то когда-то и пр...
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[14]: Вот подумалось
От: Костя Ещенко Россия  
Дата: 01.12.05 01:16
Оценка:
Здравствуйте, reductor, Вы писали:

R>>>Но конечно основной смысл в том, что если у нас есть

R>>>
R>>>// некий абстрактный код
R>>>int y = 5;
R>>>if (x == 1) return y;
R>>>y++;
R>>>if (x == 2) return y;
R>>>return y + 5
R>>>

R>>>То понять что здесь происходит невозможно ни компилятору (та самая проблема с автоматами) ни человеку.

V>>Я в очередной раз ловлю себя на ступоре после прочтения подобной фразы. Может я чего-то не понимаю? Откуда у компилятора или у человека сложности с прочтением? Насчет обязательности соответствия y<=f(x) мне понятно, насчет каких-то затруднений компиляции — нет. Хочешь, прямо здесь и сейчас граф детерминриованного автомата нарисую по этому куску кода? Не знаю, как другие программисты трассируют исходники в голове, но я, когда трассирую куски алгоритмов именно думаю как автомат — т.е. перехожу из состояние в состояние (состояние — множество значений всех локальных/глобальных переменных и проч. ячеек данных быстрой и медленной памяти, прямо или коссвено принимающих участие в алгоритме) в ответ на некие действия над этими переменными.


R>http://en.wikipedia.org/wiki/Halting_problem


[]

Конкретно с этим постом я согласен.
Но насколько я понял, этот текст должен был "доказать" вред множественного return, и с этим я совершенно не согласен. Произошла подмена понятий — вместо мифических сложностей верификации кода с множественным return, ты говорил о невозможности верификации в общем случае.
Сорри, если я чего не так понял.
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[15]: Вот подумалось
От: reductor  
Дата: 01.12.05 01:22
Оценка:
Здравствуйте, Костя Ещенко, Вы писали:


КЕ>Конкретно с этим постом я согласен.

КЕ>Но насколько я понял, этот текст должен был "доказать" вред множественного return,

Нет. Если вы перечитаете все сверху вниз.

КЕ>и с этим я совершенно не согласен.


Нет проблем.

КЕ>Сорри, если я чего не так понял.


Ничего, бывает.
Re[27]: error is not an exception
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 01.12.05 08:12
Оценка:
Здравствуйте, reductor, Вы писали:

R>Вам, совершенно очевидно, просто необходимо познакомиться с язками, произведенными от ML и ISWIM — Haskell или на худой конец SML


Спасибо, как-нибудь познакомлюсь...
Re[29]: error is not an exception
От: Cyberax Марс  
Дата: 01.12.05 10:39
Оценка:
GlebZ wrote:

> E>Не совсем понял... Из этого следует, что уже 40 лет есть способ

> писать безошибочные программы?
> Вообще-то reductor <http://rsdn.ru/Users/Profile.aspx?uid=48135&gt; в
> отношении функциональных языков прав. С помощью редуцирования лямбда
> функций можно построить глобальную мат. модель вычислений и
> математически проверить ее на соответвие.

На соответствие ЧЕМУ? Как вы будете составлять reference model?

У вас просто сместится сложность с проверки программного кода на
соответствие с требованиями задачи на проверку мат. модели на
соответствие требованиям задачи.

Иногда это имеет смысл, например, была доказана "правильность" софта
управления парижским метрополитеном. Под "правильностью" понимается
невозможность такой ситуации, при которой два поезда столкнутся.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[30]: error is not an exception
От: GlebZ Россия  
Дата: 01.12.05 11:52
Оценка:
Здравствуйте, Cyberax, Вы писали:


C>На соответствие ЧЕМУ? Как вы будете составлять reference model?

А что такое reference model в терминах функционального языка?

C>У вас просто сместится сложность с проверки программного кода на

C>соответствие с требованиями задачи на проверку мат. модели на
C>соответствие требованиям задачи.
Нет. Сложность получения модели можно автоматизировать. Если не иметь императива, можно получить и даже одно уравнение. Единственная проблема — это выявление мат. модели между входными и выходными параметрами.

C>Иногда это имеет смысл, например, была доказана "правильность" софта

C>управления парижским метрополитеном. Под "правильностью" понимается
C>невозможность такой ситуации, при которой два поезда столкнутся.
+1

С уважением, Gleb.
PS никогда не думал что буду защищать функциональные языки
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[30]: error is not an exception
От: GlebZ Россия  
Дата: 01.12.05 11:52
Оценка:
Здравствуйте, eao197, Вы писали:

GZ>>Вообще-то reductor в отношении функциональных языков прав. С помощью редуцирования лямбда функций можно построить глобальную мат. модель вычислений и математически проверить ее на соответвие. В отношении императивных языков, в большинстве случаев, такое не пройдет. Слишком сложная структура чтобы ее можно было автоматически описать.


E>Ребята, ни в моем вопросе, ни в утверждениях Губанова или reductor-а не было ограничений на функциональные языки или объемы программ.

Поэтому я и развернул ответ на всякий случай. То есть говорить что можно или нельзя сразу для всех стилей, невозможно. А reductor привел в пример именно функциональные языки.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[12]: Вот подумалось
От: srggal Украина  
Дата: 01.12.05 12:45
Оценка:
Здравствуйте, Belsen, Вы писали:

[]

Сейтесь-смейтесь, а мне доводилось потом разбиратся в подобно коде, дабы убрать исключения, только он был понавернутее, и без ошибок не обошлось

Есть же люди, которые шуток не понимают, вот и пишут потом точно такой код в продакшн Ж(
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[6]: Вот подумалось
От: srggal Украина  
Дата: 01.12.05 12:59
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Нет, это уже религия. Все нормальные программисты уже давно перестали

C>флеймить по поводу GOTO и структурного программирования, так как по
C>нынешним меркам это уже далеко не самый главный вопрос. Все
C>программисты, которых я знаю, думают примерно так: "GOTO это плохо?" —
C>"Плохо". "Структурное программирование хорошо?" — "Да". "Единый return,
C>выход из вложенных циклов по флагам, отсутствие break — оно надо?" — "А
C>нафига?"

МОЩНО, но есть и ещё одно, единственный ретурн заставляет писать очень маленькие по функционалц функции, в противном случае страдает читабельность, каждое ветвление, — это отступ в программе, чем больше отступ — тем больше нужна диагональ монитора. А я уже высказывал свой ИМХО: зависимость от диагонали монитора не есть гуд.

А если ещё и н епользоваться исключениями — то производители мониторов перестанут успевать за потребностями програмистов.

Пример навскидку, не жизненный, просто для демонстации того, о чем грю:

int foo()
{
    bool    RetVal = S_ERROR; // из-за единственной точки выхода

    CXXRecordset* pRs = new( nothrow ) CXXRecordset;
    
    if( pRs )
    {
        if ( pRS->Open() )
        {
            if ( !pRS->Eof() )
            {
                pRs->MoveFirst();
                while( !pRs->Eof() )
                {
                    ...
                    
                    if ( pRs->Next() )
                    {
                        RetVal = RSNEXT_ERROR;
                        break;
                    }
                }
                RetVal = S_OK; // ГЛАВНОЕ не забыть, а где именно у нас успешно выполнилась функция ;)
            }
        }
    }
    
    return bRetVal 
}
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[31]: Что вы предлагаете на замену эксепшенов?
От: IT Россия linq2db.com
Дата: 01.12.05 14:15
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Фигнёй страдаете, однако .


Да я уже понял. Тем, для кого простота и наглядность кода является пустым звуком, доказывать что-либо бесполезно.

СГ>Кстати, символ "~" в Modula/Oberon-ах обозначает инструкцию логического отрицания


Мне как-то всё равно. После того, что я увидел в твоём исполнении, я уже вряд ли когда-нибудь буду интересоваться этими языками.
Если нам не помогут, то мы тоже никого не пощадим.
Re[16]: Вот подумалось
От: vdimas Россия  
Дата: 02.12.05 00:01
Оценка:
Здравствуйте, _Winnie, Вы писали:


_W>Не-не-не.


_W>Я не написал, но подразумевал, что объект, который инициализирован по-умолчанию — можно безопасно убить.




_W>Товарищ, вы мало программировали на C


пожалуй, черезчур много, надо было раньше на С++ переходить (перешел только в 1993-94-м)

_W>Вот такой же безопасный код:

_W>
_W>error:
_W>    if (file)
_W>        fclose(file);
_W>    free(name);
_W>    free(last_name);
_W>}
_W>


_W>это общеизвестный goto cleanup паттерн.


Я бы поверил, если бы видел в жизни хоть один RollBack, который не кидает исключениями при применении его к отсутствующей транзакции (метке транзакции)

_W>Ну хорошо.

_W>То, что это на С, это я выпендрился.

Почему обязательно на С? На С++ тоже достаточно мест, где лучше и правильней использовать коды возврата, а не исключения. Там выше давались факторы, влияющие на конкретное решение. Поэтому я как бы считал что это С++. Разумеется, если написано на С, и если операция rollback ничего фатального не сделает в случае невалидных аргументов (я никакие неупомянутые сразу "если" не забыл?), то ты почти отмазался


_W>Мда. Всё-таки с исключениями проще...

_W>Придётся согласиться.

Да, но в С++ свои сложности с исключениями. Навскидку:
— нет единого стандартного базового исключения, соответственно зачастую или непонятно что ловить, или ловить приходится много несвязанных типов
— безопасно можно использовать только семантику по значению, ввиду этого:
— сложно вкладывать исключения друг в друга (как в Java/C#), из-за этого невозможно получить цепочку на некоем верхнем уровне после серии фильтраций на нижних
— если взять иерархию от STL-ексепшена, то возникают вопросы по формированию char* what() динамически. Нам же надо обеспечить конструкторы копирования, т.е. приходится возиться со смарт-поинтерами для строки сообщения — накладные расходы, и в этом случае ситуацию нехватки памяти приходится обрабатывать сквозняком через все уровни отдельно, без фильтрации и динамических выделений.

В общем, я неоднократно строил свои иерархии ексепшенов, и боком и раком, но никогда не получалось сделать так, чтобы остался полностью доволен. Ввиду этого, наборы исключений и их фильтрацию в разных сценариях необходимо проектировать вместе с системой. Но при эттом теряется весьма удобное св-во ексепшенов — расширения множества оных "по мере надобности".
Re[8]: Что вы предлагаете на замену эксепшенов?
От: vdimas Россия  
Дата: 02.12.05 00:08
Оценка:
Здравствуйте, Дарней, Вы писали:

ПК>>Несложно и недолго начиная с VC++ 6 SP4 или GCC 2.95. Вы используете что-нибудь более старое?


Д>это давно уже было, да и компилятор — специально заточенная под девайс версия GCC

Д>в общем, с шаблонами там проблематично было

Ну... можно еще макросами генерить код, не только шаблонами

#define DEF_DELEGATE1(arg_type1) ...

#define DEF_DELEGATE2(arg_type1, arg_type2) ...

вот как бы исходник, который несложно переделать http://www.rsdn.ru/Forum/Message.aspx?mid=908731&amp;only=1
Автор: vdimas
Дата: 21.11.04


-------
там где с компиляторами С++ сложно, имхо с .Net еще сложнее
Re[32]: Что вы предлагаете на замену эксепшенов?
От: SleepyDrago Украина  
Дата: 02.12.05 06:45
Оценка:
Здравствуйте, IT, Вы писали:
//код примера красоты работы с исключениями поскипан

Прочитал всю тему и захотелось подлить масла в огонь (пусть я и не согласен с автором темы).
Если я не перепутал то прекрасный пример который мы видели основан на гарантиях небросания
db_connection.rollback()throw()
db_connection.close()throw()
db_connection.~db_connection()throw()

В жизни подобные гарантии эээ "не совсем верны" так ведь ? Насколько я помню дискуссию на clcm по этому поводу
("RAII and resource release functions that can throw" Scott Meyers 20 Фев. 04:26)
в реальном коде обработки банковских транзакций придется ловить все что оттуда вылетает. (те красота в природе не встречается).

И еще один вопросик.
Сдесь была подветка по обработке "нечисел" в формулах и вычислениях. Кто нибудь может показать минимальный пример кода с использованием исключений ? А то создается впечатление что в хендлере верхнего уровня можно "угадать" результат функции по типу "нечисла" которое оттуда вылетело

wbr

Зы все вышесказанное всего лишь мои пять копеек.
Re[2]: Фильтрация исключений
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.12.05 09:09
Оценка:
Здравствуйте, Ignoramus, Вы писали:

I>Как обычно осуществляют фильтрацию исключений? Может существует какой-то хитрый способ автоматического "оборачивания" исключений на промежуточных уровнях, о котором я не знаю?

Пардон, а чего ты ожидаешь от этого автоматического оборачивания?
В дотнете, к примеру, можно на каждом логическом уровне оборачивать исключения для указания контекста.
Примерно так:
public static Library OpenLibrary(string libId)
{
    #region Arguments validation
  if(libId == null)
      throw new ArgumentNullException("libId");
    #endregion
    try
    {
       return libraries[libId].Open();
    }
    catch(IndexOutOfRange ioor)
    {
      throw new LibraryNotFoundException("specified library not found", libId, ioor);
    }
    catch(Exception e)
    {
      throw new LibraryException("Could not load library with id = " + libId, e);
    }
}

Это означает, что вызывающий код
а) может не заморачиваться с тем, чтобы ловить абстрактные NullReferenceException, который произошел хрен знает где ниже по стеку. Вместо этого можно отлавливать более осмысленные, с его точки зрения, LibraryException и строить на них свою логику (например, попытаться загрузить дефолтную Library, чтобы это ни значило).
б) может получить информацию о причинах проявления высокоуровневого исключения через InnerException. В частности, админ (если от него это не скрыть) сможет понять, что был AccessViolation или FileNotFound.

Да, на первый взгляд это все очень плохо, т.к альтернативой был бы
public static Library OpenLibrary(string libId)
{
     return libraries[libId].Open();
}

который намного короче, яснее, и удобнее в написании. К сожалению, в поддержке подобный код далеко не настолько удобен. К счастью, далеко не всегда нужно писать так много кода.
Как правило речь идет только о фасадном коде, а все внутренние потроха можно оставить в первоначальном виде. Вовсе незачем заворачивать исключение в столько же оберток, сколько методов было на стеке. Обычно обертывание полезно только при пересечении логического уровня.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[28]: Что вы предлагаете на замену эксепшенов?
От: 3axapov  
Дата: 02.12.05 09:47
Оценка:
Здравствуйте, IT, Вы писали:

IT>Да, кстати, использование ref и out параметров считается признаком плохого дизайна. FxCop на это заявляет "Consider a design that does not require that 'parameter_name' be an out parameter".


Если не трудно, нельзя ли раскрыть эту мысль, или носом ткните, где почитать, что плошого в ref и out параметрах?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Фильтрация исключений
От: Ignoramus  
Дата: 02.12.05 10:10
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Ignoramus, Вы писали:


I>>Как обычно осуществляют фильтрацию исключений? Может существует какой-то хитрый способ автоматического "оборачивания" исключений на промежуточных уровнях, о котором я не знаю?

S>Пардон, а чего ты ожидаешь от этого автоматического оборачивания?

Хороший вопрос, я и пытаюсь понять, как бы я хотел чтобы это работало Надеюсь, что вы мне поможете.

S>Это означает, что вызывающий код

S>а) может не заморачиваться с тем, чтобы ловить абстрактные NullReferenceException, который произошел хрен знает где ниже по стеку. Вместо этого можно отлавливать более осмысленные, с его точки зрения, LibraryException и строить на них свою логику (например, попытаться загрузить дефолтную Library, чтобы это ни значило).

Вот-вот, проблема в том, что на уровень функции OpenLibrary подымаются всякие исключения — и абстрактные, и более-менее конкретные. Хотя причины неоткрытия библиотеки вполне конкретные и информативные (например, отсутствует файл, неправильная версия и т.п.), вместо них приходится иметь дело с абстрактными вроде null reference. Ставить на них общую затычку и говорить клиенту "не удалось открыть библиотеку".

S>б) может получить информацию о причинах проявления высокоуровневого исключения через InnerException. В частности, админ (если от него это не скрыть) сможет понять, что был AccessViolation или FileNotFound.


Сможет ли он понять это без раскрутки стека сверху вниз? Точнее, чтобы понять причину сбоя требуется информация от первого метода в стеке, а не последнего, которая приходит.

S>Да, на первый взгляд это все очень плохо, т.к альтернативой был бы

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

Эта грань между логическими уровнями довольна расплывчата...


Кроме того, меня интересуют следующие проблемы, связанные с исключениями. Интересно было бы услышать комментарии.

1) Если все исключения нижнего уровня все равно подавляются на текущем методе и перевыбрасывается одно исключение, свойственное данному уровню и методу, то зачем вкладывать какую-либо информацию в исключения нижнего уровня — она все равно не используется?

2) Как следствие из 1), заключение дополнительной информации в исключениях нижнего уровня имеет смысл только в том случае, если предполагается реюзать код нижнего уровня в других проектах. В таком случае, иерархии исключений разных уровней должны быть независимы, точнее нет смысла им быть зависимыми. (хотя первым побуждением есть создание единой иерархии исключений для всего приложения)

3) В каких случаях следует наследовать новый класс исключения от базового, а в каких следует лишь параметризовать его типом/сообщением?

4) Если же требуется транспортировать какое-то сообщение в исключении, как правильно это сделать на практике? Например, как организовать возможность централизованной локализации строк сообщений, загрузку их из ресурсов?
Re[4]: Фильтрация исключений
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.12.05 12:11
Оценка:
Здравствуйте, Ignoramus, Вы писали:

I>Вот-вот, проблема в том, что на уровень функции OpenLibrary подымаются всякие исключения — и абстрактные, и более-менее конкретные.

Это не так. В данном случае OpenLibrary — это "середина" стека. В нее может приезжать тоже вполне высокоуровневая информация
I>Хотя причины неоткрытия библиотеки вполне конкретные и информативные (например, отсутствует файл, неправильная версия и т.п.), вместо них приходится иметь дело с абстрактными вроде null reference.
Это от того, что предыдущий слой не взял на себя работу по оборачиванию NullReferenceException во что-то более осмысленное.
I>Ставить на них общую затычку и говорить клиенту "не удалось открыть библиотеку".

S>>б) может получить информацию о причинах проявления высокоуровневого исключения через InnerException. В частности, админ (если от него это не скрыть) сможет понять, что был AccessViolation или FileNotFound.


I>Сможет ли он понять это без раскрутки стека сверху вниз? Точнее, чтобы понять причину сбоя требуется информация от первого метода в стеке, а не последнего, которая приходит.

Я не знаю, с какой стороны ты считаешь методы в стеке. В нормальном случае печатается весь пакет — от высокоуровневого (не удалось сохранить документ), через средний уровень (не удалось открыть библиотеку) до самого нижнего (файл не найден).

I>Эта грань между логическими уровнями довольна расплывчата...

Нет. Если у тебя внятная архитектура, границы между слоями четко очерчены.

I>1) Если все исключения нижнего уровня все равно подавляются на текущем методе и перевыбрасывается одно исключение, свойственное данному уровню и методу, то зачем вкладывать какую-либо информацию в исключения нижнего уровня — она все равно не используется?

Используется!
Еще раз объясняю: пользователю достаточно информации о том, что чего-то сделать не удалось. Админ посмотрит в логи и сможет понять, где не хватило прав (а приложение может лезть в какое-нибудь неожиданное место), где просто убился файл, а где не удалось достучаться до сайта в сети.
I>2) Как следствие из 1), заключение дополнительной информации в исключениях нижнего уровня имеет смысл только в том случае, если предполагается реюзать код нижнего уровня в других проектах. В таком случае, иерархии исключений разных уровней должны быть независимы, точнее нет смысла им быть зависимыми. (хотя первым побуждением есть создание единой иерархии исключений для всего приложения)
Совершенно верно. Иерархии исключений разных слоев не нуждаются в объединении.
I>3) В каких случаях следует наследовать новый класс исключения от базового, а в каких следует лишь параметризовать его типом/сообщением?
Наследоваться имеет смысл в тех случаях, если данный тип исключения имеет смысл ловить отдельным catch(). Трудно сформулировать более точно. Когда ты начнешь писать реальный код, ты сам увидишь, есть ли ситуации, которые ты можешь обработать в рамках данного слоя.
I>4) Если же требуется транспортировать какое-то сообщение в исключении, как правильно это сделать на практике? Например, как организовать возможность централизованной локализации строк сообщений, загрузку их из ресурсов?
Особой нужды в локализации исключений нижнего уровня нет. Локализация исключений, проникающих на уровень UI, делается относительно стандартными средствами: конкретный класс исключения оборудуется конструктором с соответствующими параметрами, берет шаблон строки из ресурсов, и компонует сообщение из шаблона и значений своих параметров.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Фильтрация исключений
От: Ignoramus  
Дата: 02.12.05 13:05
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Это от того, что предыдущий слой не взял на себя работу по оборачиванию NullReferenceException во что-то более осмысленное.


Т.е. в промышленном коде именно так и делают? Оборачивают на каждом уровне? Как именно выглядит это оборачивание — в самом начале каждого публичного метода и конструктора ставится try, а в самом конце catch с пере-throw? Иначе я не вижу способа обеспечить полный отлов всех исключений в целях их оборачивания.

S>Используется!

S>Еще раз объясняю: пользователю достаточно информации о том, что чего-то сделать не удалось. Админ посмотрит в логи и сможет понять, где не хватило прав (а приложение может лезть в какое-нибудь неожиданное место), где просто убился файл, а где не удалось достучаться до сайта в сети.

При условии присутствия промежуточных оборачивателей — да. Я пытался выяснить можно ли обойтись одним try/catch на верхнем уровне и при этом получать более подробную информацию о сбое. По-видимому это невозможно .

S>Совершенно верно. Иерархии исключений разных слоев не нуждаются в объединении.


Интересно, а где лучше размещать описания классов исключений? Наверное в том же пространстве имен, что и "логический уровень", все классы которого бросают одни и те же исключения? Не выделять в отдельный namespace Exceptions?

I>>4) Если же требуется транспортировать какое-то сообщение в исключении, как правильно это сделать на практике? Например, как организовать возможность централизованной локализации строк сообщений, загрузку их из ресурсов?

S>Особой нужды в локализации исключений нижнего уровня нет. Локализация исключений, проникающих на уровень UI, делается относительно стандартными средствами: конкретный класс исключения оборудуется конструктором с соответствующими параметрами, берет шаблон строки из ресурсов, и компонует сообщение из шаблона и значений своих параметров.

А как тогда анализировать причину сбоя и выводить пользователю инфу, если она приходит с нижнего нелокализованного уровня? Может тогда вообще отказаться от текста и идентифицировать исключения нижнего уровня только по их типу, а соответствующий текст добавлять в верхнем уровне? Или это нарушает инкапсуляцию исключений?
Re[6]: Фильтрация исключений
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.12.05 13:27
Оценка:
Здравствуйте, Ignoramus, Вы писали:

I>Т.е. в промышленном коде именно так и делают? Оборачивают на каждом уровне?

Да.
I>Как именно выглядит это оборачивание — в самом начале каждого публичного метода и конструктора ставится try, а в самом конце catch с пере-throw?
Нет. Не каждого публичного метода. При пересечении границы слоев. Сколько слоев в твоей архитектуре?
I>Иначе я не вижу способа обеспечить полный отлов всех исключений в целях их оборачивания.
I>При условии присутствия промежуточных оборачивателей — да. Я пытался выяснить можно ли обойтись одним try/catch на верхнем уровне и при этом получать более подробную информацию о сбое. По-видимому это невозможно .
Действительно, практически невозможно. Принципиальным ограничением является отсутствие информации о контексте. Современные управляемые среды уже предоставляют гораздо больше информации, чем это было возможно раньше — в частности, call stack. К сожалению, пока что нет возможности автоматически получить информацию об а) значениях параметров в стеке и б) состоянии объектов. Прежде всего потому, что такая возможность вызвала бы существенное понижение быстродействия "безошибочных" приложений. В принципе, можно ожидать появления подобных возможностей в следующих поколениях управляемых систем. Пока что нам остается следовать приведенным соображениям "вручную".
I>Интересно, а где лучше размещать описания классов исключений? Наверное в том же пространстве имен, что и "логический уровень", все классы которого бросают одни и те же исключения? Не выделять в отдельный namespace Exceptions?
Наверное, да. Хотя принципиальной разницы нет — просто удобнее пользоваться, когда для исключений не нужно подключать отдельный namespace.

I>А как тогда анализировать причину сбоя и выводить пользователю инфу, если она приходит с нижнего нелокализованного уровня? Может тогда вообще отказаться от текста и идентифицировать исключения нижнего уровня только по их типу, а соответствующий текст добавлять в верхнем уровне? Или это нарушает инкапсуляцию исключений?

Не нарушает. Информация нижнего уровня все равно читается технически квалифицированными людьми, которые в состоянии понять "File Not Found" независимо от их родного языка.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Фильтрация исключений
От: Ignoramus  
Дата: 02.12.05 13:41
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Ignoramus, Вы писали:


S>Нет. Не каждого публичного метода. При пересечении границы слоев. Сколько слоев в твоей архитектуре?


Хотел бы я это знать, черт побери! Наверное 3... или 4

Однако же, под "публичными" я имел в виду методы, которые вызываются более верхним слоем (а не просто объявленные как public) С этой поправкой мое утверждение верно?

I>>Иначе я не вижу способа обеспечить полный отлов всех исключений в целях их оборачивания.

I>>При условии присутствия промежуточных оборачивателей — да. Я пытался выяснить можно ли обойтись одним try/catch на верхнем уровне и при этом получать более подробную информацию о сбое. По-видимому это невозможно .
S>Действительно, практически невозможно. Принципиальным ограничением является отсутствие информации о контексте. Современные управляемые среды уже предоставляют гораздо больше информации, чем это было возможно раньше — в частности, call stack. К сожалению, пока что нет возможности автоматически получить информацию об а) значениях параметров в стеке и б) состоянии объектов. Прежде всего потому, что такая возможность вызвала бы существенное понижение быстродействия "безошибочных" приложений. В принципе, можно ожидать появления подобных возможностей в следующих поколениях управляемых систем. Пока что нам остается следовать приведенным соображениям "вручную".

Как теоретический вариант я рассматривал возможность при получении исключения на верхнем уровне "подсмотреть" в стек, чтобы узнать от какого метода более низкого уровня пришло данное исключение. Если предположить, что каждый "публичный" метод выполняет только одну ф-цию и соответственно переизлучал бы только одно исключение (если бы в нем был оборачиватель), таким образом можно определить причину сбоя, без промежуточных оборачивателей. Бред?

I>>А как тогда анализировать причину сбоя и выводить пользователю инфу, если она приходит с нижнего нелокализованного уровня? Может тогда вообще отказаться от текста и идентифицировать исключения нижнего уровня только по их типу, а соответствующий текст добавлять в верхнем уровне? Или это нарушает инкапсуляцию исключений?

S>Не нарушает. Информация нижнего уровня все равно читается технически квалифицированными людьми, которые в состоянии понять "File Not Found" независимо от их родного языка.

Уточню вопрос: использовать ли вообще строки в исключениях нижнего уровня или достаточно их типа, а весь текст обеспечивается верхним уровнем на основании этого типа?
Re[7]: Фильтрация исключений
От: Cyberax Марс  
Дата: 02.12.05 13:42
Оценка:
Sinclair wrote:

> Современные управляемые среды уже предоставляют гораздо больше

> информации, чем это было возможно раньше — в частности, call stack. К
> сожалению, пока что нет возможности автоматически получить информацию
> об а) значениях параметров в стеке

Управляемые среды — ацтой

Вообще-то в MS VС++ вполне можно получить stacktrace, значения
аргументов, и даже значения переменных в фреймах функций. Единственное
что нужно — это иметь PDB-файл.

В управляемые среды такое добавить сильно больших сложностей не должно
представить. Вероятно это пока никому не надо, или просто еще не
додумались добавить.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[7]: Фильтрация исключений
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 02.12.05 13:42
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>К сожалению, пока что нет возможности автоматически получить информацию об а) значениях параметров в стеке и б) состоянии объектов. Прежде всего потому, что такая возможность вызвала бы существенное понижение быстродействия "безошибочных" приложений. В принципе, можно ожидать появления подобных возможностей в следующих поколениях управляемых систем. Пока что нам остается следовать приведенным соображениям "вручную".


Возможность такая, естественно, есть. В каких системах — не трудно догадаться Другое дело, что, для автоматического перезаворачивания исключений, особого толку от состояния объектов и значений параметров я не вижу.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[8]: Фильтрация исключений
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 02.12.05 13:54
Оценка:
Здравствуйте, Ignoramus, Вы писали:

I>Уточню вопрос: использовать ли вообще строки в исключениях нижнего уровня или достаточно их типа, а весь текст обеспечивается верхним уровнем на основании этого типа?


Использовать. Часто бывает, что сохраненная на самом низком уровне полная информация о причине исключения оказывается очень важной при разборе полетов. Терять такую информацию, если она есть, глупо. В частности, крайне полезным бывает сохранение значения errno.

Не обязательно это могут быть строки. Например, мне иногда приходится порождать исключения при выходе за пределы блока с десериализуемыми данными. Тогда я располагаю информацией о: размере буфера, текущей позиции в буфере и количеством байт, которые хотят прочитать. Для этого в С++ можно использовать, что-то вроде:
class bound_ex_t : public std::exception
    {
    private :
        size_t    m_buf_size;
        size_t    m_pos;
        size_t    m_required_size;
        
        //! Для того, чтобы можно было сформировать в what().
        mutable std::string m_what;
        
    public :
        bound_ex_t( size_t buf_size, size_t pos, size_t required_size )
            :    m_buf_size( buf_size ), m_pos( pos ), m_required_size( required_size )
            {}
            
        virtual const char * what() const
            {
                if( m_what.empty() )
                    {
                        <создание строки с описанием всей доступной информации>
                    }
                return m_what.c_str();
            }
    };


bound_ex_t::m_what можно формировать и в конструкторе bound_ex_t, только зачем это делать сразу, если what() у нас могут и не вызвать вообще.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[9]: Фильтрация исключений
От: Ignoramus  
Дата: 02.12.05 14:11
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Ignoramus, Вы писали:


I>>Уточню вопрос: использовать ли вообще строки в исключениях нижнего уровня или достаточно их типа, а весь текст обеспечивается верхним уровнем на основании этого типа?


E>Использовать. Часто бывает, что сохраненная на самом низком уровне полная информация о причине исключения оказывается очень важной при разборе полетов. Терять такую информацию, если она есть, глупо. В частности, крайне полезным бывает сохранение значения errno.


Кстати о номерах ошибок. Идея конечно заманичвая, но ее основной недостаток, по моему опыту, это необходимость консистентной нумерации ошибок во всем приложении, во всех уровнях архитектуры. Это лишняя связь, и довольно-таки напрягает имхо. Может поэтому в std::exception есть строковый what, а не числовой
Re[7]: Фильтрация исключений
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 02.12.05 14:26
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Действительно, практически невозможно. Принципиальным ограничением является отсутствие информации о контексте. Современные управляемые среды уже предоставляют гораздо больше информации, чем это было возможно раньше — в частности, call stack. К сожалению, пока что нет возможности автоматически получить информацию об а) значениях параметров в стеке и б) состоянии объектов. Прежде всего потому, что такая возможность вызвала бы существенное понижение быстродействия "безошибочных" приложений. В принципе, можно ожидать появления подобных возможностей в следующих поколениях управляемых систем. Пока что нам остается следовать приведенным соображениям "вручную".


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

Фрагмент:



Сама программа:

MODULE TestException;

  IMPORT StdLog, Math;

  TYPE
    MyObject = RECORD
      x, y, z: REAL
    END;
    
  PROCEDURE Sqrt (x : REAL): REAL;
  BEGIN ASSERT(x >= 0.0, 20);
    RETURN Math.Sqrt(x)
  END Sqrt;
  
  PROCEDURE Do*;
    VAR obj: MyObject;
    a, b, c: REAL;
  BEGIN
    a := 111.0;
    b := 222.0;
    c := 333.0;
    obj.x := 444.0;
    obj.y := 555.0;
    obj.z := 666.0;
    c := Sqrt(-777.0);
    StdLog.Real(c)
  END Do;
  
END TestException.


Полная развертка стека (при конвертации в plain text специальные view, естественно, исчезли):
TRAP 20  (precondition violated)

 TestException.Sqrt   [0000001FH] 
    .x    REAL    -777.0
 TestException.Do   [00000095H] 
    .a    REAL    111.0
    .b    REAL    222.0
    .c    REAL    333.0
    .obj    TestException.MyObject    fields
 StdInterpreter.CallProc   [000003A5H] 
    .a    BOOLEAN    FALSE
    .b    BOOLEAN    FALSE
    .c    BOOLEAN    FALSE
    .i    Meta.Item    fields
    .imported    ARRAY 256 OF CHAR    ""   ...
    .importing    ARRAY 256 OF CHAR    ""   ...
    .mn    Meta.Name    "TestException"
    .mod    StdInterpreter.Ident    "TestException"
    .object    ARRAY 256 OF CHAR    ""   ...
    .ok    BOOLEAN    TRUE
    .parType    INTEGER    0
    .pn    Meta.Name    "Do"
    .proc    StdInterpreter.Ident    "Do"   ...
    .res    INTEGER    0
    .v    StdInterpreter.ProcVal    fields
    .vi    StdInterpreter.ProcIVal    fields
    .vii    StdInterpreter.ProcIIVal    fields
    .vr    StdInterpreter.ProcRVal    fields
    .vri    StdInterpreter.ProcRIVal    fields
    .vrii    StdInterpreter.ProcRIIVal    fields
    .vrr    StdInterpreter.ProcRRVal    fields
    .vrri    StdInterpreter.ProcRRIVal    fields
    .vrrii    StdInterpreter.ProcRRIIVal    fields
    .vrs    StdInterpreter.ProcRSVal    fields
    .vrsi    StdInterpreter.ProcRSIVal    fields
    .vrsii    StdInterpreter.ProcRSIIVal    fields
    .vs    StdInterpreter.ProcSVal    fields
    .vsi    StdInterpreter.ProcSIVal    fields
    .vsii    StdInterpreter.ProcSIIVal    fields
    .vsr    StdInterpreter.ProcSRVal    fields
    .vsri    StdInterpreter.ProcSRIVal    fields
    .vsrii    StdInterpreter.ProcSRIIVal    fields
    .vss    StdInterpreter.ProcSSVal    fields
    .vssi    StdInterpreter.ProcSSIVal    fields
    .vssii    StdInterpreter.ProcSSIIVal    fields
 StdInterpreter.Command   [00001260H] 
    .left    StdInterpreter.Ident    "TestException"
    .ptype    INTEGER    0
    .right    StdInterpreter.Ident    "Do"   ...
 StdInterpreter.CallHook.Call   [00001385H] 
    .ch    CHAR    0X
    .e    ARRAY 64 OF CHAR    ""   ...
    .errorMsg    ARRAY 2 OF CHAR    " "
    .f    ARRAY 64 OF CHAR    ""   ...
    .g    ARRAY 64 OF CHAR    ""   ...
    .hook    StdInterpreter.CallHook    [0105F190H] 
    .i    INTEGER    17
    .i0    INTEGER    0
    .i1    INTEGER    0
    .id    StdInterpreter.Ident    "Do"   ...
    .par0    Dialog.String    ""   ...
    .par1    Views.Title    ""   ...
    .proc    ARRAY 256 OF CHAR    "TestException.Do"   ...
    .res    INTEGER    0
    .s0    Dialog.String    ""   ...
    .s1    Dialog.String    ""   ...
    .type    INTEGER    3
    .x    INTEGER    0
 Dialog.Call   [00003266H] 
    .errorMsg    ARRAY 2 OF CHAR    " "
    .proc    ARRAY 256 OF CHAR    "TestException.Do"   ...
    .res    INTEGER    0
 DevCommanders.Execute   [00000662H] 
    .beg    INTEGER    439
    .cmd    Dialog.String    "TestException.Do"   ...
    .end    INTEGER    440
    .pos    INTEGER    423
    .res    INTEGER    0
    .s    DevCommanders.Scanner    fields
    .t    TextModels.Model    [010FB6C0H] 
    .unload    BOOLEAN    TRUE
 DevCommanders.Track   [00000795H] 
    .buttons    SET    {2, 16, 25}
    .c    Models.Context    [01188A90H] 
    .end    INTEGER    440
    .f    Views.Frame    [0100A720H] 
    .h    INTEGER    152400
    .in    BOOLEAN    TRUE
    .in0    BOOLEAN    TRUE
    .isDown    BOOLEAN    FALSE
    .m    SET    {2, 25}
    .v    DevCommanders.View    [01018DF0H] 
    .w    INTEGER    177800
    .x    INTEGER    98425
    .y    INTEGER    69850
 DevCommanders.StdView.HandleCtrlMsg   [00000946H] 
    .f    Views.Frame    [0100A720H] 
    .focus    Views.View    NIL
    .msg    Controllers.TrackMsg    fields
    .v    DevCommanders.StdView    [01018DF0H] 
 Views.ForwardCtrlMsg   [000026B0H] 
    .a    Views.View    NIL
    .f    Views.Frame    [0100A720H] 
    .focus    Views.View    NIL
    .g    Views.Frame    [010233E0H] 
    .h    Views.Frame    NIL
    .msg    Controllers.TrackMsg    fields
    .op    INTEGER    1
    .req    BOOLEAN    FALSE
    .v    Views.View    [01018DF0H] 
 Views.ForwardCtrlMsg   [0000276BH] 
    .a    Views.View    NIL
    .f    Views.Frame    [010233E0H] 
    .focus    Views.View    [01018DF0H] 
    .g    Views.Frame    [01019830H] 
    .h    Views.Frame    [0100A720H] 
    .msg    Controllers.TrackMsg    fields
    .op    INTEGER    1
    .req    BOOLEAN    FALSE
    .v    Views.View    [01018D30H] 
 Views.ForwardCtrlMsg   [0000276BH] 
    .a    Views.View    NIL
    .f    Views.Frame    [01019830H] 
    .focus    Views.View    [01018D30H] 
    .g    Views.Frame    NIL
    .h    Views.Frame    [010233E0H] 
    .msg    Controllers.TrackMsg    fields
    .op    INTEGER    1
    .req    BOOLEAN    FALSE
    .v    Views.View    [010FC860H] 
 Windows.Window.ForwardCtrlMsg   [000002AFH] 
    .msg    Controllers.TrackMsg    fields
    .w    Windows.Window    [010192D0H] 
 HostWindows.Window.ForwardCtrlMsg   [00001615H] 
    .d    BOOLEAN    FALSE
    .msg    Controllers.TrackMsg    fields
    .res    INTEGER    2010420391
    .w    HostWindows.Window    [010192D0H] 
 HostWindows.Window.MouseDown   [00001BA5H] 
    .modifiers    SET    {2, 16, 25}
    .ph    INTEGER    504
    .pw    INTEGER    656
    .time    INTEGER    0
    .track    Controllers.TrackMsg    fields
    .w    HostWindows.Window    [010192D0H] 
    .x    INTEGER    17
    .y    INTEGER    398
 HostWindows.HandleMouse   [0000343DH] 
    .b    SET    {2, 16, 25}
    .f    Views.Frame    NIL
    .g    Views.Frame    NIL
    .isDown    BOOLEAN    TRUE
    .lParam    INTEGER    26083345
    .w    HostWindows.Window    [010192D0H] 
    .wParam    INTEGER    265
    .wnd    INTEGER    590618
    .x    INTEGER    17
    .y    INTEGER    398
 Kernel.Try   [00003A31H] 
    .a    INTEGER    590618
    .b    INTEGER    265
    .c    INTEGER    26083345
    .h    PROCEDURE    HostWindows.HandleMouse
 HostWindows.DocWinHandler   [00003FA3H] 
    .dx    INTEGER    0
    .dy    INTEGER    1953697393
    .lParam    INTEGER    26083345
    .message    INTEGER    513
    .res    INTEGER    0
    .st    SET    {2}
    .style    SET    {1, 2, 16, 18}
    .w    HostWindows.Window    NIL
    .wParam    INTEGER    9
    .wnd    INTEGER    590618
    .x    INTEGER    2147348480
<system>   (pc=77D48708H,  fp=0022FB84H)
<system>   (pc=77D487EAH,  fp=0022FBECH)
<system>   (pc=77D489A4H,  fp=0022FC4CH)
<system>   (pc=77D4BCCBH,  fp=0022FC5CH)
 HostMenus.Loop   [00003C52H] 
    .done    BOOLEAN    FALSE
    .f    SET    {0..5}
    .n    INTEGER    0
    .res    INTEGER    0
    .w    HostWindows.Window    NIL
 Kernel.Start   [00002B5CH] 
    .code    PROCEDURE    HostMenus.Loop
Re[10]: Фильтрация исключений
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 02.12.05 14:44
Оценка:
Здравствуйте, Ignoramus, Вы писали:

I>Кстати о номерах ошибок. Идея конечно заманичвая, но ее основной недостаток, по моему опыту, это необходимость консистентной нумерации ошибок во всем приложении, во всех уровнях архитектуры. Это лишняя связь, и довольно-таки напрягает имхо. Может поэтому в std::exception есть строковый what, а не числовой


Я ведь не предлагал вводить собственную систему номеров ошибок, а сохранять, где это имеет смысл, значение errno. А за консистентность нумерации ошибок в errno стандартная (и не только) библиотека отвечает. На Windows так же можно и GetLastError использовать при работе с WinAPI.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[8]: Фильтрация исключений
От: AndrewJD США  
Дата: 02.12.05 16:31
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Вообще-то в MS VС++ вполне можно получить stacktrace, значения

C>аргументов, и даже значения переменных в фреймах функций. Единственное
C>что нужно — это иметь PDB-файл.

От PDB файла не всегда много толку, если включена агресивная оптимизация и Frame-Pointer Omission.
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re[20]: error is not an exception
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.12.05 00:34
Оценка:
Cyberax wrote:
>
> ASSERT'ы — это НЕ мусор. Это чрезвычайно удобное средство отладки.

Более того, хорошо поставленный assert помогает защитить свой код от
лазанья в него "умелыми ручками" всяких разных других участников проекта
— из того числа, которые могут позвать любую обнаруженную ими функцию в
любом контексте, и не читают комментариев.

Без ассерта это кончится тем, что "что-то твой код глючит". С ассертом
диалог будет примерно следующий: "что-то у тебя ассерт срабатывает" —
"до твоей правки не срабатывал" — "а как тогда мне сделать XXX?". И вот
с этого последнего вопроса можно уже начинать нормальный диалог...
Posted via RSDN NNTP Server 2.0
Re[21]: error is not an exception
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.12.05 00:36
Оценка:
IT wrote:
>
> C>Или, например, вот такой код (спас часы отладки):
>
> Так может такие проверки должны быть штатными и использоваться не только
> в режиме отладки?

Да, безусловно. Ассерты должны оставаться в релизе. Надо только
придумать, как сделать так, чтобы последние слова программы попали таки
тебе в руки вместе с bag report'ом.
Posted via RSDN NNTP Server 2.0
Re[22]: error is not an exception
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.12.05 00:37
Оценка:
Глеб Алексеев wrote:
>
> IT>Так может такие проверки должны быть штатными и использоваться не
> только в режиме отладки?
> Зачем, если они срабатывают только при наличии ошибки в программе (и
> теоретически в окончательной версии их быть не должно) и могут снижать
> производительность?

Потому, что даже в релизнутой программе могут остаться ошибки. И лучше,
чтобы последние слова упавшей программы были осмысленными, чем просто
слепой GPF.
Posted via RSDN NNTP Server 2.0
Re[22]: error is not an exception
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.12.05 00:39
Оценка:
Cyberax wrote:
>
> А зачем? assert показывает ошибки программиста, а не пользователя. То
> есть ни при каком варианте работы событий пользователь не должен его
> получить, а значит и включать его не надо.
>
> В рельной жизни assert'ы обычно оставляют в бэта-версиях, и выкидывают в
> релизах.

А что, в релизах каким-то волшебным образом нет ни одной ощибки?

Какая альтернатива существует у программы, которая вошла в состояние,
когда должен бы сработать assert, а assert-а то и нету? Только сойти с
ума, и в лучшем случае упасть на GPF'е. А в худшем — безнадежно
испортить пользовательские файлы.
Posted via RSDN NNTP Server 2.0
Re[9]: Фильтрация исключений
От: Cyberax Марс  
Дата: 03.12.05 12:16
Оценка:
AndrewJD wrote:

> C>Вообще-то в MS VС++ вполне можно получить stacktrace, значения

> C>аргументов, и даже значения переменных в фреймах функций. Единственное
> C>что нужно — это иметь PDB-файл.
> От PDB файла не всегда много толку, если включена агресивная
> оптимизация и Frame-Pointer Omission.

С fomit'ом проблем нет, они есть с inline-ингом. С оптимизацией тоже
проблем никаких.

У нас в проекте в случае ошибки от пользователей приходит stacktrace и
dmp-файл (для посмертной отладки). Проблем особых пока что не было.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[31]: error is not an exception
От: Cyberax Марс  
Дата: 03.12.05 13:16
Оценка:
GlebZ wrote:

> C>На соответствие ЧЕМУ? Как вы будете составлять reference model?

> А что такое reference model в терминах функционального языка?

Модель для problem domain

> C>У вас просто сместится сложность с проверки программного кода на

> C>соответствие с требованиями задачи на проверку мат. модели на
> C>соответствие требованиям задачи.
> Нет. Сложность получения модели можно автоматизировать.

Автоматизируйте создание модели российской бухгалтерии, плиз Или хотя
бы выделение инвариантов модели.

Для софта управлением метро все было достаточно просто — там инварианты
формулируются вполне логично.

> PS никогда не думал что буду защищать функциональные языки


А что, функциональные языки предполагают достаточно интересный подход к
программированию. Если не фанатеть от него безумно (как не будем
показывать пальцами кто), то можно найти вполне полезные вещи.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[32]: error is not an exception
От: GlebZ Россия  
Дата: 03.12.05 13:38
Оценка:
Здравствуйте, Cyberax, Вы писали:

>> C>На соответствие ЧЕМУ? Как вы будете составлять reference model?

>> А что такое reference model в терминах функционального языка?
C>Модель для problem domain
Входные и выходные параметры не зависят от языка. Я и говорил о сложности получения аналогичной мат. модели зависимости выходных параметров, от входных.

>> C>У вас просто сместится сложность с проверки программного кода на

>> C>соответствие с требованиями задачи на проверку мат. модели на
>> C>соответствие требованиям задачи.
>> Нет. Сложность получения модели можно автоматизировать.
C>Автоматизируйте создание модели российской бухгалтерии, плиз Или хотя
C>бы выделение инвариантов модели.
Нуу. По моему вы переоцениваете как бухгалтерию, так и российскую.
1. Последний раз я имел дело с бухгалтерией 3 года назад, уже тогда это было близко к европейскиму варианту. А сейчас наверное практически одинаковы.
2. Бухгалтерия достаточно простая вещь. Пока к нему не примазывают склады, управление аналитическими счетами и т.п.
3. Модель действительна на какой-то промежуток времени. Это да. Но это отнюдь не противоречит вышесказанному.
4. То что в модель не вписывается человек, это известный факт.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[13]: Что вы предлагаете на замену эксепшенов?
От: pvgoran Россия  
Дата: 06.12.05 04:58
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

P>>Отлично. А сколько программисту от нормы обычного человека? А, кстати, обычному человеку?


СГ>Вы такие вопросы сложные задаёте, едва ли моих личных процентов от нормы хватит чтобы сообразить как ответить.

СГ>Хотя попробую. Дело в том что есть количественные (приблизительные) соотношения: на каждого 1 доктора приходится по 10 кандидатов, а на 1 академика приходится 10-20 докторов. Поскольку любой кандидат хочет стать доктором, и любой доктор хочет стать академиком, то отсюда заключаем, что докторами становятся люди которые в 10 раз умнее чем усреднённый кандидат; а академиками становятся люди которые в 10-20 раз умнее чем усреднённый доктор.

Не могу пройти мимо такой фундаментальной потенциальной неточности.

Такие выводы можно делать лишь при принятии/постулировании определенных предположений о распределении случайной величины "мощность ума". А именно, нужно постулировать константность произведения плотности распределения для данной величины "мощности ума" на значение этой величины.

Надеюсь, ничего не напутал.
... << RSDN@Home 1.1.4 stable rev. 510>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.