Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2007.03.25;
Скачать: [xml.tar.bz2];

Вниз

Free()   Найти похожие ветки 

 
Юрий Зотов ©   (2007-02-23 21:55) [80]

> Суслик ©   (23.02.07 21:49) [79]

Ой ли?
:o)


 
Суслик ©   (2007-02-23 22:41) [81]


> Юрий Зотов ©   (23.02.07 21:55) [80]
> > Суслик ©   (23.02.07 21:49) [79]
>
> Ой ли?
> :o)


Точно-точно.

Ну скажи, что тебе может дать обработка EMathError?
Ну ты привел выгоды в том, что можешь одной, а не двумя строчками кода обработать EMathError. Выгодно, не спорю.
Ну обработал ты это - ну и что - твои дальнейшие действия?

Не мне тебе объяснять как исключения бывают сделаны в других языках :)
Речь о том, что EMathError - типичное runtime исключение (деление на ноль - что тебе даст его обработка? , если ты, конечно, не положился на обработку этого исключения в своем алгоритме, что не есть, скорее всего, хорошо).

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

Подведу итог вот чем - мат. ошибка - типичное runtime исключение - его обработка бессмыслена. Поэтому выгода того, что ты наследуешься не от Exception, а от EMathError не в том, что библиотека гибка, а в том, что ты за неимением инаструментария в языке сам начинаешь делить и исключения на runtime и обрабатываемые (не помню, как они в java называется). В этом выгода. ИМХО. Надеюсь понятно.


 
Loginov Dmitry ©   (2007-02-24 00:09) [82]

> я считаю, что выделенная строка свидетельствует, что квалификация
> программиста недостаточна для того, чтобы его коду можно
> было доверять даже на 90%.


Каким образом выделенная строчка в данном случае о чем-то может свидетельстовать? Ну "мертвый" код. Ну не доглядел. Спасибо что заметили. Возможно и где-нибудь еще есть подобная оплошность. Исправлю.
Пути хода програмерской мысли неисповедимы :)

Вопросик, если можно: Существует ли в мире такой код (кроме конечно Вашего собственного), которому вы бы могли доверять на 99%. И еще: что для Вас важнее - идеально написанный код, либо надежное обеспечение заявленной функциональности?


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


А почему Вы считаете, что EMatrixError следует наследовать именно от EMathError? Может я чего-то не допонимаю, но каким образом наследование от EMathError позволит организовать гибкую обработку ошибок?

Еще: вместо Вашего варианта функции RaiseMatrixError() я разработал функцию DoMatrixError(). Она достаточно информативна, и кроме сообщения об ошибке показывает также дополнительную информацию: время ошибки, последовательность вызванных процедур, приведшая к возникновению ошибки. Не знаю как Вы, но я считаю такой подход очень удобным. Допустим есть вот такая функция:

 function TNumericMatrixClass.ValueOperation(const Matrix: TMatrix;
   Value: Extended; AFunc: TFloatOperation): TMatrix;
 var
   I: Integer;
 const
   SFuncName = "function TNumericMatrixClass.ValueOperation";
 begin
   if Self <> Matrix then
     Resize(Matrix.FDimensions);

   try

     for I := 0 to FElemCount - 1 do
       VecElem[I] := AFunc(Matrix.VecElem[I], Value);

   except
     on E: EMatrixError do DoMatrixError(E.Message, SFuncName);
     on E: Exception do DoError(E.Message, SFuncName);
   end;

   Result := Self;
 end;


При выполнении функции математической функции AFunc() может произойти в общем случае какая угодно ошибка (то же деление на ноль). Либо в ходе присвоения VecElem[I] := возникнет ошибка переполнения разрядной сетки. В итоге выполнится строка on E: Exception do DoError(E.Message, SFuncName);, которая сгенерирует исключение EMatrixError, и текст ошибки будет содержать подробнейший отчет: имя массива, класс массива, тип элементов массива, размеры массива, занимаемая память, время ошибки, последовательность вызванных процедур. На мой взгляд - весьма подробная информация для того, чтобы программист не тратил долгих часов на ее поиски. О делении на ноль программист, я считаю, должен думать заранее. Плюс к этому Matrix32 никого не обязывает использовать встроенные в него вычислительные функции. Если Ваш алгоритм подразумевает использование таких экстремальных операций, как деление на ноль, то оформите для этого собственную процедуру, если стандартная обработка ошибок Matrix32 Вас не устраивает.
Поскольку я считаю реализованный на данный момент в Matrix32 механизм обработки ошибок весьма удобным, и проверенным на практике (меня, как не только создателя, но еще и как пользователя Matrix32 данный подход устраивает на все 100, достойных альтернатив ему я придумать не могу), расставаться с ним только из-за того, что Вам зачем-то понадобилось иметь свой класс для каждой генерируемой ошибки, я не стану. Давайте вместе подумает, какой еще достойной альтернативой можно можно заменить существующий механизм обработки ошибок, где найти компромисс?


> Во-вторых, код полон и одновременно компактен (то есть,
> в нем есть все, что нужно и нет ни одной лишней буквы).


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


> Насколько я понял, библиотека Matrix по сути своей - математическая.
> Значит, помимо ее собственных исключений при работе с ней
> могут возникать и другие математические исключения (переполнение,
> деление на ноль и т.п.) - и все они потомки EMathError.
> Поэтому, если EMatrixError тоже отнаследовать от EMathError,
> то юзер, не теряя возможности отлавливать конкретные исключения,
> получает еще и возможность отлова разом всех математических
> исключений (в том числе, и исключения самой библиотеки)
> c их единой обработкой (если в данном месте кода юзеру конкретизация
> не нужна):


Интересно, а кому нужно для каждой ошибки анализировать возникшее исключение. Честно - мне ни разу не приходилось писать такой вот код:

try
  A := B / C;
except
  on EZeroDivide do..
  on EOverflow do..
  on EUnderflow do..
end;


Ну просто не возникает такой необходимости. Если в образовательных целях - то ладно, еще можно разок попробовать. Но вот где и зачем это использовать на практике - не понятно. Вероятно, задача - крайне специфическая. Если можно, дайте пример, где это необходимо (только не такие, как: on EZeroDivide do ShowMessage("Ой! Деление на ноль")).


 
Юрий Зотов ©   (2007-02-24 00:26) [83]

> Суслик ©   (23.02.07 22:41) [81]

> деление на ноль - что тебе даст его обработка?

В численных алгоритмах может дать ОЧЕНЬ многое. Уточнять нужно? Честно говоря, тратить время влом, поэтому лучше просто поверь - но если будешь настаивать, то приведу пример, когда обработка, например, деления на ноль позволяет довольно просто получить решение, которое без этой обработки было бы либо не получить совсем, либо гораздо сложнее.

> runtime исключение - его обработка бессмыслена

Дим, вдумайся (только правда - сделай паузу и спокойно ВДУМАЙСЯ) - это ведь бред. Деление исключений на run-time и обрабатываемые - бред. Во-первых, когда программа УЖЕ запущена и УЖЕ работает, ЛЮБОЕ исключение становится run-time, как ты его ни дели. Во-вторых, ЛЮБОЕ исключение, независимо от его источника, должно допускать ЛЮБУЮ свою обработку (от полного игнорирования до полного Halt) - иначе чего будет стоить программа, неподвластная даже программисту?

> в Java

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


 
Суслик ©   (2007-02-24 00:31) [84]


> Юрий Зотов ©   (24.02.07 00:26) [83]

Весь этот разговор настолько долог, что скорее подходит для личной беседы и споров :)


 
Суслик ©   (2007-02-24 00:36) [85]


> Юрий Зотов ©   (24.02.07 00:26) [83]

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

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


 
Юрий Зотов ©   (2007-02-24 01:30) [86]

> Loginov Dmitry ©   (24.02.07 00:09) [82]

> Каким образом выделенная строчка в данном случае о чем-то может
> свидетельстовать?

Очень простым - ДЕЙСТВИТЕЛЬНО квалифицированный программист ТАКОГО не напишет НИКОГДА. Даже спьяну. Встроенный автопилот не пустит.

> Ну не доглядел.

Нет. Не "не доглядел", а "еще нет автопилота". См. п.1.

> Возможно и где-нибудь еще есть подобная оплошность.

Даже и без "возможно". Она есть (я специально смотрел) во всех подобных местах, без исключений. Значит - система, а вовсе не случайность. То есть - человек не вполне понимает, что он пишет и как оно будет работать.

> Существует ли в мире такой код (кроме конечно Вашего собственного),
> которому вы бы могли доверять на 99%.

Конечно. Это код тех пакетов, которые я использую, или использовал на предыдущих местах работы. Например, Rx, Dx, DC, FR, EhGrid, FC и другие. Я видел этот код, я понял КЕМ и КАК он написан - поэтому ЕМУ я действительно верю. Кстати, СВОЕМУ коду я верю меньше. Не потому, что программирую хуже или там лучше - не в этом даже дело. А уже потому, что объем тестирования этих пакетов существенно больше, чем у моего кода. Таковы реалии и о них нужно помнить.

> что для Вас важнее - идеально написанный код, либо надежное
> обеспечение заявленной функциональности?

Софистика. Потому что это одно и то же. ЗАЯВИТЬ можно что угодно, но вот НАДЕЖНО ОБЕСПЕЧИТЬ заявленное без ОТЛИЧНО написанного кода - это не получится. Осетрины второй свежести не бывает. И именно поэтому, когда в коде я вижу откровенные ляпы, то понимаю, что его писал человек с недостаточной квалификацией - соответственно, перестаю верить, что код ДЕЙСТВИТЕЛЬНО обеспечит заявленную функциональность. Как следствие, юзать такой код я не стану. Хватает и своих глюков, зачем еще чужие? Свои я хоть знаю, где править, а с чужими еще разбираться придется.

> каким образом наследование от EMathError позволит организовать гибкую
> обработку ошибок?

Так. Читаем ВНИМАТЕЛЬНО. И чужих слов не ИСКАЖАЕМ. Я говорил, что гибкую обработку ошибок позволяет реализовать СВОЕ исключение (которого у Вас нет). От чего бы оно ни порождалось. Еще я говорил, что будет лучше, если породить его от EMathError. Почему - см. [77].

> вместо Вашего варианта функции RaiseMatrixError()

Простите, ВАШЕГО. В ней я всего лишь заменил имя и класс исключения.

> я разработал функцию DoMatrixError(). Она достаточно информативна, и
> кроме сообщения об ошибке показывает также дополнительную
> информацию: время ошибки, последовательность вызванных процедур,

Это здорово. Безусловное достижение. Заслуживает инкремента мажора.
LOL.

> О делении на ноль программист, я считаю, должен думать заранее.

Да. Причем, не только о нем. Вы ведь программист?
:о)

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

В таких случаях Кейт рекомендует метлу. Я не столь категоричен, поэтому рекомендую больше практики.

> Посмотрите свои собственные исходные коды - мне что-то не верится, что
> в них нет ни одной лишней буквы

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

> я ведь разрабатываю open-source - инструментарий, и уровень конечно
> должен быть соответствующим.

Вот именно. Кстати, и не для open-source - тоже, разницы нет. Именно этим я, в основном, и занимаюсь последние лет этак 8-10.

> мне ни разу не приходилось писать такой вот код:
> ...
> Ну просто не возникает такой необходимости.

ПОКА не приходилось ПОКА не возникало. Но разработчик ИНСТРУМЕНТАРИЯ просто ОБЯЗАН такие вещи предвидеть. Иначе - однозначно РАНО ему еще ИНСТРУМЕНТАРИЙ писать, прикладник он еще по сути своей.

> Если можно, дайте пример

См. [83]. "Честно говоря, тратить время влом, поэтому лучше просто поверь - но если будешь настаивать, то приведу пример, когда обработка, например, деления на ноль позволяет довольно просто получить решение, которое без этой обработки было бы либо не получить совсем, либо гораздо сложнее".

Надеюсь, Вы уже знаете, что я ничего никогда не говорю просто так. Поэтому - если пример нужен, я его приведу, но лучше просто поверьте на слово. Поскольку пример этот будет связан с численными алгоритмами, чтобы он был понятен, многое придется разжевывать и потребуется совсем не час времени. А мне его жаль. Моего СЛОВА - недостаточно?


 
Юрий Зотов ©   (2007-02-24 01:45) [87]

> Суслик ©   (24.02.07 00:31) [84]

Дим, ты еще никогда не был так прав, как в [84]
:о)

> Суслик ©   (24.02.07 00:36) [85]

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

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

2. Обработать деление на ноль, сдвинуть текущее значение X (например, на машинное эпсилон) и продолжить решение. С ОЧЕНЬ большой вероятностью корень таки будет найден. Юзер тоже останется в восторге.


 
Суслик ©   (2007-02-24 01:49) [88]


> Юрий Зотов ©   (24.02.07 01:45) [87]
> > Суслик ©   (24.02.07 00:31) [84]
>
> Дим, ты еще никогда не был так прав, как в [84]

Это намек? :)


> Пример навскидку. Представь, что ты ищешь корень уравнения
> <skiped>
> тоже останется в восторге.

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

Почему придираюсь? Да просто потому, что наследование от EMathError ничего не говорит о "гибкости и удобстве использования своей библиотеки".
Все. Собственно - я ни на что более не претендую :)


 
vuk ©   (2007-02-24 10:02) [89]

to Юрий Зотов ©   (24.02.07 01:30) [86]:
>Например, Rx, Dx, DC, FR, EhGrid, FC и другие.
Юр, FR - это FastReport? Если да, то выкидывай из списка. У него там сплошняком следующее:

Obj := TSomeClass.Create(...);
//Разные действия
Obj.Free;

То есть обработки исключений в таких случаях нет вообще. Похоже, что из принципа. Я самую последнюю (4.х) версию не видел, но в предпоследней (3.х) все было по-прежнему.


 
Anatoly Podgoretsky ©   (2007-02-24 12:42) [90]

> Loginov Dmitry  (24.02.2007 00:09:22)  [82]

> я ведь разрабатываю open-source - инструментарий, и уровень конечно должен быть соответствующим

Это точно и большинство open-source оправдывают это.


 
Ketmar ©   (2007-02-24 13:01) [91]

> Loginov Dmitry ©   (24.02.07 00:09) [82]
>  я ведь разрабатываю open-source

не надо.


 
Суслик ©   (2007-02-24 13:16) [92]

Критикующим и критикумому я могу вот что сказать - что такое хороший код, понять достаточно сложно (ну, или не всегда просто), а вот что такой плохой код - запросто.

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

Присоединюсь посему к Юре: опыт - сын ошибок трудных (так кажется - не соврал). Больше пиши, больше читай чужого кода, потом опять пиши - потом понимание хорошего кода само собой прийдет.

PS Для опенсорсной разработки приведенная библиотека не дотягивает по уровню. И не ИМХО.


 
Loginov Dmitry ©   (2007-02-24 23:54) [93]

Насчет обработки исключений. Правильно Суслик [81], [88] говорит, наследование от EMathError ровным счетом не даст ничего. Это ничем не лучше, чем наследоваться от Exception и не сможет сделать систему более гибкой.


> [87] Юрий Зотов ©   (24.02.07 01:45)


Юрий, очень хороший пример, причем без строчки кода. Теперь мне стало ясно, что некоторые классы исключений действительно в некоторых случаях очень важны. Спасибо! (И Юрию, и Дмитрию). Буду менять механизм обработки исключений. Уже начал строить иерархию исключений. Получается примерно следующее:


type
  EMatrixError = class(Exception);
  {....}
  end;

  EMatrixErrorClass = class of EMatrixError;

  EMatrixIntError = class(EMatrixError);
  EMatrixEDivByZero = class(EMatrixIntError);

  EMatrixMath = class(EMatrixError);
  EMatrixZeroDivide = class(EMatrixMath);

  EMatrixUnderflow = class(EMatrixMath);
  EMatrixWrongCoord = class(EMatrixError);
  EMatrixAbstractError = class(EAbstractError);


В класс исключения EMatrixError можно добавлять поля, в которые и следует заносить дополнительную информацию (имя объекта, тип объекта, последовательность вызовов процедур, приведшая к ошибке, и т.д.). Дополнительные поля можно будет использовать, а можно и не обращать внимание на содержащуюся в них информацию. Код станет даже короче. Различные процедуры Matrix32 так и будут заворачиваться в блок try...except. Примерно так:


procedure TMatrix.Foo;
begin
  try
    if C = 0 then
      raise EMatrixZeroDivide.Create("Ошибка деления на ноль!")
  except
    on E: Exception do
      RaiseMatrixError(E, "procedure TMatrix.Foo");
  end;
end


Но функция RaiseMatrixError будет переписана. Примерно так:


procedure RaiseMatrixError(Error: Exception; const FunctionName: string);
var
  NewError: EMatrixError;
begin
  if Error is EMatrixError then
  begin
    NewError := EMatrixError.Create(Error.Message);
    NewError.FunctionList := FunctionName + " -> " + NewError.FunctionList;
  end else
  begin
    if Error is EDivByZero then
    begin
      NewError := EMatrixDivByZero.Create(Error.Message);
      NewError.FunctionList := FunctionName;
    end else if Error is EZeroDivide then
    begin
      NewError := EMatrixZeroDivide.Create(Error.Message);
      NewError.FunctionList := FunctionName;
    end else
    begin
      NewError := EMatrixError.Create(Error.Message);
      NewError.FunctionList := FunctionName;
    end;
  end;
  raise NewError;
end;


Кстати, написал этот код средствами DMClient я понят что его вполне можно сократить процентов на 30. (Это так, чтобы не издевались лишний раз над этим псевдокодом). Это один вариант обработки исключений. Еще на ум пришел другой вариант, значительно сокращающий функцию RaiseMatrixError:


procedure RaiseMatrixError(Error: Exception; const FunctionName: string);
var
  NewError: EMatrixError;
begin
  NewError := EMatrixError.Create(Error.Message);
  NewError.ErrorClass := Error.ClassType;

  if Error is EMatrixError then
    NewError.FunctionList := FunctionName + "->" + NewError.FunctionList
  else
    NewError.FunctionList := FunctionName;    

  raise NewError;
end;


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


try
  with TByteMatrix.Create do
  try
    Resize([1]);
    FillByValue(100);
    ValueOperation(ThisMatrix, 0, opDiv);
  finally
    Free;
  end;
except
  on E: EMatrixError do
  begin
    if E.ErrorClass is EDivByZero then
      ShowMessage("Деление на ноль в результаты выполнения процедур: " + E.FunctionList);
  end;
end;


Юрий, я представил выше два возможных варианта обработки исключений в Matrix32. Как вы считаете, какой из вариантов может иметь право на существование? (Представленные мною варианты конечно весьма сыроваты, но смысл надеюсь понятен).


 
Ketmar ©   (2007-02-25 00:28) [94]

ну и за каким половым органом надо портить стандартные исключения?


 
Игорь Шевченко ©   (2007-02-25 00:30) [95]

Суслик ©   (23.02.07 11:47) [76]


> type
>   TMatrix = class
>      public type EException = class abstract(Exception);
>
>      public type EWrongCoord = class sealed(EException);
>
>      public procedure GetValue(const aRow, aCol: Integer):
>  Integer;
>      strict private function fValidCoord(const aRow, aCol:
>  Integer): Boolean;
>   end;  


Переведи пожалуйста фрагмент для бестолковых. Например, зачем типы объявлены внутри класса, зачем EException объявлен, как абстрактный, зачем от EWrongCoord нельзя наследоваться и зачем функция fValidCoord во-первых, названа так, во-вторых объявлена как strict private.

Мне на самом деле интересно.


 
Ketmar ©   (2007-02-25 00:33) [96]

как всё запущено...


 
Юрий Зотов ©   (2007-02-25 00:36) [97]

> Loginov Dmitry ©   (24.02.07 23:54) [93]

Дмитрий, во-первых я не понимаю. Вы говорите: "наследование от EMathError ровным счетом не даст ничего. Это ничем не лучше, чем наследоваться от Exception и не сможет сделать систему более гибкой".

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

Как это понять?

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

У исключений ДРУГАЯ концепция, прямо противоположная концепции предварительных проверок данных.

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

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

Вводим в библиотеку функцию GetCallStack (которая выдает стек вызовов вплоть до себя самой) и документируем ее. Все, больше ничего не надо. Юзер (если хочет) использует ее так:

try
 ...
except
 GetCallStack;
 raise
end;

Просто, как веник. Так на фига ж мудрить?


 
Суслик ©   (2007-02-25 00:39) [98]


> Переведи пожалуйста фрагмент для бестолковых. Например,
> зачем типы объявлены внутри класса, зачем EException объявлен,
>  как абстрактный, зачем от EWrongCoord нельзя наследоваться
> и зачем функция fValidCoord во-первых, названа так, во-вторых
> объявлена как strict private.


1. Зачем abstract? (она правда в д2006 есть как ключевое слово, но пока не делает то зачем создан). Данное ключевое слово показывает, что для того, чтобы создать класс исключение, то нужно отнаследовать от EException, т.к. инстанцировать EException нельзя - по идее (сейчас этого нет) компилятор не должен дать этого сделать.
2. Зачем sealed? (это ключевое слово в д2006 работает корректно).
Потому как разработчик, т.е. я, разработал библиотеку таким образом, что EWrongCoord является конечным листом в иерархии. Т.е. это своего рода хинт в понимании кода - это конечный лист, в дизайне других потомков не предполагается.
3. Зачем внутри класса?
Ну здесь понятно - лишняя детализация в namespace"ах имхо еще никому не вредила. ИНаче тебе пришлось бы придумывать более информативные имена классам.
4. Почему fValidCoord?
Это же был пример :) Ну это проверка координат. Там еще были предполагаются методы.
5. Почему strict private?
Если это личный член, зачем его делать видимым другим членам модуля? Инкапсуляция, е-мое.


 
Суслик ©   (2007-02-25 00:48) [99]


> Вводим в библиотеку функцию GetCallStack (которая выдает
> стек вызовов вплоть до себя самой) и документируем ее. Все,
>  больше ничего не надо. Юзер (если хочет) использует ее
> так:
>
> try
>  ...
> except
>  GetCallStack;
>  raise
> end;


Э... Юра ты с javой не перепутал? Такую функцию просто так не создашь :)

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

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

В итоге можно получить такое сообщение (например)
1. Указанный цвет не существует.
2. Ошибка работы со стилем "Деньги"
3. Ошибка работы с таблице стилей.
4. Ошибка работы со закладкой "Доходы".
5. Ошибка работы с файорм "бла-бал.xls".

(это пример).

Более того, аналогичный стек у меня строится и для пользователя. Он в настройках может отключить показ полного стека - будет показываться только головное сообщение (в приведенном примере это "Указанный цвет не существует"). Но не это главное! Главное то, что каждый уровень может нести доп. информацию. В частности у меня есть такой функционал. Представь:
1. Есть объект (с кучей вложенных объектов любого уровня).
2. Есть ГУИ (ясное дело, что это неплохо разделено).
3. В объекте возникает в одном из полей ошибка.
4. Строится стек исключений.
5. ГУИ по стеку исключений находит визуальный компонент, который отвечает за поле, вызвавшее ошибку.


 
Игорь Шевченко ©   (2007-02-25 00:52) [100]

Суслик ©   (25.02.07 00:39) [98]


> Данное ключевое слово показывает, что для того, чтобы создать
> класс исключение, то нужно отнаследовать от EException


Я, Дима, спрашивал не что то или иное слово означает, и как оно работает, а зачем сделано именно так, а не иначе, например, как у Юры Зотова в его коротком коде (номер поста сейчас не приведу, на второй странице, по-моему).


> Ну здесь понятно - лишняя детализация в namespace"ах имхо
> еще никому не вредила. ИНаче тебе пришлось бы придумывать
> более информативные имена классам.


То есть, тебе придется в обработчике писать
on E: TMatrix.EWrongCoord do
 ...

или on E: TMatrixDescendant.EWrongCoord do
 ...

Я верно понимаю, на наследников эти типы тоже распространяются ?


 
Юрий Зотов ©   (2007-02-25 01:06) [101]

> Суслик ©   (25.02.07 00:48) [99]

> Такую функцию просто так не создашь :)

Я тоже удивился. Но раз автор УЖЕ строит стек - значит, инструмент для этого он УЖЕ имеет? Вот он и есть та самая функция.

