English 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Стать хорошим программистом (Часть 1): избавляемся от пяти привычек, чтобы лучше программировать на MQL5

Стать хорошим программистом (Часть 1): избавляемся от пяти привычек, чтобы лучше программировать на MQL5

MetaTrader 5Примеры | 9 сентября 2021, 14:24
4 929 17
Omega J Msigwa
Omega J Msigwa

Введение

«Разум, однажды расширивший свои границы, никогда не вернется в прежние» (Альберт Эйнштейн).

Чтобы стать лучшим программистом, надо учиться программировать 24/7, избавляться от плохих привычек, нарабатывать хорошие, знакомиться с лучшими практиками, а возможно и заново изучить основополагающие принципы программирования. Это всё важно для любого, кто стремится построить успешную карьеру программиста. Зная, как и почему, мы осознаем, что делаем. Это развивает наши способности запоминать информацию и в целом помогает добиться лучшего качества кода.

Рассмотрим здесь некоторые проверенные методы, которые практически моментально могут улучшить ваш стиль программирования — для этого надо внимательно прочитать эту статью и начать применять советы на практике.


1. Откажитесь от слепого копирования кода

«Самое благородное удовольствие — это радость понимания» (Леонардо да Винчи).

Это любимая привычка начинающих программистов (но и опытные иногда ею грешат). Когда я только начал программировать в 2019 году, большую часть времени я искал по форумам «работающий код». Я не обращал внимания на сопутствующие разъяснения, когда искал конкретные примеры. Мне нужен был только тот самый комментарий, в котором кто-нибудь отвечал что-то вроде «Спасибо! Код работает!» — любой комментарий с благодарностями (особенно если благодарность исходила от человека, который изначально просил помощи на форуме). Вы же понимаете, что я делала, когда находил работающий кусок кода? Правильно - копировал.

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

  


Теперь-то я знаю, почему код не работал. Причина была во мне. Просто потому, что я скопировал этот код откуда-то (сам не помню, откуда). И вот что я хочу сказать:

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

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

Как правильно: всегда надо стремиться понять, а не просто найти решение!

Программировать будет проще, сам процесс станет естественнее, если вы поймете саму суть.

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

2. Не пытайтесь хакнуть проблему

Прежде чем искать решения для своей проблемы, надо понять причины ее возникновения. Только разобравшись, вы сможете задавать правильные вопросы на форуме, а не постить код в надежде получить исправленное и правильно работающее решение в ответ. А ведь проблема может быть связана с тем, что вы просто не понимаете, что и зачем пишете. Опять же возьмем мой пример: я скопировал где-то код, чтобы изменить шаблон графика, не понимая и вообще не зная ничего о работе с графиками через стандартную библиотеку. И что в итоге? Я написал, что библиотека не работает.

Как только вы столкнетесь с проблемой или ошибкой, убедитесь, что понимаете все библиотеки и код, который не работает. Есть разные способы найти полезную информацию на MQL5. Основные, это:

  • Документация по MQL5
  • Форум

Документация по MQL5:

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

Доступ к документации

Форум MQL5:

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

 «Дорога мастера ведет к настоящему пониманию».

Новички варятся в том, что я называю нуб-циклом.

Нуб-цикл

3. Откажитесь от перфекционизма

«Сделанное лучше идеального» (популярная идея из силиконовой долины).

Как много раз я не решался запостить свои разработки именно из-за перфекционизма. Я пытался найти идеальный Святой Грааль, которым можно было бы поделиться на сайте с другими пользователями. Мне потребовалось время, чтобы осознать вот что: если есть чем поделиться, надо делиться, а не мучиться в постоянных сомнениях.

Что лучше, написать один индикатор, советник, библиотеку или кусок кода в ближайшие несколько лет или плодотворно создать сотни несовершенных решений?

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

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

  • Мобильные приложения постоянно обновляются 
  • Постоянно выходят обновления операционных систем компьютеров и телефонов
  • Даже языки программирования, такие как MQL5, Python и другие, периодически обновляются 

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

Это же касается и сайта MQL5.com. Например, продукты, продаваемые на Маркете, тоже периодически обновляются.

Обновление версий

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

4. Не пишите заумный код

«Отладка в два раза сложнее, чем написание кода с самого начала. Следовательно, если вы напишете код настолько умно, насколько это возможно, вы по определению недостаточно умны, чтобы его отлаживать» (Брайан Керниган).

Код, хорошо написанный с учетом документации, уже достаточно хорош! 

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

Вот несколько советов по написанию чистого кода:

  • Используйте стилизатор 
  • Будьте последовательными
  • Комментируйте
  • Следуйте принципу DRY 

Стилизация:

В качестве примера я покажу функцию, которая считает позиции по их типу

int CountPosByType(ENUM_POSITION_TYPE type){
 int counter = 0; 
  for (int i=PositionsTotal(); i>=0; i--)
     if (m_position.SelectByIndex(i))
     if (m_position.Magic()==MagicNumber && m_position.Symbol()==Symbol() && m_position.PositionType()==type)
      { counter++; }
  return counter;
}

Функция довольно проста и вроде ее можно понять. Но она не отвечает требованиям чистого кода. Поэтому применим стилизатор. Это просто: нажимаем на синюю кнопку в виде расчески в MetaEditor и причесываем код.

Стилизатор кода MQL5

А вот как выглядит код с правильными стилями:

int CountPosByType(ENUM_POSITION_TYPE type)
  {
   int counter = 0;
   for(int i=PositionsTotal(); i>=0; i--)
      if(m_position.SelectByIndex(i))
         if(m_position.Magic()==MagicNumber && m_position.Symbol()==Symbol() && m_position.PositionType()==type)
            { 
                counter++; 
            }
   return counter;
  }

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

Будьте последовательными:

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

Давайте назовем нашу функцию так:

int CountPositionsByType(ENUM_POSITION_TYPE type)

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


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

Лучший способ писать хороший код — это использовать ООП (объектно-ориентированное программирование).

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

Комментируйте:

Новичкам может показаться, что комментарии — это мелочь. Однако именно они могут существенно повлиять на вашу производительность. Они не только улучшают читабельность кода, но и могут служить напоминанием о том, например, что же делает эта функция.

Давайте еще раз определим наш счетчик, добавив комментарий с объяснением:

int counter = 0; // Переменная для записи количества позиций

В следующий раз для использования счетчика нужно сделать только следующее:

mql5 code Intellisense

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

Следуйте принципу DRY

DRY - от английского Don't repeat yourself, "не повторяйся". В соблюдении этого принципа хорошо помогает ООП. Не надо создавать множество функций, которые делают практически одно и тоже. Например, нет смысла писать функцию, которая проверяет существование позиции по ее типу, если у вас уже есть готовая функция для подсчета позиций по типам.

5. Не старайтесь написать максимально короткий код

«Код прежде всего должен читаемым. Все остальное потом».

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

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

Иногда краткость кода связана с ленью (это как раз про меня - я был ленивым). Мы реализуем минимально необходимое решение, просто чтобы закончить, к примеру, заказ на Фрилансе или любую другую задачу.

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

Вот что я хочу сказать:

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

Реализовывать все информационные функции каждый раз с нуля не нужно — есть более удобный способ. Вы можете хранить весь этот функционал в отдельных include-файлах или копировать и вставлять нужный код по месту.


Заключение

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

Спасибо за внимание!


Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/9643

Последние комментарии | Перейти к обсуждению на форуме трейдеров (17)
Maxim Kuznetsov
Maxim Kuznetsov | 9 сент. 2021 в 23:59

всем (и автору статьи тем более) к прочтению обязательно : 97 Things Every Programmer Should Know

Daniil Kurmyshev
Daniil Kurmyshev | 10 сент. 2021 в 02:41
Исходный:
int CountPosByType(ENUM_POSITION_TYPE type)
  {
   int counter = 0;
   for(int i=PositionsTotal(); i>=0; i--)
      if(m_position.SelectByIndex(i))
         if(m_position.Magic()==MagicNumber && m_position.Symbol()==Symbol() && m_position.PositionType()==type)
            { 
                counter++; 
            }
   return counter;
  }

Вариант работающий быстрее и на мой взгляд понятнее:

int PositionsByType(ENUM_POSITION_TYPE type)
  {
   int counter = 0;
   for(int i=PositionsTotal()-1; i>=0; i--)
   {
      if(!m_position.SelectByIndex(i))
         return (INVALID_HANDLE);

      if(m_position.PositionType()!=type ||
         m_position.Magic()!=MagicNumber ||
         m_position.Symbol()!=Symbol())
         continue;

      counter++; 
   }
   return counter;
  }

1. Ошибка в инициализации цикла от количества необходимо отнимать 1, когда делаем обратный перебор.

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

3. Сначала надо проверять переменные bool, далее перечисления ENUM и только после проверять int, double, string, если проверка не удалась то сразу переходить к следующему элементу цикла.

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

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

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


Aliaksandr Hryshyn
Aliaksandr Hryshyn | 10 сент. 2021 в 07:52
По поводу этого вы ошибаетесь:
"Если делать операции сравнения через &&, то программа будет в обязательном порядке делать проверку каждого условия.".
Происходит сравнение по порядку до первого false.
Кстати, ещё в таких ситуациях можно учитывать вероятность невыполнения условия.

Daniil Kurmyshev
Daniil Kurmyshev | 10 сент. 2021 в 12:19
Aliaksandr Hryshyn #:
По поводу этого вы ошибаетесь:
"Если делать операции сравнения через &&, то программа будет в обязательном порядке делать проверку каждого условия.".
Происходит сравнение по порядку до первого false.
Кстати, ещё в таких ситуациях можно учитывать вероятность невыполнения условия.

Да, Вы меня верно поправили, проверка будет до первого false, главное, чтобы мелкие типы данных были вначале.

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

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

[Удален] | 10 сент. 2021 в 12:57
Vitaly Muzichenko #:

Это фриланс, заказчики чаще всего вообще не понимают в коде, а отзывы плохие не за качество кода. Написал, прибыль программа не дала, вот и отзыв.

А вы заказчику скажите заранее об этом или деньги важнее
Графика в библиотеке DoEasy (Часть 82): Рефакторинг объектов библиотеки и коллекция графических объектов Графика в библиотеке DoEasy (Часть 82): Рефакторинг объектов библиотеки и коллекция графических объектов
В статье доработаем все объекты библиотеки - присвоим каждому объекту его уникальный тип и продолжим разработку класса-коллекции графических объектов библиотеки.
Графика в библиотеке DoEasy (Часть 81): Интегрируем графику в объекты библиотеки Графика в библиотеке DoEasy (Часть 81): Интегрируем графику в объекты библиотеки
Начинаем интегрирование уже созданных графических объектов в остальные — ранее созданные объекты библиотеки, что в итоге наделит каждый объект библиотеки своим графическим объектом, позволяющим интерактивно взаимодействовать пользователю с программой.
Почти конструктор для создания советника Почти конструктор для создания советника
Предлагаю свой набор торговых функций в виде готового советника. Представленный способ позволяет получать множество торговых стратегий простым добавлением индикаторов и изменением входных параметров.
Комбинаторика и теория вероятностей для трейдинга (Часть III): Первая математическая модель Комбинаторика и теория вероятностей для трейдинга (Часть III): Первая математическая модель
Закономерным продолжением темы стала потребность разработки многофункциональных математических моделей для задач трейдинга. В связи с этим в данной статье я буду описывать весь процесс разработки первой математической модели для описания фракталов с нуля. Данная модель должна стать важным кирпичиком и быть многофункциональной и универсальной, в том числе для того, чтобы нарастить теоретическую базу для дальнейшего развития ветки.