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

 
fxsaber:
 

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

Все верно. Я сам так всегда делаю (и в этот раз, как видишь,  тоже).

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

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

 
fxsaber:

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


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

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


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


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


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


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

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

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

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

сразу понимаешь все минусы такой записи:

1. Много символов.

2. Чрезмерная "упакованность".

3. Непрокомментированные мат.операции.

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


2. Не смотреть чужой код и просто подключать?

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

Работать может и будет. Но это, -  программы "на коленках".

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

 
Реter Konow:

Работать может и будет. Но это, -  программы "на коленках".

Вы можете посмотреть мои публикации в КБ. Наверное, их кто-то использует.

Я же пишу только для себя и "на коленках". Публикации - побочный продукт.

 
Georgiy Merts:

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

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

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

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

Добавить проверки на LONG_MAX/MIN - и что-то мне подсказывает, что тесты производительности не будут столь радужными. И человек на стд замену замахнулся, значит должно работать на всём диапазоне значений.

 
pavlick_:

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

Добавить проверки на LONG_MAX/MIN - и что-то мне подсказывает, что тесты производительности не будут столь радужными. И человек на стд замену замахнулся, значит должно работать на всём диапазоне значений.

long в ulong (и обратно) - сплошь и рядом.

long в char - редко.

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

Насчет проверки на диапазон - я ж подчеркнул, стоит ASSERT - то есть, такая проверка работает лишь в DEBUG-версии. У меня в начале любой public-функции всегда все входящие параметры проверяются на допустимый диапазон с помощью assert'ов, и это меня не раз выручало. RELEASE-версии - разумеется, уже работают без всяких проверок.

 
fxsaber:

Вы можете посмотреть мои публикации в КБ. Наверное, их кто-то использует.

Я же пишу только для себя и "на коленках". Публикации - побочный продукт.

Не ставлю под сомнение Ваш опыт и профессионализм.

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

Я просто поделился своей точкой зрения.

 
Georgiy Merts:

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

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

 
pavlick_:

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

Счетчик.

void OnStart()
{
  const long Num1 = 9007199254967295;
  const long Num2 = Num1 + 1;

  Print(Num1 == Num2); // false
  Print((double)Num1 == (double)Num2); // true
}

double не теряет инфу всего int-диапазона, с long уже не так.

Особенности языка mql5, тонкости и приёмы работы
Особенности языка mql5, тонкости и приёмы работы
  • 2018.01.15
  • www.mql5.com
В данной теме будут обсуждаться недокументированные приёмы работы с языком mql5, примеры решения тех, или иных задач...
 
fxsaber:

Счетчик.

Ну до стольки ещё досчитать нужно )). А если очень хочется, то чем не вариант:

double cnt;
double high_cnt;
if (++ cnt == 1 000 000) {
   ++ high_cnt;
   cnt = 0;
}
 
pavlick_:

Ну до стольки ещё досчитать нужно )). А если очень хочется, то чем не вариант:

Да понятно, что извратиться-то можно. Но стоит ли  ?

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

И даже целое - в зависимости от алгоритма, на мой взгляд, должно быть объявлено либо как знаковое, либо как беззнаковое, причем, не обязательно long, возможно и более "короткое" - как раз для того, чтобы глядя на код - можно было бы сразу понять, какой диапазон значений допускает данная переменная.

То, что в Lua нет целых значений - на мой взгляд, серьезный минус.

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