OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Суббота, 15 Декабрь, 2018 12:48

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 29 ]  На страницу Пред.  1, 2

Механизм исключений в PureBuilder...
Лучше соответствует структурному программированию 25%  25%  [ 2 ]
Уменьшает количество ошибок (багов) в программе 13%  13%  [ 1 ]
Проще при чтении программы 25%  25%  [ 2 ]
Проще при отладке программы 0%  0%  [ 0 ]
Проще при кодировании программы 13%  13%  [ 1 ]
Проще для разработки транслятора 0%  0%  [ 0 ]
Быстрее при трансляции программы 0%  0%  [ 0 ]
Быстрее при исполнении программы 0%  0%  [ 0 ]
Не имеет ни одного из указанных выше преимуществ 25%  25%  [ 2 ]
Всего голосов : 8
Автор Сообщение
СообщениеДобавлено: Воскресенье, 06 Февраль, 2011 20:03 

Зарегистрирован: Четверг, 23 Апрель, 2009 18:01
Сообщения: 219
Кажется, я вас наконец-то понял.

Мой вариант: функция возвращает флаг результата, а значение в OUT-параметре. Если нужна более детализированная информация об ошибке, то ещё один аргумент - сама ошибка. Таким образом количество аргументов функции увеличивается на 1-2.

Плюсы:
+) Сохраняется правило: у блока один вход и один выход, а с ним и все формальные доказательства о свойствах кода.
+) Функции унифицированны. Не нужно знать имён исключений или расшифровывать мета-информацию в результатах. TRUE - успех, FALSE - нет.
+) Любые естественные логические выражения легко строятся из функций, не возвращающих гарантированно результат (если удалость А и удалось Б или не удалось С, то попробовать Д или Е).
-) Лишние параметры, что кажется громоздким.
-) Непривычный и громоздкий стиль использования результата функции в качестве аргумента.
Ранее: A(B(C())); Теперь: A(ResA) AND B(ResA, ResB) AND C(ResB, ResC);

Ваш вариант. Конструкция catch относится к вызывающей процедуре.
+) Функции сохраняют свой естественный вид.
*) Структурность нарушается лишь частично - на одном уровне.
?) PureBuilder поддерживает выражения из функций? К какой части выражения тогда относится catch? catch может быть применён к целому блоку кода?
-) Если catch не применяем к блоку кода, то отсутствует возможность последовательного условного выполнения функций, которое встречается очень часто:
A;
B;
C;
catch
// хотели попадать сюда, если A, B или C завершилось не успешно.
end;

Аналог:

Result:=A AND B AND C;
-) У catch нет ветки else/elseif, так что развилка естественным образом не пишется:

Код:
IF StrPos(...) THEN // если нашли подстроку, то один код
...
ELSE // другой код
...
END;

StrPos(...);
catch
  ... // код обработки исключения без развилки
end;


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Воскресенье, 06 Февраль, 2011 23:20 
Аватара пользователя

Зарегистрирован: Воскресенье, 08 Июль, 2007 00:38
Сообщения: 778
Откуда: Москва
Александр Шостак писал(а):
Мой вариант: ...
Плюсы:
+) Сохраняется правило: у блока один вход и один выход, а с ним и все формальные доказательства о свойствах кода.


Разве свойства кода в PureBuilder менее понятны? А вот сигнальные значения функции несут в себе опасности:
  • нарушение строгой типизации для возвращаемого значения
  • потенциальная возможность возврата сигнального значения в результате нормальной работы функции
  • возможная попытка применить сигнальное значение функции в дальнейшей работе алгоритма в качестве нормального результата

Александр Шостак писал(а):
+) Функции унифицированны. Не нужно знать имён исключений или расшифровывать мета-информацию в результатах. TRUE - успех, FALSE - нет.


Аналогичная по функциональности вещь будет в PureBuilder - это универсальный блок catch exception, который будет работать при любом исключении. Я о нем уже думал раньше, но пока не успел добавить на сайт. Остальные блоки catch имя исключения программист может не заполнять, если в этом нет необходимости.

Александр Шостак писал(а):
+) Любые естественные логические выражения легко строятся из функций, не возвращающих гарантированно результат (если удалость А и удалось Б или не удалось С, то попробовать Д или Е).

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

Александр Шостак писал(а):
Ваш вариант. Конструкция catch относится к вызывающей процедуре.
*) Структурность нарушается лишь частично - на одном уровне.


Я не вижу, чтобы она вообще нарушалась. Блоки catch выбираются в зависимости от имени исключения - аналогично действию оператора switch/case, который самый что ни на есть "структурный".

Александр Шостак писал(а):
?) PureBuilder поддерживает выражения из функций?

Да.
Александр Шостак писал(а):
К какой части выражения тогда относится catch?

К любой, вызвавшей исключение.

Александр Шостак писал(а):
catch может быть применён к целому блоку кода?

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


Последний раз редактировалось Сергей Прохоренко Понедельник, 07 Февраль, 2011 00:25, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Воскресенье, 06 Февраль, 2011 23:54 

Зарегистрирован: Четверг, 23 Апрель, 2009 18:01
Сообщения: 219
Цитата:
Я не вижу, чтобы она вообще нарушалась. Блоки catch выбираются в зависимости от имени исключения - аналогично действию оператора switch/case, который самый что ни на есть "структурный".

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 07 Февраль, 2011 00:15 
Аватара пользователя

Зарегистрирован: Воскресенье, 08 Июль, 2007 00:38
Сообщения: 778
Откуда: Москва
Александр Шостак писал(а):
Цитата:
Я не вижу, чтобы она вообще нарушалась. Блоки catch выбираются в зависимости от имени исключения - аналогично действию оператора switch/case, который самый что ни на есть "структурный".

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


