![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Добрый вечер,
В общем есть программа, которая по совместительству является фреймворком. В программе этой есть классы всяких объектов, геометрических фигур, типа rectangle, polygon, text и так далее и естественно у них есть общий предок, пусть будет object. Необходимо иметь возможность модифицировать, копировать и делать другие нехорошие вещи с этим объектами. На данный момент все это сделано через одно место, от меня требуется сделать это через другое. В общем надо заменить безобразие типа
на что-то более вразумительное. Здесь на помощь приходит полиморфизм, но С одной стороны мне не очень хочется обогащать интерфейс несчастного класса object такими функциями, как copy, move, rotate...и так далее. Здесь по моему довольно неплохо справится шаблон visitor, это позволит добавлять новый функционал объектам, не затрагивая при этом самих объектов, но... С другой стороны это фреймворк, другая группа может добавить свой тип объектов, который не обязательно можно перемещать или переворачивать, к тому же добавив новый объект, ему также придется добавлять новую функцию в моем visitor-е, чтобы компиляция прошла. Можно конечно добавить шаблонный метод visit, который будет принимать все остальное и генерировать исключения, но все равно другой группе придется ковыряться в моих "посетителях", на что мне в принципе наплевать, но чтобы сделать объект копируемым и модифицируемым, ему придется добавлять три функции в трех разных классах. Выходит вроде как что с одной стороны хорошо, с другой плохо. Возможно здесь подойдет что-то вроде query interface-а, т.е.
но тогда все функции смешивается в кучу. В общем давайте дружно обсуждать качества и недостатки подходов. Это сообщение отредактировал(а) azesmcar - 10.11.2011, 17:46 |
||||
|
|||||
spyswamp |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 349 Регистрация: 18.8.2006 Репутация: 1 Всего: 7 |
Голосую за полиморфизм. Один раз посидишь, потратишь время, зато не будет дикого оверхеда. Подход должен быть удобный в использовании и очевидный при чтении. А то получится COM какой-то.
![]() -------------------- - why you call it beta? - cuz it's betta then nothin' |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Вопрос, насколько вероятно расширение состава объектов и насколько часто это может происходить.
Если редко, и визитеров предполагается немного, то я бы поставила на визитеров (с доп. шаблоном Visit и т.д.). С другой стороны, простая реализация визитера предполагает (как вариант), что в интерфейсе объекта есть ф-я типа Apply (Vis), а визитер наследуется от абстрактного класса, имеющего метод для каждого существующего класса. Таким образом, если конкретных визитеров много, добавление хотя бы одного типа объекта превращается в тихий ужас. Здесь и могут помочь примесные интерфейсы IMove, ICopy и т.д. Но код
( в каждом месте, где нужно перемещать) - это тоже тихий ужас. Поэтому можно совместить ежа с ужом, т.е. засунуть это дело в визитера, который может содержать методы для всех "стабильных" объектов, а может switch, а может просто преобразовывать obj к IMove... Зачем нам QueryInterface, если есть dynamic_cast. В общем в каждом случае визитера можно реализовывать как удобно. Есть же не только линейные иерархии. Например, полигон - это та же полилиния, но замкнутая, и т.д. Это, конечно, не совсем визитер уже будет, скорее просто некий функциональный объект, напускаемый на фигуры... Но от необходимости добавлять в интерфейс объекта все эти Move точно избавит. -------------------- ... |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
не надо пугать людей.. все это хорошо прячется (внутри функции обертки) и никаких неудобств не причиняет ![]() Добавлено через 3 минуты и 34 секунды
вообще картина описана слишком скудно.. все зависит от насыщенности, куда делить вглубь или вширь.. еслиб парочка конкретных примеров была бы потребованиям, то можно было бы думать.. а так остается только перечислить подходы, и напомнить что может выйграть не чистый вид, а комбинация.. Это сообщение отредактировал(а) mes - 10.11.2011, 19:05 |
|||
|
||||
spyswamp |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 349 Регистрация: 18.8.2006 Репутация: 1 Всего: 7 |
Лучше не примеры, а UML того, что есть сейчас: общая и детальная.
-------------------- - why you call it beta? - cuz it's betta then nothin' |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Ну я, собственно, обертку и предложила... и комбинацию... ![]() Ну да, ну да... Вот у меня в программе как раз для графических объектов реализован вариант простого визитера. Типы объектов давно фиксированы. Но вот подумываю добавить еще один тип (и больше, видимо, долго не понадобится). Вроде все ничего, но визитеров разных развелось просто тьма, по всей программе... При добавлении нового типа, конечно, компилятор поможет - вопить будет. Но править придется много. А если представить, что это делать пришлось бы другой команде... В общем, подумавши, прихожу к выходу, что тут важнее не частота изменений вширь\вглубь, а наличие разных команд. Т.е. нужно строить код так, чтобы "чужие" ковырялись только в собственном... -------------------- ... |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Операций свыше десятка, объектов тоже немало, я затрудняюсь ответить чего здесь больше. Желательно максимально облегчить труд другим группам, при добавлении новых объектов, но при этом не потерять красоты решения. Я сейчас не вспомню все типов и операций, но пусть это будет десяток объектов и операции copy, move, rotate, scale, split, save. Новые команды в принципе добавляются не так часто, объекты тоже, но объекты в основном добавляются совершенно другой группой и труд им желательно максимально облегчить, будет не совсем приятно заставлять их копаться в наших посетителях, это все таки фреймворк и должен предоставлять удобные средства для расширения. А я ни о чем другом и не писал, все варианты в так или иначе реализуют полиморфизм. Вопрос в том, как его реализовать. Вот об этом я и думаю, как бы скомбинировать.
Полиморфизм в голом виде здесь лишь будет засорять интерфейс базового класса, тем более, что не объекты не будут поддерживать все возможные операции. Скажем объект типа point нельзя переворачивать или масштабировать. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
какая задача все таки стоит перед фреймворком ? математические расчеты, визуальный редактор или что то другое ? Добавлено через 2 минуты и 35 секунд какие принципиально отличительные от геометрических фигур бывают объекты, которые разделяют с мими часть команд ? |
|||
|
||||
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
и то и другое + сохранение результатов в специальный формат файлов, загрузка этих файлов, конвертация... и много чего другого.
это могут быть линейки, флаги, тексты и тому подобное. Другими словами - объекты для разметки. Это сообщение отредактировал(а) azesmcar - 10.11.2011, 21:53 |
||||
|
|||||
spyswamp |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 349 Регистрация: 18.8.2006 Репутация: 1 Всего: 7 |
azesmcar, я имел ввиду унифицированный базовый интерфейс.
Таким образом было очень легко поддерживать кучу элементов технического анализа графиков свечных функций + добавлять новые инструменты, не обязательно связанные с анализом, а просто имеющие возможность присутствовать на графике. Ну, это если не брать в рассчет сами координатные оси и т.п. Они таким же макаром были организованы от базовых графических объектов. Добавлено через 9 минут и 4 секунды azesmcar, естественно, основной базовый класс все в себе не хранит, от него идет несколько абстрактных веток, чтобы разделить объекты по логическим типам и конкретным возможным операциям. Иначе это даже логичным назвать нельзя. Ведь что общего между стрелкой и засечкой со значением на линейке, ГРУБО ГОВОРЯ, кроме метода, скажем, draw? На мой взгляд, подводить все объекты под один базовый тип, это очень сомнительное удовольствие. Это сообщение отредактировал(а) spyswamp - 10.11.2011, 23:27 -------------------- - why you call it beta? - cuz it's betta then nothin' |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
тогда делить надо не по сущностям, а по функционалу..
например так :
на скорую руку но суть я думаю видна.. Добавлено @ 23:56 а должен ли быть этот метод, тоже вопрос.. Это сообщение отредактировал(а) mes - 11.11.2011, 01:45 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
1. выделено понятие блок с которым можно проводить некоторе кол-во операций
2. возможность операций определяется дескриптором 3. позволено создание нового типа фигуры, путем определения дескриптора и регистрации необходимых методов, как например figure_render_method.. 4. uid позволяет связывать методы разных производителей.. |
|||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
когда возможно расширение и классов и методов помогает аспектно-ориентированный подход. для него, увы, нет достаточных средств в С++ (да и во многих других популярных языках) поэтому применяются препроцессоры типа AspectC++ и иже с ими.
если задача не слишком сложна, можно привлечь метапрограммирование шаблонов. если есть явный перекос в сторону расширения объектов (либо методов), то принимается одно из соответствующих решений, остальное врукопашную. в данном случае похоже объекты будут чаще добавляться, чем методы. в этом случае как-то не очень... |
|||
|
||||
azesmcar |
|
||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Тогда модификация какой либо конкретно функции превращается в кошмар. Например чтобы изменить функцию копирования, в этом случае придется модифицировать код в каждом классе. Это уже затрудняет мою дальнейшую работу. Я понимаю, что мне хочется угодить все, что в принципе нереально, потому хочется найти золотую середину.
согласен ![]() потому чистый visitor не подходит. Думаю такое разделение на "стабильных" и не "стабильных" сильно затруднит понимание и чтение кода.
проект огромен, так что задача сложна ![]() по какой причине?
Сложно сказать. У нас редко добавляется и то и другое, но скорее всего так и есть. Методы добавляются редко, объекты добавляют другие, так-что мы часто и не в курсе, это уже другой продукт. нет, но это уже совсем другая задача. Это сообщение отредактировал(а) azesmcar - 11.11.2011, 09:36 |
||||||
|
|||||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
||||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Это сообщение отредактировал(а) math64 - 11.11.2011, 10:01 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
есть два основных противоположных подхода, получение интерфейса и возбуждение события.. при наличии стабильности в командах, стоит выбирать второй подход, так как первый вызывает в этом случае нагромождение.. не забывать опять таки то про комбинацию |
|||
|
||||
newbee |
|
|||
![]() Бревно ![]() ![]() Профиль Группа: Участник Сообщений: 703 Регистрация: 24.8.2011 Репутация: 4 Всего: 19 |
Я наверное не поняла всю сложность задачи,.. потому что по-моему все просто. Каждому типу объекта задается уникальный идентификатор. Далее регистрируем наборы функций для каждого типа (устанавливаем соответствие идентификатор-типа -> функция-делания-чего-то). Теперь общая функция, например copy, будет смотреть, какой объект к ней пришел, и вызывать соответствующую ему функцию копирования или пытаться выполнить какую-то операцию по умолчанию (попытаться самой провести копирование, или бросить эксепшн Ахтунг, или еще что-нибудь).
-------------------- You're face to face With man who sold the world |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
если разделить функции по сущностям, тогда каждая сущность будет иметь свою функцию копирования, пусть в Вашем примере она не будет засорять интерфейс основного класса, но тем не менее она привязана к сущности, а значит для изменения конкретной функции для всех сущностей, придется менять все классы. Конечно, с другой стороны, если сделать через что-то вроде visitor-а и придется менять все функции для конкретной сущности, тогда возникнет та же проблема, но это редкость, не думаю, что такое вообще может понадобиться. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
еще одно, делите на слои.. так для визуального редактора явно выделяются два :
модели фигур и контролеры их взаимодействия с пользователем.. соотношение сущностей не прямое.. то есть на каждую фигуру свой контролер - плохо.. Добавлено через 6 минут и 21 секунду
если смешаете обработку команд и логику фигур в одно месиво, да придется.. (только я этого не предлогал) Добавлено через 8 минут и 32 секунды насчет визитор, они хорошо, но только когда они выделены для определенной группы.. замыкать на них проект обернется трудоемкой поддержкой.. Добавлено через 10 минут и 45 секунд ну давайте выберем момент который Вам не понятен, сформулируем для него задачу, и реализуем на псевдопримере.. и так шаг за шагом будет видно какое решение самое подохдящее.. |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
math64
Этих IMovable, IRotatable и всего остального будет слишком много, чтобы пихать их в параметры функции.
Мне самом не нравится, просто интересует и Ваше мнение. Мне оно не нравится по той же причине. Про какую? ![]() А ничего сложного в самой задаче нету, сложность в выборе правильного решения ![]() Это обыкновенный полиморфизм, сделанный своими руками ![]() Ничем не лучше visitor-а, и опять таки встает вопрос о том, что другая группа, которая будет добавлять свои типы и желательно ограничить их деятельность в рамках своего кода и не заставлять их копаться в нашем. Добавлено через 3 минуты и 10 секунд Это все уже давно сделано, система спроектирована давно и существует на протяжении многих лет. Хорошо или плохо, но менять ее никто не собирается, но конкретно часть с редактированием сделана просто ужасно, потому было решено предоставить мне немного времени на редизайн, чтобы я не свихнулся, сопровождая это недоразумение. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
упущена одна деталь.. проблема классического визитора в том что он замкнут на типы языка.. при отражении типов на ран-тайм значения , развязывает руки по расширению функционала.. правда перекладывается и часть ответсвенности.. но за все надо платить и при правильной организации плата не велика.. |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Можешь реализовать и с отдельными visit(IMovable), visit(IRotatable), и т.д. - eсли не смущает то, что если объект поддерживает несколько интерфейсов, visit() придётся вызывать несколько раз, по разу для каждого интерфейса. Главное определить набор интерфейсов так, чтобы при добавлении нового класса не нужно было добавлять нового интерфейса. |
|||
|
||||
spyswamp |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 349 Регистрация: 18.8.2006 Репутация: 1 Всего: 7 |
Такое ощущение, что кто-то недавно прочитал про Visitor и сразу бросился им загромождать код. -) Уж извините, такое впечатление сложилось.
-------------------- - why you call it beta? - cuz it's betta then nothin' |
|||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
Вам виднее, но второе не обязательно следствие первого. смотря что под огромностью проекта понимается. тут вопрос в архитектурной сложности и количестве классов, а не количестве строк.
если методы добавляются редко лучше использовать visitor. query interface-подобные решения не дают возможности привычного статического контроля. тем более на объектах надо сконцентрироваться, что бы пользователям продукта предоставить более удобные и надежные средства Добавлено через 2 минуты и 47 секунд мне нравится способ, примененный в boost::operators. Добавлено через 3 минуты и 39 секунд при таком подходе вам при добавлении метода надо будет только поменять шаблоны. |
|||
|
||||
azesmcar |
|
||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Читал о нем очень давно и кстати вторую страницу пишу о том, что это решение мне не нравится. Привел в качестве рассматриваемых решений.
не совсем понял. имелось ввиду, что и классов и функций достаточно много.
т.е. Вы за Но это значить заставлять пользователей копаться в нашем коде, а в случае с query_interface он просто реализует в своем классе соответствующие функции, которые его тип будет поддерживать. Вы про CRTP? А как это здесь поможет? Я на данный момент не даю предпочтение какому либо методу, просто привожу варианты решения, которые вижу и пишу свое видение недостатков и преимуществ каждого из предложенных. Это сообщение отредактировал(а) azesmcar - 11.11.2011, 10:59 |
||||||
|
|||||||
newbee |
|
|||
![]() Бревно ![]() ![]() Профиль Группа: Участник Сообщений: 703 Регистрация: 24.8.2011 Репутация: 4 Всего: 19 |
Ты не связан статической системой типов языка. Ты сделаешь свою маленькую динамическую.
-------------------- You're face to face With man who sold the world |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Читал котда-то давно статью в "Мир ПК", в каком номере не помню, про модифакцию патерна Visitor с возможностью добавления новых посещаемых классов, но реализация довольно сложная - для того, чтобы пользоваться новыми классами в модифицированном Visitor. их нужно регистрировать.
|
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Регистратор прикрутить как раз несложно. Но проблема в том, что при добавлении нового типа объектов, существующие визиторы о них ничего не узнают (кроме факта существования, регистрация ничего не добавит). Как сделать DoSomething с объектом неизвестной породы? Только вызвать его соответствующий виртуальный метод. А методы плодить на все случаи жизни не хочется. Можно сделать что-то типа Invoke с параметром "заданное действие". И пусть объект решает, поддерживает он это действие или ну его нафик. Вот только действие передавать придется либо идентификатором, либо каким-то классом-тэгом и в конечной реализации возникнут if или switch... -------------------- ... |
|||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
если я правильно понял, пользователи будут реализовывать классы, а набор операций предопределен (и может меняться от версии к версии). тогда пользователь в классе просто реализует виртуальные функции, query_interface не нужен. если набор операций может меняться (пользователем), то можно использовать либо visitor либо query_interface. в этом случае я за первое. но у Вас как я понял пользователи только классы добавляют, но не методы. я не про механизм CRTP, я про идею расширения класса методами (которая может использовать CRTP как средство, но может и иначе). у авторов boost::operators, на мой взгляд, получилось изящно. |
|||
|
||||
azesmcar |
|
||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
нет, они определяют типы и операции с ними.
т.е. в итоге получается, что базовый интерфейс должен поддерживать операции move, rotate, copy ... и так далее, или должны быть интерфейсы imovable, irotatable, icopyable... а пользователь сам решает, какие интерфейсы он будет поддерживать. Это приводит нас опять таки к query interface, в том или ином виде.
не совсем представляю как это можно применить к текущей задаче? Это сообщение отредактировал(а) azesmcar - 11.11.2011, 12:14 |
||||||
|
|||||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
видимо я не вполне понял Вашу задачу. прочитал еще раз, внимательно, но нового не увидел. давайте на примере: пользователь определил новый тип объекта "пирог" и операцию над ним "съесть" как ваш базовый интерфейс узнает об этом методе? или все-таки методы определяет фреймворк, а пользовательские классы его реализуют (или не реализуют)? |
|||
|
||||
azesmcar |
|
||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
методы определяет фреймворк, пользователи его либо реализуют, либо нет. Попробую упростить задачу до примера. Начну с нуля. Допустим есть библиотека для работы с геометрическими объектами. Библиотека широко используется по всей компании и должна предоставлять возможности для расширения. Библиотека предоставляет некоторые базовые геометрические типы - полигон, прямоугольник, круг, а также некоторые объекты для разметки, такие как линейка и текст. Вот иерархия классов:
С объектами можно производить некоторые операции, например копировать или перемещать. Возьмем для примера копирование. Копирование по сути это текстовая сериализация объекта, далее этот текст помещается в буфер обмена. Далее. Группа B используется библиотеку в своем проекте, они добавлают новый тип объектов - точка. Они добавляют свой класс, наследник от figure_base и регистрируют его в библиотеке, далее они должны реализовать копирование объекта типа point. Теперь о реализации. Реализовать это можно многими способами, дело в том, чтобы выбрать самый подходящий. 1. Самый тупой способ - поместить все возможные функции в базовый класс figure_base, т.е. поместить туда функцию copy с default реализацией.
если автор класса point добавит в свой класс функцию копирования - тогда все прекрасно, а нет - значит копирование не поддерживается, покажем пользователю фигу. Но недостаток этого подхода в том, что интерфейс базового класса засоряется. 2. Более цивильный способ, разделить все на интерфейсы, т.е. добавить интерфейс icopyable, imovable... и так далее, а потом проверять, реализует ли класс этот интерфейс с помощью dynamic_cast-а. В итоге получается queryInterface. Недостаток подхода в том, что получается нагромождение всех функций в одном классе, который должен поддерживать и перемещение и копирование и поворот и многое другое. Чем больше функций, тем больше нагромождение, хотя интерфейс базового класса в этом случае не засоряется. Еще один минус подхода в медленной работе самого dynamic_cast-а. 3. С помощью вышеупомянутого шаблона visitor. В принципе все удобно, все разделено по функциональности, надо поменять функцию copy - меняем один класс, можно добавлять функции не меняя интерфейс самих классов. Недостаток в данном случае заключается в том, что при реализации копирование для объектов типа point, программисту придется лезть в нашу библиотеку и менять исходники, что не очень приятно. Желательно, чтобы его расширение было самодостаточно и не требовало модификаций нашего кода. Надеюсь смог нормально описать. Это сообщение отредактировал(а) azesmcar - 11.11.2011, 14:25 |
||||||
|
|||||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
или таблицы.. ![]() Добавлено через 3 минуты и 29 секунд
если исходить из классического представления с ориентировкой на объекты, то толку от регистрации в принципе не.. но если сделать ориентировку на методы (не функции челены, а методы алгоритма) то будет понятно что где и как регистрировать.. Добавлено через 5 минут и 59 секунд
ложить интерфейсы в ядро, это неподъемный труд.. ядро вначале нужно разделить на функционал, а уж каждый функционал можно реализовывать по разному, в том числе и через интерфейсы.. |
||||
|
|||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Нет, регистрировался не просто класс, а связка его с методом Посетителя - точно не помню как.
Что-то похожее на это (но вряд ли это):
|
|||
|
||||
baldina |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
я так и предполагал. тогда достаточно объявить виртуальные методы в базовом классе.
конечно. для решения этой проблемы существует классификация и декомпозиция. почитал дальше, вроде разобрался))) кажется, проблема заключается не в наследовании и операциях, а в том, о чем Вы не упоминаете: операции производятся ядром над объектами базового класса, и нет возможности узнать какие именно интерфейсы реализуются классом. скажем, end-user выбирает правой кнопкой мыши объект, и контекстное меню должно отобразить доступные операции. если новые объекты подключаются на этапе компиляции, это можно решить статической проверкой. остальное сделает компилятор. если интерфейс нужно определять динамически, то либо callback (эдакие динамические visitorы) либо query-interface. принципиальной разницы в этом случае не вижу. если я все правильно понял, и речь идет о статической задаче (периода компиляции), то MP (типа is_function_member<>) Добавлено через 2 минуты и 32 секунды а статические посетители применяются, если набор операций не предопределен. у Вас это не так |
||||
|
|||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
несколько важных моментов упущено.. сейчас попробую выудить их.. |
|||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
угу. но на самом деле тут нет одного, "правильного" взгляда. нужно несколько иерархий одновременно, в том и проблема. я потому и упоминал аспектный подход. |
|||
|
||||
mes |
|
||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
о полиморфности ни слова..
динамически добавляют ?
у всех трех способов есть очевидный недостаток, это жесткая завязанность на системе типов.. второй недостаток, все в одной яме Добавлено через 1 минуту и 2 секунды про АОП читал, но пока его не понимаю, поэтому в этой связи ничего не могу сказать.. Добавлено через 2 минуты и 18 секунд угу нету.. но есть пара деталей, о которых забывает тс, и поэтому не может связать задачу с подходящем решением.. именно на них я и пытаюсь сконцентрировать внимание.. |
||||||
|
|||||||
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
А какие здесь нужны слова? Нет, статически добавляют и сами же используют. Расширяют библиотеку для своих целей, нас это не касается.
На данный момент я не вижу подходящего решения, чтобы связать с ней задачу ![]() Добавлено через 1 минуту и 56 секунд не совсем понял мысль. Почему нет такой возможности? Есть dynamic_cast. На данный момент так и сделано, проверяется реальный тип и вызывается соответствующая функция для этого типа. Цель как раз в том, чтобы избавиться от этого. Добавлено через 2 минуты и 57 секунд
ну предложите четвертый, мне мои 3 тоже не нравятся ![]() |
||||
|
|||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
немножко переформулирую.. и так у нас есть задача полиморфно сереализовать объект.. и есть проблема не все наследники объекта известны, и предполагается возможность их динамической регистрации.. так правильно ? |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
||||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
от этого зависит регистрацию переложить на шаблоны в компилтайм, или же осуществлять ее в рантайме.. со статическим контролем не получится без изменения кода, просто его можно организовать так, чтоб не лезле в ваш, а просто добавляли свои исходники.. |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
так все ж в каком направлении думать ? для меня например желательно знать заранее.. если остановитесь на статическом, то Александреску разбирает в одной из своих книг (в какой сейчас не помню) генерацию визитеров по списку типов.. от списка типов уйти не получится и поэтому перекомпиляция при изменении будет неизбежна.. Это сообщение отредактировал(а) mes - 11.11.2011, 15:32 |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
угу тем более что библиотека для работы с полиморфными объектами.. Добавлено через 2 минуты и 35 секунд но тогда надо будет ввести свою систему типов.. (или просто uid, если предполагается взаимодействие выходящее за границы приложения.. например по сети) |
|||
|
||||
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
т.е. query_interface? Добавлено через 1 минуту и 47 секунд
нет, этого не предполагается. |
||||
|
|||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
это можно, да. но это уже не полиморфизм, а огромный switch. если бы он Вам нравился, темы не было б С++ статически типизирован, а dynamic_cast не добавляет динамичности в полной мере, эт только костыль поможет. почитайте. интересно. только сами не захотите использовать, т.к. слишком громоздко. если кратко, то АОП решает те же задачи, что и ООП, а также те, которые он не в состоянии решить (и добавляет проблем которых раньше не было ![]() для приспособления идеи к существующим языкам существуют пакеты, суть которых сводится к языковым расширениям, которые компилируются в код на целевом языке. плюс в том, что на расширении функционал реализовать гораздо проще. например, добавление аспекта (например, функции) делается элементарно, а в итоговой программе на целевом языке исправляются все классы, куда ее нужно добавить. почитайте сами, это слишком обширная тема для одного поста ![]() Йес!! ![]() хорошо бы иметь больше информации об архитектуре проекта, о том как фреймворк связывается с кодом пользователей. Если пользователи просто пишут расширения к откомпилированному коду, видимо без query-interface в каком-то его виде не обойтись. изобретёте еще один COM. когда я приводил в пример boost::operators, имелось в виду, что проект компилируется целиком, т.е. ваш код и пользовательский Добавлено через 2 минуты и 47 секунд а, еще... если пользователи добавляют расширения к откомпилированному коду в виде откомпилированного кода, т.е. интерфейс предопределен и неизменен, то никакой АОП не поможет. точнее, он поможет Вам как разработчику при внесении изменений/расширений в проект, но с точки зрения пользователей ничего не изменится |
|||
|
||||
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Дело в том, что на данный момент никто не с чем ничего не связывает, если кому-то что-то нужно, это делаем мы. ![]() Вот мы и хотим взвалить ненужную нам работу на чужие плечи. А как - это уже другое дело. У них есть заголовочные файлы и библиотеки, будет считать исходников у других нету, мы выдаем им уже готовый фреймворк. Добавлено через 31 секунду Примерно так оно и должно быть. Добавлено через 57 секунд
Вот именно ![]() |
||||
|
|||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
http://liveworkspace.org/code/045bcd682434...0273f990d385bb7 Добавлено через 3 минуты и 40 секунд a, b пользовательские типы.. пользователь также должен до использования своих типов проивести регистрацию (init).. писалась на скорую руку, чтоб передать идею.. также использовал голый ид, но можно это приукрасить, если нижно.. Добавлено через 5 минут и 44 секунды пример - база для реализации алгоритмов copy/paste.. Добавлено через 10 минут и 54 секунды правда для примера сериализация выбрана немножко неудачно, так как ей должен обладать по идеи любой объект, что предполагает ее простой виртуальной функцией.. но вот например рендеры, тем более что их может быть несколько, могут иметь такой подход.. |
|||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
угу. подобное решение было первой мыслью после прочтения темы, но это уже внеязыковые средства. как, впрочем, и query-interface. но вообще - хороший способ, поддержам Добавлено через 3 минуты и 51 секунду это АОП-way |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
а у С++ вообще с динамикой плохо, хорошо что руки не связывает и позволяет выкрутится обходными вариантами.. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
ну тогда можно притянуть его и сюда
разгрузив через список типов.. ![]() где то так : http://liveworkspace.org/code/0532d48b65fd...f0e78f2ba25ee9f Это сообщение отредактировал(а) mes - 11.11.2011, 17:52 |
|||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
azesmcar, медитирую над этим примером
пытаюсь понять откуда оно возникло. вот собственный пример с контекстным меню мне ясен, понятны средства его реализации. насколько это близко к вашим "нехорошим вещам", которые делаются с объектами? |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
mes
Просматриваю, немного не нравиться то, что функции по идее должны быть глобально видимыми, позже попробую сгруппировать глобальные функции по классам. не понял вопроса. что откуда возникло? |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
с чего это взяли ? Добавлено через 44 секунды не понятно что делает выражение, процитированное baldina Добавлено через 2 минуты и 37 секунд сформулируйте требования, попробую отразить в коде ![]() Добавлено через 3 минуты и 31 секунду функции это вы o serialize или o serialize_fn<T> ? Добавлено через 4 минуты и 45 секунд глобальными или глобально видимыми ? |
|||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
||||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Если в ваш пример с сериализатором переписать так, чтобы можно было его использовать не только с сериализатором, но и с перемещением, вращением, перекрашиванием и др. визиторами (но избавившись от getId() ) - получится примерно то, что было в журнале "Мир ПК"
|
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
подкорректируем задачу..
есть команда print и есть несколько групп объект ов разных производителей.. задача: 1. позволить динамическое подключение каждой групы объектов 2. избежать зависимость между группами 3. внутри группы позволить использовать средства контроля типов Это сообщение отредактировал(а) mes - 11.11.2011, 22:05 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
вот решение с комбинацией различных подходов :
http://liveworkspace.org/code/6148d7bc1a09...f9f74430ebd53c4 неймспайсы условно предствавляют модули разных производителей нужно подумать как сделать более благородные средства регистрации.. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
немного изменил завязку (регистрацию), пододвинув ее в сторону си идеологии :
http://liveworkspace.org/code/c76143b44b1e...126584d06c5f01f Это сообщение отредактировал(а) mes - 11.11.2011, 23:13 |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
уже лучше - регистрировать нужно не отдельные классы, а модули.
|
|||
|
||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
отличная идея! правда для моей задачи ;) |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
math64, какую задачу озвучил, ту и решал ![]() а регистрятся, кстати, не классы, а колбяк-функции ![]() Это сообщение отредактировал(а) mes - 11.11.2011, 23:55 |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
mes
Из дома сложновато бывает засесть за компьютер, попробую сегодня посмотреть и отписаться. Спасибо за старания. |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
но раньше нужно было регистрировать по одному callback'у на функцию, теперь - на модуль. Внутри модуля используется обычный Vsitor. А задача была поставлена немного не такая. Регистрацию пожно проводить примерно так (не тестировал, могут быть ошибки):
|
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
вот пример того, о чем я говорил изначально : http://liveworkspace.org/code/e04fcdd67b04...047a56795ec837a или так : http://liveworkspace.org/code/ff77f7b542c5...9f12ab7392a4504 Это сообщение отредактировал(а) mes - 12.11.2011, 16:26 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
math64, основная идея примеров, это разбиение действий на методы..
это позволяет для каждой группы объектов иметь свой метод, что в свою очередь позволяет легко подключать/отключать нужную группу, что позволяет группе разработчиков предоставлять полноценный метод для работы с группой, а пользователю выбирать какие методы использовать в действии.. Это сообщение отредактировал(а) mes - 12.11.2011, 15:46 |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
mes, Ваш пример делает одно действие - print - причём только в cout.
Мой пример (он - модификация Вашего примера, и в нём есть ошибки, но их можно исправить) позволяет делать несколько действий с группой объектов. Подключать/отключать группу ещё проще - не нужен init(), регистрация происходит автоматически при подключения модуля к проекту. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
может потому что акцент (моей) задачи стоял не нем ? ![]() а пока что смотрю, что получается в каком случае.. и жду более подробного освещения проблем от тс.. тот пример лишь был показательным эксперементом для group_id и не очень оправдавшим себя.. сейчас я склоняюсь к другому ![]() уточню, я на ините и не настаивал.. Это сообщение отредактировал(а) mes - 12.11.2011, 19:54 |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Вот есть ещё такая идея (незавершённая) - в class Visitor новые методы не добавить, а в namespace - можно
Регистрация состоит в том, чтобы обеспечить включение всех нужных заголовков. |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Вызывает функцию передвижения прямоугольника, если это прямоугольник. Т.е. решает if-ом ту задачу, которую решают виртуальные функции. В итоге выходит, что средствами C++ красивого решения придумать не получается (имеется ввиду встроенными средствами) и приходиться выкручиваться своей собственной таблицей. mes Спасибо. Поработаю немного над примером, посмотрим что получиться. ![]() Всем спасибо за участие. Это сообщение отредактировал(а) azesmcar - 14.11.2011, 14:01 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
мне кажется Вы рано закрываете тему и стоило бы дать еще подробностей, ибо пример затрагивает лишь одну линию взаимотношений.. Какправильно заметил math64, команда представлена одним экземпляром и это в большой степени потому что разнятся подходы, для случаев "классического" использования или динамической/визуальной среды.. |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
По всей видимости дорабатывать придется еще некоторое время, так-как сейчас у нас на работе гости из Штатов и шансов поработать за компьютером у нас меньше, чем можно себе представить ![]() Рабочий день проходит в основном в конференс-зале, потому на всякий случай закрыл, открою потом если что ![]() На данный момент хочу сказать, что вариант с командами я тоже рассматривал, но отбросил по причине большой нагрузки при реализации новых команд, которых довольно много. Есть желание их сгруппировать, хотя пока не представляю каким образом. Это сообщение отредактировал(а) azesmcar - 14.11.2011, 15:44 |
|||
|
||||
mes |
|
||||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
На данный момент я вижу вашу задачу так.. Есть лист на котоый могут быть положены объекты разных типов.. 1. Объекты разделены по группам (фигуры, разделители, текст и т.д.) при этом должна быть возможность динамечиски добавлять 2. Лист предоставляет набор фиксированных действий предоставляемых над любыми объектами, и реализаторы сами решают какие команды поддерживают.. Это все что удалось с Вас вытянуть.. В таком изложении задача не очень большая, но внутрене чувствуются что это далеко не все..
мне кажется Вы упустили чего то..
так наоборот хорошо есть время пообсуждать.. (конечнонастаивать я не могу, просто тема заинтересовала )
Вы напишите все "словосочетания", пусть даже не связанные, которые описывают что должно предоствалять решение этой задачи.. Без описания с Вашей стороны, форумчане лишь могут предложить решение только своих представлений о вашей задаче, которые к сожалению в большинстве случаев далеки от Вашей десйтвительности.. Это сообщение отредактировал(а) mes - 14.11.2011, 16:21 |
||||||||
|
|||||||||
azesmcar |
|
||||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
В принципе да, но здесь есть одно но, добавлять могут разные люди. И те, у кого есть доступ к исходникам, и те, у кого их нет. Т.е. Я могу добавить новый тип объектов, а может добавить программист из другой команды, который просто использует наш редактор как фреймворк для своего приложения. Так она и не большая, большой ее делают количество операций с объектами, а задача сама небольшая, просто душа требует красивого решения ![]() я имел ввиду, что реализовывать новый класс для каждой команды как-то не привлекательно. да, если получиться приблизиться к компьютеру ![]() но я буду стараться.
Давайте так. Разберем по полочкам что необходимо решению? Возможность добавлять новые типы объектов не меняя при этом исходников. Значит группировать операции над объектами по операциям не получиться, т.е.
такое отменяется (это я про visitor-а). Остается либо группировать по типам объектов, либо не группировать вовсе, т.е. либо так
либо через интерфейсы и dynamic_cast.
Забудем на секунду о реализации, вернемся к ней попозже, сейчас попробуем сосредоточиться на самой идее. Я вижу эти варианты. Реализация новых функций так или иначе должны находиться вне нашего исходного кода, т.е. они либо должны быть в самом классе нового типа (виртуальная функция), либо какая-то статические функции, сгруппированные в каком нибудь классе. Вы видите еще какие либо варианты? Добавлено через 2 минуты и 33 секунды Я не знаю как еще описать, Вы же все поняли |
||||||||
|
|||||||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
и добавлять новые типы команд, не влезая в чужие исходники и избегая перекомпиляции чужих библиотек.. Добавлено через 2 минуты и 41 секунду вобщем предполагаю такую картину есть библиотека фреймворка со стандартным наобором примитивов и команд, есть стороняя библиотека расширяющая как каманды так и набор примитивов, и есть пользователь, который должен не смотря на наличие компилированных библиотек , должен не чувствовать связанности рук.. пойду обдумывать.. |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
Во всех предложенных вариантах наблюдается принуждение пользователя..Все варианты хороши как локальное решение,глобально же любая группа/слой должна иметь обособленность, чего примеры не отражают.. |
|||
|
||||
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
![]() Добавлено @ 16:52 к чему? Добавлено @ 16:54
А какие могут быть еще варианты? Реализация функций в сторонней библиотеке должна содержаться в самой библиотеке и это должен быть либо виртуальный, либо статический метод какого-либо класса, либо команда (pattern command/функтор), что не очень приятно, так-как выделять по классу на каждую операцию будет накладно. Добавлено @ 16:59 Самым простым и выполняющим все требования решением на данный момент мне видится интерфейсы и dynamic_cast, т.е. что-то такое
сторонняя библиотека может добавлять собственные интерфейсы и реализовывать их независимо от нас. решение мне не нравиться применением dynamic_cast-а и нагромождением функций, но оно достаточно простое для понимания и к тому же выполняет все требования. Добавлено @ 17:02 На самом деле я не вижу какие реальные привилегии мне дает собственная таблица функций. Их надо регистрировать, что отнимает время и хоть чуть-чуть, но все же усложняет жизнь, а что дает взамен? Это сообщение отредактировал(а) azesmcar - 14.11.2011, 17:03 |
||||
|
|||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
mes
сейчас думаю над такой вариацией query interface-а. пользователь запрашивает интерфейс, реализующий модифицирующие операции над объектом текущего типа. Если возвращается 0, значит модифицирующие операции не поддерживаются.
но здесь есть два минуса. 1. в самой функции приходиться получать объект базового типа, так-что от cast-а это не избавляет. Думаю как бы обойти. 2. нет возможности реализовать для объекта функцию move, но не реализовывать скажем функцию rotate (хотя этот минус есть и в случае виртуальных обычных функций, но там интерфейс можно максимально разделить, а в данном случае это приведет к необходимости писать кучу кода). Это сообщение отредактировал(а) azesmcar - 14.11.2011, 17:24 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
другими не словами, вносит ограничение впо возможности выражения пользователя своих желаний.. самый большой минус в ваших высказываниях, Вы сводите все в одну линии, от команды до варианта фигуры.. т.е рассматриваете программу как один монолит, и именно это проблема, а не какой то из выбранных направлений..
в таком выражении и не дает.. если вы о примере, то плюс дает не таблица функций, а разбиение на прослойки, где для каждой группы можно добавить свой обработчик. Чтоб лучше понять представьте что вместо print, у нас execute_action (iaction &); у командного паттерна (алсо обработчика сообщений) большая динамичность.. что позволяет легко расширять командынй состав.. но.. не стоит сразу бростаься в него и из каждой фигуры делать обработчик... Я уже много раз говорил про разложении на слои, и именно на этом нужно акцептировать в первую очередь внимание, ибо для каждого слоя разный вариант исполнения предпочтителен.. чуть позже сделаю пример с пояснением как я вижу вашу решение.. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
azesmcar, неплохо было бы, если бы Вы привели бы список по парочке разнотипных по смыслу команд ..
так например сдвигающее воздействие над фигурой в принципе из одной группы команд.. Это сообщение отредактировал(а) mes - 14.11.2011, 18:14 |
|||
|
||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
вот каракас для допиливания : http://liveworkspace.org/code/9c9ae402c782...be5c4d3264d0e35 как видите определение новой команды может быть всего лишь типа :
при этом будет сохранена безопасность типизации, и уникальность id (внутри рамок рабочего приложения) независимо от производителя.. правда до этого придется немного поработать в том числе и с шаблонами ( но выделка,имхо, того стоит).. как плюшка следствия такого подхода, контролер может выдавать список всех поддерживаемых комманд.. аналог quеry_iface, но при этом деление на интерфейсы идет по -командно, что позволяет манипулировать более свободно.. для полноценного тестового запуска нужно добавить сериализацию/десериализацию, но суть и так понятна.. если что может помочь в этом направлении так и не доведенная до конца тема : http://forum.vingrad.ru/forum/topic-323593...ed-discoly.html Это сообщение отредактировал(а) mes - 14.11.2011, 23:00 |
||||
|
|||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
mes
У нас древний компилятор, boost-а нет...я смутно представляю чего мне будет стоить такая реализация. Завтра с утра посмотрю повнимательнее что да как и отвечу. Спасибо. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
для начала определимся с лексиконом, чтоб удобно было делить по группом вводим понятия тип_примитива и вариант_примитива.. где тип : ifigure, а вариант : наследник ifigure (rect, circle).. вариант всего лишь реализует интерфейс ifigure и никакой обработки команд не имеет. для обработки вводим еще связывующее звено, для нас это figure_commander .. commander`ы должны быть зарегистрированы в main_commander.. тогда.. 1. при добавление нового типа, регистрируется новый коммандер 2. при добавлении нового варианта, достаточно изменить/отнаследовать нужный коммандер 3. при добавлении новой группы команд можно добавить для нужных групп еще по командеру, или же отнаследоваться от имеющихся.. Добавлено через 34 секунды
так предупреждать надо было сразу ![]() Добавлено через 1 минуту и 47 секунд сейчас поправлю ключевые места, чтоб видно было как для старого писать.. кода будет правда немножко побольше, как при разработке, так и при пользовании, но все ж.. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
держите и тестируйте на своем компиляторе: http://liveworkspace.org/code/ca6c4fecda3d...d3101dcc94b165b (обновлено) естственно все написанно на скорую руку и требует детальной доработки, но для работоспособности никакого буста не надо.. пример any есть где то на форуме, но нужен только если, необходимо удлиненное хранение аргументов.. при ассинхронном подходе.. ну а кол-во аргументов можно расшить например до (входные const& , выходные&); чтоб была возможность диалога.. естественно регистрация в маин сделана для простоты примера, можно автоматизировать это дело.. это я на всякий случай от лишних придирок предостерегаюсь.. ах да забыл сказать, возникающая при таком подходе трудность применение метода к двум вариантам разных типов.. но насколько я представляю задачу, подобное и не требуется, а межтиповое взаимодействие (например конвертация) особых проблем не имеет.. Это сообщение отредактировал(а) mes - 15.11.2011, 00:44 |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Если команды будут с 0..2 параметрами можно переписать так, что будет компилироваться в VS.
(уже сделали - не посмотрел на новую страницу темы) Это сообщение отредактировал(а) math64 - 15.11.2011, 07:18 |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
mes
Разобрался. В конечном итоге решение сводиться к регистру шаблона команда со стандартным параметром void*, который в дальнейшем приводиться в соответствующий вид и передается конечному обработчику. Теперь давайте поговорим о том, какое преимущество дает это решение? Для каждой операции над объектом (а их много) необходимо создавать структуру параметров. Каждую операцию надо регистрировать. Каждая операция требует создания отдельного класса. Усложненная реализация в плане понимания исходного кода. Что я получаю взамен, чего мне не дает dynamic_cast? Как это решение облегчает дальнейшее сопровождение кода? Какие дает возможности расширения в будущем? Я сам не люблю dynamic_cast, но в конечном итоге все делается для удобства написания и дальнейшего сопровождения. Я понимаю Ваше решение, но не понимаю какие плюсы мне это дает. Не примите за критику, я пока просто пытаюсь понять плюсы предложенного решения ![]() Это сообщение отредактировал(а) azesmcar - 15.11.2011, 10:22 |
|||
|
||||
mes |
|
||||||||||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
Для каждой операции над объектом (а их много) необходимо создавать структуру параметров.[/quote]
не для каждой, а для каждой разнотипной.. Т.е. для одного набора аргументов может быть несколько комманд.. если не операцию, а метод обработчика, то да.. не понимаю о чем Вы.. вот как выглядет пользование
для гибкости интерфейсы тоже придется делить на мелкие, и кол-во кода будет одного порядка.. к тому же при множественном наследованнии вероятность нарыва на конфликт.. неправильная постановка вопроса.. это не альтернатива dynamic_cast, это просто иной подход к понятию интерфейс..
опять акцептирования внимание не на том.. dynamic_cast тут не при чем..
вот на это уже можно отвечать.. 1. например у вас много обработчиков разных команд, (std::vector <handler_t*> v); вы хотите в цикле для каждого вызвать команду move.. в случае с командами я напишу примерно так :
2. у нас появилось новая группа команда для нашего типа, я просто создаю для нее новый обработчик
3. нам нужно до обработчика и/или после выполнить какое то действие.. например хотим вывести лог.. то добавляем необходиммый обработчик.. т.е у нас получается стек обработчиков.. 4. хотим заменить поведение группы разработонной другим разработчиком, просто меняем его обработчик 5. любая смена поведения, осуществляется динамически, и не требует перекомпиляции чужих библиотек.. (большой привет жесткой связке множественного наследования).. и еще куча вариантов, на вспоминание которых сейчас нет времени ![]() а теперь попробуйте переписать перечисленное через интерфейсы.. Добавлено через 5 минут и 37 секунд
советую также внимательнее рассмотреть моменты, которыми отличается предложенное решение от "классического" паттерна команда.. Добавлено через 7 минут и 43 секунды и да и dynamic_cast никто не отменял, он остается как вариант взаимодействия обработчика с вариантами типов.. (или же вместо него будет визитор).. Это сообщение отредактировал(а) mes - 15.11.2011, 10:51 |
||||||||||||||
|
|||||||||||||||
azesmcar |
|
||||||||||||||||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Они практически все разнотипные. Об этом
Для начала можно и не делить. В данном случае делить можно будет по необходимости. К примеру для начала создать интерфейс i_modifier, который будет содержать функции типа rotate, move, change_layer ... итд, а далее по необходимости реазделять на более мелкие интерфейсы.
Как дизайн - возможно, но в данном случае мы рассматриваем несколько разных подходов к решению одной задачи, так-что это альтернатива решению.
Это уже другой разговор. Теперь давайте думать о том, нужно ли это? В основном предполагается производить операцию над объектами через интерфейс базового класса. Пример использования: пользователь выбрал несколько объектов и набрал команду move {10 20}, все объекты должны быть перемещены. Того, что Вы описали не планируется, но я еще подумаю об этом.
Еще его надо будет зарегистрировать. В случае с dynamic_cast я просто создаю новый интерфейс и наследую его там, где его нужно реализовывать. Так-что разница небольшая.
Не нужно, эта возможность у нас уже есть. Все операции вызываются из команд, которые вызываются из интерпретатора. Для команд можно устанавливать pre/post callback-и.
Не совсем понял о чем это. Если вы про изменения расширений других разработчиков, то у нас нет доступа к их исходникам, мы с ними никак не связаны. Они используют наш продукт, мы с их продуктом не работаем.
А зачем нужно перекомпилировать чужую библиотеку в случае с интерфейсами?
далее другая группа делает следующее
зачем ей что-то перекомпилировать? |
||||||||||||||||||||
|
|||||||||||||||||||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Кажется понял. Это вы про смену поведения для наших объектов? В общем-то этого нам тоже не нужно, они не имеют на это право. Другие могут только добавлять свои типы и операции, менять у нас они ничего не должны. Еще раз скажу, что я не защищаю какое либо решение. Просто перед тем как принять одно, я должен понять что оно мне дает и чем я ради него жертвую. На данный момент я нахожу наименьшим злом решение с query interface-ом, потому все предложения сравниваю с ним. ![]() Это сообщение отредактировал(а) azesmcar - 15.11.2011, 11:34 |
|||
|
||||
mes |
|
||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
ну ну.. успеха ![]() регистрация обработчика сводится к карте соответсвий.. и обработчик может быть самодостаточным.. т.е. вклюпчать в себя как диспетчер, так и сам обработчик.. так что не вижу никаких опасений.. в случае наследования тянет за собой вплоть до полной перекомпиляции, при этом если добавляют разные производители, то каждый лезет в чужой исходник.. в случае с обработчиками каждый может делать свою часть не пересекаясь с другими... это называется игра в темную.. Если у вас уже есть команды то чего мы придумываем то тут ? исходники не при чем, пользователь добавил команду, например вывод в особом виде, теперь ему не придется переколошмачивать чужие исходники, а просто добавить в стек обработчик нужного поведения..
потому что вы не можете воздействовать реализацию в следствии ее монолитности.. появилась еще команда и в moveble добавили еще один метод.. ![]() Добавлено через 1 минуту и 56 секунд
т.е. Вы заранее знаете как пользователю лучше ? ![]() Добавлено через 3 минуты и 1 секунду
при таком подходе я Вам не советчик.. ![]() |
||||||
|
|||||||
azesmcar |
|
||||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Не вижу как это добавляет объем работы. Объем будет нарастать по требованию и интерфейсы этот процесс никак не затрудняют.
Я говорил не про регистрацию, а про то, что
Мы кажется друг друга не понимаем. Никто в чужие исходники не лезет. Зачем это нужно? Есть базовый класс geometry и некоторые операции типа move, rotate...которые определены в виде интерфейсов, другая команда разработчиков наследует свой тип, пусть будет rectangle и реализует интерфейсы move и rotate, о наших классах он ничего не знает, нашего кода у него нет и ему это не нужно.
Команды - это другая история, их использовать нельзя, потому я о них молчу. Это не просто команда, а немного необычный класс, который работает через интерпретатор. В общем это долгая история, на данный момент все реализовано через эти команды и мы как раз пытаемся от этого избавиться. Просто если я начну рассказывать всю архитектуру, писать мне придется очень долго. Ему и так не придется, он добавляет свой интерфейс, реализует его и работает с ним, с нами это никак не связано, мы этот вывод в особом виде не обрабатываем. Наша библиотека обрабатывает только то, о чем она знает. Если Вы это про нашу команду, тогда да, но это не чужие исходники а свои, так-что все в порядке. Конечно, придется делать практически полную перекомпиляцию своих исходников и это неприятно, но ради одной быстрой компиляции писать столько кода, создавать по структуре для параметров на каждый тип операций, регистрировать каждую операцию...как-то не привлекательно ![]() |
||||||||
|
|||||||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
давайте сравним.. пойдем разымышлять от QI : есть набор типов , которые поддерживают некоторые интерфейсы.. поддерживать они могут через множественноенаследование - что приводит к статическому монолиту, либо динамически региструя наследника, что позволяет расширять динамически поведение.. Если планируется расширение комманд и разрозренная разроботка (как в вашем случае) требуется второй вариант.. Для увелечения мобильности, интерфейсы должны быть минимализированы.. В принципе получили теже команды только в другом виде.. В чем же отличие ? В передачи действия : представим картину.. мастеру пришло задание, QI : он по одному вызывает рабочего, смотрит может ли он это выполнить , если да то дирижирует им.. Cmd : письмо передается по очереди, в которой каждый выполняет лишь свое действие.. разница очень тонка в одном случае передается интерфейс в запрашиваемое место, в другом идет комманда до нужного интерфейса.. в обоих случаях они идут как (условно) void*, в оноих для динамики надо регистрировать, Это сообщение отредактировал(а) mes - 15.11.2011, 16:31 |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Нет, я знаю что он должен делать, а чего не должен ![]() А что не так с подходом? Я должен яростно защищать dynamic_cast? Тогда зачем создавать тему, если в итоге я все равно настроен решать так, как хочу сейчас? Перед тем как принять решение, я должен понять его плюсы и минусы, и эти плюсы должны перевесить минусы. mes Давайте перед началом сравнения проясним кое-что. Я не нашел в Вашем примере где Вы вообще обрабатываете объекты? Вы вызвали обработчик, но где ему передается rectangle, polygon и тому подобное? Этого здесь нет, как предполагается передача самого объекта обработчику? Это сообщение отредактировал(а) azesmcar - 15.11.2011, 16:26 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
Я ж специально выделил.. не буду сразу подсказывать ответ, но Ваш первый вывод неверный... я возмутился над другим аспектом.. Добавлено через 3 минуты и 3 секунды операция это обработчик ? не требует, Вы можете это делать как это удобнее, но лучше делить на группы, для достижения мобильности.. или операция это комманда ? да требует определения структуры аргументов, что не так много и определения переменной.. немногим больше, чем написание прототипа функции.. Это сообщение отредактировал(а) mes - 15.11.2011, 16:32 |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Вы насчет жертвы? А что Вы в этом нашли такого? Любой подход и любое решение - это плюс в одну сторону и минус в другую. Принятие минусов конкретного решения и есть эта жертва, сделанная ради ее плюсов. |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Предлагаю такое решение: Вместо идентификатора у объект можно получить "пульт управления":
|
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
Я бы предпочел вариант, "что я от этого выигрываю"... не говоря о слишком жестком акценте над словом "одно"... ![]() поэтому закуем в наручники ![]() Сорри за придирки, просто иначе не знаю варианта, как "заставить" Вас взглянуть под другим углом ![]() |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Одно - подразумевалось одно из решений. С той же логикой можно отменить спецификаторы доступа. Долой private, делаем все методы и поля публичными ![]()
Я пытаюсь, но из плюсов я на данный момент вижу только ослабленную монолитность, зато работы это прибавляет значительно. Я не придираюсь, просто хочу понять. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
azesmcar,
Вот с этого и надо было начинать уточнение.. что не до конца прояснил пример.. с непривычки он действителен сложен для понимания.. там получилось два полупримера, один с фигурами (и принтом), другой с командами их надо считать за одно целое.. А вспомнил еще один недостаток монолитного QI, при множественном наследовании может возникнуть коллизия имен.. ( ну и пра затруднительное проксирование я уже говорил)... я кажись придумал откуда надо плясать.. Это сообщение отредактировал(а) mes - 15.11.2011, 16:56 |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Но ведь что я теряю - это тоже важно, потому вариант не подходит ![]() Добавлено через 1 минуту и 15 секунд
Да, это есть, но это не так страшно. В данном случае меня больше всего волнует монолитность класса и использование кастов. Здесь я вижу самый большой минус. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
||||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Попробую еще раз сформулировать свою позицию.
Ваш пример сильно усложняет дизайн и чтение кода, добавляет работы, при этом он конечно вносит некоторое количество плюсов, 90% которых в данном случае не нужны и использоваться не будут. Единственное его достоинство, которое в моей задаче является большим плюсом - это ослабленная монолитность, но я пока не чувствую, что оно того стоит.
Я теряю простоту и понятность кода. Скорее всего мне очень долго придется объяснять как это работает и почему третье лицо должно что-то регистрировать и создавать структуры для параметров. И в общем-то я не уверен, что у меня получится. Это сообщение отредактировал(а) azesmcar - 15.11.2011, 17:02 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
вот о жертвах.. при правильном подходе монолитности не будет и при подходе с интерфейсами, только придется прикрутить, QI рeгистрацию интерфейсов и ту же кучу кода как при Command.. преимущества : получение полноценного интерфейса.. несдостатки усложненость при составлении цепочки ответсвенностей.. у Command акценты расставлены наоборот.. |
|||
|
||||
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Каким образом? Где будет реализован интерфейс, если не в самих классах? Добавлено через 2 минуты и 37 секунд
давайте подумаем в этом направлении. Это сообщение отредактировал(а) azesmcar - 15.11.2011, 17:06 |
||||
|
|||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
Еще раз.. я не знаю вашу задачу поэтому не могу подобрать правильно подходящее решение.. В нашем споре я не настаиваю на нем, а лишь отвергаю необоснованные доводы.. Вот например вышеприведенная цитата, может перевести в конструктивный поток.. и так, у нас есть набор интерфейсов, предполагается маличие QI, как получить ослабленную монолитность.. сейчас должен отойти, чуть позже напишу пример.. Да от понимания концепции сильно зависит реализация.. Тогда следующие решения буду предлагать с учетом этого.. вышеобсужденные требовани оставляю в силе ![]() Добавлено через 1 минуту и 18 секунд я как раз об этом написал.. значит нашли точку соприкосновения.. дальше нужно стараться не потерять, а то у насдо этого получалось переливание оз пустого в порожнее ![]() |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Я имел ввиду, не уверен, что у меня получиться объяснить. ![]()
Я действительно не могу описать ее всю целиком, мне надо будет рассказывать всю архитектуру проекта, а это займет пару дней ![]() В принципе основные ключевые моменты я описал, остальное приходится рассказывать по мере необходимости. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
пока вы тут, опишите фигуру, кроме перемещения и поворота что она умеет, и в каких случаях она не должна уметь..
чтоб мысли уходили на реализацию, а не на фантазирование поведения ![]() Это сообщение отредактировал(а) mes - 15.11.2011, 17:20 |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
mirroring, scale, смена layer-а. там на самом деле не только фигуры, есть флаги, точки, которые нельзя передвигать или вращать, зато можно копировать или сохранять в файл, т.е. нужна сериализация. Третье лицо может добавить свой топ, который нельзя копировать, в общем вариаций много. |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
вот что пока что получилось, сейчас надо бежать, позже буду дорабатывать, просто выложил в качестве сырья и объекта для обсуждения написанный на скорую руку.
Это сообщение отредактировал(а) azesmcar - 15.11.2011, 17:49 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
ага, в pпринципе именно то, только не у geom, а у object.. но только забыто одно но.. ну вот есть у нас эти интерфейсы.. кто ими пользоваться будет ? если пользователь, то ему удобнее узнать фигура , текст, это ли что другое.. если это прослойка для комманд, то не вижу разделение на слои.. Это сообщение отредактировал(а) mes - 15.11.2011, 18:16 |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Вот рабочий пример по моей идее - ни одного dynamic_cast<>:
|
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Не совсем понял о чем речь. В основном мы. Вообще-то на данный момент расширять ее никто не будет, так-как весь фреймворк пока к этому не готов, но меняя дизайн чего либо мы к этому стремимся, так-что в основном пользоваться будем мы, т.е. я.
Тут тоже не совсем понял о чем речь. Добавлено через 28 секунд math64 спасибо, мне надо это переварить, понадобиться время ![]() |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
немного размышлений о том , как я это представляю.. задачу можно разделить на несколько слоев, каждый из который соответсвует определенной концепции.. срез представляет "оголенные" интерфейсы.. в зависимости от того какие слои будут соприкасаться, зависит какими интерфейсы должен предоставлять слой... в некоторых случаях бывает нужным сделать прослойку/адаптер.. Зачастую чтоб не забивать голову, просто лепят мониолит.. К слоям относятся не только программные компоненты, но в том числе оборудование и юзер.. Так например например между консольной программой и юзером один тип среза, а между юзером и ГУИ совсем другой, поэтому отличается подход по формированию.. При Этом слои вполне могут располагаться как консолька<->Гуи<->Юзер.. Саму программу также можно условно разделить на слои : например первый - предметная область, второй взаимодействие с базой,взаимодействие с юзером.. для того чтоб представить задачу нужно понять о каком слое идет речь, другими словами определить, что на входе, а что на выходе.. Добавлено @ 00:20 так например если я описываю предметную область, то все эти moveable вообще не нужны, гораздо ближе "родные " названия самих типов.. если я хочу интерактивное взаимодействие, то я выбрал бы динамический интерфейс (в основе которого паттерн комманда) и по запросу о поддержке команд формировал бы юзеру меню возможных вариантов... ну и дальше в таком же духе.. Добавлено через 10 минут и 52 секунды применительно к вашей задаче : есть набор фигур - предметная область , тут вроде все понятно.. но это одна часть а вот вторая : есть какой то фреймворк, который что то там делает с набором фигур, и который еще кто-то будет использовать как то, по своему усмотрению.. но там имеются еще команды и интерпретатор.. вот так я вижу этот слой на основе ваших деталей ![]() ![]() ![]() Добавлено через 11 минут и 39 секунд Но задача вроде интересная ![]() ![]() Это сообщение отредактировал(а) mes - 16.11.2011, 00:21 |
|||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
я пытался выяснить, но внятного ответа не получил(((
а советывать не имея исходной информации занятие малополезное. однако из контекста у меня сложилось некое мнение, что речь идет о программе, работающей с разными (геометрическими?) объектами, над которыми и осуществляются операции при помощи команд. при этом end-user может выбрать множество объектов и выполнить некую команду из общего списка, и она должна быть применена ко всем объектам множества, которые в состоянии обработать такую команду. если я правильно понял, есть разработчики ядра (ака фреймворк), они добавляют типы и команды и прочие разработчики (они вроде только типы добавляют) Добавлено через 2 минуты и 49 секунд мне самому жутко интересно, что же разрабатывается Добавлено через 5 минут и 44 секунды почти сразу было понятно, что языковыми средствами не обойтись, но какая именно комбинация средств наиболее подходящая зависит от деталей задачи и распределении ролей в разработке |
|||
|
||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
эту часть тс, особенно ревностно оберегает ![]() ![]()
![]() тема постепенно превращаются в оффтопные мультимонологи ![]() |
||||
|
|||||
azesmcar |
|
||||||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
на какой именно вопрос? Я уже и не знаю о чем рассказать ![]() Как конечный пользователь будет использовать программу? Все что есть я описал.
Да
Да. А для тех, которые не поддерживают сгенерировать исключение.
Да. Что еще нужно описать а не понимаю, Вы же все прекрасно понимаете. Добавлено через 1 минуту и 18 секунд
Я же писал об этом несколько раз.
Вот оно. mes На Ваш предыдущий пост отвечу позже. |
||||||||||
|
|||||||||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
мы это предполагаем наиболее подходящий вариант, но внутри чувство, а вдруг в данной ситуации по другому и придумываем еще парочку вариантов, которые также имееют право на жизнь.. Вы там писали что есть интерпретатор с командами, как понимаю они остаются, и Вам необходимо добавить фигуры и осуществить связку.. так ? если да, то как выглядит условный вызов команды и передача ее на обработку.. |
|||
|
||||
azesmcar |
|
||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Вот потому я и не хочу выдавать лишнюю информацию. С интерпретатором это никак не связано. Нет, они не остаются, от этих команд надо избавиться. Добавлено через 2 минуты и 5 секунд
|
||||||
|
|||||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
ну вот хоть что то
![]() ![]() и теперь стало сразу понятно, что значила та строчка,о которой допытывал вас baldina (с copy_rectangle).. мой пример с командой можете забыть (он мог быть вместо вашей командера, но в дополнении не смотрится ) остальное отвечу позже Это сообщение отредактировал(а) mes - 16.11.2011, 10:08 |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Ну вот, я же говорю не надо загружать лишними деталями. Нет у меня команд, это одна команда на move всего движимого и недвижимого, она понятия не имеет с какого типа объектами она имеет и будет иметь дело. Это могут быть объекты, которые созданы другой группой, это могут быть наши геометрии. Абсолютно без разницы откуда это вызывается, главное создать возможность полиморфно обрабатывсть объекты, не зная их реальных типов. Добавлено @ 10:13 Я видимо очень плохо объясняю. Забудьте про интерпретаторы и команды. Есть базовый класс geom, есть наследуемые от него разного рода геометрии. Есть predifined список операций, которые можно проводить с этими типами. Некоторые типы поддерживают все операции, некоторые нет. Например точка не поддерживает вращения, а полигон поддерживает. Операции добавляются и изменяются чаще, чем сами типы, но необходимо оставить возможность добавлять новые типы, не изменяя исходников, так-как возможно добавление типов со стороны третьих лиц. Все. Задача в этом, все остальное не важно. Вот все требования. Это сообщение отредактировал(а) azesmcar - 16.11.2011, 10:14 |
|||
|
||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
есть разница какие интерфейсы требуются коммандеру, юзеру, или для отображения в меню..
Команда как действие у вас условно есть (то есть неважно физическое наличие, важно что мы знаем что команда может вызваться) и надо написать логику команды.. или так называемую связку, в которой как я и понимаю есть та загвоздка.. Добавлено @ 10:29 это была как раз не загружающая, а разгружающая деталь ![]() Добавлено @ 10:31
да , не важно откуда вызовется, главное что есть вызов, а не пустые предоставлемые пользователю интерфейсы.. Добавлено @ 10:33 вот как раз три слоя и определились : коммандер, исполнитель, типы ( условно C,B,A) ![]() при этом концентрация на втором, с учетом третьего.. для начала надо сконцетрировать на предмете.. что такое geom ? это некий объект занимающий некий прямоугольник, может быть фигурой, текстом спецсимволом и т.д. он может быть сохранен в разных форматах, и отрисован разными рендерами.. если он фигура, то над ним могут быть произведены скалирование, перемещение, конвертация и т.д. если он текст что то подобное и смена текста.. но может быть разработон стороний тип, правила к которому определяется тртьим лицом.. жду поправок ![]() Это сообщение отредактировал(а) mes - 16.11.2011, 10:54 |
||||
|
|||||
azesmcar |
|
||||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Да.
Некоторые из них могут быть сохранены в текстовом виде, возможно в дальнейшем нужно будет добавить и другой формат. Насчет отрисовки - верно, но это нашей задачи не касается, отрисовкой мы не занимаемся, наша задача - editing.
Да. Да. Только здесь могут быть еще и неведомые нам типы, которые будут поддерживать неизвестные нам заранее комбинации интерфейсов. Т.е. если на данный момент у нас нет типов, которые нельзя перемещать, но можно вращать, это не значит, что потом этого не понадобиться.
Да. Конкретно в приведенной мною реализации query interface мне не нравится один момент. Придется заранее разбивать на мелкие интерфейсы, сгруппировать не получиться, так-как после группировки будет невозможно дальнейшее разделение. Скажем я создал интерфейс i_editable - который поддерживает операции rotate и move, а потом у нас появился тип, который можно перемещать, но нельзя вращать и придется менять кучу кода, чтобы разделить rotate интерфейс от move-а. А в случае с наследованием интерфейсов можно разделить интерфейс на i_rotatable и i_movable, оставить интерфейс i_editable : i_rotatable, i_movable для поддержки старых реализаций. Добавлено @ 11:24 EDA инструменты ![]() Это сообщение отредактировал(а) azesmcar - 16.11.2011, 11:25 |
||||||||
|
|||||||||
xvr |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 60 Всего: 223 |
А перекомпиляция исходников допускается? Если да, то описать все операции в виде класса с виртуальными методами (по 1 штуке на операцию) и телами, которые бросают исключение - 'not-implemented'. Отдать этот класс на растерзание пользователю, но унаследовать все ваши классы от него. |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Да, это самое первое, что пришло на ум, но операций довольно таки много, интерфейс базового класса будет похож интерфейс класса std::string ![]() В общем-то решить можно по всякому, но разве это лучший из существующих вариантов? |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
azesmcar, вот теперь задача обрела очертания..
следует уделить внимание разбиению на собственное поведение, и внешне реализованное.. так например возвращать себе в сериализованном виде это внутреннее поведение, а запись в определенном формате внешне реализованный модуль.. собсвенное поведение должно быть минимализировано и максимально универсально.. недостаток, неохбходимость для сторне разработанного типа динамической регистрации, преимущество легкая расширяемость и поддерживаемость (правда с небольшим наличием избыточного кодирования) но это забегая вперед, а теперь вернемся к текущему :
Да, об этом изначально говорилось, что интерфейс стремится к единичной "ответственности".. Груповые интерфейсы же представляют собой адаптеры для мелких.. А то что в вас вызывает опасения по этому поводу решается через динамические примеси, которые позволяют избежать вынужденного кодирования при реализацию этих интерфейсов.. пример чуть позже.. |
|||
|
||||
baldina |
|
||||||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
это не понимание а телепатия ![]() я спросил про фрагмент if (is_reсtangle) cope_rectangle(); но в ответ получил то, что и так из этой строчки ясно
вот это понятно ![]()
почти решает проблему. почти, потому что при расширении набора операций приходится все соответствующие классы наследовать еще от одного интерфейса. еще остается вопрос с обработкой исключений (хотя это совсем не вопрос, если при несовпадении типа просто ничего не надо делать). если требуется обработать каждый случай несовпадения типа, можно помещать "провинившиеся" объекты в отдельный список, который обрабатывается по завершении операции. если все несовпадения типа обрабатываются единообразно, это можно делать и внутри цикла. но это мелочи, обратимся к главной задаче: требуется независимо изменять набор типов и набор операций. для этого надо сделать типы и операции независимыми, разделить их. концептуально это означает использовать visitor. к сожалению, это ослабляет систему типов (мы используем внеязыковые средства), но упрощает разработку и сопровождение. с академической точки зрения тут должен последовать совет о разработке проблемно-ориентированного языка, и в итоге для упрощения реализации мы придем к использованию пакета АОП, но я не столь жесток ![]() как реализовать? возможность добавлять новые типы без перекомпиляции обеспечивает динамическая регистрация обработчика и карта(map) обработчиков. про это mes изложил подробно и разнообразно. в дополнение могу предложить перекладывание задачи регистрации на базовый интерфейс, типа
таким образом интерфейсы используются не для наследования, а для задач регистрации обработчиков интерфейса это позволяет в одних случаях (разработка фреймворка) применять наследование (или шаблоны), а в других (добавление типов пользователями) - явную регистрацию методов остальное - разработка синтаксического сахара в стиле, который Вам больше нравится еще замечание. признаться, я не очень верю, что возможных команд очень много. с точки зрения пользователя может и много, но они наверняка классифицируются, и менеджер команд (о котором мы не говорим) в состоянии на выходе иметь ограниченный перечень. так, например, команды преобразования move, scale, rotate etc суть одна функция transform, если для преобразований используются матрицы. тогда кстати и точку вполне можно вращать ;-) далее, наверняка реализация команд для разных типов отличается, но этих отличий может быть не очень много и они, в свою очередь, тоже классифицируются. например, графический элемент может иметь ограничения на преобразования, связанные с его состоянием (заблокирован, "заморожен") и с состоянием связанных с ним объектов. с другой стороны, изменение элемента может повлечь изменение элементов, зависящих от него. тогда потребуется некая несложная архитектура выполнения команды типа
ясно. собственно на догадки меня навел пост, где присутствует команда move{0,2}, оч. похоже на всякие CADы Это сообщение отредактировал(а) baldina - 16.11.2011, 17:09 |
||||||||||||
|
|||||||||||||
xvr |
|
||||||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 60 Всего: 223 |
Самое главное, что в этом базовом классе не будет ничего другого. Только интерфейсы. И их можно будет легко добавить, ничего больше не меняя
Порезать на логические части и оформить в виде иерархии интерфейсов.
Пользователь может добавлять новые методы, новые группы методов, может добавить уровней иерархии в интерфейсы и т.д. и т.п. Но библиотеку придется перекомпилировать Пожалуй самый простой. Если устроит, то может и самый лучший ![]() |
||||||
|
|||||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
ловите примеси :
http://liveworkspace.org/code/98eac02abcba...b5316128ef8154a сейчас каждый объект содержит карту, но можно переделать так, чтоб касрта свойств была общая (статическая ) для всего класса.. использовал авторегистрацию для типов, но она накладывает некие ограничения.. если что придется пожертвовать (вот в этом случае как раз жертвуем ;) ) все представленные миксы самодостаточные, но вполне допустимы и захватывающие контекст.. кстати обратите внимание что самопонятие moveable (и ему подобные) не являются типом и вообще исключены из рациона. и команда move реализуется на основе свойств.. Это позволяет минимизировать набор свойств и развязать руки при составлении команд.. вот одна из вариаций ручной ассоции типов : http://liveworkspace.org/code/3b5206ae1eed...48112a18a4621b5 те части в которых произошли изменения :
другой подход можно позаимствовать из примера с коммандами (action_type , action_rawdata ( в роли идентификатора интерфейса ) ) Это сообщение отредактировал(а) mes - 17.11.2011, 10:13 |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
mes, В обоих ваших примерах нельзя определить несколько свойств одного типа, правда, в некоторых случаях можно вывернуться - для линии использовать pair<point,point>, для полигона - vector<point>.
И регистрировать в мутаторе лучше не объект, а геттер и сеттер. Исходя из назначения (разводка печатных плат, как я понял), объекты делятся на две категории: примитивы (point, rect, line. circle, arc, polyline, polygon, path, text) - новые понадобятся редко, если нужно что-то новой формы - есть path. Вешать на них интерфейсы, мутаторы и т.д. - не рационально, всё это займёт больше места, чем сам примитив. Но если новые примитивы добавляются редко, можно применить visitor. Компоненты высокого уроня: component, connection, lay Новые компоненты создаются в редакторе компонентов, как правило, без создания новых классов C++ - здесь как раз мутаторы уместны. Но нужно иметь возможность динамического добавления свойств. |
|||
|
||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
в QI нельзя получить два одинаковых интерфейса .. все зависит от задачи ![]() нужнен массив точек,определите такое свойство.. у геттера/сеттера нет типа.. нужен отдельный геттер/сеттер сделайте такой микс.. ![]() Добавлено через 1 минуту и 17 секунд
экономичность это следущий шаг.. пока я лишь показал какие еще варианты бывают ![]() чтоб не было зацикливания на imoveable ![]() |
||||
|
|||||
math64 |
|
||||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Можно сделать так:
У статических методов тип уже есть - их можно добавить в map (лучше не в тот, куда добавляют объекты, а в отдельные для геттеров и сеттеров) Но в общем, как делать уже ясно - детали зависят от конкретной реализации. |
||||
|
|||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
о каком типе идет речь ? я о том который вытупает в роли идентификара свойства/интерфейса |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Вот такие типы:
|
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
это не позволяет определенно и однозначно соотнести тип к методу.. а тс. чего то не видно.. или это я такой нетерпеливый.. Это сообщение отредактировал(а) mes - 17.11.2011, 18:49 |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
mes, вот определяется (добавить недостающие куски из Вашего примера):
Без typedef можно обойтись. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
ну и ? увсех сеттеров типа void (*)(figure&,const int&), а их множество, будет один и тот же тип.. про ограничения на кол-во аргументов мы промолчим .. во вторых как будет выглядить пользователем получение это сеттера.. да и вообще зачем нам эти сеттеры ? интерфейсы (мутаторы) намного более симпатичны.. на один ид отражены сразу все необходимые методы в удобном и привычном виде.. |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Так и в Вашем примере для одного типа возможен один мутатор - устранение этого ограничения аналогично. Ну вот нужно установить центр Rect. Поля Point center нет, а есть левый верхний угол. А если и есть, всё равно нужно сделать перерасчёт левого верхнего угла, а если хранить и остальные углы - то и их. |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Чтобы уйти от сеттеров можно использовать паттерн Observer - это рентабельно, если будем его применять для объектов высокого уровня
Это сообщение отредактировал(а) math64 - 17.11.2011, 20:45 |
|||
|
||||
mes |
|
||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
да, только как относится наблюдатель к нашей задачи по динамическому описанию любого типа фигуры ? или вы уже следующую решаете ?
один мутатор/интерфейс про ид.. или множество про один ид ![]()
![]() Так в том то и дело, что мой пример был направлен на уход от подобной традиции.. В C++ООП мы представляем что класс это набор данных и методов описанных вместе.. В НашемОП , есть объекты предоставляющие данные и модули содержащие методы по их обработке ![]() Это сообщение отредактировал(а) mes - 17.11.2011, 23:56 |
||||||
|
|||||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Observer прекрасно сочетается с Вашими мутаторами (при разделении на примитивы, для которых применяется обычное программирование, и объекты высокого уровня) - я не стал приводить общий пример.
Но возможно, у Вас другой взгляд на построение системы - нужно послушать ТС. |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Я понял Вашу концепцию - Rotatoin не хранит угол поворота, а делает поворот (из Вшего примера это было не очень ясно - следовло бы написть комментарий). В этом случае сеттеры действительно не нужны. Обсерверы, если и нужны, то редко.
|
|||
|
||||
mes |
|
||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
не совсем так, возможно как хранение даных и/или воздействие тад ними, так и проксирование действия... все зависит от выбранной модели..
ну я вроде бы и написал:
мне уже по почте писали, что мой стиль труден для восприятия.. но я честно не специально.. если не понятно покажите момент, и я с удовольствие попробую объснить другими словами.. Вы имеете ввиду средства обратной связи для взаимодествия между разными свойствами внутри объекта ? в большинстве случаев это не имеет смысла, потому какв рамках предложенноймодели, стоит рассматривать объект, как набор данных(т.е. как структуру), а не как единицу поведения (объект ООП) |
||||||
|
|||||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Доброе утро.
Извиняюсь что пропал, ненадолого уехал из города. Сегодня попробую все осмыслить и продолжить тему. Это сообщение отредактировал(а) azesmcar - 30.11.2011, 09:31 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
отлично, а то у меня столько мыслей по этому поводу поднакопилось, будет повод разобрать их по полочкам ![]() |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |