ООП - Что такое хорошо?
Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Здравствуйте ClaList!
За ряд лет сложилось какое-то представление о хорошeм коде при
процедурном программировании. Перехожу на ООП, а чем одно решение
лучше-хуже другого не понимаю. Есть ли какие хотя бы приблизительные
показатели качества кода в ООП?
--
С уважением,
SAN mailto:vgsan@yandex.ru
(Добавление)
Насчет показателей качества и критериев оценки ООП кода вообще, это,
наверное к тем, кто преподает теорию программирования на кафедре какого-нить
ВУЗа IMHO, это сильно зависит от конкретной задачи. Если программист вник
в предметную область, правильно выполнил декомпозицию (выделил простые
составляющие сложных понятий) и оформил это в объекты с учетом основных
принципов ООП, то бишь инкапсуляция, полиморфизм и наследование, то код
может претендовать на "знак качества" ... какой-нибудь там степени
Только не надо думать, что выполнить качественный код в ООП сложнее, чем
качественный код в структурном подходе, скорее наоборот
Удачи!
__________________________________
Владимир Якимченко (ICQ: 16993194)
Написал: ClaList(2)
За ряд лет сложилось какое-то представление о хорошeм коде при
процедурном программировании. Перехожу на ООП, а чем одно решение
лучше-хуже другого не понимаю. Есть ли какие хотя бы приблизительные
показатели качества кода в ООП?
--
С уважением,
SAN mailto:vgsan@yandex.ru
(Добавление)
Насчет показателей качества и критериев оценки ООП кода вообще, это,
наверное к тем, кто преподает теорию программирования на кафедре какого-нить
ВУЗа IMHO, это сильно зависит от конкретной задачи. Если программист вник
в предметную область, правильно выполнил декомпозицию (выделил простые
составляющие сложных понятий) и оформил это в объекты с учетом основных
принципов ООП, то бишь инкапсуляция, полиморфизм и наследование, то код
может претендовать на "знак качества" ... какой-нибудь там степени
Только не надо думать, что выполнить качественный код в ООП сложнее, чем
качественный код в структурном подходе, скорее наоборот
Удачи!
__________________________________
Владимир Якимченко (ICQ: 16993194)
Написал: ClaList(2)
Я бы акцентировался на другой аспект: необходимость хранения
промежуточных данных между вызовом одного и того же набора
процедур.
Поясню:
Предположим, что Д - это какая-то структура. Процедура А для данных
Д1 приводит систему в состояние А1, а для данных Д2 - в А2.
Соответственно, возможна задача, когда необходимо иметь
одновременно оба набора состояний - А1 и А2. В процедурном
стиле пришлось бы делать какие-то промежуточные буфера
состояний, процедуры восстановления состояний и т.п.
В ООП же мы имеем два экземпляра класса А, каждый из которых
работает со своей структурой Д и поддерживает свое состояние.
Т.е. это хорошее средство изоляции одновременно выполняющихся
наборов кода и данных.
Плюс некоторые прелести наследования...
Прочие же задачи, на мой вгляд, в равной степени легко реализуются
и в процедурном, и в ОО подходе.
Остальное - дело вкуса и привычки.
Про качество - вроде как везде. Вертикальная подчиненность,
отсутствие горизонтальных связей между процедурами (методами).
Хотя, судя по сообщениям в листе, с классами вытворяют все, что угодно
С уважением,
Владимир Смелик.
Написал: 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)
Возможно, я не совсем корректно описал пример.
"Состояние А" может не описываться полностью "структурой Д".
Кроме того, наборов данных для структуры Д может быть n, где
n на этапе разработки неизвестно. И еще: под "процедурой А"
следует понимать возможный набор функций и внутренних данных,
описывающих и поддерживающих "состояние А" в завистимости от
наполнения данными "структуры Д".
А про то, что в ПП можно решить те же задачи, что и в ООП - я и сам
знаю. Более того, вся практика моего применения ООП ограничивается
меньше чем десятком написанных мной классов :):)
Просто мне сложно мыслить категориями классов, вот я и пишу в ПП-стиле.
Кроме того, в ПП-стиле мне всегда хватало комментариев в тексте, а
в ООП-стиле приходилось создавать отдельный документ по классу.
Осознаю, что документирование полезно, но трудозатратно.
Впрочем, Clarion допускает использование и ПП и ООП в одной программе.
Например, в ШВС есть класс для "красивого" термометра. Очень прост и понятен
в использовании. Хотя большая часть кода по этим шаблонам генерируется в
ПП-стиле.
Только что пришла в голову мысль, что WinAPI выглядит скорее процедурно,
чем объектно...
С уважением,
Владимир Смелик
Написал: ClaList(2)
"Состояние А" может не описываться полностью "структурой Д".
Кроме того, наборов данных для структуры Д может быть n, где
n на этапе разработки неизвестно. И еще: под "процедурой А"
следует понимать возможный набор функций и внутренних данных,
описывающих и поддерживающих "состояние А" в завистимости от
наполнения данными "структуры Д".
А про то, что в ПП можно решить те же задачи, что и в ООП - я и сам
знаю. Более того, вся практика моего применения ООП ограничивается
меньше чем десятком написанных мной классов :):)
Просто мне сложно мыслить категориями классов, вот я и пишу в ПП-стиле.
Кроме того, в ПП-стиле мне всегда хватало комментариев в тексте, а
в ООП-стиле приходилось создавать отдельный документ по классу.
Осознаю, что документирование полезно, но трудозатратно.
Впрочем, Clarion допускает использование и ПП и ООП в одной программе.
Например, в ШВС есть класс для "красивого" термометра. Очень прост и понятен
в использовании. Хотя большая часть кода по этим шаблонам генерируется в
ПП-стиле.
Только что пришла в голову мысль, что WinAPI выглядит скорее процедурно,
чем объектно...
С уважением,
Владимир Смелик
Написал: ClaList(2)
Зачем!? Нормально написанный класс никак не "напрягает"Спасибо! А вот надо ли бороться за сокращение времени жизни объекта?
ни систему ни другие обьекты. Если, конечно, размер
данных, используемый этим обьектом, не превышает разумных
границ! Или, к примеру, в коде какого-либо метода этого
обьекта не используются бесконечные циклы, написанные,
к тому-же, без учета правил много -задачности и -поточности.
Что ты имеешь в виду?И если кто знает как оценить затраты связанные с инициализацией
обекта?
Если отбросить пока код, выполняемый в конструкторе обьекта,
то инициализация нового обьекта зависит от способа его обьявления:
- если обьект обьявлен как статический (не STATIC-аттрибут!) типа
tMyObj CLASS.,TYPE
MyObj1 CLASS(tMyObj).
MyObj2 tMyObj
то вся инициализация таких обьектов производится на этапе
компиляции приложения и при входе в область видимости этих
обьектов производится автоматическая очистка буфера их
данных и вызов их конструкторов (если есть).
- если обькт обьявлен как динамический типа
MyObj1 &tMyObj
то при входе в область видимости этих обьктов НИКАКИХ действий
по их инициализации автоматом не производится.
Только при выполнении оператора MyObj1 &= NEW(tMyObj)
производится выделение из локальной кучи памяти под буфер
данных этого обьекта, очистка этого буфера и запуск
конструктора (если есть).
Если тебя этот вопрос волнует в плане производительности
выполнения программы, то следует иметь в виду только одно -
если производится многократное выделение/освобождение
мелких кусков памяти, то может на некотором этапе наступить
значительное замедление выполнение программы из-за
свойств (ошибок?) менеджера памяти Клариона.
Например, создаешь очередь, запись которой содержит
рефералы на некоторые обьекты, и добавляешь в нее большое
число записей (несколько сотен тысяч и более), а потом
удаляешь эти записи с одновременным уничтожением обьектов,
рефералы на которые в них содержались. Так вот, если
повторно выполнять вышеописанное (заново добавление записей),
то могут наблюдаться тормоза выполнения.
ABC не пользую, так что - увы, ничем помочь в данном вопросе не могу!P.S. В эхе есть люди располагающие нормальным толкованием устройства и
происходящего в файлах ...bc.clw - ...bcN.clw, что то никак не найду
таких?
=============================
С уважением, Олег А. Руденко.
Oleg_Rudenko@mail.ru
Oleg_Rudenko@mail333.com
Библиотека DynaLib
http://dynalib.narod.ru
(Добавление)
Максим, я пока разбираюсь со стандартными решениями CW в ООП и пытаюсьА если задача все-таки
этого требует, то делай соотв. методы protected, чтобы можно было унаследоваться
от твоего класса. Все остальное - private, и пользователи твоего класса (в т.ч.
ты сам) никоим образом не должны зависеть от реализации.
понять почему и что они делают. На сколько я понял кларион АБС для
приложения для каждой обявленной таблицы при инициализации АПП создает
ряд объектов. Мне показалось что это противоречит ООП принципам ( с
одной стороны использ ряд решений по изоляции, а с другой задолго до
использования создаются объекты ). Кроме того для приложения средней
тяжести в 100-200 таблиц на подобную инициализацию уйдут ресурсы. Вот
мне и хотелось получить разъяснения по поводу ..bc.clw - ...bcN.clw (
возможно хоть кто-то написал себе комментарии к этому коду) и
мнение людей пользующих ООП.
--
С уважением,
SAN
Я не уверен, что ставить самодостаточность класса во главу угла это правильно.
Я стараюсь применять немного другие принципы:Создавай public интерфейс таким, чтобы всем его
хватало и не возникало желания влезть во внутренности. А если задача все-таки
этого требует, то делай соотв. методы protected, чтобы можно было унаследоваться
от твоего класса. Все остальное - private, и пользователи твоего класса (в т.ч.
ты сам) никоим образом не должны зависеть от реализации.
- Если метод используется внутри самого класса, то он должен быть виртуальным
В этом случае класс-наследник при необходимости может изменить алгоритм
этого метода.
- Создавать защищённые методы (PROTECTED) только в крайнем случае - только
если ДЕЙСТВИТЕЛЬНО необходимо, чтобы данный метод нельзя было использовать
вне классов-наследников.
Вообще я с трудом представляю зачем это нужно.
- Использовать вместо частных методов процедуры прописанные в том же самом
модуле, где и класс. Т.е. по хорошему объявление класса должно быть "чистым".
В общем-то PRIVATE-методы для наследников бесполезны.
- Для связи с внешними классами (или для использования их возможностей)
использовать интерфейсы (INTERFACE).
Это обеспечивает гораздо меньшую зависимость классов друг от друга.
Вообще, ООП удобно (и предназначено!) для создания унифицированных
механизмов и мне не совсем понятно, зачем вводить какие-либо ограничения
на использование класса его наследниками. Особенно это касается базовых
классов.
Сергей - chusha@mail333.com ; chusha@hotbox.ru
(Добавление)
Я считаю (и некоторые другие товарищи тоже), что очень желательно, чтобы классЯ не уверен, что ставить самодостаточность класса во главу угла это правильно.
максимально близко отображал реальную сущность, которую он представляет. В
пределах, требуемых задачей, конечно. Это позволяет делать использование класса
максимально прозрачным для его пользователей (нас с вами, т.е. программистов).
RTFM тут на самом деле не поможет пока в жизни с этим не столкнешься, тогдаЯ стараюсь применять немного другие принципы:
- Если метод используется внутри самого класса, то он должен быть виртуальным
В этом случае класс-наследник при необходимости может изменить алгоритм
этого метода.
Не следует увлекаться виртуальностью без нужды.
- Создавать защищённые методы (PROTECTED) только в крайнем случае - только
если ДЕЙСТВИТЕЛЬНО необходимо, чтобы данный метод нельзя было использовать
вне классов-наследников.
Вообще я с трудом представляю зачем это нужно.
поймешь, точнее _прочувствуешь_, зачем.
Реализация должна оставаться реализацией, и что там внутри не должно волноватьВообще, ООП удобно (и предназначено!) для создания унифицированных
механизмов и мне не совсем понятно, зачем вводить какие-либо ограничения
на использование класса его наследниками. Особенно это касается базовых
классов.
никого, даже наследников (если проектирование не подразумевает альтернативную
реализацию в процессе развития данной библиотеки классов этим же или другими
разработчиками).
--
Best regards,
Maxim Yemelyanov
(Добавление)
Хм, мне кажется что ты роешь не совсем в ту сторону :/Максим, я пока разбираюсь со стандартными решениями CW в ООП и пытаюсь
понять почему и что они делают. На сколько я понял кларион АБС для
приложения для каждой обявленной таблицы при инициализации АПП создает
ряд объектов. Мне показалось что это противоречит ООП принципам ( с
одной стороны использ ряд решений по изоляции, а с другой задолго до
использования создаются объекты ). Кроме того для приложения средней
тяжести в 100-200 таблиц на подобную инициализацию уйдут ресурсы.
[Кусь!]
Ну скажи на милось, тебя ОЧЕНЬ сильно волнует, будет твоя прога
потреблять памяти 20 Мбайт или 20,05 Мбайт (из расчета 250-500 байт
дополнительных ресурсов на таблицу)?! Я ещё понимаю, когда
речь заводится о порядка 10% от УСТАНОВЛЕННОЙ на компьютере
памяти. А когда речь идет о десятых (и даже сотых!!!) долях процента,
ну честное слово - не понимаю я этого! Угрохаешь кучу времени на
изучение теории, разбор "полёта", оптимизацию и в результате
получишь... ноль эффекта :/ Тебе это надо?!!
Не знаю как в других языках, а в Кларионе по моему, введением ООП
не ставилась задача экономии ресурсов, скорее наоборот. За счет
потребления доп.ресурсов добиться унификации кода. А вот уже
за счет унификации кода добиться сокращения затрат на
непосредственно кодирование, модификацию и развитие продукта
(в частности, ABC), т.е. труд. А это НАИБОЛЕЕ затратно в единичном
и мелкосерийонм производстве, как известно. Ведь кларион и
позиционируется как инструмент для создания единичных и
мелкосерийных программ (клиентских приложений - АРМов).
Хотя с его помощью и можно создать что хочешь, но тема топора и
мастера, им владеющего - это уже другая тема )
Думаю, что даже не ставилась задача на сокращение размеров
самой проги, хотя при аккуратном и продуманном подходам к ООП
на относительно больших прогах можно получить заметное сокращение
размера полученной программы. Но это опять же, не главное в ООП.
Главное в ООП - это экономия трудозатрат, как и в шаблонах собственно.
IMHO, конечно...
Сергей
(Добавление)
Для каждой _используемой_ в приложении таблицы.Максим, я пока разбираюсь со стандартными решениями CW в ООП и пытаюсь
понять почему и что они делают. На сколько я понял кларион АБС для
приложения для каждой обявленной таблицы при инициализации АПП создает ...
Это следствие принятой парадигмы - таблицы/файлы являются глобальными... ряд объектов. Мне показалось что это противоречит ООП принципам ( с
одной стороны использ ряд решений по изоляции, а с другой задолго до
использования создаются объекты ). Кроме того для приложения средней ...
объектами. В какой-то степени это отражает тот факт, что время жизни БД
больше времени работы использующего ее приложения и она является объектом
внешнего, по отношению к приложению, мира.
Ты посмотри сколько ресурсов берет такой объект (FM + RM). Где-то ок 350... тяжести в 100-200 таблиц на подобную инициализацию уйдут ресурсы.
байт. Из них 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 тут на самом деле не поможет пока в жизни с этим не столкнешься, тогда
поймешь, точнее _прочувствуешь_, зачем.
Пока в своей практике я не смог логически убедительно доказать ни в одном
случае, что именно в этом случае требуется защищённый метод.
Что в моей практике, что в коде других я пока вижу только один аргумент: "я так решил!"
Реализация должна оставаться реализацией, и что там внутри не должно волновать
никого, даже наследников (если проектирование не подразумевает альтернативную
реализацию в процессе развития данной библиотеки классов этим же или другими
разработчиками).
И да и нет. Если ты пишешь классы только для реализации конкретной (текущей) задачи
и больше тебя ничто не волнует, то как ты будешь их писать - до лампочки,
покуда больше они пользоваться никем и никогда не будут. Разницы между ООП и
процедурным типом я здесь не вижу.
Если же пишется класс с претензией, что он может использоваться в дальнейшем,
то необходимо писать его так, чтобы у последующего пользователя было как можно
меньше проблем, в т.ч. и с изменением алгоритмов и свойств класса. Т.е. опять же,
в этом случае ты изначально должен думать о минимизации трудозатрат при
последующем использовнии этого класса. Тут ООП имеет заметные преимущества
перед процедурным.
Сергей
(Добавление)
В этом случае класс-наследник при необходимости может изменить алгоритм
этого метода.
Я полагаю, что для этого предназначены PROTECTED методы. А виртуальные нужны
для того, чтобы класс мог управлять действиями, которые в момент написания
класса еще не сформулированы. Пример: в момент написания BrowseManager еще
не известно какую очередь, откуда и чем предстоит заполнять.
Пока в своей практике я не смог логически убедительно доказать ни в одном
случае, что именно в этом случае требуется защищённый метод.
Что в моей практике, что в коде других я пока вижу только один
аргумент: "я так решил!"
Думаю не только. Предположим, что некоторый метод класса решеат достаточно
сложную задачу. Например, делает ход в шахматной партии. . Для реализации
этого метода разработчик выбрал один из возможных алгоритмов или разработал
свой и в рамках реализации этого алгоритма написал несколько
подпрограмм-методов чисто внутреннего употребления. Более того, разработчик
планирует в следующей версии по результатам эксплуатации доработать, а
возможно и заменить этот алгоритм. ИМХО совершенно естественно сделать эти
методы не просто защищенными, а приватными, чтобы не было никакой
возможности их использования извне, дабы не иметь в будущем проблем
сопровождением умерших или радикально переработанных методов.
Реализация должна оставаться реализацией, и что там внутри не
должно волновать
никого, даже наследников (если проектирование не подразумевает ...
Поддерживаю.
... альтернативную
реализацию в процессе развития данной библиотеки классов этим
же или другими
разработчиками).
Не вижу связи между волнением наследников и альтернативной реализацией. ИМХО
это не аргумент.
И да и нет. Если ты пишешь классы только для реализации
конкретной (текущей) задачи
и больше тебя ничто не волнует, то как ты будешь их писать - до лампочки,
покуда больше они пользоваться никем и никогда не будут. Разницы
между ООП и
процедурным типом я здесь не вижу.
Если же пишется класс с претензией, что он может использоваться в
дальнейшем,
то необходимо писать его так, чтобы у последующего пользователя
было как можно
меньше проблем, ...
Только за.
... в т.ч. и с изменением алгоритмов и свойств
класса. Т.е. опять же, ...
Вижу только один вариант - отдавать вместе с исходниками. Обратите внимание.
Несмотря на критику 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)