Оператор throw служит только для отладки и не применяется в рабочей программе. Поэтому считайте его комментарием. Комментарии ведь не нарушают структурность. :D В отличие от escape он находится в той же процедуре/функции, что и блоки catch.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 07 Февраль, 2011 00:35 

Зарегистрирован: Четверг, 23 Апрель, 2009 18:01
Сообщения: 219
Данные недостоверны - отлично. Но хотелось бы закрыть дескрипторы, вызвать деструкторы, обнулить кое-какие поля в структурах. Иными словами - привести систему в исходное состояние до выова подпрограммы. Такое возможно?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 07 Февраль, 2011 21:56 
Аватара пользователя

Зарегистрирован: Воскресенье, 08 Июль, 2007 00:38
Сообщения: 778
Откуда: Москва
Александр Шостак писал(а):
Данные недостоверны - отлично. Но хотелось бы закрыть дескрипторы, вызвать деструкторы, обнулить кое-какие поля в структурах. Иными словами - привести систему в исходное состояние до выова подпрограммы. Такое возможно?


Все переменные в процедурах и функциях PureBuilder строго локальные, никакие побочные эффекты не возможны, поэтому вызов процедуры/функции ничего не меняет в состоянии вызывающей процедуры/функции. Деструкторов в PureBuilder нет, так как концепция ООП заимствована из Oberon-07.

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

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 07 Февраль, 2011 22:58 

Зарегистрирован: Четверг, 23 Апрель, 2009 18:01
Сообщения: 219
Я имел в виду аналог ветки завершения у функции. Код, который идёт после второго // * * * * * //:
Код:
FUNCTION FileToMemEx
(
          CONST FilePath:   STRING;
(* On *)  OUT   MemBuffer:  POINTER;
          OUT   StrBuffer:  STRING;
          OUT   FileSize:   INTEGER;
                BufferType: TBufferType
): BOOLEAN;
VAR
(* U *) Buffer:     POINTER;
        hFile:      INTEGER;
        FileSizeL:  INTEGER;
        FileSizeH:  INTEGER;
        BytesRead:  INTEGER;

BEGIN
  {!} ASSERT(MemBuffer = NIL);
  hFile     :=  -1;
  StrBuffer :=  '';
  Buffer    :=  NIL;
  // * * * * * //
  RESULT  :=  WinWrappers.FileOpen(FilePath, SysUtils.fmOpenRead OR SysUtils.fmShareDenyWrite, hFile);
  IF NOT RESULT THEN BEGIN
    Log.Write('FileSystem', 'OpenFile', 'Cannot open file "' + FilePath + '"');
  END // .IF
  ELSE BEGIN
    RESULT  :=  WinWrappers.GetFileSize(hFile, FileSizeL, FileSizeH);
    IF NOT RESULT THEN BEGIN
      Log.Write('FileSystem', 'GetFileSize', 'Cannot get size of file "' + FilePath + '"');
    END; // .IF
  END; // .ELSE
  IF RESULT THEN BEGIN
    RESULT  :=  FileSizeH = 0;
    IF NOT RESULT THEN BEGIN
      Log.Write
      (
        'FileSystem',
        'LoadFile',
        'Size of file "' + FilePath +'" exceeds 2 GB (=' + SysUtils.IntToStr(INT64(FileSizeH) * $FFFFFFFF + FileSizeL) + ')'
      );
    END; // .IF
  END; // .IF
  IF RESULT AND (FileSizeL <> 0) THEN BEGIN
    IF BufferType = MEM_BUFFER THEN BEGIN
      GetMem(MemBuffer, FileSizeL);
      Buffer  :=  MemBuffer;
    END // .IF
    ELSE BEGIN
      SetLength(StrBuffer, FileSizeL);
      Buffer  :=  POINTER(StrBuffer);
    END; // .ELSE
    RESULT  :=  WinWrappers.FileRead(hFile, Buffer^, FileSizeL);
    IF NOT RESULT THEN BEGIN
      Log.Write
      (
        'FileSystem',
        'ReadFile',
        'Error reading file "' + FilePath + '"'
      );
    END // .IF
  END; // .IF
  // * * * * * //
  IF hFile <> -1 THEN BEGIN
    Windows.CloseHandle(hFile);
  END; // .IF
  IF RESULT THEN BEGIN
    FileSize  :=  FileSizeL;
  END // .IF
  ELSE BEGIN
    IF BufferType = MEM_BUFFER THEN BEGIN
      FreeMem(MemBuffer); MemBuffer :=  NIL;
    END // .IF
    ELSE BEGIN
      StrBuffer :=  '';
    END; // .ELSE
  END; // .ELSE
END; // .FUNCTION FileToMemEx


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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 07 Февраль, 2011 23:53 
Аватара пользователя

Зарегистрирован: Воскресенье, 08 Июль, 2007 00:38
Сообщения: 778
Откуда: Москва
Александр Шостак писал(а):
Допустим у вас язык со сборкой мусора. Но внешние ресурсы - это внешние ресурсы. Если деструкторов нет, а работа закончена на любом шаге, ресурсы нужно освободить. И тут как нельзя мешает ваш подход, когда всё кидает исключение. Функциям вдруг хочется выполняться на любом уровне до конца )


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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 08 Февраль, 2011 01:03 

Зарегистрирован: Четверг, 23 Апрель, 2009 18:01
Сообщения: 219
Я имел в виду, что если часто встречаются функции, которым нужна финализация работы, то единственный вариант для них - заводить булеву переменную и если она FALSE, то в конце функции бросать исключение. А такой подход уж очень близок к простому возврату true/false.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 29 ]  На страницу Пред.  1, 2

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2018, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB