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

 
Maxim Kuznetsov:

во простыню растянули :-) видать соскучились по холивар`ам , модеры позажимали флеймовые темы...а тут вдруг ООП vs не-ООП

кстати 99% что @Реter Konow использует ООП, только он об этом незнает :-) ООП это не обязательно "class & template"

и наоборот кстати тоже..наличие в программе объектов и классов не свидетельствует об ООП

Это очень интересная мысль. Возможно так и есть, а я не подозреваю. ))


А как это можно узнать?

 
Реter Konow:

Это очень интересная мысль. Возможно так и есть, а я не подозреваю. ))


А как это можно узнать?

например ОО вполне реализуема через диспетчеризацию сообщений (причём с некоторыми "плюшками" которых нет в class/template MQL),

не смотрел ваш код и вряд-ли смогу его прочесть, но раз у вас GUI библиотека, уверен что там есть своя (как минимум одна) очередь и через обработку эвентов/посылок/состояний много чего закручено. И эта самая "закрутка" в конечном итоге как раз и есть наследование/полиморфизм.

 
Dmitry Fedoseev:

Про ежика:

Стоит ежи на полянке, позирует, бицепсы напрягает: - я сильный, я смелый, я ловкий, я сильный, я смелый, я ловкий...

Мимо шел медведь - раз ему пинка, ежик улетел за елку, встает от отряхивается:

- Я  сильный, я смелый, я ловкий... но лёёёёгкий...


Как говорил мой друг детства, еж - птица гордая, не пнешь, не полетит ))
 
Alexey Volchanskiy:

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

Во... А Лёха - за бабс... И это - правильно. Гораздо интереснее, чем ООП.

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

 

А насчет ООП...

Если бы у меня была такая память, как у Реter Konow'а - возможно, я бы согласился, что ООП - не нужно, какой смысл городить все эти интерфейсы, классы, объекты, систему наследования и виртуальных функций...

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

Мне была непонятна позиция Реter Konow'а до тех пор, пока он не показал свой код. Сейчас - все понятно, и я даже могу с ним согласиться, если удается все это держать в памяти, и длинные if'ы не напрягают - то, подозреваю, что разумнее как раз писать так, как пишет он. Более того - ООП в этом случае, действительно, становится "пятым колесом в телеге". 

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

Причем, иногда я сам пишу такой код, в котором самому же трудно разбираться. Вот фрагмент МОЕГО "неправильного" кода, в котором я точно так же утону (я его приводил выше):

virtual bool IsTPCInUnloss() const { if(GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE) return(false); if(GetTPCType() == POSITION_TYPE_BUY) { if(GetTPCStopLoss() >= GetTPCOpenPrice()) return(true); } else { if(GetTPCStopLoss() <= GetTPCOpenPrice())return(true); }; return (false); };

Это функция интерфейса торговой компоненты CTradePosComponentI, которая определяет, находится ли данная компонента в безубытке.

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

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

Вот так:

virtual bool IsTPCInUnloss() const 
{ 
    // Отсеем вариант, когда СЛ отсутствует
    if(GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE)
         return(false);

    //  Проверим тип торговой компоненты
    if(GetTPCType() == POSITION_TYPE_BUY)
        { 
        // Торговая компонента - лонг
        if(GetTPCStopLoss() >= GetTPCOpenPrice())
            return(true);
        }
    else
        { 
        // Торговая компонента - шорт
        if(GetTPCStopLoss() <= GetTPCOpenPrice())
             return(true); 
        }; 

    return (false); 
};

И только после того, как все это было проверено и отлажено - код был очищен от комментариев и "вытянут в строку".

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

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

 
Maxim Kuznetsov:

например ОО вполне реализуема через диспетчеризацию сообщений (причём с некоторыми "плюшками" которых нет в class/template MQL),

не смотрел ваш код и вряд-ли смогу его прочесть, но раз у вас GUI библиотека, уверен что там есть своя (как минимум одна) очередь и через обработку эвентов/посылок/состояний много чего закручено. И эта самая "закрутка" в конечном итоге как раз и есть наследование/полиморфизм.

Ну, раз уж я сказал "А" то и "Б" сказать нужно.) Опишу свою технологию более конкретно.

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

Сначала о плюсах:

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

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

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

Далее, функция OnChartEvent() фиксирует события графика, которые должны менять состояния элемента под курсором. На этих событиях блок контроля состояний (который интегрирован в саму OnChartEvent() ) сразу видит какое окно, элемент и объект находятся в фокусе и какие у них свойства. Ничего передавать этому блоку не нужно, потому что все нужное уже находится в фокусе, в глобальных переменных. Его задача - поменять значения свойств объекта в ядре G_CORE и перерисовать элемент. Он меняет значения и вызывает блок Рисования.

В блок рисования нужно передать только три параметра - окно, канвас и элемент. Он перерисовывает элемент, придавая ему вид соотвествующий текущему состоянию. Все вспомогательные функции блока рисования, также используют глобальные переменные в фокусе. Например приведенная выше функция "Цвет детали()" использует "ОКНО","ОБЪЕКТ","КАТЕГОРИЯ_ОБЪЕКТА" и т.д... Все это очень удобно.


Теперь о минусах:

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

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

Конечно, сама шлифовка блоков, вещь достаточно долгая и муторная, но в этом заключается отладка любого механизма.

 
George Merts:

А насчет ООП...

Если бы у меня была такая память, как у Реter Konow'а - возможно, я бы согласился, что ООП - не нужно, какой смысл городить все эти интерфейсы, классы, объекты, систему наследования и виртуальных функций...

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

Мне была непонятна позиция Реter Konow'а до тех пор, пока он не показал свой код. Сейчас - все понятно, и я даже могу с ним согласиться, если удается все это держать в памяти, и длинные if'ы не напрягают - то, подозреваю, что разумнее как раз писать так, как пишет он. Более того - ООП в этом случае, действительно, становится "пятым колесом в телеге". 

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

Причем, иногда я сам пишу такой код, в котором самому же трудно разбираться. Вот фрагмент МОЕГО "неправильного" кода, в котором я точно так же утону (я его приводил выше):

Это функция интерфейса торговой компоненты CTradePosComponentI, которая определяет, находится ли данная компонента в безубытке.

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

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

Вот так:

И только после того, как все это было проверено и отлажено - код был очищен от комментариев и "вытянут в строку".

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

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

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

Наверное дело в привычке.))

 
Реter Konow:

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

Наверное дело в привычке.))


Совершенно бессмысленный разговор: нет критерия отнесения кода к "хорошему" или "плохому". Именно поэтому не ясно про ООП.

Для меня таким критерием является  НАГЛЯДНОСТЬ кода, которая проявляется в том, что автор или сторонний человек через довольно большой промежуток времени сможет прочесть код и его использовать для модификации, поиска багов.....


Вот выше Федосеев заменил переключатель ООП. Этот конкретный пример, может быть неудачный, для меня это доказательством порочности ООП: наглядный код с переключателем из 100 позиций заменен одной строкой. Чтобы понять эту строку необходимо куда-то лезть. Для меня это не допустимо.

Второй пример выше George Merts

Когда наглядный код после отладки был заменен на НЕ наглядный. По моему критерию качественный код (легко читался) был заменен на недопустимый для меня.


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

 
СанСаныч Фоменко:

1. Совершенно бессмысленный разговор: нет критерия отнесения кода к "хорошему" или "плохому". Именно поэтому не ясно про ООП.

Для меня таким критерием является  НАГЛЯДНОСТЬ кода, которая проявляется в том, что автор или сторонний человек через довольно большой промежуток времени сможет прочесть код и его использовать для модификации, поиска багов.....


2. Вот выше Федосеев заменил переключатель ООП. Этот конкретный пример, может быть неудачный, для меня это доказательством порочности ООП: наглядный код с переключателем из 100 позиций заменен одной строкой. Чтобы понять эту строку необходимо куда-то лезть. Для меня это не допустимо.

Второй пример выше George Merts

Когда наглядный код после отладки был заменен на НЕ наглядный. По моему критерию качественный код (легко читался) был заменен на недопустимый для меня.


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


1. Есть критерий. Главный критерий - скорость работы.

Наглядность кода - это неправильный критерий. Код пишется не для того, чтобы на него глядеть, а для того, чтобы он работал.

2. Ясненько, оказывается некоторые еще не доросли до структурирования кода функциями. Значит вы не в свою тему влезли, вам нужно в тему "код одной простыней против кода структурированного функциями". 

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

3. Может вам это... инженерной графикой заняться? Или начертательной геометрией. Там все наглядно.

 
Dmitry Fedoseev:
 

Наглядность кода - это неправильный критерий. Код пишется не для того, чтобы на него глядеть, а для того, чтобы он работал.

Ну, я не согласен.

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

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

Скорость - тоже надо меть ввиду, но я не думаю, что надо стремиться к "скорости любой ценой". Должна быть разумная достаточность.

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