Оверхед для ООП - страница 3

 
George Merts:

1. Например, вам нужен массив объектов.

Это вполне можно сделать как в процедурном виде, так и на основе CArrayObj и СОbject.  Проблемы  начнутся тогда, когда надо будет изменить поведение, скажем, при добавлении или удалении объектов или их сортировке. В ООП - поддержка собственно массива указателей, и работа с ним - заключена в базовых объектах. Изменение объектов-наследников, которые реально содержатся в массиве - ничего не затрагивает. При процедурном же стиле - изменение реальных объектов, которые содержатся в массиве - как правило, затрагивает гораздо больше мест, как минимум, потому, что надо учитывать изменение размера объектов. Что гораздо легче приведет к ошибкам.

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

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

4. А затем, что у нас существует, скажем, ряд видов ордеров, в которых масса общего. Разумно сделать объект COrderInfo - который будет базовым, а его наследники - будут представлять различные виды ордеров. При этом торговый процессор (у меня класс CTradeProcessor) - будет автоматом поддерживать именно тот ордер, который ему передали, именно теми процедурами, которые нужны для обработки этого ордера.

5.Ловить баги легче там, где наименьшее количество перекрестных связей. Что как раз и обеспечивается инкапсуляцией и полиморфизмом. Мы запрашиваем интерфейс торговой позиции (CTradePositionI) - и все связи с реальными классами, представляющими эту позицию (CMT4PositionInfo,CMT5PositionInfo) - осуществляются исключительно через этот интерфейс, что как раз и способствует более легкому устранению ошибок, чем если бы мы работали непосредственно с реальными функциями, возвращающими данные торговой позиции.

1. Для чего например?

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

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

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

5. Так еще нужно в добавок все эти связи запрограммировать и потом отслеживать через интерфейсы и т.п, где тоже баги могут быть трудноуловимые. Занятие это ненужное и бессмысленное изначально.

 
Andrei:

1. Для чего например?

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

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

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

5. Так еще нужно в добавок все эти связи запрограммировать и потом отслеживать через интерфейсы и т.п, где тоже баги могут быть трудноуловимые. Занятие это ненужное и бессмысленное изначально.

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

2. Как раз интерфейс один. Для всех платформ. И в случае ООП - мы вобще не задумываемся, где мы работаем. Не надо учитывать платформозависимые и ордер-зависимые моменты.

3. А в чем отличие между объектом и функцией в такой упаковке-то ? Я ж об этом и говорю - по сути, это одно и то же. В случае объекта - добавляется также автоматическая функция конструктора, однако, по умолчанию - она пустая.

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

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

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

 
George Merts:

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

А чем плохо держать ордера в массиве структур или так, как это реализовано в МТ4?

 
Andrei:

А чем плохо держать ордера в массиве структур или так, как это реализовано в МТ4?

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

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

 
George Merts:

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

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

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

 
Andrei:

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

Моя практика показывает, что, таки, нужен.

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

Как только на МТ4 появилось ООП - я все мои наработки тут же стал переводить к единой форме, на основе интерфейсов.

 
George Merts:

1. Моя практика показывает, что, таки, нужен. Это меня привело к пониманию его ошибочности. 

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

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

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

 
Andrei:
 

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

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

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

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

 
George Merts:

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

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

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

 
Andrei:

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

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

Вам оно не нужно - ну что ж... не используйте ООП.