Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> полиморфная модификация объектов 
:(
    Опции темы
azesmcar
Дата 10.11.2011, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Добрый вечер,

В общем есть программа, которая по совместительству является фреймворком. В программе этой есть классы всяких объектов, геометрических фигур, типа rectangle, polygon, text и так далее и естественно у них есть общий предок, пусть будет object.
Необходимо иметь возможность модифицировать, копировать и делать другие нехорошие вещи с этим объектами. На данный момент все это сделано через одно место, от меня требуется сделать это через другое.
В общем надо заменить безобразие типа
Код

if (is_rectangle) copy_rectangle();

на что-то более вразумительное.
Здесь на помощь приходит полиморфизм, но
С одной стороны мне не очень хочется обогащать интерфейс несчастного класса object такими функциями, как copy, move, rotate...и так далее. Здесь по моему довольно неплохо справится шаблон visitor, это позволит добавлять новый функционал объектам, не затрагивая при этом самих объектов, но...
С другой стороны это фреймворк, другая группа может добавить свой тип объектов, который не обязательно можно перемещать или переворачивать, к тому же добавив новый объект, ему также придется добавлять новую функцию в моем visitor-е, чтобы компиляция прошла. Можно конечно добавить шаблонный метод visit, который будет принимать все остальное и генерировать исключения, но все равно другой группе придется ковыряться в моих "посетителях", на что мне в принципе наплевать, но чтобы сделать объект копируемым и модифицируемым, ему придется добавлять три функции в трех разных классах.
Выходит вроде как что с одной стороны хорошо, с другой плохо. Возможно здесь подойдет что-то вроде query interface-а, т.е.
Код

if (i_movable *obj = object->query_interface<i_movable>())
{
    obj->move();
} else
{
    throw std::runtime_error("нельзя двигать недвижимость!");
}

но тогда все функции смешивается в кучу.
В общем давайте дружно обсуждать качества и недостатки подходов.


Это сообщение отредактировал(а) azesmcar - 10.11.2011, 17:46
PM   Вверх
spyswamp
Дата 10.11.2011, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 349
Регистрация: 18.8.2006

Репутация: 1
Всего: 7



Голосую за полиморфизм. Один раз посидишь, потратишь время, зато не будет дикого оверхеда. Подход должен быть удобный в использовании и очевидный при чтении. А то получится COM какой-то. smile


--------------------
- why you call it beta?
- cuz it's betta then nothin'
PM MAIL   Вверх
Earnest
Дата 10.11.2011, 19:00 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Вопрос, насколько вероятно расширение состава объектов и насколько часто это может происходить.
Если редко, и визитеров предполагается немного, то я бы поставила на визитеров (с доп. шаблоном Visit и т.д.). 
С другой стороны, простая реализация визитера предполагает (как вариант), что в интерфейсе объекта есть ф-я типа Apply (Vis), а визитер наследуется от абстрактного класса, имеющего метод для каждого существующего класса. Таким образом, если конкретных визитеров много, добавление хотя бы одного типа объекта превращается в тихий ужас. Здесь и могут помочь примесные интерфейсы IMove, ICopy и т.д. Но код 
Код

if (i_movable *obj = object->query_interface<i_movable>())
{
    obj->move();
} else
{
    throw std::runtime_error("нельзя двигать недвижимость!");
}

( в каждом месте, где нужно перемещать) - это тоже тихий ужас.
Поэтому можно совместить ежа с ужом, т.е. засунуть это дело в визитера, который может содержать методы для всех "стабильных" объектов, а может switch, а может просто преобразовывать obj к IMove... Зачем нам QueryInterface, если есть dynamic_cast. В общем в каждом случае визитера можно реализовывать как удобно. Есть же не только линейные иерархии. Например, полигон - это та же полилиния, но замкнутая, и т.д. Это, конечно, не совсем визитер уже будет, скорее просто некий функциональный объект, напускаемый на фигуры... Но от необходимости добавлять в интерфейс объекта все эти Move точно избавит.



--------------------
...
PM   Вверх
mes
Дата 10.11.2011, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Earnest @  10.11.2011,  18:00 Найти цитируемый пост)
 в каждом месте, где нужно перемещать  - это тоже тихий ужас

не надо пугать людей.. все это хорошо прячется (внутри функции обертки) и никаких неудобств не причиняет smile

Добавлено через 3 минуты и 34 секунды
Цитата(Earnest @  10.11.2011,  18:00 Найти цитируемый пост)
 насколько вероятно расширение состава объектов и насколько часто это может происходить.

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




Это сообщение отредактировал(а) mes - 10.11.2011, 19:05


--------------------
PM MAIL WWW   Вверх
spyswamp
Дата 10.11.2011, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 349
Регистрация: 18.8.2006

Репутация: 1
Всего: 7



Лучше не примеры, а UML того, что есть сейчас: общая и детальная.


--------------------
- why you call it beta?
- cuz it's betta then nothin'
PM MAIL   Вверх
Earnest
Дата 10.11.2011, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(mes @  10.11.2011,  20:05 Найти цитируемый пост)
все это хорошо прячется (внутри функции обертки) и никаких неудобств не причиняет 

Ну я, собственно, обертку и предложила... и комбинацию... smile 
Цитата(mes @  10.11.2011,  20:05 Найти цитируемый пост)
вообще картина описана слишком скудно

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


--------------------
...
PM   Вверх
azesmcar
Дата 10.11.2011, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  10.11.2011,  19:05 Найти цитируемый пост)
вообще картина описана слишком скудно..

не хотелось сразу грузить тему большим количество деталей, а то вдруг не прочтут smile 

сейчас, сейчас..только вернулся. чуть попозже попробую добавить побольше деталей.
PM   Вверх
azesmcar
Дата 10.11.2011, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  10.11.2011,  19:05 Найти цитируемый пост)
еслиб парочка конкретных примеров была бы потребованиям, то можно было бы думать.. а так остается только перечислить подходы, и напомнить что может выйграть не чистый вид, а комбинация.. 

Операций свыше десятка, объектов тоже немало, я затрудняюсь ответить чего здесь больше.
Желательно максимально облегчить труд другим группам, при добавлении новых объектов, но при этом не потерять красоты решения.
Я сейчас не вспомню все типов и операций, но пусть это будет десяток объектов и операции copy, move, rotate, scale, split, save.
Новые команды в принципе добавляются не так часто, объекты тоже, но объекты в основном добавляются совершенно другой группой и труд им желательно максимально облегчить, будет не совсем приятно заставлять их копаться в наших посетителях, это все таки фреймворк и должен предоставлять удобные средства для расширения.

Цитата(spyswamp @  10.11.2011,  18:23 Найти цитируемый пост)
Голосую за полиморфизм

А я ни о чем другом и не писал, все варианты в так или иначе реализуют полиморфизм. Вопрос в том, как его реализовать.

Цитата(mes @  10.11.2011,  19:05 Найти цитируемый пост)
может выйграть не чистый вид, а комбинация

Вот об этом я и думаю, как бы скомбинировать.

Цитата(spyswamp @  10.11.2011,  18:23 Найти цитируемый пост)
Подход должен быть удобный в использовании и очевидный при чтении

Полиморфизм в голом виде здесь лишь будет засорять интерфейс базового класса, тем более, что не объекты не будут поддерживать все возможные операции. Скажем объект типа point нельзя переворачивать или масштабировать.
PM   Вверх
mes
Дата 10.11.2011, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  10.11.2011,  20:24 Найти цитируемый пост)
Операций свыше десятка, объектов тоже немало, я затрудняюсь ответить чего здесь больше.
Желательно максимально облегчить труд другим группам, при добавлении новых объектов, но при этом не потерять красоты решения.

какая задача все таки стоит перед фреймворком ?  математические расчеты, визуальный редактор или что то другое ?

Добавлено через 2 минуты и 35 секунд
какие принципиально отличительные от геометрических фигур бывают объекты, которые разделяют с мими часть команд ?



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 10.11.2011, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  10.11.2011,  21:33 Найти цитируемый пост)
какая задача все таки стоит перед фреймворком ?  математические расчеты, визуальный редактор или что то другое ?

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

Цитата(mes @  10.11.2011,  21:33 Найти цитируемый пост)
какие принципиально отличительные от геометрических фигур бывают объекты, которые разделяют с мими часть команд ?

это могут быть линейки, флаги, тексты и тому подобное. Другими словами - объекты для разметки.

Это сообщение отредактировал(а) azesmcar - 10.11.2011, 21:53
PM   Вверх
spyswamp
Дата 10.11.2011, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 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'
PM MAIL   Вверх
mes
Дата 10.11.2011, 23:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



тогда делить надо не по сущностям, а по функционалу.. 

например так :

Код

struct figure_kind
{
     bool moveable;
     bool rotateable;  
     uint figure_uid;
};

struct figure_render 
{
   void draw (figure_block const& block)
   {
       _map[block.get_figure_uid] (block);
   }
   
   std::map<uint, figure_render_method*> _map;
};


struct figure_block {

      bool can_move () const;
      void move ();
      
      bool can_rotate () const;
      void rotate ();
      
      figure_block (figure_kind const&)..

   private:           
      figure_kind figure_kind;      
};

namespace figure_kind_type {

figure_kind point = { true, false, 0001  },
            rect  = { true, true,  0100  },
            circle = { true, true, 0200  };



}

на скорую руку но суть я думаю видна.. 


Добавлено @ 23:56
Цитата(spyswamp @  10.11.2011,  22:24 Найти цитируемый пост)
кроме метода, скажем, draw? 

а должен ли быть этот метод, тоже вопрос..


Это сообщение отредактировал(а) mes - 11.11.2011, 01:45


--------------------
PM MAIL WWW   Вверх
mes
Дата 11.11.2011, 00:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



1. выделено понятие блок с которым можно проводить некоторе кол-во операций
2. возможность операций определяется дескриптором
3. позволено создание нового типа фигуры, путем определения дескриптора
и регистрации необходимых методов, как например figure_render_method..
4. uid  позволяет связывать методы разных производителей.. 




--------------------
PM MAIL WWW   Вверх
baldina
Дата 11.11.2011, 00:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



когда возможно расширение и классов и методов помогает аспектно-ориентированный подход. для него, увы, нет достаточных средств в С++ (да и во многих других популярных языках) поэтому применяются препроцессоры типа AspectC++ и иже с ими.
если задача не слишком сложна, можно привлечь метапрограммирование шаблонов.
если есть явный перекос в сторону расширения объектов (либо методов), то принимается одно из соответствующих решений, остальное врукопашную.
в данном случае похоже объекты будут чаще добавляться, чем методы.
Цитата(azesmcar @  10.11.2011,  17:36 Найти цитируемый пост)
query interface
 в этом случае как-то не очень...

PM MAIL   Вверх
azesmcar
Дата 11.11.2011, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  10.11.2011,  23:54 Найти цитируемый пост)
тогда делить надо не по сущностям, а по функционалу.. 

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

Цитата(Earnest @  10.11.2011,  19:24 Найти цитируемый пост)
Т.е. нужно строить код так, чтобы "чужие" ковырялись только в собственном... 

согласен smile 
потому чистый visitor не подходит.

Цитата(Earnest @  10.11.2011,  19:00 Найти цитируемый пост)
Поэтому можно совместить ежа с ужом, т.е. засунуть это дело в визитера, который может содержать методы для всех "стабильных" объектов, а может switch, а может просто преобразовывать obj к IMove... 

Думаю такое разделение на "стабильных" и не "стабильных" сильно затруднит понимание и чтение кода.

Цитата(baldina @  11.11.2011,  00:27 Найти цитируемый пост)
если задача не слишком сложна, можно привлечь метапрограммирование шаблонов.

проект огромен, так что задача сложна smile 

Цитата(baldina @  11.11.2011,  00:27 Найти цитируемый пост)
 в этом случае как-то не очень...

по какой причине?

Цитата(baldina @  11.11.2011,  00:27 Найти цитируемый пост)
в данном случае похоже объекты будут чаще добавляться, чем методы.

Сложно сказать. У нас редко добавляется и то и другое, но скорее всего так и есть. Методы добавляются редко, объекты добавляют другие, так-что мы часто и не в курсе, это уже другой продукт.

Цитата(mes @  10.11.2011,  23:54 Найти цитируемый пост)
а должен ли быть этот метод, тоже вопрос..

нет, но это уже совсем другая задача.


Это сообщение отредактировал(а) azesmcar - 11.11.2011, 09:36
PM   Вверх
mes
Дата 11.11.2011, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  08:26 Найти цитируемый пост)
Тогда модификация какой либо конкретно функции превращается в кошмар.
Например чтобы изменить функцию копирования, в этом случае придется модифицировать код в каждом классе.

 smile кто то кого то не понимает или оба друг друга.. 



--------------------
PM MAIL WWW   Вверх
math64
Дата 11.11.2011, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Код

class Visitor;
class GObject {
public:
virtual void visit(Visitor* v) = 0;
};

class IMovable {
public:
};

class IRotatable {
public:
};

class Visitor
{
public:
virtual void visit(GObject* g, IMovable* m = NULL, IRotatable* r = NULL, bool after = false) = 0;
};

class Rect : public GObject, public IMovable {
public:
virtual void visit(Visitor* v) { v->Visit(this, this, NULL); }
};

class Poligon : public GObject, public IMovable, public IRotatable {
public:
virtual void visit(Visitor* v) { v->Visit(this, this, this); }
};
class Unmovable : public GObject {
public:
virtual void visit(Visitor* v) { v->Visit(this, NULL, NULL); }
};
class Group : public GObject {
public:
virtual void visit(Visitor* v) {
 v->Visit(this, NULL, NULL, false); 
 for(list<GObject*>::iterator i = childs.begin(); i != childs.end(); ++i)
   (*i)->visit(v);
 v->Visit(this, NULL, NULL, true); 
}
private:
list<GObject*> childs;
};


Это сообщение отредактировал(а) math64 - 11.11.2011, 10:01
PM   Вверх
mes
Дата 11.11.2011, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  08:26 Найти цитируемый пост)
по какой причине?

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



--------------------
PM MAIL WWW   Вверх
newbee
Дата 11.11.2011, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: 4
Всего: 19



Я наверное не поняла всю сложность задачи,.. потому что по-моему все просто. Каждому типу объекта задается уникальный идентификатор. Далее регистрируем наборы функций для каждого типа (устанавливаем соответствие идентификатор-типа -> функция-делания-чего-то). Теперь общая функция, например copy, будет смотреть, какой объект к ней пришел, и вызывать соответствующую ему функцию копирования или пытаться выполнить какую-то операцию по умолчанию (попытаться самой провести копирование, или бросить эксепшн Ахтунг, или еще что-нибудь).


--------------------
You're face to face
With man who sold the world
PM   Вверх
azesmcar
Дата 11.11.2011, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  11.11.2011,  09:42 Найти цитируемый пост)
 smile кто то кого то не понимает или оба друг друга.. 

если разделить функции по сущностям, тогда каждая сущность будет иметь свою функцию копирования, пусть в Вашем примере она не будет засорять интерфейс основного класса, но тем не менее она привязана к сущности, а значит для изменения конкретной функции для всех сущностей, придется менять все классы.
Конечно, с другой стороны, если сделать через что-то вроде visitor-а и придется менять все функции для конкретной сущности, тогда возникнет та же проблема, но это редкость, не думаю, что такое вообще может понадобиться.
PM   Вверх
mes
Дата 11.11.2011, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



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

Добавлено через 6 минут и 21 секунду
Цитата(azesmcar @  11.11.2011,  08:50 Найти цитируемый пост)
но тем не менее она привязана к сущности, а значит для изменения конкретной функции для всех сущностей, придется менять все классы.

если смешаете обработку команд и логику фигур в одно месиво, да придется.. (только я этого не предлогал)

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

Добавлено через 10 минут и 45 секунд
Цитата(azesmcar @  11.11.2011,  08:26 Найти цитируемый пост)
проект огромен, так что задача сложна

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




--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 11.11.2011, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



math64
Этих IMovable, IRotatable и всего остального будет слишком много, чтобы пихать их в параметры функции.

Цитата(mes @  11.11.2011,  09:46 Найти цитируемый пост)
при наличии стабильности в командах, стоит выбирать второй подход, так как первый вызывает в этом случае нагромождение.. 

Мне самом не нравится, просто интересует и Ваше мнение. Мне оно не нравится по той же причине.

Цитата(mes @  11.11.2011,  09:46 Найти цитируемый пост)
не забывать опять таки то про комбинацию 

Про какую? smile 

Цитата(newbee @  11.11.2011,  09:46 Найти цитируемый пост)
Я наверное не поняла всю сложность задачи

А ничего сложного в самой задаче нету, сложность в выборе правильного решения smile 

Цитата(newbee @  11.11.2011,  09:46 Найти цитируемый пост)
Далее регистрируем наборы функций для каждого типа (устанавливаем соответствие идентификатор-типа -> функция-делания-чего-то). Теперь общая функция, например copy, будет смотреть, какой объект к ней пришел, и вызывать соответствующую ему функцию копирования или пытаться выполнить какую-то операцию по умолчанию 

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

Добавлено через 3 минуты и 10 секунд
Цитата(mes @  11.11.2011,  09:51 Найти цитируемый пост)
еще одно, делите на слои..  так для визуального редактора явно выделяются два :
модели фигур и контролеры их взаимодействия с пользователем.. 
соотношение сущностей не прямое.. то есть на каждую фигуру свой контролер - плохо..

Это все уже давно сделано, система спроектирована давно и существует на протяжении многих лет. Хорошо или плохо, но менять ее никто не собирается, но конкретно часть с редактированием сделана просто ужасно, потому было решено предоставить мне немного времени на редизайн, чтобы я не свихнулся, сопровождая это недоразумение.
PM   Вверх
mes
Дата 11.11.2011, 10:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  09:09 Найти цитируемый пост)
Ничем не лучше visitor-а, 

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



--------------------
PM MAIL WWW   Вверх
math64
Дата 11.11.2011, 10:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Цитата(azesmcar @  11.11.2011,  10:09 Найти цитируемый пост)
Этих IMovable, IRotatable и всего остального будет слишком много, чтобы пихать их в параметры функции.

Можешь реализовать и с отдельными visit(IMovable), visit(IRotatable), и т.д.  - eсли не смущает то, что если объект поддерживает несколько интерфейсов, visit() придётся вызывать несколько раз, по разу для каждого интерфейса.
Главное определить набор интерфейсов так, чтобы при добавлении нового класса не нужно было добавлять нового интерфейса.

PM   Вверх
spyswamp
Дата 11.11.2011, 10:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 349
Регистрация: 18.8.2006

Репутация: 1
Всего: 7



Такое ощущение, что кто-то недавно прочитал про Visitor и сразу бросился им загромождать код. -) Уж извините, такое впечатление сложилось.


--------------------
- why you call it beta?
- cuz it's betta then nothin'
PM MAIL   Вверх
baldina
Дата 11.11.2011, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(azesmcar @  11.11.2011,  09:26 Найти цитируемый пост)
проект огромен, так что задача сложна

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

Цитата(baldina @  11.11.2011,  00:27 Найти цитируемый пост)
Цитата(azesmcar @  10.11.2011,  17:36 )
query interface
 в этом случае как-то не очень...

если методы добавляются редко лучше использовать visitor. query interface-подобные решения не дают возможности привычного статического контроля.

Цитата(azesmcar @  11.11.2011,  09:26 Найти цитируемый пост)
 объекты добавляют другие, так-что мы часто и не в курсе

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

Добавлено через 2 минуты и 47 секунд
Цитата(azesmcar @  11.11.2011,  10:09 Найти цитируемый пост)
Это все уже давно сделано, система спроектирована давно и существует на протяжении многих лет. Хорошо или плохо, но менять ее никто не собирается, но конкретно часть с редактированием сделана просто ужасно, потому было решено предоставить мне немного времени на редизайн, чтобы я не свихнулся, сопровождая это недоразумение. 

мне нравится способ, примененный в boost::operators.

Добавлено через 3 минуты и 39 секунд
при  таком подходе вам при добавлении метода надо будет только поменять шаблоны.

PM MAIL   Вверх
azesmcar
Дата 11.11.2011, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(spyswamp @  11.11.2011,  10:33 Найти цитируемый пост)
Такое ощущение, что кто-то недавно прочитал про Visitor и сразу бросился им загромождать код. -) Уж извините, такое впечатление сложилось. 

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

Цитата(mes @  11.11.2011,  10:14 Найти цитируемый пост)
упущена одна деталь.. проблема классического визитора в том что он замкнут на типы языка.. 

не совсем понял.

Цитата(baldina @  11.11.2011,  10:35 Найти цитируемый пост)
Вам виднее, но второе не обязательно следствие первого. смотря что под огромностью проекта понимается. тут вопрос в архитектурной сложности и количестве классов, а не количестве строк.

имелось ввиду, что и классов и функций достаточно много.

Цитата(baldina @  11.11.2011,  10:35 Найти цитируемый пост)
тем более на объектах надо сконцентрироваться, что бы пользователям продукта предоставить более удобные и надежные средства

т.е. Вы за
Цитата(baldina @  11.11.2011,  10:35 Найти цитируемый пост)
лучше использовать visitor

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

Цитата(baldina @  11.11.2011,  10:35 Найти цитируемый пост)
мне нравится способ, примененный в boost::operators.

Вы про CRTP? А как это здесь поможет?

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


Это сообщение отредактировал(а) azesmcar - 11.11.2011, 10:59
PM   Вверх
newbee
Дата 11.11.2011, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: 4
Всего: 19



Цитата(azesmcar @  11.11.2011,  11:55 Найти цитируемый пост)
не совсем понял.
Ты не связан статической системой типов языка. Ты сделаешь свою маленькую динамическую.


--------------------
You're face to face
With man who sold the world
PM   Вверх
math64
Дата 11.11.2011, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Читал котда-то давно статью в "Мир ПК", в каком номере не помню, про модифакцию патерна Visitor с возможностью добавления новых посещаемых классов, но реализация довольно сложная - для того, чтобы пользоваться новыми классами в модифицированном Visitor. их нужно регистрировать.
PM   Вверх
Earnest
Дата 11.11.2011, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(math64 @  11.11.2011,  12:08 Найти цитируемый пост)
 но реализация довольно сложная - для того, чтобы пользоваться новыми классами в модифицированном Visitor. их нужно регистрировать. 

Регистратор прикрутить как раз несложно. Но проблема в том, что при добавлении нового типа объектов, существующие визиторы о них ничего не узнают (кроме факта существования, регистрация ничего не добавит). Как сделать DoSomething с объектом неизвестной породы? Только вызвать его соответствующий виртуальный метод. А методы плодить на все случаи жизни не хочется. Можно сделать что-то типа Invoke с параметром "заданное действие". И пусть объект решает, поддерживает он это действие или ну его нафик. Вот только действие передавать придется либо идентификатором, либо каким-то классом-тэгом и в конечной реализации возникнут if или switch...




--------------------
...
PM   Вверх
baldina
Дата 11.11.2011, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(azesmcar @  11.11.2011,  10:55 Найти цитируемый пост)
т.е. Вы за
Цитата(baldina @  11.11.2011,  10:35 )
лучше использовать visitor

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

если я правильно понял, пользователи будут реализовывать классы, а набор операций предопределен (и может меняться от версии к версии).
тогда пользователь в классе просто реализует виртуальные функции, query_interface  не нужен.

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

Цитата(azesmcar @  11.11.2011,  10:55 Найти цитируемый пост)
Вы про CRTP? 

я не про механизм CRTP, я про идею расширения класса методами (которая может использовать CRTP как средство, но может и иначе).
у авторов boost::operators, на мой взгляд, получилось изящно.
PM MAIL   Вверх
azesmcar
Дата 11.11.2011, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(baldina @  11.11.2011,  12:01 Найти цитируемый пост)
если я правильно понял, пользователи будут реализовывать классы, а набор операций предопределен (и может меняться от версии к версии).

нет, они определяют типы и операции с ними.

Цитата(baldina @  11.11.2011,  12:01 Найти цитируемый пост)
тогда пользователь в классе просто реализует виртуальные функции

т.е. в итоге получается, что базовый интерфейс должен поддерживать операции move, rotate, copy ... и так далее, или должны быть интерфейсы imovable, irotatable, icopyable...
а пользователь сам решает, какие интерфейсы он будет поддерживать. Это приводит нас опять таки к query interface, в том или ином виде.

Цитата(baldina @  11.11.2011,  12:01 Найти цитируемый пост)
я не про механизм CRTP, я про идею расширения класса методами (которая может использовать CRTP как средство, но может и иначе).

не совсем представляю как это можно применить к текущей задаче?

Это сообщение отредактировал(а) azesmcar - 11.11.2011, 12:14
PM   Вверх
baldina
Дата 11.11.2011, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(azesmcar @  11.11.2011,  12:09 Найти цитируемый пост)
они определяют типы и операции с ними

видимо я не вполне понял Вашу задачу. прочитал еще раз, внимательно, но нового не увидел.

давайте на примере:
пользователь определил новый тип объекта "пирог" и операцию над ним "съесть"

как ваш базовый интерфейс узнает об этом методе? или все-таки методы определяет фреймворк, а пользовательские классы его реализуют (или не реализуют)?
PM MAIL   Вверх
azesmcar
Дата 11.11.2011, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(baldina @  11.11.2011,  14:02 Найти цитируемый пост)
как ваш базовый интерфейс узнает об этом методе? или все-таки методы определяет фреймворк, а пользовательские классы его реализуют (или не реализуют)? 

методы определяет фреймворк, пользователи его либо реализуют, либо нет.

Попробую упростить задачу до примера.

Начну с нуля.

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

Вот иерархия классов:
Цитата

figure_base
   rectangle
   polygon
   circle
   text
   ruler


С объектами можно производить некоторые операции, например копировать или перемещать. Возьмем для примера копирование.
Копирование по сути это текстовая сериализация объекта, далее этот текст помещается в буфер обмена.
Далее.
Группа B используется библиотеку в своем проекте, они добавлают новый тип объектов - точка. Они добавляют свой класс, наследник от figure_base и регистрируют его в библиотеке, далее они должны реализовать копирование объекта типа point.
Теперь о реализации.
Реализовать это можно многими способами, дело в том, чтобы выбрать самый подходящий.

1. Самый тупой способ - поместить все возможные функции в базовый класс figure_base, т.е. поместить туда функцию copy с default реализацией.
Код

virtual std::string copy() { throw std::runtime_error("not implemented"); };

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

2. Более цивильный способ, разделить все на интерфейсы, т.е. добавить интерфейс icopyable, imovable... и так далее, а потом проверять, реализует ли класс этот интерфейс с помощью dynamic_cast-а. В итоге получается queryInterface. Недостаток подхода в том, что получается нагромождение всех функций в одном классе, который должен поддерживать и перемещение и копирование и поворот и многое другое. Чем больше функций, тем больше нагромождение, хотя интерфейс базового класса в этом случае не засоряется. Еще один минус подхода в медленной работе самого dynamic_cast-а.

3. С помощью вышеупомянутого шаблона visitor. В принципе все удобно, все разделено по функциональности, надо поменять функцию copy - меняем один класс, можно добавлять функции не меняя интерфейс самих классов. Недостаток в данном случае заключается в том, что при реализации копирование для объектов типа point, программисту придется лезть в нашу библиотеку и менять исходники, что не очень приятно. Желательно, чтобы его расширение было самодостаточно и не требовало модификаций нашего кода.

Надеюсь смог нормально описать.


Это сообщение отредактировал(а) azesmcar - 11.11.2011, 14:25
PM   Вверх
mes
Дата 11.11.2011, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Earnest @  11.11.2011,  10:46 Найти цитируемый пост)
и в конечной реализации возникнут if или switch..

или таблицы.. 

Цитата(newbee @  11.11.2011,  10:06 Найти цитируемый пост)
. Ты сделаешь свою маленькую динамическую. 

 smile , если надо чтоб "визетеры" могли быть динамически расширяемыми..

Добавлено через 3 минуты и 29 секунд
Цитата(Earnest @  11.11.2011,  10:46 Найти цитируемый пост)
. Но проблема в том, что при добавлении нового типа объектов, существующие визиторы о них ничего не узнают

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

Добавлено через 5 минут и 59 секунд
Цитата(azesmcar @  11.11.2011,  11:09 Найти цитируемый пост)
 и так далее, или должны быть интерфейсы imovable, irotatable, icopyable...
а пользователь сам решает, какие интерфейсы он будет поддерживать

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



--------------------
PM MAIL WWW   Вверх
math64
Дата 11.11.2011, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Нет, регистрировался не просто класс, а связка его с методом Посетителя - точно не помню как.
Что-то похожее на это (но вряд ли это):
Код

template <typename Visitor, typename Visitable> class Register {
void visit(Visitor* visitor, Visitable* visitable) { visitor->visit(visitable); }
};


PM   Вверх
baldina
Дата 11.11.2011, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(azesmcar @  11.11.2011,  14:22 Найти цитируемый пост)
методы определяет фреймворк, пользователи его либо реализуют, либо нет.

я так и предполагал. тогда достаточно объявить виртуальные методы в базовом классе.

Цитата(azesmcar @  11.11.2011,  14:22 Найти цитируемый пост)
недостаток этого подхода в том, что интерфейс базового класса засоряется.

конечно. для решения этой проблемы существует классификация и декомпозиция. 

почитал дальше, вроде разобрался)))

кажется, проблема заключается не в наследовании и операциях, а в том, о чем Вы не упоминаете: операции производятся ядром над объектами базового класса, и нет возможности узнать какие именно интерфейсы реализуются классом.
скажем, end-user выбирает правой кнопкой мыши объект, и контекстное меню должно отобразить доступные операции.
если новые объекты подключаются на этапе компиляции, это можно решить статической проверкой. остальное сделает компилятор. 
если интерфейс нужно определять динамически, то либо callback (эдакие динамические visitorы) либо query-interface. принципиальной разницы в этом случае не вижу.

если я все правильно понял, и речь идет о статической задаче (периода компиляции), то MP (типа is_function_member<>)

Добавлено через 2 минуты и 32 секунды
а статические посетители применяются, если набор операций не предопределен. у Вас это не так
PM MAIL   Вверх
mes
Дата 11.11.2011, 14:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  13:22 Найти цитируемый пост)
Надеюсь смог нормально описать.

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



--------------------
PM MAIL WWW   Вверх
baldina
Дата 11.11.2011, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(mes @  11.11.2011,  14:41 Найти цитируемый пост)
если исходить из классического представления с ориентировкой на объекты, то толку от регистрации в принципе не.. но если сделать ориентировку на методы (не функции челены, а методы алгоритма) то будет понятно что где и как регистрировать..

угу. но на самом деле тут нет одного, "правильного" взгляда. нужно несколько иерархий одновременно, в том и проблема. я потому и упоминал аспектный подход.
PM MAIL   Вверх
mes
Дата 11.11.2011, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  13:22 Найти цитируемый пост)
Допустим есть библиотека для работы с геометрическими объектами .

о полиморфности ни слова.. 

Цитата(azesmcar @  11.11.2011,  13:22 Найти цитируемый пост)
 Они добавляют свой класс, наследник от figure_base и регистрируют его в библиотеке, далее они должны реализовать копирование объекта типа point.

динамически добавляют ?
Цитата(azesmcar @  11.11.2011,  13:22 Найти цитируемый пост)
. Самый тупой способ, Более цивильный способ, с помощью умянутого шаблона visitor

у всех трех способов есть очевидный недостаток, это жесткая завязанность на системе типов.. 
второй недостаток, все в одной яме

Добавлено через 1 минуту и 2 секунды
Цитата(baldina @  11.11.2011,  13:59 Найти цитируемый пост)
в том и проблема. я потому и упоминал аспектный подход. 

про АОП читал, но пока его не понимаю, поэтому в этой связи ничего не могу сказать..

Добавлено через 2 минуты и 18 секунд
Цитата(baldina @  11.11.2011,  13:59 Найти цитируемый пост)
нет одного, "правильного" взгляда

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



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 11.11.2011, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  11.11.2011,  15:02 Найти цитируемый пост)
о полиморфности ни слова.. 

А какие здесь нужны слова?

Цитата(mes @  11.11.2011,  15:02 Найти цитируемый пост)
динамически добавляют ?

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

Цитата(mes @  11.11.2011,  15:02 Найти цитируемый пост)
угу нету.. но есть пара деталей, о которых забывает тс, и поэтому не может связать задачу с подходящем решением.. именно на них я и пытаюсь сконцентрировать внимание.. 

На данный момент я не вижу подходящего решения, чтобы связать с ней задачу smile

Добавлено через 1 минуту и 56 секунд
Цитата(baldina @  11.11.2011,  14:48 Найти цитируемый пост)
кажется, проблема заключается не в наследовании и операциях, а в том, о чем Вы не упоминаете: операции производятся ядром над объектами базового класса, и нет возможности узнать какие именно интерфейсы реализуются классом.

не совсем понял мысль. Почему нет такой возможности? Есть dynamic_cast. На данный момент так и сделано, проверяется реальный тип и вызывается соответствующая функция для этого типа. Цель как раз в том, чтобы избавиться от этого.

Добавлено через 2 минуты и 57 секунд
Цитата(mes @  11.11.2011,  15:02 Найти цитируемый пост)
у всех трех способов есть очевидный недостаток, это жесткая завязанность на системе типов.. 

ну предложите четвертый, мне мои 3 тоже не нравятся smile 
PM   Вверх
mes
Дата 11.11.2011, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  13:22 Найти цитируемый пост)
С объектами можно производить некоторые операции, например копировать или перемещать. Возьмем для примера копирование.
Копирование по сути это текстовая сериализация объекта, далее этот текст помещается в буфер обмена.

немножко переформулирую.. 

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

так правильно ?




--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 11.11.2011, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(baldina @  11.11.2011,  14:59 Найти цитируемый пост)
угу. но на самом деле тут нет одного, "правильного" взгляда. нужно несколько иерархий одновременно, в том и проблема. я потому и упоминал аспектный подход. 

потом почитаю для интереса, во всяком случае как я понимаю решению задачи это не поможет?
PM   Вверх
mes
Дата 11.11.2011, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  14:08 Найти цитируемый пост)
Нет, статически добавляют и сами же используют. Расширяют библиотеку для своих целей, нас это не касается.

и при добавлении вынуждены перекомпилировать библиотеку ? или ж это не желательно ?



Это сообщение отредактировал(а) mes - 11.11.2011, 15:20


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 11.11.2011, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  11.11.2011,  15:17 Найти цитируемый пост)
и при добавлении вынуждены перекомпилировать библиотеку ? или ж это не желательно ?

А зачем это нужно? Они же не меняют наших исходников.
PM   Вверх
mes
Дата 11.11.2011, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  14:19 Найти цитируемый пост)
А зачем это нужно? Они же не меняют наших исходников. 

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

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



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 11.11.2011, 15:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  11.11.2011,  15:22 Найти цитируемый пост)
со статическим контролем не получится без изменения кода, просто его можно организовать так, чтоб не лезле в ваш, а просто добавляли свои исходники..

а, в этом смысле...ну в принципе не желательно, но это возможно.
PM   Вверх
mes
Дата 11.11.2011, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  14:23 Найти цитируемый пост)
ну в принципе не желательно, но это возможно. 

так все ж в каком направлении думать ?  для меня например желательно знать заранее..

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




Это сообщение отредактировал(а) mes - 11.11.2011, 15:32


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 11.11.2011, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  11.11.2011,  15:25 Найти цитируемый пост)
если остановитесь на статическом, то Александреску разбирает в одной из своих книг (в какой сейчас не помню) генерацию визитеров по списку типов.. 

На мой взгляд динамически было бы правильнее в данной ситуации.
PM   Вверх
mes
Дата 11.11.2011, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  14:45 Найти цитируемый пост)
На мой взгляд динамически было бы правильнее в данной ситуации. 

угу тем более что  библиотека для работы с полиморфными объектами..

Добавлено через 2 минуты и 35 секунд
но тогда надо будет ввести свою систему типов.. (или просто uid, если предполагается взаимодействие выходящее за границы приложения.. например по сети)


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 11.11.2011, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  11.11.2011,  15:55 Найти цитируемый пост)
но тогда надо будет ввести свою систему типов.. (или просто uid, если предполагается взаимодействие выходящее за границы приложения.. например по сети) 

т.е. query_interface?

Добавлено через 1 минуту и 47 секунд
Цитата(mes @  11.11.2011,  15:55 Найти цитируемый пост)
если предполагается взаимодействие выходящее за границы приложения.. например по сети

нет, этого не предполагается.

PM   Вверх
baldina
Дата 11.11.2011, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(azesmcar @  11.11.2011,  15:08 Найти цитируемый пост)
Почему нет такой возможности? Есть dynamic_cast.

это можно, да. но это уже не полиморфизм, а огромный switch. если бы он Вам нравился, темы не было б
С++ статически типизирован, а dynamic_cast не добавляет динамичности в полной мере, эт только костыль

Цитата(azesmcar @  11.11.2011,  15:12 Найти цитируемый пост)
 как я понимаю решению задачи это не поможет? 

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

Цитата(mes @  11.11.2011,  15:22 Найти цитируемый пост)
Цитата(azesmcar @  11.11.2011,  14:19 )
А зачем это нужно? Они же не меняют наших исходников. 

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

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

Йес!!  smile я о том и говорил. 
хорошо бы иметь больше информации об архитектуре проекта, о том как фреймворк связывается с кодом пользователей.
Если пользователи просто пишут расширения к откомпилированному коду, видимо без query-interface в каком-то его виде не обойтись. изобретёте еще один COM.
когда я приводил в пример boost::operators, имелось в виду, что проект компилируется целиком, т.е. ваш код и пользовательский

Добавлено через 2 минуты и 47 секунд
а, еще...
если пользователи добавляют расширения к откомпилированному коду в виде откомпилированного кода, т.е. интерфейс предопределен и неизменен, то никакой АОП не поможет.
точнее, он поможет Вам как разработчику при внесении изменений/расширений в проект, но с точки зрения пользователей ничего не изменится
PM MAIL   Вверх
azesmcar
Дата 11.11.2011, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(baldina @  11.11.2011,  16:22 Найти цитируемый пост)
хорошо бы иметь больше информации об архитектуре проекта, о том как фреймворк связывается с кодом пользователей.


Дело в том, что на данный момент никто не с чем ничего не связывает, если кому-то что-то нужно, это делаем мы. smile 
Вот мы и хотим взвалить ненужную нам работу на чужие плечи. А как - это уже другое дело.
У них есть заголовочные файлы и библиотеки, будет считать исходников у других нету, мы выдаем им уже готовый фреймворк.

Добавлено через 31 секунду
Цитата(baldina @  11.11.2011,  16:22 Найти цитируемый пост)
если пользователи добавляют расширения к откомпилированному коду в виде откомпилированного кода, т.е. интерфейс предопределен и неизменен, то никакой АОП не поможет.

Примерно так оно и должно быть.

Добавлено через 57 секунд
Цитата(baldina @  11.11.2011,  16:22 Найти цитируемый пост)
это можно, да. но это уже не полиморфизм, а огромный switch. если бы он Вам нравился, темы не было б

Вот именно smile 
PM   Вверх
mes
Дата 11.11.2011, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  14:08 Найти цитируемый пост)
ну предложите четвертый

http://liveworkspace.org/code/045bcd682434...0273f990d385bb7

Добавлено через 3 минуты и 40 секунд
a, b пользовательские типы.. пользователь также должен до использования своих типов проивести регистрацию (init)..
писалась на скорую руку, чтоб передать идею..  также использовал голый ид, но можно это приукрасить, если нижно..

Добавлено через 5 минут и 44 секунды
пример - база для реализации алгоритмов copy/paste..

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



--------------------
PM MAIL WWW   Вверх
baldina
Дата 11.11.2011, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата

std::map<int, void(*)(object const&) > methods;

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

Добавлено через 3 минуты и 51 секунду
Цитата(mes @  11.11.2011,  15:25 Найти цитируемый пост)
 генерацию визитеров по списку типов.
 это АОП-way
PM MAIL   Вверх
mes
Дата 11.11.2011, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(baldina @  11.11.2011,  16:08 Найти цитируемый пост)
 но это уже внеязыковые средства.

а у С++ вообще с динамикой плохо, хорошо что руки не связывает и позволяет выкрутится обходными вариантами..



--------------------
PM MAIL WWW   Вверх
mes
Дата 11.11.2011, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(baldina @  11.11.2011,  16:08 Найти цитируемый пост)
 это АОП-way 

 ну тогда можно притянуть его и сюда 
Цитата

  serialize.reg<a> ();
  serialize.reg<b> ();

разгрузив через список типов..  smile  

где то так :
http://liveworkspace.org/code/0532d48b65fd...f0e78f2ba25ee9f

Это сообщение отредактировал(а) mes - 11.11.2011, 17:52


--------------------
PM MAIL WWW   Вверх
baldina
Дата 11.11.2011, 17:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



azesmcar, медитирую над этим примером
Цитата(azesmcar @  10.11.2011,  17:36 Найти цитируемый пост)
if (is_rectangle) copy_rectangle();

пытаюсь понять откуда оно возникло. вот собственный пример с контекстным меню мне ясен, понятны средства его реализации. насколько это близко к вашим "нехорошим вещам", которые делаются с объектами?
PM MAIL   Вверх
azesmcar
Дата 11.11.2011, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



mes

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

Цитата(baldina @  11.11.2011,  17:47 Найти цитируемый пост)
пытаюсь понять откуда оно возникло. вот собственный пример с контекстным меню мне ясен, понятны средства его реализации. насколько это близко к вашим "нехорошим вещам", которые делаются с объектами? 


Цитата(baldina @  11.11.2011,  17:47 Найти цитируемый пост)
пытаюсь понять откуда оно возникло

не понял вопроса. что откуда возникло?
PM   Вверх
mes
Дата 11.11.2011, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  16:54 Найти цитируемый пост)
немного не нравиться то, что функции по идее 

с чего это взяли ?

Добавлено через 44 секунды
Цитата(azesmcar @  11.11.2011,  16:54 Найти цитируемый пост)
 что откуда возникло? 

не понятно что делает выражение, процитированное baldina

Добавлено через 2 минуты и 37 секунд
Цитата(azesmcar @  11.11.2011,  16:54 Найти цитируемый пост)
Просматриваю, немного не нравиться

сформулируйте требования, попробую отразить в коде smile

Добавлено через 3 минуты и 31 секунду
Цитата(azesmcar @  11.11.2011,  16:54 Найти цитируемый пост)
 что функции 

функции это вы o serialize  или o serialize_fn<T> ?

Добавлено через 4 минуты и 45 секунд
Цитата(azesmcar @  11.11.2011,  16:54 Найти цитируемый пост)
быть глобально видимыми

глобальными или глобально видимыми ? 



--------------------
PM MAIL WWW   Вверх
baldina
Дата 11.11.2011, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(mes @  11.11.2011,  17:55 Найти цитируемый пост)
не понятно что делает выражение, процитированное baldina

что делает выражение, понятно. не понятно, какую задачу оно решает.
Цитата(mes @  11.11.2011,  17:55 Найти цитируемый пост)
сформулируйте требования

собственно и я об этом. хочу понять задачу

PM MAIL   Вверх
math64
Дата 11.11.2011, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Если в ваш пример с сериализатором переписать так, чтобы можно было его использовать не только с сериализатором, но и с перемещением, вращением, перекрашиванием и др. визиторами (но избавившись от getId() ) - получится примерно то, что было в журнале "Мир ПК"

PM   Вверх
mes
Дата 11.11.2011, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



подкорректируем задачу.. 

есть команда print и есть несколько групп объект ов разных производителей.. 
задача:
1. позволить динамическое подключение каждой групы объектов
2. избежать зависимость между группами
3. внутри группы позволить использовать средства контроля типов


Это сообщение отредактировал(а) mes - 11.11.2011, 22:05


--------------------
PM MAIL WWW   Вверх
mes
Дата 11.11.2011, 22:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



вот решение с комбинацией различных подходов :
http://liveworkspace.org/code/6148d7bc1a09...f9f74430ebd53c4

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




--------------------
PM MAIL WWW   Вверх
mes
Дата 11.11.2011, 23:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



немного изменил завязку (регистрацию),  пододвинув ее в сторону си идеологии :
http://liveworkspace.org/code/c76143b44b1e...126584d06c5f01f

Это сообщение отредактировал(а) mes - 11.11.2011, 23:13


--------------------
PM MAIL WWW   Вверх
math64
Дата 11.11.2011, 23:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



уже лучше - регистрировать нужно не отдельные классы, а модули.
PM   Вверх
boostcoder
Дата 11.11.2011, 23:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(mes @  11.11.2011,  23:12 Найти цитируемый пост)
немного изменил завязку (регистрацию),  пододвинув ее в сторону си идеологии :
http://liveworkspace.org/code/c76143b44b1e...126584d06c5f01f

отличная идея! правда для моей задачи ;)
PM WWW   Вверх
mes
Дата 11.11.2011, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(math64 @  11.11.2011,  22:32 Найти цитируемый пост)
уже лучше - регистрировать нужно не отдельные классы, а модули. 

math64, какую задачу озвучил, ту и решал smile

а регистрятся, кстати, не классы, а колбяк-функции smile


Это сообщение отредактировал(а) mes - 11.11.2011, 23:55


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 12.11.2011, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



mes

Из дома сложновато бывает засесть за компьютер, попробую сегодня посмотреть и отписаться.
Спасибо за старания.
PM   Вверх
math64
Дата 12.11.2011, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Цитата(mes @  11.11.2011,  23:52 Найти цитируемый пост)
а регистрятся, кстати, не классы, а колбяк-функции

но раньше нужно было регистрировать по одному callback'у на функцию, теперь - на модуль. Внутри модуля используется обычный Vsitor.
А задача была поставлена немного не такая.
Регистрацию пожно проводить примерно так (не тестировал, могут быть ошибки):
Код

namespace lib {
  struct object {
    virtual int getGroupId() = 0;
  };
  struct task {
    virtual int getTaskId() = 0;
  };
  struct RegisterBase {
    virtual void doApply(task&, object&) = 0;
    RegisterBase(int taskId, int groupId) { registry[index(taskId, groupId)] = this; }
    static std::map<int,Register*> registry;
    static void apply(task& t, object& o) { registry[index(t.getTaskId(), o.getObjectId()]->doApply(t, o); }
  private:
    int index(int taskId, int groupId) { return ((taskId << 16)&0xFFFF0000) | (groupId&0xFFFF); }
  };
  template<typename tsk, int groupId>
    struct Register {
      virtual void doApply(task& t, object& o) { apply(dynamic_cast<tsk&>(t), o); }
      virtual void doApply(tsk&, object&) = 0;
    private:
      Register() : RegisterBase(tsk::taskId, groupId) {}
      static Register register;
    };
  template<typename tsk, int groupId> Register Register::register;
    stuct printtask : task {
      enum { taskId = 1 };
      int getTaskId() { return taskId; }
      std::ostream printer;
    };
}

namespace AA { 
   enum { groupId = 2222 };
   
   struct line;
   struct rect;
   
   struct visitor
   {
      vitual void visit (const line&);
      void visit (const rect&);
   };
   
   struct figure : lib::object
   {
      enum { groupId = AA::groupId };
      virtual int  group_id () const { return groupId; }  
      virtual void accept (visitor & v)  = 0;      
   };
   
   struct printreg : Register<lib::printtask,groupId>, visitor
   {
     virtual void doApply(lib::printtask& _pt, lib::object&) {
       pt = &_pt;
       dynamic_cast<figure const&>(obj).accept(this);
     }
     void visit (const line&) { pt->printer << "AA::line "; }
     void visit (const rect&) { pt->printer << "AA::rect "; }            
   private:
     printtask* pt;
   };

   struct line : figure
   {
      virtual void accept (visitor& v) { v.visit(*this); }
   };
   
   struct rect : figure
   {
      virtual void accept (visitor& v) { v.visit(*this); }
   };
}


PM   Вверх
mes
Дата 12.11.2011, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  11.11.2011,  08:50 Найти цитируемый пост)
если разделить функции по сущностям, тогда каждая сущность будет иметь свою функцию копирования, пусть в Вашем примере она не будет засорять интерфейс основного класса, но тем не менее она привязана к сущности, а значит для изменения конкретной функции для всех сущностей, придется менять все классы

вот пример того, о чем я говорил изначально :
http://liveworkspace.org/code/e04fcdd67b04...047a56795ec837a
или так :
http://liveworkspace.org/code/ff77f7b542c5...9f12ab7392a4504


Это сообщение отредактировал(а) mes - 12.11.2011, 16:26


--------------------
PM MAIL WWW   Вверх
mes
Дата 12.11.2011, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



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


Это сообщение отредактировал(а) mes - 12.11.2011, 15:46


--------------------
PM MAIL WWW   Вверх
math64
Дата 12.11.2011, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



mes, Ваш пример делает одно действие - print - причём только в cout.
Мой пример (он - модификация Вашего примера, и в нём есть ошибки, но их можно исправить) позволяет делать несколько действий с группой объектов.
Подключать/отключать группу ещё проще - не нужен init(), регистрация происходит автоматически при подключения модуля к проекту.

PM   Вверх
mes
Дата 12.11.2011, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(math64 @  12.11.2011,  17:35 Найти цитируемый пост)
Ваш пример делает одно действие - print - причём только в cout.

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


Цитата(math64 @  12.11.2011,  17:35 Найти цитируемый пост)
Подключать/отключать группу ещё проще - не нужен init(), 

уточню, я на ините и не настаивал.. 


Это сообщение отредактировал(а) mes - 12.11.2011, 19:54


--------------------
PM MAIL WWW   Вверх
math64
Дата 13.11.2011, 12:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Вот есть ещё такая идея  (незавершённая) - в class Visitor новые методы не добавить, а в namespace - можно
Код

namespace lib {
struct printer;
}
namespace AA {
struct rect;

namespace vistors {
void visit(const AA::rect&, lib::printer&);
}
namespace AA {
struct rect { void accept(lib::printer& p) { visitors::visit(*this, p); }

namespace BB {
struct rect;

namespace vistors {
void visit(const BB::rect&, lib::printer&);
}
namespace BB {
struct rect { void accept(printer& p) { visitors::visit(*this, p); }
}

Регистрация состоит в том, чтобы обеспечить включение всех нужных заголовков.

PM   Вверх
azesmcar
Дата 14.11.2011, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(baldina @  11.11.2011,  18:18 Найти цитируемый пост)
что делает выражение, понятно. не понятно, какую задачу оно решает.

Цитата(baldina @  11.11.2011,  18:18 Найти цитируемый пост)
собственно и я об этом. хочу понять задачу

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

В итоге выходит, что средствами C++ красивого решения придумать не получается (имеется ввиду встроенными средствами) и приходиться выкручиваться своей собственной таблицей.

mes

Спасибо. Поработаю немного над примером, посмотрим что получиться.
 smile 

Всем спасибо за участие.


Это сообщение отредактировал(а) azesmcar - 14.11.2011, 14:01
PM   Вверх
mes
Дата 14.11.2011, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  14.11.2011,  12:45 Найти цитируемый пост)
. Поработаю немного над примером, посмотрим что получиться.

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



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 14.11.2011, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  14.11.2011,  15:37 Найти цитируемый пост)
мне кажется Вы рано закрываете тему и стоило бы дать еще подробностей, ибо пример затрагивает лишь одну линию взаимотношений..

По всей видимости дорабатывать придется еще некоторое время, так-как сейчас у нас на работе гости из Штатов и шансов поработать за компьютером у нас меньше, чем можно себе представить smile 
Рабочий день проходит в основном в конференс-зале, потому на всякий случай закрыл, открою потом если что smile

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

Это сообщение отредактировал(а) azesmcar - 14.11.2011, 15:44
PM   Вверх
mes
Дата 14.11.2011, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  14.11.2011,  14:41 Найти цитируемый пост)

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

На данный момент я вижу вашу задачу так.. Есть лист на котоый могут быть положены объекты разных типов..
1. Объекты разделены по группам (фигуры, разделители, текст и т.д.)  при этом должна быть возможность динамечиски добавлять 
2. Лист предоставляет набор фиксированных действий предоставляемых над любыми объектами, и реализаторы сами решают какие команды поддерживают.. 
Это все что удалось с Вас вытянуть.. В таком изложении задача не очень большая, но внутрене чувствуются что это далеко не все..

Цитата(azesmcar @  14.11.2011,  14:41 Найти цитируемый пост)
но отбросил по причине большой нагрузки при реализации новых команд

мне кажется Вы упустили чего то.. 

Цитата(azesmcar @  14.11.2011,  14:41 Найти цитируемый пост)
По всей видимости дорабатывать придется еще некоторое время, так-как сейчас у нас на работе гости

так наоборот хорошо есть время пообсуждать..  (конечнонастаивать я не могу, просто тема заинтересовала )

Цитата(azesmcar @  14.11.2011,  14:41 Найти цитируемый пост)
Есть желание их сгруппировать, хотя пока не представляю каким образом.

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




Это сообщение отредактировал(а) mes - 14.11.2011, 16:21


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 14.11.2011, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  14.11.2011,  16:19 Найти цитируемый пост)
1. Объекты разделены по группам (фигуры, разделители, текст и т.д.)  при этом должна быть возможность динамечиски добавлять 
2. Лист предоставляет набор фиксированных действий предоставляемых над любыми объектами, и реализаторы сами решают какие команды поддерживают.. 

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

Цитата(mes @  14.11.2011,  16:19 Найти цитируемый пост)
В таком изложении задача не очень большая

Так она и не большая, большой ее делают количество операций с объектами, а задача сама небольшая, просто душа требует красивого решения smile 

Цитата(mes @  14.11.2011,  16:19 Найти цитируемый пост)
мне кажется Вы упустили чего то.. 

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

Цитата(mes @  14.11.2011,  16:19 Найти цитируемый пост)
так наоборот хорошо есть время пообсуждать

да, если получиться приблизиться к компьютеру smile 
но я буду стараться.

Цитата(mes @  14.11.2011,  16:19 Найти цитируемый пост)
Вы напишите все "словосочетания", пусть даже не связанные, которые описывают что должно предоствалять решение этой задачи.. 

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

class copy_command
{
   void copy_rectangle(rectangle* r);
   void copy_polygon(polygon* r);
   // ...
};

такое отменяется (это я про visitor-а).
Остается либо группировать по типам объектов, либо не группировать вовсе, т.е. либо так
Код

class rectangle_commands
{
   void copy(rectangle* r);
   void move(rectangle *r, int x, int y);
   // ...
};

либо через интерфейсы и dynamic_cast.

Код

if (icopyable* ic = dynamic_cast<icopyable*>(obj))
{
    ic->copy();
}

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

Вы видите еще какие либо варианты?

Добавлено через 2 минуты и 33 секунды
Цитата(mes @  14.11.2011,  16:19 Найти цитируемый пост)
Без описания с Вашей стороны, форумчане лишь могут предложить решение только своих представлений о вашей задаче, которые к сожалению в большинстве случаев далеки от Вашей десйтвительности.. 

Я не знаю как еще описать, Вы же все поняли
Цитата(mes @  14.11.2011,  16:19 Найти цитируемый пост)
1. Объекты разделены по группам (фигуры, разделители, текст и т.д.)  при этом должна быть возможность динамечиски добавлять 
2. Лист предоставляет набор фиксированных действий предоставляемых над любыми объектами, и реализаторы сами решают какие команды поддерживают.. 


PM   Вверх
mes
Дата 14.11.2011, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  14.11.2011,  15:34 Найти цитируемый пост)
Давайте так. Разберем по полочкам что необходимо решению?
Возможность добавлять новые типы объектов не меняя при этом исходников.

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

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


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 14.11.2011, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  14.11.2011,  16:44 Найти цитируемый пост)
и добавлять новые типы команд, не влезая в чужие исходники и избегая перекомпиляции чужих библиотек.. 

В принципе было бы неплохо, но это не так важно.

Цитата(mes @  14.11.2011,  16:44 Найти цитируемый пост)
избегая перекомпиляции чужих библиотек

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

PM   Вверх
mes
Дата 14.11.2011, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  14.11.2011,  15:34 Найти цитируемый пост)

Вы видите еще какие либо варианты?

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



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 14.11.2011, 16:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  14.11.2011,  16:44 Найти цитируемый пост)
вобщем предполагаю такую картину есть библиотека фреймворка со стандартным наобором примитивов и команд, есть стороняя библиотека расширяющая как каманды так и набор примитивов, и есть пользователь, который должен не смотря на наличие компилированных библиотек , должен не чувствовать связанности рук.. 

 smile

Добавлено @ 16:52
Цитата(mes @  14.11.2011,  16:50 Найти цитируемый пост)
наблюдается принуждение пользователя

к чему?

Добавлено @ 16:54
Цитата(mes @  14.11.2011,  16:50 Найти цитируемый пост)
Все варианты хороши как локальное решение,глобально же любая группа/слой должна иметь обособленность, чего примеры не отражают.. 

А какие могут быть еще варианты? Реализация функций в сторонней библиотеке должна содержаться в самой библиотеке и это должен быть либо виртуальный, либо статический метод какого-либо класса, либо команда (pattern command/функтор), что не очень приятно, так-как выделять по классу на каждую операцию будет накладно.

Добавлено @ 16:59
Самым простым и выполняющим все требования решением на данный момент мне видится интерфейсы и dynamic_cast, т.е. что-то такое
Код

class rectangle: public i_movable, public i_copyable {
   virtual std::string copy() { ... }
   virtual void mvoe(int x, int y) { ... }
};

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

Добавлено @ 17:02
На самом деле я не вижу какие реальные привилегии мне дает собственная таблица функций.
Их надо регистрировать, что отнимает время и хоть чуть-чуть, но все же усложняет жизнь, а что дает взамен?

Это сообщение отредактировал(а) azesmcar - 14.11.2011, 17:03
PM   Вверх
azesmcar
Дата 14.11.2011, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



mes

сейчас думаю над такой вариацией query interface-а.
пользователь запрашивает интерфейс, реализующий модифицирующие операции над объектом текущего типа. Если возвращается 0, значит модифицирующие операции не поддерживаются. 

Код

#include <iostream>
#include <vector>
#include <map>
#include <functional>

struct object;

struct i_modify
{
    virtual void move(object* obj, int x, int y) = 0;
    virtual void rotate(object* obj, int angle) = 0;
};

struct i_copy
{
    virtual std::string copy(object* obj) = 0;
};

struct object {
    virtual i_modify* modify_interface() { return 0; };
    virtual i_copy* copy_interface() { return 0; };
};

struct rectangle: public object
{
    struct rectangle_modify: public i_modify
    {
        virtual void move(object* obj, int x, int y)
        {
            /* move the rectangle */
            std::cout << "obj = " << obj << " moved to (" << x << ", " << y << ")" << std::endl;
        }
        virtual void rotate(object* obj, int angle)
        {
            /* rotate the rectangle */
        }
    };
    virtual i_modify* modify_interface() {
        static rectangle_modify rect_mod;
        return &rect_mod;
    };
};

int main ()
{
    object *obj = new rectangle();
    if (i_modify *mod = obj->modify_interface())
    {
        mod->move(obj, 10, 10);
    }
}

но здесь есть два минуса.
1. в самой функции приходиться получать объект базового типа, так-что от cast-а это не избавляет. Думаю как бы обойти.
2. нет возможности реализовать для объекта функцию move, но не реализовывать скажем функцию rotate (хотя этот минус есть и в случае виртуальных обычных функций, но там интерфейс можно максимально разделить, а в данном случае это приведет к необходимости писать кучу кода).


Это сообщение отредактировал(а) azesmcar - 14.11.2011, 17:24
PM   Вверх
mes
Дата 14.11.2011, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  14.11.2011,  15:51 Найти цитируемый пост)
к чему?

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

Цитата(azesmcar @  14.11.2011,  16:21 Найти цитируемый пост)
сейчас думаю над такой вариацией query interface-а.

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

Цитата(azesmcar @  14.11.2011,  15:51 Найти цитируемый пост)
На самом деле я не вижу какие реальные привилегии мне дает собственная таблица функций.

в таком выражении и не дает..  если вы о примере, то плюс дает не таблица функций, а разбиение на прослойки, где для каждой группы можно добавить свой обработчик. Чтоб лучше понять представьте что вместо print, у нас execute_action (iaction &);

Цитата(azesmcar @  14.11.2011,  16:21 Найти цитируемый пост)
сейчас думаю над такой вариацией query interface-а.

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

чуть позже сделаю  пример с пояснением как я вижу вашу решение..




--------------------
PM MAIL WWW   Вверх
mes
Дата 14.11.2011, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



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


Это сообщение отредактировал(а) mes - 14.11.2011, 18:14


--------------------
PM MAIL WWW   Вверх
mes
Дата 14.11.2011, 22:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  14.11.2011,  15:34 Найти цитируемый пост)
я имел ввиду, что реализовывать новый класс для каждой команды как-то не привлекательно.

вот каракас для допиливания :

http://liveworkspace.org/code/9c9ae402c782...be5c4d3264d0e35
как видите определение новой команды может быть всего лишь типа :
Код

action<int,int> move;

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

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

для полноценного тестового запуска нужно добавить сериализацию/десериализацию, но суть и так понятна.. 
если что может помочь в этом направлении так и не доведенная до конца тема :
http://forum.vingrad.ru/forum/topic-323593...ed-discoly.html

Это сообщение отредактировал(а) mes - 14.11.2011, 23:00


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 14.11.2011, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



mes

У нас древний компилятор, boost-а нет...я смутно представляю чего мне будет стоить такая реализация.
Завтра с утра посмотрю повнимательнее что да как и отвечу.
Спасибо.
PM   Вверх
mes
Дата 14.11.2011, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  14.11.2011,  15:51 Найти цитируемый пост)
вобщем предполагаю такую картину есть библиотека фреймворка со стандартным наобором примитивов и команд, есть стороняя библиотека расширяющая как каманды так и набор примитивов, и есть пользователь, который должен не смотря на наличие компилированных библиотек ,

для начала определимся с лексиконом, чтоб удобно было делить по группом вводим понятия тип_примитива и вариант_примитива..
где тип : ifigure, а вариант : наследник ifigure (rect, circle).. вариант всего лишь реализует интерфейс ifigure и никакой обработки команд не имеет.
для обработки вводим еще связывующее звено, для нас это figure_commander .. commander`ы должны быть зарегистрированы в main_commander.. 

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

Добавлено через 34 секунды
Цитата(azesmcar @  14.11.2011,  22:05 Найти цитируемый пост)
У нас древний компилятор, boost-а нет...я смутно представляю чего мне будет стоить такая реализация.

так предупреждать надо было сразу smile

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



--------------------
PM MAIL WWW   Вверх
mes
Дата 14.11.2011, 23:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(mes @  14.11.2011,  22:17 Найти цитируемый пост)
сейчас поправлю ключевые места, 

держите и тестируйте на своем компиляторе:
http://liveworkspace.org/code/ca6c4fecda3d...d3101dcc94b165b (обновлено)

естственно все написанно на скорую руку и требует детальной доработки, но для работоспособности никакого буста не надо..
пример any  есть где то на форуме, но нужен только если, необходимо удлиненное хранение аргументов.. при ассинхронном подходе..
ну а кол-во аргументов можно расшить например до (входные const& , выходные&); чтоб была возможность диалога..

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

Цитата(mes @  14.11.2011,  22:17 Найти цитируемый пост)
тогда.. 

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


Это сообщение отредактировал(а) mes - 15.11.2011, 00:44


--------------------
PM MAIL WWW   Вверх
math64
Дата 15.11.2011, 07:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Если команды будут с 0..2 параметрами можно переписать так, что будет компилироваться в VS.
(уже сделали - не посмотрел на новую страницу темы)

Это сообщение отредактировал(а) math64 - 15.11.2011, 07:18
PM   Вверх
azesmcar
Дата 15.11.2011, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



mes

Разобрался.
В конечном итоге решение сводиться к регистру шаблона команда со стандартным параметром void*, который в дальнейшем приводиться в соответствующий вид и передается конечному обработчику.
Теперь давайте поговорим о том, какое преимущество дает это решение?
Для каждой операции над объектом (а их много) необходимо создавать структуру параметров.
Каждую операцию надо регистрировать.
Каждая операция требует создания отдельного класса.
Усложненная реализация в плане понимания исходного кода.

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

Это сообщение отредактировал(а) azesmcar - 15.11.2011, 10:22
PM   Вверх
mes
Дата 15.11.2011, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Для каждой операции над объектом (а их много) необходимо создавать структуру параметров.[/quote]

 не для каждой, а для каждой разнотипной.. Т.е. для одного набора аргументов может быть несколько комманд.. 
Цитата(azesmcar @  15.11.2011,  08:21 Найти цитируемый пост)

Каждую операцию надо регистрировать.

если не операцию,  а метод обработчика, то да.. 


Цитата(azesmcar @  15.11.2011,  08:21 Найти цитируемый пост)
Каждая операция требует создания отдельного класса.

не понимаю о чем Вы.. вот как выглядет пользование 
Цитата

struct pos_args {  int x, y; };
struct angle_args { int angle; };

action<pos_args>   move    ("move");
action<pos_args>   moveto  ("moveto");
action<angle_args> rotate  ("rotate");

   
    cmder ( move   ( a1 ) );
    cmder ( moveto ( a2 ) );
    cmder ( rotate ( a3 ) );



Цитата(azesmcar @  15.11.2011,  08:21 Найти цитируемый пост)
Для каждой операции над объектом (а их много) необходимо создавать структуру параметров.

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

Цитата(azesmcar @  15.11.2011,  08:21 Найти цитируемый пост)
Что я получаю взамен, чего мне не дает dynamic_cast?

неправильная постановка вопроса.. это не альтернатива dynamic_cast, это просто иной подход к понятию интерфейс..

Цитата(azesmcar @  15.11.2011,  08:21 Найти цитируемый пост)
Я сам не люблю dynamic_cast, но в конечном итоге все делается для удобства написания и дальнейшего сопровождения. 

опять акцептирования внимание не на том.. dynamic_cast тут не при чем.. 

Цитата(azesmcar @  15.11.2011,  08:21 Найти цитируемый пост)
Как это решение облегчает дальнейшее сопровождение кода? Какие дает возможности расширения в будущем?

вот на это уже можно отвечать.. 
1. например у вас много обработчиков разных команд, (std::vector <handler_t*> v);
вы хотите в цикле для каждого вызвать команду move.. 
в случае с командами я напишу примерно так  :
Код

for (auto p : v)
{
      p->dispatch (move(5,5));
}

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

struct handler 
{
     void on_move () {}
     void regthis (commander_t& c, bool flag);
};

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

4. хотим заменить поведение группы разработонной другим разработчиком, просто меняем его обработчик 

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

и еще куча вариантов, на вспоминание которых  сейчас нет времени  smile

а теперь попробуйте переписать перечисленное через интерфейсы..

Добавлено через 5 минут и 37 секунд
Цитата(azesmcar @  15.11.2011,  08:21 Найти цитируемый пост)
В конечном итоге решение сводиться к регистру шаблона команда со стандартным параметром void

советую также внимательнее рассмотреть моменты, которыми отличается предложенное решение от "классического" паттерна команда..

Добавлено через 7 минут и 43 секунды
и да и dynamic_cast никто не отменял, он остается как вариант взаимодействия обработчика с вариантами типов.. (или же вместо него будет визитор)..


Это сообщение отредактировал(а) mes - 15.11.2011, 10:51


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.11.2011, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  15.11.2011,  10:49 Найти цитируемый пост)
не для каждой, а для каждой разнотипной

Они практически все разнотипные.

Цитата(mes @  15.11.2011,  10:49 Найти цитируемый пост)
не понимаю о чем Вы.. вот как выглядет пользование 

Об этом
Код

struct cmd_handler2 
{
   void on_rotate(angle_args const& a)
   {
      std::cout << "rotate(" << a.angle << "); ";
   }     
};


Цитата(mes @  15.11.2011,  10:49 Найти цитируемый пост)
для гибкости интерфейсы тоже придется делить на мелкие, и кол-во кода будет одного порядка..  

Для начала можно и не делить. В данном случае делить можно будет по необходимости. К примеру для начала создать интерфейс i_modifier, который будет содержать функции типа rotate, move, change_layer ... итд, а далее по необходимости реазделять на более мелкие интерфейсы.

Цитата(mes @  15.11.2011,  10:49 Найти цитируемый пост)
неправильная постановка вопроса.. это не альтернатива dynamic_cast, это просто иной подход к понятию интерфейс..

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

Цитата(mes @  15.11.2011,  10:49 Найти цитируемый пост)
1. например у вас много обработчиков разных команд, (std::vector <handler_t*> v);

Это уже другой разговор. Теперь давайте думать о том, нужно ли это?
В основном предполагается производить операцию над объектами через интерфейс базового класса.
Пример использования: пользователь выбрал несколько объектов и набрал команду move {10 20}, все объекты должны быть перемещены.
Того, что Вы описали не планируется, но я еще подумаю об этом.

Цитата(mes @  15.11.2011,  10:49 Найти цитируемый пост)
2. у нас появилось новая группа команда для нашего типа, я просто создаю для нее новый обработчик 

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

Цитата(mes @  15.11.2011,  10:49 Найти цитируемый пост)
3. нам нужно до обработчика и/или после выполнить какое то действие.. например хотим вывести лог.. 

Не нужно, эта возможность у нас уже есть. Все операции вызываются из команд, которые вызываются из интерпретатора. Для команд можно устанавливать pre/post callback-и.

Цитата(mes @  15.11.2011,  10:49 Найти цитируемый пост)
4. хотим заменить поведение группы разработонной другим разработчиком, просто меняем его обработчик 

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

Цитата(mes @  15.11.2011,  10:49 Найти цитируемый пост)
5. любая смена поведения, осуществляется динамически, и не требует перекомпиляции чужих библиотек.. 
(большой привет жесткой связке множественного наследования).. 

А зачем нужно перекомпилировать чужую библиотеку в случае с интерфейсами?

Код

// библиотека

class i_movable {
   virtual void move(int x, int y);
};

class i_object { ... };

class rectangle: public i_object, public i_movable { ... };

далее другая группа делает следующее
Код

class triangle: public i_object, public i_movable { ... };

зачем ей что-то перекомпилировать?
PM   Вверх
azesmcar
Дата 15.11.2011, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(azesmcar @  15.11.2011,  11:09 Найти цитируемый пост)
5. любая смена поведения, осуществляется динамически, и не требует перекомпиляции чужих библиотек.. 
(большой привет жесткой связке множественного наследования).. 

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

Еще раз скажу, что я не защищаю какое либо решение. Просто перед тем как принять одно, я должен понять что оно мне дает и чем я ради него жертвую.
На данный момент я нахожу наименьшим злом решение с query interface-ом, потому все предложения сравниваю с ним. smile 

Это сообщение отредактировал(а) azesmcar - 15.11.2011, 11:34
PM   Вверх
mes
Дата 15.11.2011, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  15.11.2011,  10:09 Найти цитируемый пост)
. К примеру для начала создать интерфейс i_modifier, который будет содержать функции типа rotate, move, change_layer ... итд, а далее по необходимости реазделять на более мелкие интерфейсы.

ну  ну.. успеха smile  что то после таких слов и не верится, что Вас пугает объем работы.. 

Цитата(azesmcar @  15.11.2011,  10:09 Найти цитируемый пост)
Об этом

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

Цитата(azesmcar @  15.11.2011,  10:09 Найти цитируемый пост)
Еще его надо будет зарегистрировать. В случае с dynamic_cast я просто создаю новый интерфейс и наследую его там, где его нужно реализовывать. Так-что разница небольшая.

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

Цитата(azesmcar @  15.11.2011,  10:09 Найти цитируемый пост)
Не нужно, эта возможность у нас уже есть. Все операции вызываются из команд, которые вызываются из интерпретатора. Для команд можно устанавливать pre/post callback-и

это называется игра в темную.. Если у вас уже есть команды то чего мы придумываем то тут ? 

Цитата(azesmcar @  15.11.2011,  10:09 Найти цитируемый пост)
Не совсем понял о чем это. Если вы про изменения расширений других разработчиков, то у нас нет доступа к их исходникам, мы с ними никак не связаны. Они используют наш продукт, мы с их продуктом не работаем.

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

Цитата(azesmcar @  15.11.2011,  10:09 Найти цитируемый пост)
А зачем нужно перекомпилировать чужую библиотеку в случае с интерфейсами?

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


Цитата(azesmcar @  15.11.2011,  10:09 Найти цитируемый пост)
зачем ей что-то перекомпилировать? 

появилась еще команда и в moveble добавили еще один метод..  smile

Добавлено через 1 минуту и 56 секунд
Цитата(azesmcar @  15.11.2011,  10:29 Найти цитируемый пост)
 Другие могут только добавлять свои типы и операции, менять у нас они ничего не должны.

т.е. Вы заранее знаете как пользователю лучше ? smile

Добавлено через 3 минуты и 1 секунду
Цитата(azesmcar @  15.11.2011,  10:29 Найти цитируемый пост)
Еще раз скажу, что я не защищаю какое либо решение. Просто перед тем как принять одно, я должен понять что оно мне дает и чем я ради него жертвую.

при таком подходе я Вам не советчик..  smile 



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.11.2011, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  15.11.2011,  16:02 Найти цитируемый пост)
ну  ну.. успеха smile  что то после таких слов и не верится, что Вас пугает объем работы.. 

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

Цитата(mes @  15.11.2011,  16:02 Найти цитируемый пост)
регистрация  обработчика сводится к карте соответсвий.. и обработчик может быть самодостаточным.. т.е. вклюпчать в себя как диспетчер, так и сам обработчик.. 

Я говорил не про регистрацию, а про то, что
Цитата(azesmcar @  15.11.2011,  09:21 Найти цитируемый пост)
Каждая операция требует создания отдельного класса.


Цитата(mes @  15.11.2011,  16:02 Найти цитируемый пост)
в случае наследования тянет за собой вплоть до полной перекомпиляции, при этом если добавляют разные производители, то каждый лезет в чужой исходник..

Мы кажется друг друга не понимаем. Никто в чужие исходники не лезет. Зачем это нужно? Есть базовый класс geometry и некоторые операции типа move, rotate...которые определены в виде интерфейсов, другая команда разработчиков наследует свой тип, пусть будет rectangle и реализует интерфейсы move и rotate, о наших классах он ничего не знает, нашего кода у него нет и ему это не нужно.

Цитата(mes @  15.11.2011,  16:02 Найти цитируемый пост)
это называется игра в темную.. Если у вас уже есть команды то чего мы придумываем то тут ? 

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

Цитата(mes @  15.11.2011,  16:02 Найти цитируемый пост)
исходники не при чем,  пользователь добавил команду, например вывод в особом виде,  теперь ему не придется переколошмачивать чужие исходники, а просто добавить в стек обработчик нужного поведения.. 

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

Цитата(mes @  15.11.2011,  16:02 Найти цитируемый пост)
появилась еще команда и в moveble добавили еще один метод..  smile 

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

PM   Вверх
mes
Дата 15.11.2011, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  15.11.2011,  10:29 Найти цитируемый пост)
На данный момент я нахожу наименьшим злом решение с query interface-ом, потому все предложения сравниваю с ним.

давайте сравним.. 

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

разница очень тонка в одном случае передается интерфейс в запрашиваемое место, в другом идет комманда до нужного интерфейса.. 
в обоих случаях они идут как (условно) void*,  в оноих для динамики надо регистрировать,


Это сообщение отредактировал(а) mes - 15.11.2011, 16:31


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.11.2011, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  15.11.2011,  16:02 Найти цитируемый пост)
т.е. Вы заранее знаете как пользователю лучше ? smile

Нет, я знаю что он должен делать, а чего не должен smile 

Цитата(mes @  15.11.2011,  16:02 Найти цитируемый пост)
при таком подходе я Вам не советчик..  smile 

А что не так с подходом? Я должен яростно защищать dynamic_cast? Тогда зачем создавать тему, если в итоге я все равно настроен решать так, как хочу сейчас?
Перед тем как принять решение, я должен понять его плюсы и минусы, и эти плюсы должны перевесить минусы.

mes

Давайте перед началом сравнения проясним кое-что. Я не нашел в Вашем примере где Вы вообще обрабатываете объекты? Вы вызвали обработчик, но где ему передается rectangle, polygon и тому подобное?
Этого здесь нет, как предполагается передача самого объекта обработчику?


Это сообщение отредактировал(а) azesmcar - 15.11.2011, 16:26
PM   Вверх
mes
Дата 15.11.2011, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  15.11.2011,  15:22 Найти цитируемый пост)
А что не так с подходом? Я должен яростно защищать dynamic_cast? Тогда зачем создавать тему, если в итоге я все равно настроен решать так, как хочу сейчас?

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

Добавлено через 3 минуты и 3 секунды
Цитата(azesmcar @  15.11.2011,  15:16 Найти цитируемый пост)
Каждая операция требует создания отдельного класса.

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

Это сообщение отредактировал(а) mes - 15.11.2011, 16:32


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.11.2011, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  15.11.2011,  16:32 Найти цитируемый пост)
Я ж специально выделил.. не буду сразу подсказывать ответ, но Ваш первый вывод неверный... я возмутился над другим аспектом.. 

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

PM   Вверх
math64
Дата 15.11.2011, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Предлагаю такое решение: Вместо идентификатора у объект можно получить "пульт управления":
Код

template <typename T>
srtuct icontrol{
virtual T get() const = 0;
virtual void set(T&) = 0;
};
template <typename T>
srtuct irangecontrol : icontrol {
virtual T min() const = 0;
virtual T max() const = 0;
};
struct icontroller {
icontrol<bool>* getboolcontrol(const string&) = 0;
irangecontrol<int>* getintcontrol(const string&) = 0;
irangecontrol<double>* getintcontrol(const string&) = 0;
};
struct object { virtual icontroller* getcontroller(); }


PM   Вверх
mes
Дата 15.11.2011, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  15.11.2011,  15:35 Найти цитируемый пост)
Вы насчет жертвы? А что Вы в этом нашли такого? Любой подход и любое решение - это плюс в одну сторону и минус в другую. Принятие минусов конкретного решения и есть эта жертва, сделанная ради ее плюсов.



Цитата(mes @  15.11.2011,  15:02 Найти цитируемый пост)
Цитата

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

при таком подходе я Вам не советчик..  

Я бы предпочел вариант,  "что я от этого выигрываю"... не говоря о слишком жестком акценте над словом "одно"...  smile 
Цитата(azesmcar @  15.11.2011,  15:22 Найти цитируемый пост)
Нет, я знаю что он должен делать, а чего не должен

поэтому закуем в наручники smile

Сорри за придирки, просто иначе не знаю варианта, как "заставить" Вас взглянуть под другим углом  smile 



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.11.2011, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  15.11.2011,  16:50 Найти цитируемый пост)
одно

Одно - подразумевалось одно из решений.

Цитата(mes @  15.11.2011,  16:50 Найти цитируемый пост)
поэтому закуем в наручники smile

С той же логикой можно отменить спецификаторы доступа. Долой private, делаем все методы и поля публичными smile 

Цитата(mes @  15.11.2011,  16:50 Найти цитируемый пост)
Сорри за придирки, просто иначе не знаю варианта, как "заставить" Вас взглянуть под другим углом  smile 

Я пытаюсь, но из плюсов я на данный момент вижу только ослабленную монолитность, зато работы это прибавляет значительно.
Я не придираюсь, просто хочу понять.
PM   Вверх
mes
Дата 15.11.2011, 16:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



azesmcar
Цитата(azesmcar @  15.11.2011,  15:22 Найти цитируемый пост)
Давайте перед началом сравнения проясним кое-что. Я не нашел в Вашем примере где Вы вообще обрабатываете объекты? Вы вызвали обработчик, но где ему передается rectangle, polygon и тому подобное?

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

А вспомнил еще один недостаток монолитного QI, при множественном наследовании может возникнуть коллизия имен.. ( ну и пра затруднительное проксирование я уже говорил)... 

я кажись придумал откуда надо плясать.. 




Это сообщение отредактировал(а) mes - 15.11.2011, 16:56


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.11.2011, 16:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  15.11.2011,  16:50 Найти цитируемый пост)
Я бы предпочел вариант,  "что я от этого выигрываю"... 

Но ведь что я теряю - это тоже важно, потому вариант не подходит smile

Добавлено через 1 минуту и 15 секунд
Цитата(mes @  15.11.2011,  16:54 Найти цитируемый пост)
А вспомнил еще один недостаток монолитного QI, при множественном наследовании может возникнуть коллизия имен.. ( ну и пра затруднительное проксирование я уже говорил)... 

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

PM   Вверх
mes
Дата 15.11.2011, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  15.11.2011,  15:54 Найти цитируемый пост)
Но ведь что я теряю - это тоже важно, потому вариант не подходит 

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



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.11.2011, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



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

Цитата(mes @  15.11.2011,  16:58 Найти цитируемый пост)
Так по большему счеты вы ничего не теряете, просто переводите в другую плоскость.. 

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

Это сообщение отредактировал(а) azesmcar - 15.11.2011, 17:02
PM   Вверх
mes
Дата 15.11.2011, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  15.11.2011,  15:54 Найти цитируемый пост)
 В данном случае меня больше всего волнует монолитность класса и использование кастов.

вот о жертвах..  при правильном подходе монолитности не будет и при подходе с интерфейсами, только придется прикрутить, QI
рeгистрацию интерфейсов и ту же кучу кода как при Command.. 

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

у Command акценты расставлены наоборот..






--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.11.2011, 17:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  15.11.2011,  17:04 Найти цитируемый пост)
вот о жертвах..  при правильном подходе монолитности не будет и при подходе с интерфейсами, только придется прикрутить, QI

Каким образом? Где будет реализован интерфейс, если не в самих классах?

Добавлено через 2 минуты и 37 секунд
Цитата(mes @  15.11.2011,  17:04 Найти цитируемый пост)
при правильном подходе монолитности не будет и при подходе с интерфейсами, только придется прикрутить, QI

давайте подумаем в этом направлении.


Это сообщение отредактировал(а) azesmcar - 15.11.2011, 17:06
PM   Вверх
mes
Дата 15.11.2011, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  15.11.2011,  15:59 Найти цитируемый пост)
Единственное его достоинство, которое в моей задаче является большим плюсом - это ослабленная монолитность

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

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


Цитата(azesmcar @  15.11.2011,  15:59 Найти цитируемый пост)
И в общем-то я не уверен, что у меня получится.

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

Добавлено через 1 минуту и 18 секунд
Цитата(azesmcar @  15.11.2011,  16:06 Найти цитируемый пост)
давайте подумаем в этом направлении.

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



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.11.2011, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  15.11.2011,  17:11 Найти цитируемый пост)
Да от понимания концепции сильно зависит реализация

Я имел ввиду, не уверен, что у меня получиться объяснить. smile 

Цитата(mes @  15.11.2011,  17:11 Найти цитируемый пост)
Еще раз.. я не знаю вашу задачу поэтому не могу подобрать правильно подходящее решение

Я действительно не могу описать ее всю целиком, мне надо будет рассказывать всю архитектуру проекта, а это займет пару дней smile 
В принципе основные ключевые моменты я описал, остальное приходится рассказывать по мере необходимости.
PM   Вверх
mes
Дата 15.11.2011, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



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


Это сообщение отредактировал(а) mes - 15.11.2011, 17:20


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.11.2011, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  15.11.2011,  17:18 Найти цитируемый пост)
пока вы тут, опишите фигуру, кроме перемещения и поворота что она умеет, ив каких случаях она не должна.. 

mirroring, scale, смена layer-а.
там на самом деле не только фигуры, есть флаги, точки, которые нельзя передвигать или вращать, зато можно копировать или сохранять в файл, т.е. нужна сериализация. Третье лицо может добавить свой топ, который нельзя копировать, в общем вариаций много.
PM   Вверх
azesmcar
Дата 15.11.2011, 17:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



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

#include <iostream>
#include <map>

struct geom;
struct rectangle;

struct i_interface
{
    virtual ~i_interface() {};
};

struct i_serilization: i_interface
{
    enum { iid = 1 };
    virtual std::string serilize() const = 0;
};

template <typename T> struct object_serialization: i_serilization
{
public:
    object_serialization(const T* o): object(o) {}
protected:
    const T* get_object() const
    {
        return object;
    }
private:
    const T* object;
};

struct rectangle_serialization: object_serialization<rectangle>
{
    rectangle_serialization(const rectangle* o): object_serialization(o) {}
    std::string serilize() const
    {
        std::cout << "rectangle " << get_object() << std::endl;
        return "";
    }
};

struct geom
{
public:
    template <typename T> void register_interface(T* iface)
    {
        interfaces[T::iid] = iface;
    }
    template <typename T> T* query_interface()
    {
        auto it = interfaces.find(T::iid);
        if (it != interfaces.end())
        {
            return dynamic_cast<T*>(it->second);
        }
        return 0;
    }
private:
    std::map<int, i_interface*> interfaces;
};

struct rectangle : geom
{
    rectangle()
    {
        register_interface(new rectangle_serialization(this));
    }
};

int main()
{
    geom *obj = new rectangle();
    if (i_serilization * i = obj->query_interface<i_serilization>())
    {
        i->serilize();
    }
}



Это сообщение отредактировал(а) azesmcar - 15.11.2011, 17:49
PM   Вверх
mes
Дата 15.11.2011, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  15.11.2011,  16:47 Найти цитируемый пост)
  template <typename T> void register_interface(T* iface)
    {
        interfaces[T::iid] = iface;
    }
    template <typename T> T* query_interface()
    {
        auto it = interfaces.find(T::iid);
        if (it != interfaces.end())
        {
            return dynamic_cast<T*>(it->second);
        }
        return 0;
    }
private:
    std::map<int, i_interface*> interfaces;

ага, в pпринципе именно то, только не у geom, а у object.. 

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

Это сообщение отредактировал(а) mes - 15.11.2011, 18:16


--------------------
PM MAIL WWW   Вверх
math64
Дата 15.11.2011, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Вот рабочий пример по моей идее - ни одного dynamic_cast<>:
Код

#include <string>
#include <iostream>
#include <map>
using namespace std;
template<typename T>
  struct IControl {
    virtual T get() const = 0;
    virtual void set(T t) = 0;
  };
template<typename T>
  struct IRangeControl : IControl<T> {
    virtual T min() const = 0;
    virtual T max() const = 0;
  };

struct Object;

struct IController {
  static int getId(const string& s) { 
    if (ids.find(s)==ids.end()) { return reg(s, ++lastId); }
    return ids[s];
  }
  virtual IControl<bool> * getBoolControl(int id) { return 0; }
  virtual IRangeControl<int> * getIntControl(int id) { return 0; }
  virtual IRangeControl<double> * getDoubleControl(int id) { return 0; }
  virtual Object* create() = 0;
  virtual string name() const = 0;

  IControl<bool> * getBoolControl(const string& s) { return getBoolControl(getId(s)); }
  IRangeControl<int> * getIntControl(const string& s) { return getIntControl(getId(s)); }
  IRangeControl<double> * getDoubleControl(const string& s) { return getDoubleControl(getId(s)); }

protected:
  static int reg(const string& s, int id) { if (ids.find(s)==ids.end()) ids[s] = id; return id; }
  static map<string,int> ids;
  static int lastId;
};

map<string,int> IController::ids;
int IController::lastId = 0;

struct Object {
  virtual ~Object() {}
  virtual IController& getController() = 0;
};

struct Rect : Object {
  int x,y,w,h;

  enum { X=-1, Y=-2, W=-3, H=-4 };

  struct Control : IRangeControl<int> {
    int* p;
    virtual int get() const { return *p; }
    virtual void set(int v) { if (v >= min() && v <= max()) *p = v; }
    virtual int min() const { return 0; }
    virtual int max() const { return 1000; }
  };

  struct Controller : IController {
    Controller() { reg("x",X); reg("y",Y);  reg("w",W);  reg("h",H); }
    virtual Object* create() { Rect* r = new Rect; setRect(r); return r; }
    virtual string name() const { return "Rect"; }
    virtual IRangeControl<int> * getIntControl(int id) {
      switch(id) {
        case X: return &x;
        case Y: return &y;
        case W: return &w;
        case H: return &h;
      }
      return 0;
    }
    void setRect(Rect* r) { rect = r; x.p = &r->x; y.p = &r->y; w.p = &r->w; h.p = &r->h; }
    Rect* rect;
    Control x;
    Control y;
    Control w;
    Control h;
  };
  static Controller controller;

  virtual IController& getController() {
    controller.setRect(this);
    return controller;
  }
};
Rect::Controller Rect::controller;

struct RectF : Object {
  double x,y,w,h;

  enum { X=-1, Y=-2, W=-3, H=-4 };

  struct Control : IRangeControl<double> {
    double* p;
    virtual double get() const { return *p; }
    virtual void set(double v) { if (v >= min() && v <= max()) *p = v; }
    virtual double min() const { return 0; }
    virtual double max() const { return 1000; }
  };

  struct Controller : IController {
    Controller() { reg("x",X); reg("y",Y);  reg("w",W);  reg("h",H); }
    Object* create() { RectF* r = new RectF; setRect(r); return r; }
    virtual string name() const { return "RectF"; }
    virtual IRangeControl<double> * getDoubleControl(int id) {
      switch(id) {
        case X: return &x;
        case Y: return &y;
        case W: return &w;
        case H: return &h;
      }
      return 0;
    }
    // Можно добавить getIntControl(), который бы делал конвертацию типов
    void setRect(RectF* r) { rect = r; x.p = &r->x; y.p = &r->y; w.p = &r->w; h.p = &r->h; }
    RectF* rect;
    Control x;
    Control y;
    Control w;
    Control h;
  };
  static Controller controller;

  virtual IController& getController() {
    controller.setRect(this);
    return controller;
  }
};
RectF::Controller RectF::controller;

void setInts(Object&r) {
IController& c = r.getController();
c.getIntControl("x")->set(10);
c.getIntControl("y")->set(10);
c.getIntControl(Rect::W)->set(100);
c.getIntControl(Rect::H)->set(100);
}

void setDoubles(Object&r) {
IController& c = r.getController();
c.getDoubleControl("x")->set(10.);
c.getDoubleControl("y")->set(10.);
c.getDoubleControl(RectF::W)->set(100.);
c.getDoubleControl(RectF::H)->set(100.);
}

void printInts(Object&r) {
IController& c = r.getController();
cout << c.name() << endl;
cout << c.getIntControl("x")->get() << endl;
cout << c.getIntControl("y")->get() << endl;
cout << c.getIntControl("w")->get() << endl;
cout << c.getIntControl("h")->get() << endl;
}

void printDoubles(Object&r) {
IController& c = r.getController();
cout << c.name() << endl;
cout << c.getDoubleControl("x")->get() << endl;
cout << c.getDoubleControl("y")->get() << endl;
cout << c.getDoubleControl("w")->get() << endl;
cout << c.getDoubleControl("h")->get() << endl;
}

int main() {
Rect r; setInts(r);
printInts(r);
RectF rf; setDoubles(rf);
printDoubles(rf);
Object* o = rf.getController().create();
IController& c1 = r.getController();
IController& c = o->getController();
// Поскольку Controller - статический, так нельзя делать для копирования одинаковых типов
// Но это можно исправить.
c.getDoubleControl("x")->set(c1.getIntControl("x")->get());
c.getDoubleControl("y")->set(c1.getIntControl("y")->get());
c.getDoubleControl("w")->set(c1.getIntControl("w")->get());
c.getDoubleControl("h")->set(c1.getIntControl("h")->get());
printDoubles(*o);
return 0;
}


PM   Вверх
azesmcar
Дата 15.11.2011, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  15.11.2011,  18:00 Найти цитируемый пост)
ага, в pпринципе именно то, только не у geom, а у object.. 

Не совсем понял о чем речь.

Цитата(mes @  15.11.2011,  18:00 Найти цитируемый пост)
ну вот есть у нас эти интерфейсы.. кто ими пользоваться будет ?

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

Цитата(mes @  15.11.2011,  18:00 Найти цитируемый пост)
если пользователь, то ему удобнее узнать фигура , текст, это ли что другое..
если это прослойка для комманд, то не вижу разделение на слои.. 

Тут тоже не совсем понял о чем речь.

Добавлено через 28 секунд
math64

спасибо, мне надо это переварить, понадобиться время smile 
PM   Вверх
mes
Дата 16.11.2011, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  15.11.2011,  20:52 Найти цитируемый пост)
Тут тоже не совсем понял о чем речь.

немного размышлений о том , как я это представляю.. 
задачу можно разделить на несколько слоев, каждый из который соответсвует определенной концепции..  срез представляет "оголенные" интерфейсы.. в зависимости от того какие слои будут соприкасаться, зависит какими интерфейсы должен предоставлять слой... в некоторых случаях бывает нужным сделать прослойку/адаптер.. Зачастую чтоб не забивать голову, просто лепят мониолит..  К слоям относятся не только программные компоненты, но в том числе оборудование и юзер.. Так например например между консольной программой и юзером один тип среза, а между юзером и ГУИ совсем другой, поэтому отличается подход по формированию.. При Этом слои вполне могут располагаться как консолька<->Гуи<->Юзер.. Саму программу также можно условно разделить на слои : например  первый - предметная область, второй взаимодействие с базой,взаимодействие с юзером.. для того чтоб представить задачу нужно понять о каком слое идет речь, другими словами определить, что на входе, а что на выходе..

Добавлено @ 00:20
так например  если я описываю предметную область, то все эти moveable вообще не нужны, гораздо ближе "родные " названия самих типов..
если я хочу интерактивное взаимодействие, то я выбрал бы динамический интерфейс (в основе которого паттерн комманда) и по запросу о поддержке команд формировал бы  юзеру меню возможных вариантов... 
ну и дальше в таком же духе..

Добавлено через 10 минут и 52 секунды
применительно к вашей задаче :
есть набор фигур - предметная область , тут вроде все понятно.. но это одна часть
а вот вторая : есть какой то фреймворк, который что то там делает с набором фигур, и который еще кто-то будет использовать как то, по своему усмотрению.. 
но там имеются еще команды и интерпретатор.. вот так я вижу этот слой на основе ваших деталей smile Осмелюсь предположить, что и у других форумчан представление о нем не намного детализированней smile Поэтому приходится идтина ощупь smile

Добавлено через 11 минут и 39 секунд
Но задача вроде интересная smile будем надееться что не только из за покрывала таинственности smile


Это сообщение отредактировал(а) mes - 16.11.2011, 00:21


--------------------
PM MAIL WWW   Вверх
baldina
Дата 16.11.2011, 01:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



я пытался выяснить, но внятного ответа не получил(((
а советывать не имея исходной информации занятие малополезное.
однако из контекста у меня сложилось некое мнение, что речь идет о программе, работающей с разными (геометрическими?) объектами, над которыми и осуществляются операции при помощи команд. при этом end-user может выбрать множество объектов и выполнить некую команду из общего списка, и она должна быть применена ко всем объектам множества, которые в состоянии обработать такую команду.
если я правильно понял, есть разработчики ядра (ака фреймворк), они добавляют типы и команды и прочие разработчики (они вроде только типы добавляют)

Добавлено через 2 минуты и 49 секунд
мне самому жутко интересно, что же разрабатывается

Добавлено через 5 минут и 44 секунды
почти сразу было понятно, что языковыми средствами не обойтись, но какая именно комбинация средств наиболее подходящая зависит от деталей задачи и распределении ролей в разработке
PM MAIL   Вверх
mes
Дата 16.11.2011, 01:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(baldina @  16.11.2011,  00:20 Найти цитируемый пост)
 при этом end-user может выбрать множество объектов и выполнить некую команду из общего списка, 

эту часть  тс, особенно ревностно оберегает smile так что есть ли этот пресловутый список, или же приходится работать напрямую с интерфейсами, не понянто smile

Цитата(baldina @  16.11.2011,  00:20 Найти цитируемый пост)
почти сразу было понятно, что языковыми средствами не обойтись, но какая именно комбинация средств наиболее подходящая зависит от деталей задачи и распределении ролей в разработке 

 smile именно это и является определяющим фактором выбора, а вот где только подробности об этих стыках..

тема постепенно превращаются в оффтопные мультимонологи  smile 


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 16.11.2011, 07:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(baldina @  16.11.2011,  01:20 Найти цитируемый пост)
я пытался выяснить, но внятного ответа не получил(((

на какой именно вопрос?

Цитата(baldina @  16.11.2011,  01:20 Найти цитируемый пост)
а советывать не имея исходной информации занятие малополезное.

Я уже и не знаю о чем рассказать smile 
Как конечный пользователь будет использовать программу? Все что есть я описал.

Цитата(baldina @  16.11.2011,  01:20 Найти цитируемый пост)
речь идет о программе, работающей с разными (геометрическими?) объектами, над которыми и осуществляются операции при помощи команд. при этом end-user может выбрать множество объектов и выполнить некую команду из общего списка

Да

Цитата(baldina @  16.11.2011,  01:20 Найти цитируемый пост)
должна быть применена ко всем объектам множества, которые в состоянии обработать такую команду

Да. А для тех, которые не поддерживают сгенерировать исключение.


Цитата(baldina @  16.11.2011,  01:20 Найти цитируемый пост)
если я правильно понял, есть разработчики ядра (ака фреймворк), они добавляют типы и команды и прочие разработчики (они вроде только типы добавляют)

Да.

Что еще нужно описать а не понимаю, Вы же все прекрасно понимаете.

Добавлено через 1 минуту и 18 секунд
Цитата(mes @  16.11.2011,  01:49 Найти цитируемый пост)
именно это и является определяющим фактором выбора, а вот где только подробности об этих стыках.

Я же писал об этом несколько раз.

Цитата(baldina @  16.11.2011,  01:20 Найти цитируемый пост)
есть разработчики ядра (ака фреймворк), они добавляют типы и команды и прочие разработчики (они вроде только типы добавляют)

Вот оно.

mes

На Ваш предыдущий пост отвечу позже.
PM   Вверх
mes
Дата 16.11.2011, 09:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  16.11.2011,  06:29 Найти цитируемый пост)
 Вы же все прекрасно понимаете.

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

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




--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 16.11.2011, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  16.11.2011,  09:17 Найти цитируемый пост)
Вы там писали что есть интерпретатор с командами, как понимаю они остаются, и Вам необходимо добавить фигуры и осуществить связку.. так ?

Вот потому я и не хочу выдавать лишнюю информацию. С интерпретатором это никак не связано.
Нет, они не остаются, от этих команд надо избавиться.

Добавлено через 2 минуты и 5 секунд
Цитата(mes @  16.11.2011,  09:17 Найти цитируемый пост)
если да, то как выглядит условный вызов команды и передача ее на обработку..

Код

void MoveSelected::execute(const std::vector<geom*>& selected)
{
    for (geom* obj: selected)
        if (i_movable* m = dynamic_cast<i_movable*>(obj))
            m->move(params().x(), params.y());
}

PM   Вверх
mes
Дата 16.11.2011, 10:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



ну вот хоть что то smile у вас уже есть команды, а мы их изобретаем smile 
и теперь стало сразу понятно, что значила та строчка,о которой допытывал вас baldina (с copy_rectangle)..
мой пример с командой можете забыть (он мог быть вместо вашей командера, но в дополнении не смотрится )

остальное отвечу позже

Это сообщение отредактировал(а) mes - 16.11.2011, 10:08


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 16.11.2011, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  16.11.2011,  10:05 Найти цитируемый пост)
ну вот хоть что то smile у вас уже есть команды, а мы их изобретаем smile 

Ну вот, я же говорю не надо загружать лишними деталями.
Нет у меня команд, это одна команда на move всего движимого и недвижимого, она понятия не имеет с какого типа объектами она имеет и будет иметь дело.
Это могут быть объекты, которые созданы другой группой, это могут быть наши геометрии.
Абсолютно без разницы откуда это вызывается, главное создать возможность полиморфно обрабатывсть объекты, не зная их реальных типов.

Добавлено @ 10:13
Я видимо очень плохо объясняю. Забудьте про интерпретаторы и команды.
Есть базовый класс geom, есть наследуемые от него разного рода геометрии. Есть predifined список операций, которые можно проводить с этими типами. Некоторые типы поддерживают все операции, некоторые нет. Например точка не поддерживает вращения, а полигон поддерживает.
Операции добавляются и изменяются чаще, чем сами типы, но необходимо оставить возможность добавлять новые типы, не изменяя исходников, так-как возможно добавление типов со стороны третьих лиц.
Все. Задача в этом, все остальное не важно. Вот все требования.

Это сообщение отредактировал(а) azesmcar - 16.11.2011, 10:14
PM   Вверх
mes
Дата 16.11.2011, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  16.11.2011,  09:10 Найти цитируемый пост)
Ну вот, я же говорю не надо загружать лишними деталями.

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


Цитата(azesmcar @  16.11.2011,  09:10 Найти цитируемый пост)
Нет у меня команд, это одна команда на move всего движимого и недвижимого, она понятия не имеет с какого типа объектами она имеет и будет иметь дело.

Команда как действие у вас условно есть (то есть неважно физическое наличие, важно что мы знаем что команда может вызваться) и надо написать логику команды.. или так называемую связку, в которой как я и понимаю есть та загвоздка..

Добавлено @ 10:29
Цитата(azesmcar @  16.11.2011,  09:10 Найти цитируемый пост)
 не надо загружать лишними деталями.

это была как раз не загружающая, а разгружающая деталь smile

Добавлено @ 10:31
Цитата(azesmcar @  16.11.2011,  09:10 Найти цитируемый пост)
Абсолютно без разницы откуда это вызывается, главное создать возможность полиморфно обрабатывсть объекты, не зная их реальных типов.

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

Добавлено @ 10:33
вот как раз три слоя и определились : 
коммандер, исполнитель, типы  ( условно C,B,A)
smile
при этом концентрация на втором, с учетом третьего.. 


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

жду поправок smile



Это сообщение отредактировал(а) mes - 16.11.2011, 10:54


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 16.11.2011, 11:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  16.11.2011,  10:29 Найти цитируемый пост)
это некий объект занимающий некий прямоугольник, может быть фигурой, текстом спецсимволом и т.д. 

Да.

Цитата(mes @  16.11.2011,  10:29 Найти цитируемый пост)
он может быть сохранен в разных форматах, и отрисован разными рендерами.. 

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

Цитата(mes @  16.11.2011,  10:29 Найти цитируемый пост)
если он фигура, то над ним могут быть произведены скалирование, перемещение, конвертация    и т.д.

Да.

Цитата(mes @  16.11.2011,  10:29 Найти цитируемый пост)
если он текст что то подобное и смена текста.. 

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

Цитата(mes @  16.11.2011,  10:29 Найти цитируемый пост)
но может быть разработон стороний тип, правила к которому определяется тртьим лицом..

Да.

Конкретно в приведенной мною реализации query interface мне не нравится один момент.
Придется заранее разбивать на мелкие интерфейсы, сгруппировать не получиться, так-как после группировки будет невозможно дальнейшее разделение.
Скажем я создал интерфейс i_editable - который поддерживает операции rotate и move, а потом у нас появился тип, который можно перемещать, но нельзя вращать и придется менять кучу кода, чтобы разделить rotate интерфейс от move-а. А в случае с наследованием интерфейсов можно разделить интерфейс на i_rotatable и i_movable, оставить интерфейс i_editable : i_rotatable, i_movable для поддержки старых реализаций.

Добавлено @ 11:24
Цитата(baldina @  16.11.2011,  01:20 Найти цитируемый пост)
мне самому жутко интересно, что же разрабатывается

EDA инструменты smile 

Это сообщение отредактировал(а) azesmcar - 16.11.2011, 11:25
PM   Вверх
xvr
Дата 16.11.2011, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(azesmcar @  16.11.2011,  10:10 Найти цитируемый пост)
Операции добавляются и изменяются чаще, чем сами типы, но необходимо оставить возможность добавлять новые типы, не изменяя исходников, так-как возможно добавление типов со стороны третьих лиц.

А перекомпиляция исходников допускается? Если да, то описать все операции в виде класса с виртуальными методами (по 1 штуке на операцию) и телами, которые бросают исключение - 'not-implemented'. Отдать этот класс на растерзание пользователю, но унаследовать все ваши классы от него.

PM MAIL   Вверх
azesmcar
Дата 16.11.2011, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(xvr @  16.11.2011,  14:16 Найти цитируемый пост)
Если да, то описать все операции в виде класса с виртуальными методами (по 1 штуке на операцию) и телами, которые бросают исключение - 'not-implemented'.

Да, это самое первое, что пришло на ум, но операций довольно таки много, интерфейс базового класса будет похож интерфейс класса std::string smile 
В общем-то решить можно по всякому, но разве это лучший из существующих вариантов?
PM   Вверх
mes
Дата 16.11.2011, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



azesmcar, вот теперь задача обрела очертания.. 

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

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

но это забегая вперед, а теперь вернемся к текущему : 

Цитата(azesmcar @  16.11.2011,  10:12 Найти цитируемый пост)
Придется заранее разбивать на мелкие интерфейсы, сгруппировать не получиться, так-как после группировки будет невозможно дальнейшее разделение.

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

пример чуть позже.. 








--------------------
PM MAIL WWW   Вверх
baldina
Дата 16.11.2011, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(azesmcar @  16.11.2011,  07:29 Найти цитируемый пост)
Что еще нужно описать а не понимаю, Вы же все прекрасно понимаете.

это не понимание а телепатия smile
я спросил про фрагмент if (is_reсtangle) cope_rectangle(); но в ответ получил то, что и так из этой строчки ясно
Цитата(azesmcar @  16.11.2011,  10:10 Найти цитируемый пост)
Есть базовый класс geom, есть наследуемые от него разного рода геометрии. Есть predifined список операций, которые можно проводить с этими типами. Некоторые типы поддерживают все операции, некоторые нет. Например точка не поддерживает вращения, а полигон поддерживает.
Операции добавляются и изменяются чаще, чем сами типы, но необходимо оставить возможность добавлять новые типы, не изменяя исходников, так-как возможно добавление типов со стороны третьих лиц.

вот это понятно smile

Цитата(azesmcar @  16.11.2011,  09:21 Найти цитируемый пост)
код C++
Код

void MoveSelected::execute(const std::vector<geom*>& selected)
{
    for (geom* obj: selected)
        if (i_movable* m = dynamic_cast<i_movable*>(obj))
            m->move(params().x(), params.y());
}

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

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

но это мелочи, обратимся к главной задаче: требуется независимо изменять набор типов и набор операций.
для этого надо сделать типы и операции независимыми, разделить их. концептуально это означает использовать visitor.
к сожалению, это ослабляет систему типов (мы используем внеязыковые средства), но упрощает разработку и сопровождение.
с академической точки зрения тут должен последовать совет о разработке проблемно-ориентированного языка, и в итоге для упрощения реализации мы придем к использованию пакета АОП, но я не столь жесток  smile 
как реализовать?
возможность добавлять новые типы без перекомпиляции обеспечивает динамическая регистрация обработчика и карта(map) обработчиков. про это mes изложил подробно и разнообразно. в дополнение могу предложить перекладывание задачи регистрации на базовый интерфейс, типа
Код

void move_visitor (geom*);
struct IMovable {
  IMoveable () { register(uid_move, move_visitor); }
};

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

еще замечание. признаться, я не очень верю, что возможных команд очень много. с точки зрения пользователя может и много, но они наверняка классифицируются, и менеджер команд (о котором мы не говорим) в состоянии на выходе иметь ограниченный перечень.
так, например, команды преобразования move, scale, rotate etc суть одна функция transform, если для преобразований используются матрицы. тогда кстати и точку вполне можно вращать ;-)
далее, наверняка реализация команд для разных типов отличается, но этих отличий может быть не очень много и они, в свою очередь, тоже классифицируются. например, графический элемент может иметь ограничения на преобразования, связанные с его состоянием (заблокирован, "заморожен") и с состоянием связанных с ним объектов. с другой стороны, изменение элемента может повлечь изменение элементов, зависящих от него. тогда потребуется некая несложная архитектура выполнения команды типа
Код

  if (!obj->is_frozen())
  {
     obj->transform (matrix);
     obj->check_constraints ();
     obj->changed ();
  }
  

Цитата(azesmcar @  16.11.2011,  11:12 Найти цитируемый пост)
EDA инструменты

ясно. собственно на догадки меня навел пост, где присутствует команда move{0,2}, оч. похоже на всякие CADы


Это сообщение отредактировал(а) baldina - 16.11.2011, 17:09
PM MAIL   Вверх
xvr
Дата 16.11.2011, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(azesmcar @  16.11.2011,  14:23 Найти цитируемый пост)
Да, это самое первое, что пришло на ум, но операций довольно таки много,

Самое главное, что в этом базовом классе не будет ничего другого. Только интерфейсы. И их можно будет легко добавить, ничего больше не меняя
Цитата(azesmcar @  16.11.2011,  14:23 Найти цитируемый пост)
интерфейс базового класса будет похож интерфейс класса std::string

Порезать на логические части и оформить в виде иерархии интерфейсов.
Код


// This is user-extandable part
interface Movable {
 virtual void move(int x, int y) {throw NotImplemented("Movable::move");}
 virtual void ...
};

interface Scaleable {
 virtual void scale(int x, int y) {throw NotImplemented("Scaleable::scale");}
 ...
};

...

interface AllOperations : 
 Movable,
 Scaleable,
 ...
 {};

// This is library
class Figure : public AllOperations {
...
};

Пользователь может добавлять новые методы, новые группы методов, может добавить уровней иерархии в интерфейсы и т.д. и т.п. Но библиотеку придется перекомпилировать 

Цитата(azesmcar @  16.11.2011,  14:23 Найти цитируемый пост)
но разве это лучший из существующих вариантов? 

Пожалуй самый простой. Если устроит, то может и самый лучший  smile 

PM MAIL   Вверх
mes
Дата 16.11.2011, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



ловите примеси  :
http://liveworkspace.org/code/98eac02abcba...b5316128ef8154a


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

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

все представленные миксы самодостаточные, но вполне допустимы и захватывающие контекст..

кстати обратите внимание что самопонятие moveable (и ему подобные)  не являются типом и вообще исключены из рациона. 
и команда move реализуется на основе свойств.. 
Это позволяет минимизировать набор свойств и развязать руки при составлении команд.. 

Цитата(mes @  16.11.2011,  18:48 Найти цитируемый пост)
использовал авторегистрацию для типов,

вот одна из вариаций ручной ассоции типов :
http://liveworkspace.org/code/3b5206ae1eed...48112a18a4621b5

те части в которых произошли изменения :
Код

typedef int  mixid_t;
struct mix_typeinfo
{
   int id;
   std::string name;
};

template<typename> 
struct mix_type
{
   static mixid_t get_id ()
   {      
      return info.id;
   }
 
  private: 
    static mix_typeinfo info;
};
//----
template<>
mix_typeinfo mix_type<position>::info =   { 1, "position" };
template<>
mix_typeinfo mix_type<rotation>::info =   { 2, "rotation" };
template<>
mix_typeinfo mix_type<visibility>::info = { 3, "visibility" };
//----


другой подход можно позаимствовать из примера с коммандами (action_type ,  action_rawdata ( в роли идентификатора интерфейса )  )

Это сообщение отредактировал(а) mes - 17.11.2011, 10:13


--------------------
PM MAIL WWW   Вверх
math64
Дата 17.11.2011, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 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++ - здесь как раз мутаторы уместны. Но нужно иметь возможность динамического добавления свойств.
PM   Вверх
mes
Дата 17.11.2011, 10:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(math64 @  17.11.2011,  09:24 Найти цитируемый пост)
В обоих ваших примерах нельзя определить несколько свойств одного типа,

в QI нельзя получить два одинаковых интерфейса .. все зависит от задачи smile
нужнен массив точек,определите такое свойство.. 

Цитата(math64 @  17.11.2011,  09:24 Найти цитируемый пост)
И регистрировать в мутаторе лучше не объект, а геттер и сеттер.

у геттера/сеттера нет типа.. нужен отдельный геттер/сеттер сделайте такой микс.. smile

Добавлено через 1 минуту и 17 секунд
Цитата(math64 @  17.11.2011,  09:24 Найти цитируемый пост)
Вешать на них интерфейсы, мутаторы и т.д. - не рационально, всё это займёт больше места, чем сам примитив.

экономичность это следущий шаг.. пока я лишь показал какие еще варианты бывают smile
чтоб не было зацикливания на imoveable smile


--------------------
PM MAIL WWW   Вверх
math64
Дата 17.11.2011, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Цитата(mes @  17.11.2011,  10:50 Найти цитируемый пост)
у геттера/сеттера нет типа.. нужен отдельный геттер/сеттер сделайте такой микс..

Можно сделать так:
Код

class Rect {
  Point location;
  Size size;
public:
  Point getLocation() const { return location; }
  Size getSize() const { return size; }
  void selLocation(Point loc);
  void setSize(Size sz);
  static Point getLocation(const Rect&r) { return r.getLoation(); }
  static Size getSize(const Rect&r) { return r.getSize(); }
  static void setLocation(Rect&r, Point pt) { r.setLocation(pt); }
  static void setSize(Rect&r, Size sz) { r.setSize(sz); }
};

У статических методов тип уже есть - их можно добавить в map (лучше не в тот, куда добавляют объекты, а в отдельные для геттеров и сеттеров)
Но в общем, как делать уже ясно - детали зависят от конкретной реализации.
PM   Вверх
mes
Дата 17.11.2011, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(math64 @  17.11.2011,  10:53 Найти цитируемый пост)
У статических методов тип уже есть

о каком типе идет речь ? я о том который вытупает в роли идентификара свойства/интерфейса



--------------------
PM MAIL WWW   Вверх
math64
Дата 17.11.2011, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Вот такие типы:
Код

typedef Point (*PointGetterOfRect)(const Rect&r);
typedef Size (*SizeGetterOfRect)(const Rect&r);
typedef void (*PointSetterOfRect)(Rect&r, Point pt);
typedef void (*SizeSetterOfRect)(Rect&r, Size sz);


PM   Вверх
mes
Дата 17.11.2011, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(math64 @  17.11.2011,  16:15 Найти цитируемый пост)
Вот такие типы:

это не позволяет определенно и однозначно соотнести тип к методу..

а тс. чего то не видно.. или это я такой нетерпеливый.. 

Это сообщение отредактировал(а) mes - 17.11.2011, 18:49


--------------------
PM MAIL WWW   Вверх
math64
Дата 17.11.2011, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



mes, вот определяется (добавить недостающие куски из Вашего примера):
Код

typedef void(*setter)(int&,const int&); // на тот случай, если указатели на функции и обычные указатели разных размеров
std::map<mixid_t, setter> setters;
template <typename G, typename T>
  void call_setter(G& g, const T& t) {
    typedef void (*setter)(G&,const T&);
    ((setter)setters[mix_type<setter>::get_id()])(g, t);
  }

void set(figure&,const int&) { std::cout << "set" << std::endl; }

int main ()
{
  figure f1;
  void (*_setter)(figure&,const int&) = set;
  setters[mix_type<void (*)(figure&,const int&)>::get_id()] = (setter)_setter;
  int two = 2;
  call_setter(f1, two);
}

Без typedef можно обойтись.
PM   Вверх
mes
Дата 17.11.2011, 20:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(math64 @  17.11.2011,  18:48 Найти цитируемый пост)
mix_type<void (*)(figure&,const int&)>::get_id()]

ну и ? увсех сеттеров типа void (*)(figure&,const int&), а их множество, будет один и тот же тип.. 
про ограничения на кол-во аргументов мы промолчим .. 
во вторых как будет выглядить пользователем получение это сеттера.. 
да и вообще зачем нам эти сеттеры ?   интерфейсы (мутаторы) намного более симпатичны.. на один ид  отражены сразу все необходимые методы в удобном и привычном виде..
 




--------------------
PM MAIL WWW   Вверх
math64
Дата 17.11.2011, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Цитата(mes @  17.11.2011,  20:05 Найти цитируемый пост)
ну и ? увсех сеттеров типа void (*)(figure&,const int&), а их множество, будет один и тот же тип..

Так и в Вашем примере для одного типа возможен один мутатор - устранение этого ограничения аналогично.

Цитата(mes @  17.11.2011,  20:05 Найти цитируемый пост)
да и вообще зачем нам эти сеттеры ?

Ну вот нужно установить центр Rect. Поля Point center нет, а есть левый верхний угол. А если и есть, всё равно нужно сделать перерасчёт
левого верхнего угла, а если хранить и остальные углы -  то и их.
PM   Вверх
math64
Дата 17.11.2011, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Чтобы уйти от сеттеров можно использовать паттерн Observer - это рентабельно, если будем его применять для объектов высокого уровня
Код


struct Observer<T> {
virtual void onChanged(T& t, const T& old) = 0;
};

struct Rect {
  Point location;
  Size size;
  Observer<Rect>* observer;
  Rect(const Rect& r) : observer(0) {
    location = r.location; size = r.size;
  }
  Rect& operator =(const Rect&r) {
    Rect save = *this;
    location = r.location; size = r.size;
    if (observer)
     observer->onChanged(*this, save);
    return *this;
  }
};

struct Component : public Observer<Rect> {
Rect boundRect;
Component() { boundRect.observer = this; }
void onChanged(Rect& old, const Rect& _new);
};



Это сообщение отредактировал(а) math64 - 17.11.2011, 20:45
PM   Вверх
mes
Дата 17.11.2011, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(math64 @  17.11.2011,  19:43 Найти цитируемый пост)
Чтобы уйти от сеттеров можно использовать паттерн Observer - это рентабельно, если будем его применять для объектов высокого уровня

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

Цитата(math64 @  17.11.2011,  19:19 Найти цитируемый пост)
Так и в Вашем примере для одного типа возможен один мутатор - устранение этого ограничения аналогично.

один мутатор/интерфейс про ид.. или множество про один ид smile 

Цитата(math64 @  17.11.2011,  19:19 Найти цитируемый пост)
Ну вот нужно установить центр Rect. Поля Point center нет, а есть левый верхний угол. А если и есть, всё равно нужно сделать перерасчёт
левого верхнего угла, а если хранить и остальные углы -  то и их. 

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


Это сообщение отредактировал(а) mes - 17.11.2011, 23:56


--------------------
PM MAIL WWW   Вверх
math64
Дата 17.11.2011, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Observer прекрасно сочетается с Вашими мутаторами  (при разделении на примитивы, для которых применяется обычное программирование, и объекты высокого уровня) -  я не стал приводить общий пример.
Но возможно, у Вас другой взгляд на построение системы - нужно послушать ТС.

PM   Вверх
math64
Дата 17.11.2011, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Я понял Вашу концепцию - Rotatoin не хранит угол поворота,  а делает поворот (из Вшего примера это было не очень ясно - следовло бы написть комментарий). В этом случае сеттеры действительно не нужны. Обсерверы, если и нужны, то редко.
PM   Вверх
mes
Дата 17.11.2011, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(math64 @  17.11.2011,  21:12 Найти цитируемый пост)
Я понял Вашу концепцию - Rotatoin не хранит угол поворота,  а делает поворот

не совсем так, возможно как хранение даных и/или воздействие тад ними, так и проксирование действия...  все зависит от выбранной модели.. 


Цитата(math64 @  17.11.2011,  21:12 Найти цитируемый пост)
из Вшего примера это было не очень ясно - следовло бы написть комментарий

ну я  вроде бы и написал:
Цитата(mes @  16.11.2011,  18:48 Найти цитируемый пост)
все представленные миксы самодостаточные, но вполне допустимы и захватывающие контекст..


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

Цитата(math64 @  17.11.2011,  21:12 Найти цитируемый пост)
Обсерверы, если и нужны, то редко. 

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





--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 30.11.2011, 09:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Доброе утро.

Извиняюсь что пропал, ненадолого уехал из города. Сегодня попробую все осмыслить и продолжить тему.

Это сообщение отредактировал(а) azesmcar - 30.11.2011, 09:31
PM   Вверх
mes
Дата 30.11.2011, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(azesmcar @  30.11.2011,  08:30 Найти цитируемый пост)
и продолжить тему

отлично, а то у меня столько мыслей по этому поводу поднакопилось, будет повод разобрать их по полочкам smile



--------------------
PM MAIL WWW   Вверх
Страницы: (11) [Все] 1 2 3 ... Последняя »
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.5194 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.