Español Português
preview
От начального до среднего уровня: Struct (III)

От начального до среднего уровня: Struct (III)

MetaTrader 5Примеры |
344 0
CODE X
CODE X

Введение

В предыдущей статье "От начального до среднего уровня: Индикатор (IV)", мы показали, как простым и понятным способом сделать то, что для многих новичков было бы очень сложным. Теперь все знают простой и легкий способ, чтобы воплотить свои идеи в жизнь. Целью было создание индикатора, который бы с помощью цветов показывал некую торговую систему. Конечно, там мы показали, как реализовать модель внутреннего бара. Но эти знания можно применить к любой модели, цветовой паттерн свечей которой указывает (или не указывает) на возможность торговли.

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

В статьях о структурах, особенно на сайте "От начального до среднего уровня: Struct (II)", мы объяснили, как работать со структурами для создания блоков записи. В тех двух статьях, мы упоминали, что структуры - это особый вид данных, в которых можно размещать различную информацию, но организовывая ее логичным и упрощенным способом. Однако, поскольку ранее мы ничего другого не показали, углубляться в детали строений было бы сложно и даже ненужно. Но предыдущая статья создала достаточный задел для того, чтобы мы могли углубиться в некоторые другие вопросы. В принципе, мы сейчас хотим показать, что структуры можно использовать не только для организации данных записи.

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


Структурированный код

Наверное, больше всего меня удручает, когда я вижу код, в котором всё перепутано. Во времена доброго старого BASIC, некий смысл имелся в том, чтобы код был без заранее определенной структуры. Это обусловлено самой природой языка. В языках типа BATCH, как, например, языки пакетной обработки, основанные на скриптах (примером может служить SQL), в определенном смысле мы можем не иметь очень четко определенной структуры. Ведь в большинстве случаев задачи, которые необходимо выполнить, относительно просты, как и коды, которые обычно довольно короткие.

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

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

Чтобы добиться по-настоящему структурированного кода, нам нужно использовать методы и концепции, которые многие считают безумными или, по крайней мере, слишком сложными. Одним из таких средств являются классы. Но пока ещё не время говорить о классах, ведь классы появились не потому, что в один прекрасный день программисты проснулись и сказали: «Мы собираемся создать нечто, что усложнит жизнь всем, кто только начинает свою карьеру. Так мы станем самыми крутыми программистами». Нет, классы появились для того, чтобы решить проблему создания действительно структурированного кода.

Чтобы понять данное ограничение, нам нужно обратиться к более сложным вопросам. Так что приготовьтесь, потому что с этого момента всё станет очень интересно и даже весело.

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

В предыдущей статье мы видели следующий код:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. input bool user01 = true;       //Show time scale
05. input bool user02 = true;       //Show price scale
06. //+----------------+
07. struct st_Mem
08. {
09.     long    View_DateScale,
10.             View_PriceScale;
11. }gl_StyleGraphic;
12. //+------------------------------------------------------------------+
13. int OnInit()
14. {
15.     gl_StyleGraphic.View_DateScale = ChartGetInteger(0, CHART_SHOW_DATE_SCALE);
16.     gl_StyleGraphic.View_PriceScale = ChartGetInteger(0, CHART_SHOW_PRICE_SCALE);
17. 
18.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, user01);
19.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, user02);
20. 
21.     return INIT_SUCCEEDED;
22. };
23. //+------------------------------------------------------------------+
24. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
25. {
26.     return rates_total;
27. };
28. //+------------------------------------------------------------------+
29. void OnDeinit(const int reason)
30. {
31.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, gl_StyleGraphic.View_DateScale);
32.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, gl_StyleGraphic.View_PriceScale);
33.     ChartRedraw();
34. };
35. //+------------------------------------------------------------------+

Код 01

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

Однако, несмотря на кажущуюся простоту данного кода, многие считают его структурированным кодом. На мой взгляд, то, что мы видим в коде 01, - это не совсем структурированный код, а скорее хорошо организованный код. Несмотря на свою простоту, это не совсем тот код, который, на мой взгляд, идеально подходит для объяснения структурированного кода. Для этого мы обратимся к чему-то еще более простому: к скриптам. Это происходит так, потому что скрипты реагируют только на событие Start. По окончании данного события код завершается. Проще этого НЕ БЫВАЕТ.

Хорошо, давайте начнем с кода, показанного ниже.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     struct st_Mem
07.     {
08.         long    View_DateScale,
09.                 View_PriceScale;
10.     }StyleGraphic;
11. 
12.     StyleGraphic.View_DateScale = ChartGetInteger(0, CHART_SHOW_DATE_SCALE);
13.     StyleGraphic.View_PriceScale = ChartGetInteger(0, CHART_SHOW_PRICE_SCALE);
14. 
15.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, false);
16.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, false);
17.     ChartRedraw();
18. 
19.     Sleep(2000);
20. 
21.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, StyleGraphic.View_DateScale);
22.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, StyleGraphic.View_PriceScale);
23.     ChartRedraw();
24. }
25. //+------------------------------------------------------------------+

Код 02

Данный код намного проще, чем в примере 01, и имеет ту же цель: скрыть, а затем заменить ценовые и временные шкалы. Запустив данный скрипт на графике, вы увидите нечто похожее на анимацию ниже:

Анимация 01

Как видите, всё очень просто: строка 19 отвечает за то, чтобы шкалы на несколько мгновений скрылись. В ней мы указываем, что хотим сделать паузу около двух секунд перед повторным выполнением кода. Однако я хочу, чтобы вы обратили внимание на два момента: строки 17 и 23. В предыдущей статье я рассказал, почему эту команду следует использовать в коде. Однако здесь мы работаем со скриптом, и таймаут короткий, поэтому данная команда, присутствующая в обеих строках, упомянутых выше, очень важна. Без него мы, скорее всего, не увидели бы, как скрываются и снова проявляются ценовые и временные шкалы.

Хорошо. Пока всё понятно. Но код 02, на мой взгляд, не является структурированным кодом, хотя в строке 06 мы объявляем структуру. Итак, давайте начнем писать то, что многие считают структурированным кодом. Для этого изменим код 02 на показанный ниже:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. struct st_Mem
05. {
06.     long    View_DateScale,
07.             View_PriceScale;
08. };
09. //+------------------------------------------------------------------+
10. void OnStart(void)
11. {
12.     st_Mem StyleGraphic;
13. 
14.     StyleGraphic = SAVE();
15. 
16.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, false);
17.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, false);
18.     ChartRedraw();
19. 
20.     Sleep(2000);
21.     
22.     RESTORE(StyleGraphic);
23. }
24. //+------------------------------------------------------------------+
25. st_Mem SAVE(void)
26. {
27.     st_Mem local;
28. 
29.     local.View_DateScale = ChartGetInteger(0, CHART_SHOW_DATE_SCALE);
30.     local.View_PriceScale = ChartGetInteger(0, CHART_SHOW_PRICE_SCALE);
31. 
32.     return local;
33. }
34. //+------------------------------------------------------------------+
35. void RESTORE(const st_Mem &arg)
36. {
37.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, arg.View_DateScale);
38.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, arg.View_PriceScale);
39. 
40.     ChartRedraw();
41. }
42. //+------------------------------------------------------------------+

Код 03

Код 03 даст тот же результат, что и анимация 01, но с небольшим оттенком. В отличие от кода 02, у нас здесь лучшая организация, поскольку можем использовать функцию в строке 25 в разное время, а также процедуру в строке 35 в любой момент. Основное преимущество такого типа моделирования и реализации, которое мы можем увидеть в коде 03, заключается именно в том, что мы можем сохранять и восстанавливать все значения свойств графика, не беспокоясь о том, какие значения будут изменены. Это позволяет избежать необходимости создавать большое количество строк, которые всегда содержат один и тот же вид кода.

Но с этим подходом есть небольшая проблема, которая видна в коде 03. Проблема заключается в следующем: мы работаем со структурой, содержащей данные. Пока всё понятно. Но какой смысл реализовывать функцию в строке 25 и процедуру в строке 35, если цель - работать непосредственно с данными, присутствующими в структуре?

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

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

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

В структурированном коде функции SAVE и RESTORE больше не будут объявлены так, как мы видим в коде 03, где они не связаны должным образом с контекстом структуры, определенной в строке 04, а будут объявлены, или, скорее, реализованы в контексте данной структуры. Поскольку это невозможно показать фрагментарно, мы перейдем непосредственно к решению, рассмотренному в других кодах, только теперь в полностью структурированной модели. Это можно увидеть в приведенном ниже коде:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. struct st_PropertyGraphics
05. {
06.     long    View_DateScale,
07.             View_PriceScale;
08. //+----------------+
09.     void SAVE(void)
10.     {
11.         View_DateScale = ChartGetInteger(0, CHART_SHOW_DATE_SCALE);
12.         View_PriceScale = ChartGetInteger(0, CHART_SHOW_PRICE_SCALE);
13.     }
14. //+----------------+
15.     void RESTORE(void)
16.     {
17.         ChartSetInteger(0, CHART_SHOW_DATE_SCALE, View_DateScale);
18.         ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, View_PriceScale);
19. 
20.         ChartRedraw();
21.     }
22. //+----------------+
23. };
24. //+------------------------------------------------------------------+
25. void OnStart(void)
26. {
27.     st_PropertyGraphics StyleGraphic;
28. 
29.     StyleGraphic.SAVE();
30. 
31.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, false);
32.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, false);
33.     ChartRedraw();
34. 
35.     Sleep(2000);
36.     
37.     StyleGraphic.RESTORE();
38. }
39. //+------------------------------------------------------------------+

Код 04

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

Что ж, мы только что подняли планку. Тот, кто не практиковал и не изучал то, что показывается сейчас, не будет иметь способа продвигаться, поскольку с этого момента возможности возрастают очень быстро в геометрической прогрессии. Однако бояться кода 04 не стоит. Я стараюсь сделать всё максимально образовательным, чтобы избежать необходимости объяснять и сосредоточиться на чем-то более интересном.

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

Пока что мы проигнорируем структуру, определенную в строке 04, и сосредоточимся на обработчике события OnStart. В строке 27 мы объявляем структуру так же, как и раньше, то есть создание нашей переменной или специальной записи будет происходить точно так же. Но обратите внимание на строки 29 и 37. О чем вы думаете, когда видите эти строки? Вы, наверное, думаете: «Ну, в строке 29 я запрашиваю сохранить что-то, а в строке 37 - что-то восстановить». Если вы так подумали, то мы на правильном пути.

Посмотрите ещё раз на те же строки: что мы просим сохранить и восстановить? Это действительно переменная, которую мы объявили в строке 27. Интересно. Давайте разберемся. В строке 27 мы объявляем переменную. При выполнении строки 29 запрашивается сохранение той же переменной. Хорошо, поскольку данная переменная является типом записи графического свойства,

Итак, в строке 29 мы запрашиваем сохранение графических свойств. Таким образом, в строках 31 и 32 мы можем изменять свойства, не беспокоясь о возможных изменениях. «Отлично, кажется, становится понятнее. Когда мы выполняем строку 37, мы просим восстановить те же сохраненные свойства, отбрасывая тем самым все изменения, сделанные между строками 29 и 37. Так ли это, и правильно ли я понял то, что делается здесь, в обработчике события OnStart?» Да, мои дорогие читатели, ваши догадки были действительно вполне адекватными.

«Супер! Но теперь у меня появились сомнения. Сравнивая код 03 с кодом 04, я заметил, что способ объявления вещей здесь отличается, что касается процедур SAVE и RESTORE. Почему между этими двумя кодами есть такая разница? Поскольку, в принципе, и те, и другие имеют одинаковые тип цели и поведения. Я до сих пор этого не понимаю».

Я рад, что вы это заметили, потому что теперь, благодаря вашему пониманию кода OnStart, пришло время объяснить код структуры, объявленной в строке 04. Итак, на этот раз я хочу, чтобы вы проигнорировали всё остальное в коде 04 и сосредоточились только на блоке структуры.

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

Прошу заметить, что мы сохраняем те же переменные, что и в предыдущих кодах. Данные переменные остаются доступными и прекрасно функционируют, как и в коде 03. Можно даже работать с ними, но об этом мы поговорим в другой раз. Важно то, что происходит внутри подпрограммы. В данном случае у нас есть процедура SAVE в строке 09 и процедура RESTORE в строке 15. Обратите внимание, что они очень похожи на те, что в коде 03.

Но именно здесь становится интересно: переменные View_DateScale и View_PriceScale больше не нужно объявлять, как показано в коде 03. Причина в том, что эти переменные являются частью контекста для компилятора и для программиста. В этом случае контекстом является именно структура st_PropertyGraphics.

То есть, поскольку мы работаем с контекстом, который имеет смысл в структуре, НЕ НУЖНО ОБЪЯВЛЯТЬ ПЕРЕМЕННЫЕ, как это делалось в коде 03 (в строках 29, 30, 37 и 38) и нам нужно было указывать тип данных, с которыми будут связаны переменные, поскольку в коде 03 и подпрограмма SAVE, и подпрограмма RESTORE не были частью контекста структуры, а это уже не имеет смысла в коде 04, поскольку обе подпрограммы принадлежат структуре.

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

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


Простые манипуляции со структурами

В предыдущей теме мы рассказали о том, как код обретает контекст путем создания структурированного кода. Но при всей его красоте есть несколько моментов, которые стоит учитывать. Конечно, именно из-за этой «заботы» и возникла необходимость в создании классов. Но об этом мы поговорим в другой раз. Теперь давайте посмотрим на некоторые из этих «забот».

Прежде всего, в структуре все данные подчиняются очень простому критерию: они могут быть публичными или частными. Как правило, при объявлении простой структуры, у нас всегда есть открытые данные. Но, когда мы работаем со структурированным программированием, мы НЕ ХОТИМ открытых данных. В таких случаях мы хотим убедиться в том, что данные останутся в целости и сохранности на протяжении всего срока службы.

Чтобы обеспечить эту целостность, мы можем изменить вид доступа к данным. А теперь внимание. То, что мы увидим здесь, НЕ ДОЛЖНО использоваться в простых конструкциях, таких как, показанные выше. Используйте это только в тех случаях, когда вы внедряете структурированный код и хотите иметь больше контроля над его работой. Если у вас нет необходимых знаний, использование показанного здесь, усложнит то, что, в принципе, довольно просто.

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

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. struct st_PropertyGraphics
05. {
06.     long    View_DateScale,
07.             View_PriceScale,
08.             Chart_Mode;
09. //+----------------+
10.     void SAVE(void)
11.     {
12.         View_DateScale = ChartGetInteger(0, CHART_SHOW_DATE_SCALE);
13.         View_PriceScale = ChartGetInteger(0, CHART_SHOW_PRICE_SCALE);
14.         Chart_Mode = ChartGetInteger(0, CHART_MODE);
15.     }
16. //+----------------+
17.     void RESTORE(void)
18.     {
19.         ChartSetInteger(0, CHART_SHOW_DATE_SCALE, View_DateScale);
20.         ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, View_PriceScale);
21.         ChartSetInteger(0, CHART_MODE, Chart_Mode);
22. 
23.         ChartRedraw();
24.     }
25. //+----------------+
26. };
27. //+------------------------------------------------------------------+
28. void OnStart(void)
29. {
30.     st_PropertyGraphics StyleGraphic;
31. 
32.     StyleGraphic.SAVE();
33. 
34.     StyleGraphic.Chart_Mode = CHART_LINE;
35. 
36.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, false);
37.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, false);
38.     ChartSetInteger(0, CHART_MODE, CHART_BARS);
39.     ChartRedraw();
40. 
41.     Sleep(2000);
42.     
43.     StyleGraphic.RESTORE();
44. }
45. //+------------------------------------------------------------------+

Код 05

Прошу заметить, что код 05 очень похож на код 04. Однако, чтобы продемонстрировать то, что мы хотим показать, мы добавили в структуру новое графическое свойство. Это свойство объявлено в строке 08 из кода 05. Обратите внимание, что вместе с ним в процедуры SAVE и RESTORE добавили новые строки. Эти изменения не настолько значительны, чтобы заслужить подробного объяснения. Также внесли незначительные изменения в процедуру OnStart, которые просты для понимания и не требуют подробного объяснения. Однако, запустив этот скрипт на графике, мы увидим нечто подобное этому:

Анимация 02

«Ух ты! Давайте остановимся и перемотаем пленку назад, потому что мы только что получили неожиданный результат, и я хочу понять, почему график не был восстановлен в исходное состояние, поскольку мы сохраняем тот же принцип и идею, что и в коде 04. Однако я думаю, что ошибка может заключаться в новом свойстве, которое мы только что добавили». Ну что ж, примерно так оно и есть. Но проблема не совсем в этом. Данная проблема известна как утечка данных или нарушение инкапсуляции, т. е. делается то, что не могло быть сделано раньше. Именно это и приводит к результату из анимации 02.

Прошу заметить, что в строке 32 мы сохраняем свойства графики, а в строке 43 восстанавливаем их, точно так же, как и в коде 04. Но здесь возникает проблема: строка 34. «Я не вижу в этом проблемы. Может, если мы удалим эту строку, всё вернется на круги своя?» Да, если мы удалим строку 34, всё станет на свои места. Но дело не в этом.

Вопрос в том, как данные хранятся в переменной StyleGraphics. Данная переменная напрямую связана с небольшой базой записей, расположенной между строками 06 и 08. Любые изменения, которые мы сделаем в этих записях, повлияют на содержимое переменной StyleGraphics.

Таким образом, когда мы запрашиваем восстановление данных в строке 43, будут использованы все данные в логе. Однако из-за изменения, внесенного в строку 34, исходная запись была утеряна. Поэтому сейчас у нас значение, отличное от того, которое было сохранено и применяется к графику, сбрасывая его с неверной информацией.

Эта проблема очень серьезная и, в то же время, очень распространенная. Чтобы решить её, мы должны изменить условие объявления значений в структуре. Помните, что по умолчанию все значения являются общедоступными. Но если мы изменим код 05 на тот, что показан ниже, всё будет по-другому:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. struct st_PropertyGraphics
05. {
06.     private:
07. //+----------------+
08.         long    View_DateScale,
09.                 View_PriceScale,
10.                 Chart_Mode;
11. //+----------------+
12.     public:
13. //+----------------+
14.         void SAVE(void)
15.         {
16.             View_DateScale = ChartGetInteger(0, CHART_SHOW_DATE_SCALE);
17.             View_PriceScale = ChartGetInteger(0, CHART_SHOW_PRICE_SCALE);
18.             Chart_Mode = ChartGetInteger(0, CHART_MODE);
19.         }
20. //+----------------+
21.         void RESTORE(void)
22.         {
23.             ChartSetInteger(0, CHART_SHOW_DATE_SCALE, View_DateScale);
24.             ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, View_PriceScale);
25.             ChartSetInteger(0, CHART_MODE, Chart_Mode);
26. 
27.             ChartRedraw();
28.         }
29. //+----------------+
30. };
31. //+------------------------------------------------------------------+
32. void OnStart(void)
33. {
34.     st_PropertyGraphics StyleGraphic;
35. 
36.     StyleGraphic.SAVE();
37. 
38.     StyleGraphic.Chart_Mode = CHART_LINE;
39. 
40.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, false);
41.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, false);
42.     ChartSetInteger(0, CHART_MODE, CHART_BARS);
43.     ChartRedraw();
44. 
45.     Sleep(2000);
46.     
47.     StyleGraphic.RESTORE();
48. }
49. //+------------------------------------------------------------------+

Код 06

В этом случае при компиляции кода появится предупреждение, очень похожее на это:

Изображение 01

Обратите внимание на ошибку, поскольку в строке 38 мы пытаемся получить доступ к значению, которое больше не является публичным; это происходит, потому что в строке 06 мы включили условие private. Однако, если мы удалим строку 38 из кода 06, мы сможем скомпилировать код, поскольку подпрограммы SAVE и RESTORE являются общедоступными, именно потому, что мы включили условие public в строку 12. Я знаю, что в этот момент всё может показаться запутанным, но поверьте, всё гораздо проще, чем вы думаете, особенно потому, что с этого момента мы начинаем использовать форму структурного программирования, включая в наш код публичные и приватные части кода.


Заключительные идеи

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

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

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

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

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

Прикрепленные файлы |
Anexo.zip (2.89 KB)
Нейросети в трейдинге: Спайково-семантический подход к пространственно-временной идентификации (Основные компоненты) Нейросети в трейдинге: Спайково-семантический подход к пространственно-временной идентификации (Основные компоненты)
В статье мы подробно рассмотрели интеграцию модуля SSAM в блок SEW‑ResNeXt, демонстрируя, как фреймворк S3CE‑Net позволяет эффективно объединять спайковое внимание с остаточными блоками. Такая архитектура обеспечивает точную обработку временных и пространственных потоков данных и высокую стабильность обучения. Модульность и гибкость компонентов упрощают расширение модели и повторное использование проверенных методов.
Автоматизация торговых стратегий на MQL5 (Часть 13): Создание торгового алгоритма для паттерна "Голова и Плечи" Автоматизация торговых стратегий на MQL5 (Часть 13): Создание торгового алгоритма для паттерна "Голова и Плечи"
В настоящей статье мы автоматизируем паттерн «Голова-Плечи» на MQL5. Мы анализируем его архитектуру, реализуем советник для его обнаружения и торговли, а также тестируем результаты на истории. Этот процесс раскрывает практичный торговый алгоритм, который можно усовершенствовать.
От начального до среднего уровня: Struct (IV) От начального до среднего уровня: Struct (IV)
В данной статье мы рассмотрим, как создавать так называемый структурный код, в котором весь контекст и способы манипулирования переменными и информацией помещаются в структуру, чтобы создать подходящий контекст для реализации любого кода. Итак, мы рассмотрим необходимость использования приватной (private) части кода, чтобы отделить то, что является общедоступным, от того, что не является таковым, соблюдая тем самым правило инкапсуляции и сохраняя контекст, для которого была создана структура данных.
От начального до среднего уровня: Индикатор (IV) От начального до среднего уровня: Индикатор (IV)
В этой статье мы рассмотрим, как легко создать и внедрить операционную методологию для окрашивания свечей. Данная концепция высоко ценится трейдерами. При реализации такого рода вещей необходимо проявлять осторожность, чтобы бары или свечи сохраняли свой первоначальный вид и не затрудняли чтение свечи за свечой.