ООП - Что такое хорошо?

Разработка программ на пес его знает на чем
Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
Гость

Сообщение Гость »

Здравствуйте ClaList!

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

--
С уважением,
SAN mailto:vgsan@yandex.ru

(Добавление)

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

Только не надо думать, что выполнить качественный код в ООП сложнее, чем
качественный код в структурном подходе, скорее наоборот :)

Удачи!
__________________________________
Владимир Якимченко (ICQ: 16993194)
Написал: ClaList(2)
Гость

Сообщение Гость »

Я бы акцентировался на другой аспект: необходимость хранения
промежуточных данных между вызовом одного и того же набора
процедур.
Поясню:
Предположим, что Д - это какая-то структура. Процедура А для данных
Д1 приводит систему в состояние А1, а для данных Д2 - в А2.
Соответственно, возможна задача, когда необходимо иметь
одновременно оба набора состояний - А1 и А2. В процедурном
стиле пришлось бы делать какие-то промежуточные буфера
состояний, процедуры восстановления состояний и т.п.
В ООП же мы имеем два экземпляра класса А, каждый из которых
работает со своей структурой Д и поддерживает свое состояние.
Т.е. это хорошее средство изоляции одновременно выполняющихся
наборов кода и данных.
Плюс некоторые прелести наследования...

Прочие же задачи, на мой вгляд, в равной степени легко реализуются
и в процедурном, и в ОО подходе.

Остальное - дело вкуса и привычки.

Про качество - вроде как везде. Вертикальная подчиненность,
отсутствие горизонтальных связей между процедурами (методами).
Хотя, судя по сообщениям в листе, с классами вытворяют все, что угодно :)

С уважением,
Владимир Смелик.
Написал: ClaList(2)
Гость

Сообщение Гость »

IMHO, это сильно зависит от конкретной задачи. Если программист
вник в предметную область, правильно выполнил декомпозицию (выделил простые составляющие сложных понятий) и оформил это в объекты с учетом основных принципов ООП, ...
И это все? Нет меня не интересовали вопросы завязанные на конкр.
задачу. Скорее вопрос надо понимать так - за что бороться (что
минимизировать) при ООП кодинге. А если на этом пункте отправляют в
ВУЗ то непонятно как Вы пишете?
Про качество - вроде как везде. Вертикальная подчиненность,
отсутствие горизонтальных связей между процедурами (методами).
Хотя, судя по сообщениям в листе, с классами вытворяют все, что угодно :)
Спасибо! А вот надо ли бороться за сокращение времени жизни объекта?
И если кто знает как оценить затраты связанные с инициализацией
обекта?

P.S. В эхе есть люди располагающие нормальным толкованием устройства и
происходящего в файлах ...bc.clw - ...bcN.clw, что то никак не найду
таких?
:(

--
С уважением,
SAN

(Добавление)

Про техничексие характеристики кода ты или сам почитай, или тебе расскажут, если
будешь настойчивей. Тем более, применительно к клаше.
Я бы выделил фактор чисто человеческий. И связанную с ним инкапсуляцию -
создавай классы так, чтобы каждый класс был самодостаточной сущьностью, не особо
зависящей от того, что вокруг. Создавай public интерфейс таким, чтобы всем его
хватало и не возникало желания влезть во внутренности. А если задача все-таки
этого требует, то делай соотв. методы protected, чтобы можно было унаследоваться
от твоего класса. Все остальное - private, и пользователи твоего класса (в т.ч.
ты сам) никоим образом не должны зависеть от реализации.

--
Best regards,
Maxim Yemelyanov,
Enigma Soft Company
phone: +380 572 177977
WEB: http://enigmasoft.com.ua
e-mail: clalist@enigmasoft.com.ua
ICQ: 12253836
Написал: ClaList(2)
Гость

Сообщение Гость »

Если я понял правильно задачу, то и в ПП можно объявить группу Д1 и Д2
LIKE(Д1) и процедуры, которые будут их переводить в соответствующие
состояния.

Сергей
Написал: ClaList(2)
Гость

Сообщение Гость »

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

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

Впрочем, Clarion допускает использование и ПП и ООП в одной программе.
Например, в ШВС есть класс для "красивого" термометра. Очень прост и понятен
в использовании. Хотя большая часть кода по этим шаблонам генерируется в
ПП-стиле.


Только что пришла в голову мысль, что WinAPI выглядит скорее процедурно,
чем объектно...

С уважением,
Владимир Смелик
Написал: ClaList(2)
Гость

Сообщение Гость »

Спасибо! А вот надо ли бороться за сокращение времени жизни объекта?
Зачем!? Нормально написанный класс никак не "напрягает"
ни систему ни другие обьекты. Если, конечно, размер
данных, используемый этим обьектом, не превышает разумных
границ! Или, к примеру, в коде какого-либо метода этого
обьекта не используются бесконечные циклы, написанные,
к тому-же, без учета правил много -задачности и -поточности.
И если кто знает как оценить затраты связанные с инициализацией
обекта?
Что ты имеешь в виду?
Если отбросить пока код, выполняемый в конструкторе обьекта,
то инициализация нового обьекта зависит от способа его обьявления:

- если обьект обьявлен как статический (не STATIC-аттрибут!) типа
tMyObj CLASS.,TYPE
MyObj1 CLASS(tMyObj).
MyObj2 tMyObj

то вся инициализация таких обьектов производится на этапе
компиляции приложения и при входе в область видимости этих
обьектов производится автоматическая очистка буфера их
данных и вызов их конструкторов (если есть).

- если обькт обьявлен как динамический типа
MyObj1 &tMyObj

то при входе в область видимости этих обьктов НИКАКИХ действий
по их инициализации автоматом не производится.
Только при выполнении оператора MyObj1 &= NEW(tMyObj)
производится выделение из локальной кучи памяти под буфер
данных этого обьекта, очистка этого буфера и запуск
конструктора (если есть).

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

Например, создаешь очередь, запись которой содержит
рефералы на некоторые обьекты, и добавляешь в нее большое
число записей (несколько сотен тысяч и более), а потом
удаляешь эти записи с одновременным уничтожением обьектов,
рефералы на которые в них содержались. Так вот, если
повторно выполнять вышеописанное (заново добавление записей),
то могут наблюдаться тормоза выполнения.
P.S. В эхе есть люди располагающие нормальным толкованием устройства и
происходящего в файлах ...bc.clw - ...bcN.clw, что то никак не найду
таких?
:(
ABC не пользую, так что - увы, ничем помочь в данном вопросе не могу!

=============================
С уважением, Олег А. Руденко.
Oleg_Rudenko@mail.ru
Oleg_Rudenko@mail333.com

Библиотека DynaLib
http://dynalib.narod.ru

(Добавление)
А если задача все-таки
этого требует, то делай соотв. методы protected, чтобы можно было унаследоваться
от твоего класса. Все остальное - private, и пользователи твоего класса (в т.ч.
ты сам) никоим образом не должны зависеть от реализации.
Максим, я пока разбираюсь со стандартными решениями CW в ООП и пытаюсь
понять почему и что они делают. На сколько я понял кларион АБС для
приложения для каждой обявленной таблицы при инициализации АПП создает
ряд объектов. Мне показалось что это противоречит ООП принципам ( с
одной стороны использ ряд решений по изоляции, а с другой задолго до
использования создаются объекты ). Кроме того для приложения средней
тяжести в 100-200 таблиц на подобную инициализацию уйдут ресурсы. Вот
мне и хотелось получить разъяснения по поводу ..bc.clw - ...bcN.clw (
возможно хоть кто-то написал себе комментарии к этому коду) и
мнение людей пользующих ООП.

--
С уважением,
SAN

Я не уверен, что ставить самодостаточность класса во главу угла это правильно.
Создавай public интерфейс таким, чтобы всем его
хватало и не возникало желания влезть во внутренности. А если задача все-таки
этого требует, то делай соотв. методы protected, чтобы можно было унаследоваться
от твоего класса. Все остальное - private, и пользователи твоего класса (в т.ч.
ты сам) никоим образом не должны зависеть от реализации.
Я стараюсь применять немного другие принципы:
- Если метод используется внутри самого класса, то он должен быть виртуальным
В этом случае класс-наследник при необходимости может изменить алгоритм
этого метода.
- Создавать защищённые методы (PROTECTED) только в крайнем случае - только
если ДЕЙСТВИТЕЛЬНО необходимо, чтобы данный метод нельзя было использовать
вне классов-наследников.
Вообще я с трудом представляю зачем это нужно.
- Использовать вместо частных методов процедуры прописанные в том же самом
модуле, где и класс. Т.е. по хорошему объявление класса должно быть "чистым".
В общем-то PRIVATE-методы для наследников бесполезны.
- Для связи с внешними классами (или для использования их возможностей)
использовать интерфейсы (INTERFACE).
Это обеспечивает гораздо меньшую зависимость классов друг от друга.

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

Сергей - chusha@mail333.com ; chusha@hotbox.ru

(Добавление)
Я не уверен, что ставить самодостаточность класса во главу угла это правильно.
Я считаю (и некоторые другие товарищи тоже), что очень желательно, чтобы класс
максимально близко отображал реальную сущность, которую он представляет. В
пределах, требуемых задачей, конечно. Это позволяет делать использование класса
максимально прозрачным для его пользователей (нас с вами, т.е. программистов).
Я стараюсь применять немного другие принципы:
- Если метод используется внутри самого класса, то он должен быть виртуальным
В этом случае класс-наследник при необходимости может изменить алгоритм
этого метода.
Не следует увлекаться виртуальностью без нужды.
- Создавать защищённые методы (PROTECTED) только в крайнем случае - только
если ДЕЙСТВИТЕЛЬНО необходимо, чтобы данный метод нельзя было использовать
вне классов-наследников.
Вообще я с трудом представляю зачем это нужно.
RTFM тут на самом деле не поможет пока в жизни с этим не столкнешься, тогда
поймешь, точнее _прочувствуешь_, зачем.
Вообще, ООП удобно (и предназначено!) для создания унифицированных
механизмов и мне не совсем понятно, зачем вводить какие-либо ограничения
на использование класса его наследниками. Особенно это касается базовых
классов.
Реализация должна оставаться реализацией, и что там внутри не должно волновать
никого, даже наследников (если проектирование не подразумевает альтернативную
реализацию в процессе развития данной библиотеки классов этим же или другими
разработчиками).

--
Best regards,
Maxim Yemelyanov

(Добавление)
Максим, я пока разбираюсь со стандартными решениями CW в ООП и пытаюсь
понять почему и что они делают. На сколько я понял кларион АБС для
приложения для каждой обявленной таблицы при инициализации АПП создает
ряд объектов. Мне показалось что это противоречит ООП принципам ( с
одной стороны использ ряд решений по изоляции, а с другой задолго до
использования создаются объекты ). Кроме того для приложения средней
тяжести в 100-200 таблиц на подобную инициализацию уйдут ресурсы.
[Кусь!]
Хм, мне кажется что ты роешь не совсем в ту сторону :/
Ну скажи на милось, тебя ОЧЕНЬ сильно волнует, будет твоя прога
потреблять памяти 20 Мбайт или 20,05 Мбайт (из расчета 250-500 байт
дополнительных ресурсов на таблицу)?! Я ещё понимаю, когда
речь заводится о порядка 10% от УСТАНОВЛЕННОЙ на компьютере
памяти. А когда речь идет о десятых (и даже сотых!!!) долях процента,
ну честное слово - не понимаю я этого! Угрохаешь кучу времени на
изучение теории, разбор "полёта", оптимизацию и в результате
получишь... ноль эффекта :/ Тебе это надо?!!

Не знаю как в других языках, а в Кларионе по моему, введением ООП
не ставилась задача экономии ресурсов, скорее наоборот. За счет
потребления доп.ресурсов добиться унификации кода. А вот уже
за счет унификации кода добиться сокращения затрат на
непосредственно кодирование, модификацию и развитие продукта
(в частности, ABC), т.е. труд. А это НАИБОЛЕЕ затратно в единичном
и мелкосерийонм производстве, как известно. Ведь кларион и
позиционируется как инструмент для создания единичных и
мелкосерийных программ (клиентских приложений - АРМов).
Хотя с его помощью и можно создать что хочешь, но тема топора и
мастера, им владеющего - это уже другая тема :))
Думаю, что даже не ставилась задача на сокращение размеров
самой проги, хотя при аккуратном и продуманном подходам к ООП
на относительно больших прогах можно получить заметное сокращение
размера полученной программы. Но это опять же, не главное в ООП.
Главное в ООП - это экономия трудозатрат, как и в шаблонах собственно.
IMHO, конечно...

Сергей

(Добавление)
Максим, я пока разбираюсь со стандартными решениями CW в ООП и пытаюсь
понять почему и что они делают. На сколько я понял кларион АБС для
приложения для каждой обявленной таблицы при инициализации АПП создает ...
Для каждой _используемой_ в приложении таблицы.
... ряд объектов. Мне показалось что это противоречит ООП принципам ( с
одной стороны использ ряд решений по изоляции, а с другой задолго до
использования создаются объекты ). Кроме того для приложения средней ...
Это следствие принятой парадигмы - таблицы/файлы являются глобальными
объектами. В какой-то степени это отражает тот факт, что время жизни БД
больше времени работы использующего ее приложения и она является объектом
внешнего, по отношению к приложению, мира.
... тяжести в 100-200 таблиц на подобную инициализацию уйдут ресурсы.
Ты посмотри сколько ресурсов берет такой объект (FM + RM). Где-то ок 350
байт. Из них 260 на имя файла. Методы кодируются вообще всего один раз. 350
х 200 = 70 к. Это так критично? Если критично, то ответь на вопрос, нужно ли
в задаче иметь одновременный доступ ко всем 200-м таблицам? Если нужно, то
куда ты в конце концов денешься? А если нет - дели приложение на части.


WBR, Nick Tsigouro. MailTo:Nick@arsis.r
Написал: ClaList(2)
Гость