Правда, тоже непонятно, почему не юзать JEDI, а непременно надо изобрести что-то свое. Ну да это дело хозяйское.


 
Суслик ©   (2007-02-25 01:36) [102]


> Юрий Зотов ©   (25.02.07 01:06) [101]

Ну я тебе 3мя или 4мя постами ранее объяснил, почему свой стек имеет место быть.

Хотя ПОЛностью согласен, что для разработчика JEDI будет достаточно и более чем.


 
Loginov Dmitry ©   (2007-02-25 07:46) [103]

>
> try
> ...
> except
> GetCallStack;
> raise
> end;


Юрий, идея Ваша, как всегда, замечательная. Если пользователь хочет получить подробности об ошибке, он должен вызвать некую функцию GetCallStack. Т.е. в ходе обработки ошибки в Matrix32 информация об ошибке накапливается в неком списке, а при вызове GetCallStack содержимое этого списка выдается пользователю.
Для генерации начально исключения достаточно написать функцию:

procedure RaiseException(AText: string; ExceptClass: TExceptionClass);
begin
 {1. Обнуляем список для GetCallStack}
 {2. Генерируем исключение}
end;

Хотя трудности с тем, как вовремя очистить список еще будут.


 
Ketmar ©   (2007-02-25 10:25) [104]

нет тут никаких трудностей. ибо список давно сделан. и управляется автоматически. смотреть по адресу SS:ESP.


 
Loginov Dmitry ©   (2007-02-26 15:46) [105]

> Правда, тоже непонятно, почему не юзать JEDI, а непременно
> надо изобрести что-то свое. Ну да это дело хозяйское.


Откуда, интересно, я должен был знать о таких вот возможностях JEDI. Вот скачал, посмотрел, теперь знаю, что изобретаю велосипед. JEDI позволяет узнать не только текст ошибки но всю последовательность вызовов функций, адреса и номера строк, в которых ошибка возникла, обрабатывалась (использовались блоки try..except, try..finally), имя модуля, файл модуля. Понравилось :)
Блин, чтож мне теперь всю "обработку" ошибок у себя удалять что-ли? Жалко... :(


 
Jeer ©   (2007-02-26 15:50) [106]

Loginov Dmitry ©   (26.02.07 15:46) [105]

> теперь знаю, что изобретаю велосипед


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


 
Loginov Dmitry ©   (2007-02-26 15:53) [107]

Говорят то все, а убедить могут только очень немногие.


 
Jeer ©   (2007-02-26 16:02) [108]


> Loginov Dmitry ©   (26.02.07 15:53) [107]


У некоторых хватает терпения убеждать того, кто настойчиво лезет в 10-й раз по граблям.


 
Ketmar ©   (2007-02-26 16:08) [109]

> Loginov Dmitry ©   (26.02.07 15:53) [107]
> Говорят то все, а убедить могут только очень немногие.

так это потому, что линейкой по рукам в виртуале не получается.


 
Сергей М. ©   (2007-02-26 16:34) [110]


> Loginov Dmitry ©   (26.02.07 15:53) [107]


Ты ж с TMyThread.Create(..).Terminate намедни облажался по полной программе, продемонстрировав полное нежелание/неумение пользовать встр.отладчик, что уж там говорить про идеологию/концепцию/реализацию метода Free ?) Кто после этого будет "убеждать" тебя ?)


 
Loginov Dmitry ©   (2007-02-26 19:58) [111]

> [110] Сергей М. ©   (26.02.07 16:34)


Ну спасибо! Вот похвалил!

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


{$DEFINE CanChangeExceptionMessage}
try
 C := 0;
 A := B / C;
except
 on E: Exception do
 begin
   {$CanChangeExceptionMessage WriteCallStack}E.Message := E.Message + sLineBreake + FunctionName;{$ENDIF}
   raise;
 end;
end;


И все дела :)
Никакого изобретения велосипедов. И в тоже время можно без проблем пользоваться средствами JEDI.
Вот блин! Столько возни, а разгадка была совсем рядом :))


 
Eraser ©   (2007-02-26 20:08) [112]

> [111] Loginov Dmitry ©   (26.02.07 19:58)


> И все дела :)
> Никакого изобретения велосипедов

как раз наоборот ))

не приведи Господь потом код разгребать после вот таких девелоперов )


 
Loginov Dmitry ©   (2007-02-26 20:29) [113]

Ну тут-то какие претензии могут быть? Я почти совсем уже не вмешиваюсь в обработку исключений. Выключи опцию CanChangeExceptionMessage (тогда уже вмешательства не будет абсолютно никакого) и обрабатывай исключения как хочешь. Это, я считаю, ГОРАЗДО лучше, чем было раньше.


 
Loginov Dmitry ©   (2007-02-26 22:09) [114]

И тут обломался :(

Оказывается нельзя изменить текст у исключений, генерируемых ОС.


 
Ketmar ©   (2007-02-26 22:20) [115]

и это правильно.


 
Anatoly Podgoretsky ©   (2007-02-27 00:45) [116]

> Loginov Dmitry  (26.02.2007 15:53:47)  [107]

Вот когда будут убеждать рублем, то эффект будет налицо.


 
Ketmar ©   (2007-02-27 01:06) [117]

> Anatoly Podgoretsky ©   (27.02.07 00:45) [116]
неа. будут темы "а мне зряплату дали не всю! зато всё лицо набили..."


 
Loginov Dmitry ©   (2007-02-28 21:22) [118]

Вернемся к велосипедам.
Есть два варианта регенерации исключения:

1)

procedure Foo;
begin
 try
   raise Exception.Create("Ошибка!");
 except
   on E: Exception do
   begin
     MatrixCorrectExceptMsg(E, "procedure Foo");
     raise;
   end;  
 end;
end;


2)

procedure Foo;
begin
 try
   raise Exception.Create("Ошибка!");
 except
   on E: Exception do
     raise ReCreateExceptObj(E, "procedure Foo");
 end;
end;


Оба варианта хороши, но есть достоинства и недостатки.

Первый вариант не трогает объект исключения "Е". Он лишь форматирует текст исключения определенным образом. Соответственно raise работает с этим же объектом исключения. Недостаток данного способа - громоздкость записи (каждый раз добавлять begin...end - несколько неудобно и некрасиво).

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

Еще есть третий вариант

3)

function Foo: Integer;
begin
 Result := 0;
 try
   raise Exception.Create("Ошибка!");
 except
   on E: Exception do ReRaiseMatrixError(E, "procedure Foo");
 end;
end;


Третий вариант аналогичен второму, и выглядет более коротко. Однако ему присущи недостатки:
- компилятор не знает, что функция ReRaiseMatrixError в результате своей работы сгенерирует исключение, поэтому пишет варнинги, если в функции Foo не выполнить инициализацию Result за пределами оператора try...except.
- Такой код сложнее отлаживать с помощью все того-же JEDI, т.к. исключение генерируется в какой-то сторонней функции ReRaiseMatrixError.

На каком варианте (1) или (2) остановиться - я не знаю. Корректно ли использование второго варианта в любых ситуациях - не знаю. Полагаюсь на ваши советы. (Боюсь опять поити в ложном направлении).


 
Игорь Шевченко ©   (2007-02-28 21:29) [119]

Loginov Dmitry ©   (28.02.07 21:22) [118]

Тут в соседней ветке Алекс Коншин пишет про исключения - почитай, оно интересно


 
Loginov Dmitry ©   (2007-02-28 22:16) [120]

> Тут в соседней ветке Алекс Коншин пишет про исключения -
> почитай, оно интересно


Интересно конечно. Постараюсь в эти технологии трассировки стэка вникнуть поскорее.
Но хотелось бы ответа на вопрос [118].



Страницы: 1 2 3 4 вся ветка

Форум: "Прочее";
Текущий архив: 2007.03.25;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.77 MB
Время: 0.082 c
1-1169895678
Garacio
2007-01-27 14:01
2007.03.25
Запустить программу в режиме совместимости с ...


2-1172951338
KIBSOFT
2007-03-03 22:48
2007.03.25
Прога как бы зависает!


2-1173016423
Roman_S
2007-03-04 16:53
2007.03.25
UpperCase для Memo


10-1130505467
Volodya_
2005-10-28 17:17
2007.03.25
WebBrowser


2-1173084807
Pigeonhole
2007-03-05 11:53
2007.03.25
глюк в OpenDialog





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский