Новая версия платформы MetaTrader 5 build 2085: Интеграция с Python и массовые улучшения в тестере стратегий - страница 20

 
Alexey Navoykov:
Приведение double к bool ( даже явное!) - это во-первых, концептуальная ошибка.  Не вижу причин, чтобы в нормальном коде такое могло понадобиться.  Во-вторых, приведения вещественных чисел должны производиться через нормализацию - это известно мало-мальскому программисту.  Какое уж тут неявное приведение...


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

void OnStart()
{
  int i = 1, j = 2;
  double d = 10;
  
  bool b = d; // Все нормально, потому что это b = (d != 0);
      
  if (b + 1); // Здесь невозможно совершить ошибку, поэтому предупреждение неоправдано.
  if (d + 1); // Здесь возможна ошибка, поэтому предупреждение оправдано.
  
  d += 1;
  
  // Случай, когда нет однозначного решения, делать предупреждение или нет.
  // Т.к. эта запись удобна и понятна (см. пример внизу), но все же может быть ошибочной.
  if (d); // Здесь возможна ошибка только в том случае, если была замена типа переменной с int на double.

  // Предупреждение частой ошибки, когда клавиша не сработала повторно или не переключился с другого языка.
  if (i & j); // Здесь мог иметься в виду &&, поэтому предупрежедение может помочь.
  if (i | j); // Здесь мог иметься в виду ||, поэтому предупрежедение может помочь.
  
  if (i ^ j); // Здесь все однозначно, поэтому предупреждение ни к чему.
  if (i & 1); // Здесь все однозначно, поэтому предупреждение ни к чему.

  MqlTick Tick[1] = {0};
  
  CopyTicks(_Symbol, Tick, COPY_TICKS_ALL, 0, 1);
  
  if (Tick[0].bid && Tick[0].ask) // Здесь все однозначно, поэтому нет и не должно быть предупреждения.
    Print("Tick is OK.");
}
 
fxsaber:

Для начала, нужно разделить сферы использования.  Выражение в if - это одно (в C++ оно означает явное приведение выражения к bool, поэтому там и предупреждений нет). А вот передача аргумента в функцию (с чего я и начал разговор) - это кардинально другое, и там должно быть всё очень строго.  Впрочем, я считаю, что if тоже надо сделать более строго (и все прочие случаи тоже).   До беспощадности C# конечно дело не доводить, но сделать хотя бы нечто среднее между C++ и C#.  Ибо слабая типизация - зло.   А все эти "невозможно совершить ошибку" рано или поздно выходят боком.

if (b + 1); // Здесь невозможно совершить ошибку, поэтому предупреждение неоправдано.

Что вы тогда понимаете под ошибкой вообще?  Если b имеет тип bool, то это выражение лишено смысла, а значит вероятней всего вы перепутали переменную (предполагалось int).  Вот это и есть потенциальная ошибка.

bool b = d; // Все нормально, потому что это b = (d != 0);

Такая запись даже глаз режет.  Вам нет?

 
Alexey Navoykov:

Что вы тогда понимаете под ошибкой вообще?  Если b имеет тип bool, то это выражение лишено смысла, а значит вероятней всего вы перепутали переменную (предполагалось int).  Вот это и есть потенциальная ошибка.

Да, при написании примера допустил невнимательность. Имелся в виду int.

Если бы был bool - там должно было быть предупреждение. Если же взять int, то невозможно совершить ошибку при такой записи. Попробуйте ее придумать.

Такая запись даже глаз режет.  Вам нет?

Не режет. Пример с тиком привел.

 

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

if (error) ... // Исходя из названия переменной мы понимаем, что запись корректна

if (handle) ... // А здесь, очевидно, запись некорректна

А вот названия функций далеко не всегда дают понимание о возвращаемом типе:

if (File.Open()) ...  // Не очевидно, что возвращает функция: true/false или значение хэндла?  Т.е. во втором случае у нас будет ошибка, но мы не видим этого

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

 
Alexey Navoykov:

Кстати, ещё такой момент

Плохо будет, если на if(double) будет ругаться.

template <typename T>
bool f1( T Value )
{
  return(Value ? true : false); // Разрешаю указатели, запрещаю строки.
}

template <typename T>
bool f2( T Value )
{
  return((Value != NULL) ? true : false); // Разрешаю и указатели и строки.
}

template <typename T>
bool f3( T Value )
{
  return((bool)Value ? true : false); // Запрещаю использовать и указатели и строки.
}
 
fxsaber:

Плохо будет, если на if(double) будет ругаться.

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

Да и эти ваши примеры явно притянуты за уши. Ничто же мешает сделать перегрузку для какого-то конкретного типа, если он не подпадает под общее правило.  Да и вообще такие проверки "разрешаю" для шаблонов должны выполняться методами SFINAE на стадии раскрытия шаблона, а не внутри, иначе замаетесь потом искать.  А коль в MQL нет возможности использовать SFINAE, то нужно делать всё через перегрузки.

 
Alexey Navoykov:

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

Пример потенциальной ошибки с функцией приведите, пожалуйста.

Alexey Navoykov:

Да и эти ваши примеры явно притянуты за уши.

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

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

 
fxsaber:

Пример потенциальной ошибки с функцией приведите, пожалуйста.

Я ж уже приводил выше:  вот и вот.

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

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

Ну я лишь предложил нормальное решение.  А копаться в глубинах таких универсальных шаблонов, пытаясь понять, почему он был вызван и главное - откуда  - вот это как-раз таки уйма потерянного времени и нервов.  Намаялся в своё время, когда тоже страдал этой паранойей насчёт лишней пары строчек кода.  Краткость - далеко не всегда таланта, как показывает практика.  Да и про огромное количество перегрузок речи не шло.  Требовалось же перегрузить шаблон лишь для T* и string.  Впрочем ладно, это тема не для данной ветки.

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

 
Alexey Navoykov:

Я ж уже приводил выше:  вот и вот.

Эти примеры, кроме File.Open, не являются потенциально ошибочными.

Что касается File.Open, то там предупреждение, возможно, могло сыграть положительную роль.

Ну я лишь предложил нормальное решение.  А копаться в глубинах таких обезличенных шаблонов, пытаясь понять, почему он был вызван и главное - откуда   - вот это как-раз таки уйма потерянного времени и нервов.  Намаялся в своё время, когда тоже страдал этой паранойей насчёт лишней пары строчек кода.  Краткость - далеко не всегда таланта, как показывает практика.

Шаблоны были приведены в виде "кстати". if (double) наделять предпреждением - причина не ясна. Неудобства видны.

Что касается лаконичности, то полезность от нее только одна - быстрое улавливание сути и недопущение потенциальных ошибок при написании доп. кода.

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

Сделать MQL-код компилируемым в С++. После чего применить анализатор. Понятно, что бывают заковыристые совсем несовместимые случаи. Тогда игнорить их.

 
fxsaber:

Эти примеры, кроме File.Open, не являются потенциально ошибочными.

Ну это ваше мнение. На этом и сойдёмся.  Моя цель была донести до разработчиков.
Причина обращения: