как-то слышал о концепции, в которой код разделяются на 3 части:
1. занимается только отображением графики
2. занимается только вычислениями
3. осуществляет взаимодействие первых двух
Что касается реализации. Допустим есть 3 класса: CAnyUi (гуя), CAnyCtrl (считалка), CAny (должен ими рулить). Допустим CAnyUi ловит оконное сообщение. есть обработчик этого сообщения CAnyUi::on_command(). это сообщение по идее, должен обработать CAnyCtrl. Так вот вопрос — как можно передать это сообщение CAnyCtrl не нарушив данной концепции?
1. заюзать множественное наследование: CAny : public CAnyUi, public CAnyCtrl. соответственно появляется возможность на своё усмотрение переопределять метод CAnyUi::on_command() и вызывать соответствующий метод CAnyCtrl.
2. добавить в CAnyUi колбек обработчик. то есть на on_command функция, которая уже вызывает соответствующий метод CAnyCtrl.
собственно вопрос. может я что-то упускаю? множественное наследование юзать неохота, да и с колбеками как-то криво получится...
07.08.09 15:58: Перенесено модератором из 'Алгоритмы' — Кодт
Здравствуйте, cupuyc, Вы писали:
C>как-то слышал о концепции, в которой код разделяются на 3 части:
C>1. занимается только отображением графики C>2. занимается только вычислениями C>3. осуществляет взаимодействие первых двух
Model — View — Controller со всеми вариациями. Вообще-то если Вы поищете по RSDN по этим словам — найдёте очень много интересного.
C>Что касается реализации. Допустим есть 3 класса: CAnyUi (гуя), CAnyCtrl (считалка), CAny (должен ими рулить). Допустим CAnyUi ловит оконное сообщение. есть обработчик этого сообщения CAnyUi::on_command(). это сообщение по идее, должен обработать CAnyCtrl. Так вот вопрос — как можно передать это сообщение CAnyCtrl не нарушив данной концепции?
C>1. заюзать множественное наследование: CAny : public CAnyUi, public CAnyCtrl. соответственно появляется возможность на своё усмотрение переопределять метод CAnyUi::on_command() и вызывать соответствующий метод CAnyCtrl.
C>2. добавить в CAnyUi колбек обработчик. то есть на on_command функция, которая уже вызывает соответствующий метод CAnyCtrl.
Однозначно второе (коллбэк). Хотя бы потому, что ничто не должно мешать определить несколько одновременно действующих отображений (например, одно рисует текущую картину, второе — графики изменения, а третье — оповещает о наступлении каждой сотой итерации звонок над головой:) В один класс ты их не впихнёшь.
C>собственно вопрос. может я что-то упускаю? множественное наследование юзать неохота, да и с колбеками как-то криво получится...
С коллбэками — да, их надо творить на каждое действие (функцией-скопом или раздельно — это уже как удобнее), но получится то что надо.
Здравствуйте, cupuyc, Вы писали:
C>тогда такой вопрос. как лучше реализовать колбеки? можно опять-же унаследовать класс, типа:
Прошу не срезать существенное в квотинге. Не всем удобен древовидный показ.
C>CAny : public CAnyUi
C>и перехваченые меоды — по сути дела колбеки.
Нет.
C> или же в самом CAnyUi хранить список указателей на функции и вызывать их в соответствующих методах?
Вариант 1 — ручное заполнение списка коллбэков. Иногда хорошо, но обычно громоздко.
Вариант 2 — производить CAnyCtrl от чисто виртуального класса (интерфейса) с нужными коллбэками (назовём CAnyUICallback) и в реализации CAnyCtrl писать для них методы. В CAnyUI передавать указатель на объект CAnyCtrl, но храниться там он будет как CAnyUICallback*.
Вариант 3 — оформлять сообщения и передавать их в CAny общему обработчику, который дальше будет или сам в CAnyCtrl передавать раздельно, или вызывать такой же общий обработчик.
Есть ещё много промежуточных вариантов.
The God is real, unless declared integer.
Re: разделение кода на графику и управление
От:
Аноним
Дата:
27.07.09 10:57
Оценка:
я так понимаю, в идеале View и Control вообще не должны явно взаимодействовать? то есть, View посылает сообщения, Control изменяет данные, View отображает изменённые данные. Model ничего не знает о Control и View. Control ничего не знает о View — он лишь реагирует на сообщения, а View может только читать Model и отсылать уведомления Control'у. так?
Здравствуйте, Аноним, Вы писали:
А>я так понимаю, в идеале View и Control вообще не должны явно взаимодействовать? то есть, View посылает сообщения, Control изменяет данные, View отображает изменённые данные. Model ничего не знает о Control и View. Control ничего не знает о View — он лишь реагирует на сообщения, а View может только читать Model и отсылать уведомления Control'у. так?
Заморочаешся кодировать раздельные View и Controller, лучше их объединять.
Здравствуйте, gyraboo, Вы писали:
А>>я так понимаю, в идеале View и Control вообще не должны явно взаимодействовать? то есть, View посылает сообщения, Control изменяет данные, View отображает изменённые данные. Model ничего не знает о Control и View. Control ничего не знает о View — он лишь реагирует на сообщения, а View может только читать Model и отсылать уведомления Control'у. так?
G>Заморочаешся кодировать раздельные View и Controller, лучше их объединять.
Замучаешься если во view все запихать. А так если уметь готовить то все хоккей.
WBR, Igor Evgrafov
Re[3]: разделение кода на графику и управление
От:
Аноним
Дата:
28.07.09 03:08
Оценка:
Здравствуйте, gyraboo, Вы писали:
G>Здравствуйте, Аноним, Вы писали:
А>>я так понимаю, в идеале View и Control вообще не должны явно взаимодействовать? то есть, View посылает сообщения, Control изменяет данные, View отображает изменённые данные. Model ничего не знает о Control и View. Control ничего не знает о View — он лишь реагирует на сообщения, а View может только читать Model и отсылать уведомления Control'у. так?
G>Заморочаешся кодировать раздельные View и Controller, лучше их объединять.
чем лучше? может проще? понятно что на первом этапе будет проще. а если ты вместо GDI захочешь сделать OpenGL — переписывать всю графику, так ещё и управление?
Здравствуйте, cupuyc, Вы писали:
C>как-то слышал о концепции, в которой код разделяются на 3 части:
C>1. занимается только отображением графики C>2. занимается только вычислениями C>3. осуществляет взаимодействие первых двух
А в чём принципиальная разница по сравнению с обычным представлением документ-вид, где вся расчётная часть находится в отдельном длл или ком-объекте?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, gyraboo, Вы писали:
G>>Здравствуйте, Аноним, Вы писали:
А>>>я так понимаю, в идеале View и Control вообще не должны явно взаимодействовать? то есть, View посылает сообщения, Control изменяет данные, View отображает изменённые данные. Model ничего не знает о Control и View. Control ничего не знает о View — он лишь реагирует на сообщения, а View может только читать Model и отсылать уведомления Control'у. так?
G>>Заморочаешся кодировать раздельные View и Controller, лучше их объединять.
А>чем лучше? может проще? понятно что на первом этапе будет проще. а если ты вместо GDI захочешь сделать OpenGL — переписывать всю графику, так ещё и управление?
Скорее всего не захочу.
А лучше — тем что обычно вид-контроллер так связаны, что если приходится переписывать вид, то и систему контроллеров тоже.
Насчет GDI/OpenGL — эту часть я бы вообще к виду как части MVC не относил. Ведь под видом понимается логический вид, содержащий элементы интерфейса
и структуры данных, связывающие их с соотв.элементами модели, но никак не физическая реализация рендеринга.
При правильной реализации MVC замена одного рендерера другим вообще не должна затрагивать mvc-вид.
Re[5]: разделение кода на графику и управление
От:
Аноним
Дата:
28.07.09 08:07
Оценка:
G>Скорее всего не захочу. G>А лучше — тем что обычно вид-контроллер так связаны, что если приходится переписывать вид, то и систему контроллеров тоже. G>Насчет GDI/OpenGL — эту часть я бы вообще к виду как части MVC не относил. Ведь под видом понимается логический вид, содержащий элементы интерфейса G>и структуры данных, связывающие их с соотв.элементами модели, но никак не физическая реализация рендеринга. G>При правильной реализации MVC замена одного рендерера другим вообще не должна затрагивать mvc-вид.
я имею ввиду именно графику. именно отображение информации конечному пользователю. нужно, например, написать шахматы:
— массив с фигурками — Model
— логика игры (перемещение фигур, определение выигровшего и т.п.) — Control
— окошко с нарисованными на нём фигурами — View.
следовательно: юзер перемещает фигуру — View, получив соответствующее оконное сообщение, отправляет уведомление Control'у. Control получает уведомление, анализирует его и, если надо, модифицирует Model. Затем View отображает Model.
вот и получаем что View работает только с окошками, Control — только с логикой, Model просто хранит данные и организует доступ к ним.
Здравствуйте, Аноним, Вы писали:
А>я имею ввиду именно графику. именно отображение информации конечному пользователю. нужно, например, написать шахматы: А> — массив с фигурками — Model А> — логика игры (перемещение фигур, определение выигровшего и т.п.) — Control
Не, вот тут неправильно. Логика игры находится тоже в модели. Контроллер же отвечает за соответствие модели-вида тому что изменяет пользователь.
Т.е. его задача только в том чтобы считать input и изменить вид и/или модели.
А> — окошко с нарисованными на нём фигурами — View.
А>следовательно: юзер перемещает фигуру — View, получив соответствующее оконное сообщение, отправляет уведомление Control'у. Control получает уведомление, анализирует его и, если надо, модифицирует Model. Затем View отображает Model. А>вот и получаем что View работает только с окошками, Control — только с логикой, Model просто хранит данные и организует доступ к ним.
Получается так:
— юзер клинул на фигуру которую хочет переместить
— контроллер перехватил клик мышки и оповестил модель
— модель изменила "активную фигуру"
— вид, подписанный на это изменение, перерисовывает активную фигуру, скажем выделяет её мерцанием
— юзер кликает в новую клетку куда перемещать фигуру
— контроллер перехватывает клик и оповещает модель
— модель перемещает фигуру и оповещает вид об этом
— вид перерисовыват фигуру на новом месте
Re[7]: разделение кода на графику и управление
От:
Аноним
Дата:
28.07.09 11:19
Оценка:
G>Получается так: G> — юзер клинул на фигуру которую хочет переместить G> — контроллер перехватил клик мышки и оповестил модель G> — модель изменила "активную фигуру" G> — вид, подписанный на это изменение, перерисовывает активную фигуру, скажем выделяет её мерцанием G> — юзер кликает в новую клетку куда перемещать фигуру G> — контроллер перехватывает клик и оповещает модель G> — модель перемещает фигуру и оповещает вид об этом G> — вид перерисовыват фигуру на новом месте
нет, что-то я не допонимаю.
1. обработкой оконных сообщений занимается только View.
2. пришло сообщение WM_LBUTTONDOWN => view вызвал соответствующий обработчик из таблицы (типа on_selecting_cell(column, line)). таблица — массив указателей, или указатель на базовый виртуальный класс (vftable).
3. контроллер — конкретная реализация этого абстрактного класса. вызвался метод on_selecting_cell — контроллер вызывает соответствующий метод модели.
вопрос — зачем контроллер, если on_selecting_cell может напрямую идти модели? возможно, может быть проблема лишь с реализацией — придётся наследовать модель от абстрактного класса, которому передаёт сообщения View. но это, вообще говоря, не проблема.
Здравствуйте, Аноним, Вы писали:
G>>Получается так: G>> — юзер клинул на фигуру которую хочет переместить G>> — контроллер перехватил клик мышки и оповестил модель G>> — модель изменила "активную фигуру" G>> — вид, подписанный на это изменение, перерисовывает активную фигуру, скажем выделяет её мерцанием G>> — юзер кликает в новую клетку куда перемещать фигуру G>> — контроллер перехватывает клик и оповещает модель G>> — модель перемещает фигуру и оповещает вид об этом G>> — вид перерисовыват фигуру на новом месте
А>нет, что-то я не допонимаю. А>1. обработкой оконных сообщений занимается только View. А>2. пришло сообщение WM_LBUTTONDOWN => view вызвал соответствующий обработчик из таблицы (типа on_selecting_cell(column, line)). таблица — массив указателей, или указатель на базовый виртуальный класс (vftable). А>3. контроллер — конкретная реализация этого абстрактного класса. вызвался метод on_selecting_cell — контроллер вызывает соответствующий метод модели.
А>вопрос — зачем контроллер, если on_selecting_cell может напрямую идти модели? возможно, может быть проблема лишь с реализацией — придётся наследовать модель от абстрактного класса, которому передаёт сообщения View. но это, вообще говоря, не проблема.
Верно, отдельный контроллер нафиг не нужен, его с видом объединять нужно, например как ты и описал.
Здравствуйте, gyraboo, Вы писали:
G>Здравствуйте, Аноним, Вы писали:
G>>>Получается так: G>>> — юзер клинул на фигуру которую хочет переместить G>>> — контроллер перехватил клик мышки и оповестил модель G>>> — модель изменила "активную фигуру" G>>> — вид, подписанный на это изменение, перерисовывает активную фигуру, скажем выделяет её мерцанием G>>> — юзер кликает в новую клетку куда перемещать фигуру G>>> — контроллер перехватывает клик и оповещает модель G>>> — модель перемещает фигуру и оповещает вид об этом G>>> — вид перерисовыват фигуру на новом месте
А>>нет, что-то я не допонимаю. А>>1. обработкой оконных сообщений занимается только View. А>>2. пришло сообщение WM_LBUTTONDOWN => view вызвал соответствующий обработчик из таблицы (типа on_selecting_cell(column, line)). таблица — массив указателей, или указатель на базовый виртуальный класс (vftable). А>>3. контроллер — конкретная реализация этого абстрактного класса. вызвался метод on_selecting_cell — контроллер вызывает соответствующий метод модели.
А>>вопрос — зачем контроллер, если on_selecting_cell может напрямую идти модели? возможно, может быть проблема лишь с реализацией — придётся наследовать модель от абстрактного класса, которому передаёт сообщения View. но это, вообще говоря, не проблема.
G>Верно, отдельный контроллер нафиг не нужен, его с видом объединять нужно, например как ты и описал.
прошу прощения. ступил. всё. дошло. контроллер только лишь занимается отсылкой сообщений модели.
Здравствуйте, cupuyc, Вы писали:
C>как-то слышал о концепции, в которой код разделяются на 3 части:
C>1. занимается только отображением графики C>2. занимается только вычислениями C>3. осуществляет взаимодействие первых двух
C>Что касается реализации. Допустим есть 3 класса: CAnyUi (гуя), CAnyCtrl (считалка), CAny (должен ими рулить). Допустим CAnyUi ловит оконное сообщение. есть обработчик этого сообщения CAnyUi::on_command(). это сообщение по идее, должен обработать CAnyCtrl. Так вот вопрос — как можно передать это сообщение CAnyCtrl не нарушив данной концепции?
C>1. заюзать множественное наследование: CAny : public CAnyUi, public CAnyCtrl. соответственно появляется возможность на своё усмотрение переопределять метод CAnyUi::on_command() и вызывать соответствующий метод CAnyCtrl.
C>2. добавить в CAnyUi колбек обработчик. то есть на on_command функция, которая уже вызывает соответствующий метод CAnyCtrl.
C>собственно вопрос. может я что-то упускаю? множественное наследование юзать неохота, да и с колбеками как-то криво получится...
Почитай про паттерны MVP [Model-View-Presenter] и MVC [Model-View-Controller] — выберешь, что тебе больше подходит.
А не хочешь, подписать на оконное событие сам CAny [Presenter] (по-хорошему — на событие CAnyUi [View], которое делегирует оконное событие)?
Идея "разделения на 3 части" предполагает повышение заменяемости модулей — "провязывание" зависимостей через интерфейсы, а не через классы.
И для уменьшения количества зависимостей (пусть и от интерфейсов), надо стараться делать так, чтобы только Presenter "знал" про модели [Model] и представления [View], а они про него — нет.
Т.е. вызывать метод CAnyCtrl из CAnyUi — не есть хорошо.
Также, как и делать мешанину, наследуя презентер от модели и представления...