Альтернативные реализации стандартных функций/подходов - страница 8

 
fxsaber:

Пример моего стиля?

Например это: 

return((int)((Value > 0) ? Value / Points[digits] + HALF_PLUS : Value / Points[digits] - HALF_PLUS) * Points[digits]);

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

 
Реter Konow:

Например это: 

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

Я бы искал не более пары минут, тем более что запись в таком стиле позволяет вывести в "один экран" более нескольких десятков функций, что упрощает работу с кодом

 
Реter Konow:

Например это: 

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

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

Вы привели простейший return. Честно, не понимаю, что в нем может хоть на каплю смутить.

Признаюсь, не могу читать С++-код, потому что его не знаю совсем. Но люди пишут на нем. Значит дело просто в незнании.

 
fxsaber:

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

Вы привели простейший return. Честно, не понимаю, что в нем может хоть на каплю смутить.

Признаюсь, не могу читать С++-код, потому что его не знаю совсем. Но люди пишут на нем. Значит дело просто в незнании.

Возможно, у нас разные представления о простоте кода.

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


Буду откровенен, - я терпеть не могу С++ за чрезмерную нечитабельность. За нагромождение сущностей, существование которых можно легко избежать. И ведь будет только лучше. Просторней. 

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

ЗЫЫ. Ветка отличная. Спасибо. 

Productivity - США - MetaTrader 5
Productivity - США - MetaTrader 5
  • www.metatrader5.com
Индекс производительности труда показывает изменение объема выпущенной продукции, приходящегося на одного работника. Этот показатель полезен для предсказания инфляции и прироста объема производства. Если стоимость труда увеличивается соответственно увеличению производительности, и, кроме того, маловероятно увеличение производственных издержек...
 
Renat Fatkhullin:
Задумайтесь, что получите за пределами целого числа. 

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

Если функция возвращает double, которое мы потом преобразуем в long - то мы приходим к той же опасности переполнения.

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

 
Vitaly Muzichenko:

Я бы искал не более пары минут, тем более что запись в таком стиле позволяет вывести в "один экран" более нескольких десятков функций, что упрощает работу с кодом

Что-то я сомневаюсь в этом.

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

// Для МТ4 - возвращает otfFilingType. // Для МТ5 - возвращает тип исполнения ордера, равный otfFilingType, если он доступен на символе strSymbol, иначе - корректный вариант. ENUM_ORDER_TYPE_FILLING CSymbolInfo::GetTypeFilling(string strSymbol,ENUM_ORDER_TYPE_FILLING otfFilingType = ORDER_FILLING_FOK) {    #ifndef __MQL5__       return(otfFilingType);    #else // __MQL5__          // Функцию предложил fxsaber. Серьезной проверки не было - полагаемся на его авторитет.          const ENUM_SYMBOL_TRADE_EXECUTION steExeMode = (ENUM_SYMBOL_TRADE_EXECUTION)::SymbolInfoInteger(strSymbol, SYMBOL_TRADE_EXEMODE);    const int iFillingMode = (int)::SymbolInfoInteger(strSymbol, SYMBOL_FILLING_MODE);

   return((iFillingMode == 0 || (otfFilingType >= ORDER_FILLING_RETURN) || ((iFillingMode & (otfFilingType + 1)) != otfFilingType + 1)) ?          (((steExeMode == SYMBOL_TRADE_EXECUTION_EXCHANGE) || (steExeMode == SYMBOL_TRADE_EXECUTION_INSTANT)) ?            ORDER_FILLING_RETURN : ((iFillingMode == SYMBOL_FILLING_IOC) ? ORDER_FILLING_IOC : ORDER_FILLING_FOK)) :           otfFilingType);      #endif // __MQL5__ };

Функция реально нормально работет. Я ее много раз проверял, ошибок не возникало. Но как формируется результат в этом ужасном return'e - я так и не понял, несмотря на свой, по-моему, достаточно хороший опыт. Причем, на вопрос сам fxsaber ответил, что он и сам этого не помнит.

Виталий, расскажите, как работает данный код, если вам несложно, и вы в подобном стиле "разбираетесь за пару минут" !  

Я бы "раскрыл скобки" в операторе return, заменил бы все "вопросики" if'ами, и вернул бы найденные значения через логическое "или". Лично меня оператор "вопросик" вобще раздражает. Код он дает точно такой же, как аналогичный if, а вот его читабельность - куда хуже.

 
Georgiy Merts:

Что-то я сомневаюсь в этом.

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

Функция реально нормально работет. Я ее много раз проверял, ошибок не возникало. Но как формируется результат в этом ужасном return'e - я так и не понял, несмотря на свой, по-моему, достаточно хороший опыт. Причем, на вопрос сам fxsaber ответил, что он и сам этого не помнит.

Виталий, расскажите, как работает данный код, если вам несложно, и вы в подобном стиле "разбираетесь за пару минут" !  

Я бы "раскрыл скобки" в операторе return, заменил бы все "вопросики" if'ами, и вернул бы найденные значения через логическое "или". Лично меня оператор "вопросик" вобще раздражает. Код он дает точно такой же, как аналогичный if, а вот его читабельность - куда хуже.

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

 
Реter Konow:

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

Пример моего кода, который вот сейчас совсем не понимаю. И для понимания нужно очень хорошо въехать во множество факторов.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Последовательность выполнение Init() и DeInit()

fxsaber, 2017.04.14 23:35

  bool Check( void ) const
  {
    static bool FirstRun = true;
    static bool FirstRunInit = true;

    if (FirstRun && (!::GlobalVariableCheck(this.GlobalName)))
    {
      FirstRun = (::GlobalVariableSet(this.GlobalName, 0) == 0);

      if (!FirstRun)
      {
        ::EventKillTimer();

        ::OnInit();
        FirstRunInit = false;
      }
    }
    else if (FirstRun)
      ::EventSetMillisecondTimer(1);
    else
      FirstRunInit = true;

    return(FirstRun || !FirstRunInit);
  }

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

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


Есть еще пример чисто языковых конструкций - TypeToBytes. Там сложность с пониманием совсем иного уровня. И вот там без макросов я бы завял. А именно из-за использования макросов получается довольно быстро врубиться в исходный код. Потому что макросы не для лаконичности чаще всего, а для понимания.


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


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


Посмотрите в КБ на MT4-советники и их порты под MT5. MT5-порты - это каторга для понимания. Мало того, что лаконичностью и близко не пахнет (код в разы больше оригинала), так еще и с побрякиванием MT5-подводных камней, которые не учтены в mqh-файлах.

 
Vitaly Muzichenko:

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

В этом случае - разумно использовать функции.

И то, что ты не стал трактовать код - говорит, что сходу ты тоже не можешь понять, как он работает. Тут необходима тщательный анализ скобок, этих самых "вопросиков" и логических "или". А вот такое "нагромождение" - допустимо в очень ограниченных случаях, когда оно дает более эффективный код, который будет использоваться в "бутылочном горле" программы. В данном случае - получение типа исполнения никак не может быть "бутылочным горлом", и такой код здесь нежелателен. Я его использую исключительно основываясь на авторитете fxsaber'а и на многократной самостоятельной проверке. Но, это исключение. Как правило, я не использую код, в котором детально не разобрался сам.

 
Georgiy Merts:

Функция реально нормально работет. Я ее много раз проверял, ошибок не возникало. Но как формируется результат в этом ужасном return'e - я так и не понял, несмотря на свой, по-моему, достаточно хороший опыт. Причем, на вопрос сам fxsaber ответил, что он и сам этого не помнит.

Дело не в returne. Если Вы распишите эту же логику в виде if-else, от этого понимания у меня больше не станет. Это именно тот случай, когда берется проблема "Unsupported filling" и очень глубоко изучается. Для этого нужно написать очень много сопутствующего стресс-кода, открыть множество счетов на разных торовых серверах и гонять по всем символам. Находить закономерности среди разных комбинаций флагов. И, наконец, подвести все таблицы к одному единому знаменателю. В этом заключается "не помню".

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

Причина обращения: