ООП vs процедурное программирование - страница 11

 
Реter Konow:
 

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

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


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

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

Лично я бы в твоем коде допускал больше ошибок, и вылавливать их было бы сложнее. То есть, при всей правильности и логичности такого кода - МНЕ бы поддержка его давалась  труднее, чем если бы я все написал это в ООП-стиле.

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

 
George Merts:

Ну, наворотили...

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

Вопрос - в удобстве и эффективности поддержки.

В МТ - наиболее ООП-подходящим местом является ордерная система. Лично у меня есть виртуальные интерфейсы "позиции" и  "компоненты позиции". "Позиция" - это набор ордеров в МТ4 или набор позиций МТ5. "Компонента позиции" - это отдельный ордер или отдельная МТ5-позиция (хеджевая или неттинговая).

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

Файл интерфейса торговой компоненты следующий (выше я его приводил уже, но повторю:

Согласно этим интерфейсам - у меня реализована и ордерная система МТ4, и МТ5, как для реальных, так и для исторических ордеров.

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

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

Реter Konow, как у тебя решается вопрос с различием типов ордеров в МТ4 и МТ5  ?

Если будет введен новый тип счета (вдобавок к хеджевому и неттинговому) - какие изменения потребуется вносить, и в одном ли месте ?

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

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


Жорж, ты иногда пишешь такую клинику про женщин, но код уважуха )))

 
George Merts:

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


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

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

Лично я бы в твоем коде допускал больше ошибок, и вылавливать их было бы сложнее. То есть, при всей правильности и логичности такого кода - МНЕ бы поддержка его давалась  труднее, чем если бы я все написал это в ООП-стиле.

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

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

P.S. По поводу ООП или процедурный стиль, то - "Каждому свое" (с).

 
Alexey Volchanskiy:

Жорж, ты иногда пишешь такую клинику про женщин, но код уважуха )))

Насчет кода - я польщен. (Правда, без шуток).

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

 
George Merts:

Насчет кода - я польщен. (Правда, без шуток).

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


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

 
George Merts:

Ну, наворотили...

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

Вопрос - в удобстве и эффективности поддержки.


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

Есть задачи, которые процедурно не решите оптимальным образом.

 
Alexey Volchanskiy:

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


Алексей, а вы не проводили эксперимент, на сколько бесконечно желание женщины получать помощь? Встречали удовлетворенность помощь и как долго она длилась?

 
Реter Konow:


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

 int Элемент                     =  G_CORE[Окно][Деталь_полотна][_MAIN_ELEMENT];
 int Состояние_детали            =  G_CORE[Окно][Элемент][_CURRENT_STATE]; 

можно было бы заменить на

 int Элемент                     =  G_CORE[Окно][Деталь_полотна].MAIN_ELEMENT;
 int Состояние_детали            =  G_CORE[Окно][Элемент].CURRENT_STATE; 

Это и короче, и надёжней (безопасней), и быстрее.  В первом случае нет никакого контроля на стадии компиляции за теми значения индексов массива, которые вы ему подсовываете. И потом разгребать в рантайме всевозможные "array out of range" - и это в лучшем случае. Хуже когда индекс допустимый, но неверный.   Поэтому хорошая практика программирования - это задействовать компилятор по максимуму, выявляя ошибки на стадии компиляции, а не вылавливая в процессе работы как у вас.

Да, сейчас вы пока хорошо помните, какие значения куда надо подавать. Но это вероятно потому, что вы постоянно заняты данным проектом.  Попробуйте сделать перерыв, скажем, на полгодика, и почувствуете разницу.  Тут ведь некоторые уже упоминали об этом. Или вы думаете тут прям склеротики собрались чтоль? :)  Это обычное дело для программиста...

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

 

Пишу только и исключительно ООП.

В каком-то 1900-лохматом году никак не мог в него въехать - Pascal 6.0, потом  Borland C++ 4.5. Но когда въехал, уже иного не представляю - настолько все стало просто и удобно.

 
Alexey Navoykov:

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

можно было бы заменить на

Это и короче, и надёжней (безопасней), и быстрее.  В первом случае нет никакого контроля на стадии компиляции за теми значения индексов массива, которые вы ему подсовываете. И потом разгребать в рантайме всевозможные "array out of range" - и это в лучшем случае. Хуже когда индекс допустимый, но неверный.   Поэтому хорошая практика программирования - это задействовать компилятор по максимуму, выявляя ошибки на стадии компиляции, а не вылавливая в процессе работы как у вас.

Да, сейчас вы пока хорошо помните, какие значения куда надо подавать. Но это вероятно потому, что вы постоянно заняты данным проектом.  Попробуйте сделать перерыв, скажем, на полгодика, и почувствуете разницу.  Тут ведь некоторые уже упоминали об этом. Или вы думаете тут прям склеротики собрались чтоль? :)  Это обычное дело для программиста...

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

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

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

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

Мой главный тезис - "Если без чего то в решении можно обойтись - без этого определенно нужно обойтись".

Я вовсе не считаю, что здесь собрались склеротики.)) Просто глядя на приводимые коды становится понятно, почему они лекго забываются. Даже сам факт программирования на чужом языке играет роль. Когда программируешь на своем языке, совсем другие ощущения. Чуствуешь силу и свободу, а не напряжение и скованность. Чужой язык забирает больше сил, требует больше времени на вникание в код, и быстрее вылетает из головы. Это просто "биологический фактор".

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

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