Сообщение Гость »

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

--
С уважением,
SAN
Написал: ClaList(2)
Гость

Сообщение Гость »

Например, создаешь очередь, запись которой содержит
рефералы на некоторые обьекты, и добавляешь в нее большое
число записей (несколько сотен тысяч и более), а потом
удаляешь эти записи с одновременным уничтожением обьектов,
рефералы на которые в них содержались. Так вот, если
повторно выполнять вышеописанное (заново добавление записей),
то могут наблюдаться тормоза выполнения.
Учту, так в свое время меня доставали оверлеи.
ABC не пользую, так что - увы, ничем помочь в данном вопросе не могу!
Жаль Олег. Я просмотрел довольно много на эту тему. Абсолютное
большинство рекомендаций сводится к предложению - Вы начинайте писать
на АБС, а потом вас осенит и вы все поимете. ;)) В этих модулях идет
формирование исходных данных для работы АПП кроме того мне кажется на
их коде удобно разбираться с АБС и с идеями ООП. Кроме того где то мне
попалось, что собственно это дизайнерская находка SV и делать так
совсем не обязательно. Вот ищу классный коммент к этому коду.
Угрохаешь кучу времени на
изучение теории, разбор "полёта", оптимизацию и в результате
получишь... ноль эффекта :/ Тебе это надо?!!
Мне надо понимать! Кроме того что мт быть лучше хорошей теории. :)
Не знаю как в других языках, а в Кларионе по моему, введением ООП
не ставилась задача экономии ресурсов, скорее наоборот. За счет
потребления доп.ресурсов добиться унификации кода. А вот уже
за счет унификации кода добиться сокращения затрат на
непосредственно кодирование, модификацию и развитие продукта
(в частности, ABC), т.е. труд. А это НАИБОЛЕЕ затратно в единичном
и мелкосерийонм производстве, как известно. Ведь кларион и
позиционируется как инструмент для создания единичных и
мелкосерийных программ (клиентских приложений - АРМов).
Я тут успел про ООП почитать так вот создавалось оно прежде всего как
инструмент борьбы со сложностью и повышения качества разработки.

--
С уважением,
SAN

(Добавление)

Хм, а это разве не то же о чём говорил и я?
Увеличение сложности - увеличение трудозатрат и повышение
качества - увеличение трудозатрат. Причем нелинейно и скорее
всего экспоненциально...

Сергей

(Добавление)

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

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

Ты посмотри сколько ресурсов берет такой объект (FM + RM). Где-то ок 350
байт. Из них 260 на имя файла. Методы кодируются вообще всего один раз. 350
х 200 = 70 к. Это так критично? Если критично, то ответь на вопрос, нужно ли ...

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

... в задаче иметь одновременный доступ ко всем 200-м таблицам? Если нужно, то
куда ты в конце концов денешься?

Нет, одновременно не нужно. Как правило я буду одновременно работать с
группой таблиц. Только на это время мне и будут нужны объекты (FM +
RM) этой группы.

А если нет - дели приложение на части.

Если я тебя правильно понял - надо научиться создавать\уничтожать объекты (FM +
RM) в соответствии с потребностями в таблицах задачи, это и будет соответствовать
идеологии ООП. Способ сейчас не обсуждаем.

--
С уважением,
SAN

(Добавление)

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

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

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

Каких именно?

А если нет - дели приложение на части.
Если я тебя правильно понял - надо научиться создавать\уничтожать
объекты (FM +
RM) в соответствии с потребностями в таблицах задачи, это и будет
соответствовать
идеологии ООП. Способ сейчас не обсуждаем.

Нет. Я не имел ввиду не создание/уничтожение по мере потребности, а
разбиение приложения на такие части, каждая из которых использует лишь
некоторые таблицы. Тогда в этих кусочках вообще не нужно никакой поддержки
неиспользуемых таблиц.
Создание/уничтожение FM/RM в ABC не предусмотрено. Но видимо это можно
организовать основываясь на механизме счетчиков использования FM/RM классов.
Проблема только в том, что для организации таких счетчиков потребуется
написать еще один слой поверх существующего. И снова придется выделять
ресурсы, и снова встанет вопрос, зачем их выделять до того, как они
используются. "У попа была собака..."

WBR, Nick Tsigouro

(Добавление)

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

Не будем углубляться в теорию. Да и не большой я спец в теории - потребляю по мере
необходимости. :) Думаю, мы просто по разному понимаем понятие "самодостаточность",
отсюда и разногласие в толковании.

Не следует увлекаться виртуальностью без нужды.

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

RTFM тут на самом деле не поможет пока в жизни с этим не столкнешься, тогда
поймешь, точнее _прочувствуешь_, зачем.

Пока в своей практике я не смог логически убедительно доказать ни в одном
случае, что именно в этом случае требуется защищённый метод.
Что в моей практике, что в коде других я пока вижу только один аргумент: "я так решил!" :D

Реализация должна оставаться реализацией, и что там внутри не должно волновать
никого, даже наследников (если проектирование не подразумевает альтернативную
реализацию в процессе развития данной библиотеки классов этим же или другими
разработчиками).

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

Сергей

(Добавление)

В этом случае класс-наследник при необходимости может изменить алгоритм
этого метода.

Я полагаю, что для этого предназначены PROTECTED методы. А виртуальные нужны
для того, чтобы класс мог управлять действиями, которые в момент написания
класса еще не сформулированы. Пример: в момент написания BrowseManager еще
не известно какую очередь, откуда и чем предстоит заполнять.

Пока в своей практике я не смог логически убедительно доказать ни в одном
случае, что именно в этом случае требуется защищённый метод.
Что в моей практике, что в коде других я пока вижу только один
аргумент: "я так решил!" :D

Думаю не только. Предположим, что некоторый метод класса решеат достаточно
сложную задачу. Например, делает ход в шахматной партии. ;-). Для реализации
этого метода разработчик выбрал один из возможных алгоритмов или разработал
свой и в рамках реализации этого алгоритма написал несколько
подпрограмм-методов чисто внутреннего употребления. Более того, разработчик
планирует в следующей версии по результатам эксплуатации доработать, а
возможно и заменить этот алгоритм. ИМХО совершенно естественно сделать эти
методы не просто защищенными, а приватными, чтобы не было никакой
возможности их использования извне, дабы не иметь в будущем проблем
сопровождением умерших или радикально переработанных методов.

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

Поддерживаю.

... альтернативную
реализацию в процессе развития данной библиотеки классов этим
же или другими
разработчиками).

Не вижу связи между волнением наследников и альтернативной реализацией. ИМХО
это не аргумент.

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

Только за.

... в т.ч. и с изменением алгоритмов и свойств
класса. Т.е. опять же, ...

Вижу только один вариант - отдавать вместе с исходниками. Обратите внимание.
Несмотря на критику ABC и открытый код, серьезные переработки этого кода
делали только TS/SV. Причем делали это в каждой версии - 5.0, 5.5, 6.0.

в этом случае ты изначально должен думать о минимизации трудозатрат при ...

В любом случае об этом должен думать. Для этого класс и пишется.

WBR, Nick Tsigouro

(Добавление)

Я полагаю, что для этого предназначены PROTECTED методы.

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

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

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

Думаю не только. Предположим, что некоторый метод класса решеат достаточно
сложную задачу. Например, делает ход в шахматной партии. ;-). Для реализации
этого метода разработчик выбрал один из возможных алгоритмов или разработал
свой и в рамках реализации этого алгоритма написал несколько
подпрограмм-методов чисто внутреннего употребления. Более того, разработчик
планирует в следующей версии по результатам эксплуатации доработать, а
возможно и заменить этот алгоритм. ИМХО совершенно естественно сделать эти
методы не просто защищенными, а приватными, чтобы не было никакой
возможности их использования извне, дабы не иметь в будущем проблем
сопровождением умерших или радикально переработанных методов.

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

Вижу только один вариант - отдавать вместе с исходниками.

Совсем не обязательно.

В любом случае об этом должен думать. Для этого класс и пишется.

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

Сергей

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

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

--
Best regards,
Maxim Yemelyanov

(Добавление)

Коллеги, а могли бы вы в нескольких письмах описать как ими
пользоваться. Виртуальные методы более-менее понятны, а вот с этими
... :(

1. INTERFACE - это структура ДАННЫХ. Содержание этой структуры - таблица
адресов точек входа в методы интерфейса.

2. Интерфейс помогает решить проблему взаимодействия незнакомых между собой
классов. А именно, если класс A получает через один из своих методов
(Add...) ссылку на класс B, то через эту ссылку можно передать только класс
B или его потомка, но нельзя передать его родителя. Понятно почему нельзя. У
предка может не не оказаться методов, которые есть у B, а А имеет право к
ним обращаться. Кроме того. Класс В д.б. описан раньше, чем класс A. Т.е.
нельзя подключить еще не написанный класс.
Интерфеис гарантирует, что любой реализующий его класс содержит все эти
методы, а все остальное содержание класса (в т.ч. его описание) для
взаимодействия не важно.

WBR, Nick Tsigouro

(Добавление)

Коллеги, а могли бы вы в нескольких письмах описать как ими
пользоваться. Виртуальные методы более-менее понятны, а вот с этими
... :(

Если коротко, то примертно так:
- INTERFACE это тип(структура), который содержит декларации виртуальных методов.
Её нельзя создать, окромя посредством IMPLEMENTS, но можно создавать ссылки
как на классы, например.
- В основном используется для связи объекта(класса) с внешним объектом(классом)
о котором объект(класс) ничего не знает. Т.е. тот объект должен предоставить для
этого объекта некий интерфейс, необходимый этому объекту.
- введён в основном для удобства и унификации связи между классами
- существует параметр COM для работы с стандартными КОМ-объектами


насколько я понял, основное применение примерно такое:
есть некий клас A, которому нужен для работы интерфейс iA
и существует класс B, который пользует класс A и должен
предоствить интерфейс типа iA классу A. В принципе класс A
может сам порождать некий стандартный интерфейс для своей работы.
В таком случае, класс B может не порождать интерфейс.
В общем случае, примерно так:

Код: Выделить всё

iA  interface
Min  procedure(? par1, ? par2), ?
     end
!
A  class, implements(iA), type
i_A        &iA
eMin   real
eCurrent  real
Construct  procedure
init   procedure(iA parIA)
Calc  procedure
  end
!
B  class, implements(iA), type
cA       &A
Construct  procedure
Destruct  procedure
Clac  procedure
  end
!
A.Construct procedure
 code
  self.i_A &= self.iA ! При создании класса ссылка инициализируется родным интерфейсом
! и вся работа в классе ведётся посредством этой ссылки, а не черз прямое ображение к self.iA
!
A.Init procedure(iA parIA) ! Метод для замены интерфейса
 code
  self.i_A &= parIA
!
A.Calc procedure
 code
  self.eMin = self.i_A.Min(self.eMin, self.eCurrent)  ! Расчитать минимум
  ! следует обратить внимание, что используется ссылка на интерфейс
  ! и эта ссылка может быть инициализирована наследуемым классом
  ! на любой интерфейс типа iA (или его наследник).
!
A.iA.Min  procedure(? par1, ? par2)
 code
  return choose(par1 < par2,  par1, par2) ! По умолчанию, расчет минимума такой
!
В принципе это вариант, того самого пресловутого "самодостаточного" класса. :))
А теперь класс B...

Код: Выделить всё

B.Construct  procedure
 code
  if self.cA &= null then self.cA &= new(A) end
  self.cA.Init(self.iA) ! Заменяем "родной" интерфейс класса A на порождённый этим классом,
  ! если необходимо
  ! если бы бы у класса А не было "родного" интерфейса, то инициализация ссылки класса А
  ! на порожденный интерфейс была бы обязательной, иначе GPF при вызове метода Calc
!
B.Destruct  procedure
 code
  if ~(self.cA &= null) then dispose(self.cA) end
!
B.Calc  procedure
 code
  ! Считаем что self.cA.eCurrent уже имеет значение
  self.cA.Calc ! Сделаем расчет, вызвав метод класса A
!
B.iA.Min  procedure(? par1, ? par2) ! Метод порожденного интерфейса
 code
  ! По условию конкретной задачи, отрицательного минимума быть не может
  if par1 < 0 or par2 < 0
    return 0
  end
  return choose(par1 < par2,  par1, par2)
!
Использование класса А может бы и по другому - прямым наследованием..

Код: Выделить всё

C  class(A), type
Proc1  procedure
  end
!
В этом случае уже можно переобъявлять конкретные методы интерфейса
(вспомним, что все они виртуальные).
Примерно так:

Код: Выделить всё

C.Proc1  procedure
 code
  self.Calc ! Сделаем расчет, вызвав метод класса A
!
C.iA.Min  procedure(? par1, ? par2) ! Переобъявление виртуального метода
 code
  ! По условию конкретной задачи, отрицательного минимума быть не может
  if par1 < 0 or par2 < 0
    return 0
  end
  return choose(par1 < par2,  par1, par2)
!
Сергей
Написал: ClaList(2)
Ответить