По поводу надежности ПО. Exception handling = must have - страница 2

 
Renat :

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


И ведь ловят!



Кстати о делении на 0.

Эта тема часто возникает, увы...

И что самое главное не совсем по вине кодера!


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

1. При if(что-то==0) return;

жестко, и безсмысленно, потому что нужна работа!

поэтому юзаем п.2

2. Обходим стороной путём назначения чему-то абстрактной либо близкой величины

if(что-то==0) что-то=1;

результаты понятное дело плюс-минус по колхозному допуску...


Как пример, даже элементарный пример вычисления уровня маржи и тот страдает падучей:

Средства / Залог * 100 = Уровень

видно, что если нет открытых позиций, т.е. Залог 0, происходит то самое...

Аналогично и при делении на суммлот, который при локе 0,

правда это уже соль мт4...

 

Деление на ноль должно в 100% случаев проверяться программистом во всех местах.


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


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

 

Давайте отойдем от узкого "деления на ноль". Какие еще скриптовые ошибки приводят к остановке скрипта?


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


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

 
marketeer :

Давайте отойдем от узкого "деления на ноль". Какие еще скриптовые ошибки приводят к остановке скрипта?


В разделе "Ошибки выполенения":

В исполняющей подсистеме клиентского терминала существует возможность сохранения кода ошибки в случае ее возникновения при выполнении mql5-программы. Для каждой исполняемой mql5-программы предусмотрена предопределенная переменная _LastError.

Перед запуском функции OnInit переменная _LastError обнуляется. При возникновении ошибочной ситуации во время вычислений или в процессе вызова встроенной функции переменная _LastError принимает соответствующий код ошибки. Значение, сохраненное в этой переменной, можно получить при помощи функции GetLastError().

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

деление на ноль;
выход за пределы массива;
использование некорректного указателя на объект;
 
В четверке, если произошла скриптовая ошибка (деление на ноль, в частности), исполнение прерывается и в результате вполне может случиться убыток
Renat :

При обнаружении критической ошибки MQL5 скрипт снимается с исполнения терминалом.


Фактически нельзя оставлять работать программу, которая крешится. Это означает, что не имеет смысла даже сообщать самому скрипту об этом - все равно он ничего не сможет сделать, а скорее всего сгенерирует новые креши.


Выход для экспертописателей только один - максимально полно тестировать свои программы.

Однако вы не сможете программно обработать данный креш - эксперт, после вывода сообщения в лог, "жёстко" выгрузится (без вызова деструкторов и OnDeinit()).


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

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

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

снимется с исполнения. А в этом скрипте пользователь сам решает какие позиции закрывать.


Ошибаются все. А после критической ошибки хотелось бы, чтобы остановился не только эксперт, но и торговля :)
Документация по MQL5: Программы MQL5 / Ошибки выполнения
Документация по MQL5: Программы MQL5 / Ошибки выполнения
  • www.mql5.com
Программы MQL5 / Ошибки выполнения - Документация по MQL5
 
Kagoric :



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


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

Документация по MQL5: Основы языка / Переменные / Глобальные переменные
Документация по MQL5: Основы языка / Переменные / Глобальные переменные
  • www.mql5.com
Основы языка / Переменные / Глобальные переменные - Документация по MQL5
 

В общем, по молчанию со стороны МК я делаю вывод, что данный вопрос будет решен в "лучших" традициях: все останется как прежде, просто им это не нужно.


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


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


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


Впрочем, фиг с ними исключениями. Раз ООП - это, по мысли авторов, потолок развития МТ - пусть остается как есть.

 
marketeer :


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

Конечно проще сделать отлов делений в одном месте и получить багливую программу.


Правильно именно в каждом месте проверять делитель на ноль.


ps: не забывайте, что мы профессиональные программисты и у многих из нас по 15-20 лет опыта именно в программировании.

 
marketeer :

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


Берем левый код и не желаем его проверять, а потом трепетно думаем об убытке из-за креша непроверенного кода?


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

 
Renat :

У MQL5 программ нет механизмов Exception Handling.


То есть, эксепшены не генерятся. Вместо этого есть классический метод проверки кодов возврата.


Код возврата?

Зачем тогда было создавать урезанный С++ ?

 

Вполне хватило бы доработки до C.

Добавили бы структур, которых так не хватало, условное выражение и нормальный return, и - всё.

 

Условное выражение добавили, return сделали нормальный, но вместо добавления структур зачем-то решили доусложнять до C++.

 

class A
{
public:
  A()  { /* Actions */ if(/* Condition */) Print("Object is not created"); }
  ~A() { /* Actions */ }
};

/******************************************************************************/

int OnInit()
{
  A a;

/* Конструктор (в случае выполнения Condition) не отработал, объект не создан */
/* Объектом пользоваться нельзя, а то как деление на ноль случится, так мало не покажется... */
/* Но как об этом узнать здесь? */
/* И как конструктор мог бы передать эту информацию сюда? */

  return 0;
}
Причина обращения: