Просмотр полной версии : Хорошее MVC
Psycho Tiger
11.01.2011, 13:35
Да, в контроллере.
Привет всем, тему не осилил(прочитал все, но в башке - каша), поэтому спрашиваю, контроллер(предположим игры) создает контроллер игрока, уровня и врага. Контроллер игрока в свою очередь создает модель игрока и вьюшку игрока, с уровнем и врагом - также, дальше что? модели ни про свои ни про чужие вьюшки не знают, расчет движения игрока/врага происходит в контроллере игры? Как устроить проверку столкновений? Или я путаю теплое с мягким?
ЗЫ. Код приводить не надо, тезисно.
Контроллер игрока модель игрока не создает.
Размер топика уже превосходит здравые границы. В топике повторяются вопросы и ответы. Потому, что каждому вновь спрашивающему не осилить уже всё написанное ранее, проще еще раз спросить.
Как будет выглядеть MVC для проекта на Papervision3D?
Zebestov
22.01.2011, 22:42
Я не большой мастак, но подозреваю, что MVC в Papervision3D и ему подобных самое последнее, о чем стоит заботиться. Там приоритет №1 — скорость, а не элегантность.
ясно, тогда другой вопрос - насколько сильно упадет скорость приложения, при использовании MVC?
Возьмем например гамес уровня TD и ТаймЗэро.
Zebestov
23.01.2011, 03:28
Ну это разговор ни о чем. Игры уровня TD никак не пострадают от использования MVC. Как вообще в данном случае можно сравнивать 3d движок и казуальную игру?
Возьмем например гамес уровня TD и ТаймЗэро.
Без MVC TimeZero валила бы Core i7 на раз-два.
Я бы сказал по другому: без mvc, чтобы TimeZero не валила бы Core i7 на раз-два, пришлось бы приложить гораздо больше усилий, и не факт что получилось бы так же хорошо.
Psycho Tiger
23.01.2011, 19:21
Без MVC TimeZero валила бы Core i7 на раз-два.
MVC для скорости? Всегда видел в нём небольшой упадок в ней в угоду сильно возрастающему удобству разработки.
Расскажи пожалуйста за счет чего, по твоему мнению, из за MVC появляется megaboost в скорости?
Dukobpa3
24.01.2011, 09:56
Всегда видел в нём небольшой упадок в ней в угоду сильно возрастающему удобству разработки.
Как по мне - внятная архитектура и есть залогом производительности. А как ты сам несколько раз повторял в своих постах - МВЦ у всех разный;)
Psycho Tiger
24.01.2011, 13:46
Поменять текущее имя игрока:
1) Кривоархитектура с логикой и отображение в одном классе:
1.1) Поменять поле класса
2.2) Обновить новое значение визуально
2) MVC:
2.1) Диспатч события об изменении
2.2) Поймали событие, меняем модель
2.3) Поменяли модель, рассылаем событие
2.4) Ловим событие, обновляем отображение
На фоне общей картины это микроны, но отчего MVC даёт производительность я не понимаю. Только удобство, имхо.
Dukobpa3
24.01.2011, 21:02
скорее не так:)) Твой пример на подгонку фактов похож уж слишком)
Поменять текущее имя игрока:
1) MVC:
1.1) Диспатч события об изменении
1.2) Поймали событие, меняем модель
1.3) Поменяли модель, рассылаем событие
1.4) Ловим событие, обновляем отображение
2) Кривоархитектура с логикой и отображение в одном классе:
2.1) Диспатч события об изменении (ввели в поле, нажали ок)
2.2) Поймали событие
2.3) Выполнили с десяток непонятных действий, объяняемых тем что архитектура писалась кучей программистов
2.4) И еще десяток действий
2.4.хх) Не забываем что в процессе написания поправили я пяток-другой классов чтоб предыдущие пункты выполнялись.
2.5) теперь у нас есть переменная с именем новым (и старым)
2.6) для верности продублировали в десяток переменных
2.7) послали в базу данных
2.8) оно до базы не дошло (почему-то О_о)
2.9) поправили еще с пяток классов
....................
Ну и в таком духе. Так и блуждет наше нажатие на кнопку "Ок" при смене Никнейма по всей системе, плодя за собой еще целые кучи событий и кучи переменных....
Psycho Tiger
24.01.2011, 22:28
Ещё до начала пользования MVC код у меня был более-менее, так что не разделяю :)
Вот я кретин - у Мука зоопарк был построен на MVC - пойду перечитаю...
MVC для скорости? Всегда видел в нём небольшой упадок в ней в угоду сильно возрастающему удобству разработки.
Расскажи пожалуйста за счет чего, по твоему мнению, из за MVC появляется megaboost в скорости?
В централизации событий. Не нужно бегать по всем контролам и обновлять данные. Нет посредников в операции обновления.
Psycho Tiger
25.01.2011, 12:45
Спасиб.
Цель MVC - отделить то, что на экране от того, что происходит логикой. Короче, если проект расчитывался как консольный, а потом вдруг трах тибидох и хотим 3д - надо будет менять лишь вьюшку.
если в контроллере происходит расчет коллизий, а мы вдруг трах тибидох и 3d, контроллер тоже надо будет менять, так как в расчете столкновений появляется z координата, и модель наверно тоже надо будет дополнить?
если я туплю не пинайте сильно, модель может состоять из 5-7 классов?
если в контроллере происходит расчет коллизий, а мы вдруг трах тибидох и 3d, контроллер тоже надо будет менять, так как в расчете столкновений появляется z координата, и модель наверно тоже надо будет дополнить?
если я туплю не пинайте сильно, модель может состоять из 5-7 классов?
Столкновения визуальных объектов должен рассчитывать View, и результат(столкнулся/не столкнулся) отдавать контроллеру.
terbooter
01.03.2011, 17:10
Столкновения визуальных объектов должен рассчитывать View, и результат(столкнулся/не столкнулся) отдавать контроллеру.
Очень спорное утверждение
Столкновения визуальных объектов должен рассчитывать View, и результат(столкнулся/не столкнулся) отдавать контроллеру.
у меня 10 вьюшек которые ничего друг о друге не знают. у них есть модели, а у контроллера есть и модели и вьюхи
Psycho Tiger
01.03.2011, 17:29
Столкновения визуальных объектов должен рассчитывать View, и результат(столкнулся/не столкнулся) отдавать контроллеру.
Минус. Столкновение — это логика.
Минус. Столкновение — это логика.
И где оно тогда будет рассчитываться?
terbooter
01.03.2011, 18:14
надо смотреть на конкретный случай, что это за объекты.
Если их границы определены математически (сфера или куб),
то явно не вьюха должна рассчитывать коллизии, а контроллер.
Если используется hitTest (уже про 2D), то можно и во вьюхе. Но, имхо, лучше тоже в контроллере.
надо смотреть на конкретный случай, что это за объекты.
vHuman расширяет DisplayObject3D - это papervision3d.
наверно нужно написать еще collisionController в который будут передаваться модели от вьюшек, которые нуждаются в расчете столкновений, и он то и будет отчитываться геймКонтроллеру о столкновениях на основе математических вычислений данных из моделей.
Но, имхо, лучше тоже в контроллере.
По таймерам и enterFrame-ам?
Psycho Tiger
01.03.2011, 18:58
И где оно тогда будет рассчитываться?
А с чего вьюха то начала управлять логикой?
Получается, что вьюха сама двигает объекты, не читая данные из модели (т.к. писать в модель она не может по определению).
Получается, что вьюха сама двигает объекты, не читая данные из модели (т.к. писать в модель она не может по определению).
Вьюха только сообщает, что произошёл хиттест вот этого и вот этого. Что с этим делать — решает контроллер.
Но оперировать с display-объектами контроллер не должен.
Psycho Tiger
01.03.2011, 19:24
Вьюха только сообщает, что произошёл хиттест вот этого и вот этого. Что с этим делать — решает контроллер.
Но оперировать с display-объектами контроллер не должен.
Спорно. Может действительно удобней. Удаляюсь думать.
@etc, bgg, спасибо.
Вьюха только сообщает, что произошёл хиттест вот этого и вот этого. Что с этим делать — решает контроллер.
Но оперировать с display-объектами контроллер не должен.
ок, возьмем 2d, передвигается мувик, допустим автомобиль, на пути следования автомобиля стоит столб(другой мувик). Контроллер получает событие от клавы, что машинка должна двигаться вперед, и меняет модельАвто.х и модельАвто.у, вьюхаАвто, услышав изменение модели - передвигается в новые координаты. как вьюхаАвто узнает, что влупилась в столб?
Psycho Tiger, спорно ровно до того момента, когда мы поменяем вьювер. И тогда контроллер, который гонял квадратики, с шариками уже не управится.
cr0w312, никак, ей это не нужно. Узнает вьювер всей трассы, сообщит контроллеру. Контроллер уже дальше решит, сломать машинку или нет (оперируя только моделью машины, а не её вьювером!). Либо другой вариант — контроллер перед изменением координат сначала узнает, можно ли в них попасть. А вот у кого он это узнает, от модели или от вьювера — зависит от конкретного проекта.
cr0w312, никак, ей это не нужно. Узнает вьювер всей трассы, сообщит контроллеру. Контроллер уже дальше решит, сломать машинку или нет (оперируя только моделью машины, а не её вьювером!). Либо другой вариант — контроллер перед изменением координат сначала узнает, можно ли в них попасть. А вот у кого он это узнает, от модели или от вьювера — зависит от конкретного проекта.
Браво. Вопрос исчерпан, спасибо(отзывы к твоим постам почему-то не добавляются:( )!
Psycho Tiger
01.03.2011, 20:21
Psycho Tiger, спорно ровно до того момента, когда мы поменяем вьювер. И тогда контроллер, который гонял квадратики, с шариками уже не управится.
Ну, ага. А в случае если они должны отскочить при пересечении то придётся ещё менять и контроллер: физика столкновений квадрата не такая, как у круга. Обобщая чуть дальше можно придти к выходу, что в "более общем" подходе в контроллер нужно ещё передавать и характер столкновения и вообще много чего, вроде состояния объектов после столкновения.
Спорно сколько информации должен сообщить вью контроллере при столкновении.
terbooter
02.03.2011, 00:55
Либо другой вариант — контроллер перед изменением координат сначала узнает, можно ли в них попасть. А вот у кого он это узнает, от модели или от вьювера — зависит от конкретного проекта.
По Таймеру или enterFrame-у ?
Psycho Tiger
02.03.2011, 01:04
@terbooter: это где ты такой пост увидел? =)
@etc, в цитате terbooter`а: Вот это уже как я обычно делаю.
@terbooter: это где ты такой пост увидел? =)
@etc, в цитате terbooter`а: Вот это уже как я обычно делаю.
оффтоп: это пост первую строчку которого ты процитировал 3 поста назад. А на форуме есть тег сполера?
По Таймеру или enterFrame-у ?
По событию от вью «Я хочу туда!». А туда нельзя, например.
Добавлено через 3 минуты
Ну, ага. А в случае если они должны отскочить при пересечении то придётся ещё менять и контроллер: физика столкновений квадрата не такая, как у круга. Обобщая чуть дальше можно придти к выходу, что в "более общем" подходе в контроллер нужно ещё передавать и характер столкновения и вообще много чего, вроде состояния объектов после столкновения.
Спорно сколько информации должен сообщить вью контроллере при столкновении.
Пусть отскакивают, контроллеру на это наплевать. Ему нужно знать, кто с кем столкнулся и какие последствия. Непосредственно физики в нём нет.
Въехав, например, на машине в столб, твоей страховой совершенно пофиг, под каким углом и сколько раз тебя крутило вокруг оси, ей интересен лишь ущерб.
Пусть отскакивают, контроллеру на это наплевать. Ему нужно знать, кто с кем столкнулся и какие последствия. Непосредственно физики в нём нет.
Въехав, например, на машине в столб, твоей страховой совершенно пофиг, под каким углом и сколько раз тебя крутило вокруг оси, ей интересен лишь ущерб.
трассаView.as
var объектыДляОбсчетаСтолкновений:Array = new Array();
объектыДляОбсчетаСтолкновений.push(мувикСтена);
объектыДляОбсчетаСтолкновений.push(мувикСтолб);
мувикАвто.addEventListener(Event.CHANGE_POSITION, проверкаКоллизийHandler);
private function проверкаКоллизий(e:Event):void
{
for(var i:int=0;объектыДляОбсчетаСтолкновений.length;i++)
{
if(e.currentTarget.hitTestObject(объектыДляОбсчетаСтолкновений[i])
{
super.dispatchEvent(new Event(Event.МАШИНКА_ВЛУПИЛАСЬ));
}
}
}
контроллер услышал событие а как он узнает какая именно машинка влупилась?
и предположим контроллер узнал какая машинка попала в дтп, машинка начинает вращаться а заставляет ее вращаться контроллер машинки, изменяя ее модель?
Psycho Tiger
02.03.2011, 13:46
Пусть отскакивают, контроллеру на это наплевать. Ему нужно знать, кто с кем столкнулся и какие последствия. Непосредственно физики в нём нет.
Въехав, например, на машине в столб, твоей страховой совершенно пофиг, под каким углом и сколько раз тебя крутило вокруг оси, ей интересен лишь ущерб.
Физики нет в контроллере? Тогда вью говорит контроллеру какие последствия и вью, без раздумий, меняет модель на основании того, что подсказала вьюха?
Psycho Tiger, это зависит от того, какие именно данные находятся в модели. Если это бильярд, например, то значения x, y, скорости и прочие параметры не нужны в модели. В модели только номер шара и в лунке он или нет. Вью получает коллекцию шаров и гоняет её по экрану, с собственными координатами. При попадании в лунку, шлёт событие. Далее контроллер решает, что забита 8-ка, то значит начисляем столько-то. Физики в контроллере нет, он рулит только по правилам игры.
Безусловно, смотря что понимать под контроллером. Гоняющий шары вью — это в некотором понимании контроллер физики + вью. В моём личном понимании контроллер занимается бизнес-логикой.
Psycho Tiger
02.03.2011, 20:54
Хм, забавно. Я всегда представлял себе модель как "полное состояние игры", по которому можно восстановить процесс игры полностью. То есть, имея на руках модель и сериализатор этой модели можно сохранить её куда нибудь (например, в SharedObject), а потом загрузить, получив ту же самую ситуацию. То есть угол поворота шарика для бильярда — речь о том угле, который крутит шар в оси, который, по сути, меняет только положение циферки-номера шара на шаре — вот он не попадает в модель, потому что неважный. А координаты, соответственно, попадают.
Вообще именно ты мне рассказал об MVC и образовал в моей голове костяк информации об этой теме, а сейчас рушишь мои пирамиды знаний )
Как на самом деле?
И координаты не попадают :)
В модели хранится ровно та информация, которая действительно необходима всему приложению.
Psycho Tiger
02.03.2011, 22:31
В бильярде я вижу такую модель игры:
GameModel
- Players:Player (Array)
- Balls:Ball (Array)
- turnId:int (индекс в массиве players)
- misc (ерунда, вроде рейтинговый матч или нет/and so on)
Соответственно Ball имеет x,y,scored,num.
Почему x,y не нужны всему приложению? Они нужны вьюхе. Кроме того, получив состояние игры с сервера нужно как-то расположить шары на поле. Приказывать вьюхе прямо? Последнее время мне совсем не нравится это дело. Приказы контроллер-вью я передаю через модель.
x, y больше никому, кроме вью и не нужен, соответственно нет смысла хранить это и на сервере, он все равно не справится с контролем каждого клиента.
Psycho Tiger
02.03.2011, 23:34
Ну так, примерно понятно. То есть можно трактовать это так: "в модели хранится то, что гипотетически может быть послано на сервер". В двойных кавычках, конечно.
он все равно не справится с контролем каждого клиента.
Объясни про вот это пожалуйста.
По мне, тут нет однозначного правила.
В ммо - всегда хранятся координаты персонажей, например.
В бильярде - Xто Знает. Как решено проверять логику, если не надо проверять на физику ударов от читеров, то координаты и не нужны.. Хотя для реконнектов всё равно пригодились бы..
Ну вот, вернулись в самое начало. Что хранит в себе модель? Контроллер знает о координатах вью, но меняет их через модель которой эти координаты как мертвому припарка. Или как? в модели есть состояния - идет/стоит, а вьюха видя состояние модели чалится вперед/стоит на месте, то-есть алгоритм движения во вьюшке а управляет этим алгоритмом контроллер через состояние модели?
Добавлено через 2 часа 6 минут
А. Модель хранит в себе то, что необходимо в конкретной ситуации(имеется ввиду не в определенный момент времени, а реализация проекта)? Контроллер принимает решения типа "Нада памыть пасуду" и т.п. а вьюшка уже идет и моет посуду, идет она по своей воле ее не толкает контролер, а модель просто знает чем сейчас занята вьюшка, и если пользователь пхнет мышой во вьюшку, мол хватит, вьюшка сама по себе не перестанет мыть посуду(ну чисто визуально), она посылает контроллеру вопрос - мол хватит?, контроллер оценит степень чистоты посуды и вынесет решение - модель, мыть посуду еще 10 секунд. Вьюшка слушает изменения модели и через 10 сек заканчивает. Ну вот, снова получилось "на пальцах" и никакой конкретики.
Psycho Tiger, ну вот, в бильярде координаты серверу уж точно не нужны. Он просто не сможет гонять шары для всех-всех пользователей, никаких серверов не хватит (это к твоему вопросу насчет контроля).
Котяра, а что реконнект, клиент может и не закрывать сессию, отвалился-подключился, сервер состояние и так помнит.
cr0w312, насчет изменения координат — всё зависит от конкретного проекта. В общем случае обязанности не распределишь. Если это бильярдный шар, то гоняет его вьювер-контейнер. Если это персонаж на локации, то его может гонять сама модель по заранее просчитаному пути, например. Если машинка какая-то, то тут уже контроллер ею может управлять.
Про мытьё посуды почти так, только модель о вьюверах вообще ничего не знает никогда. Контроллер при получении события может оценить прогресс и, либо остановить процесс, путем изменения состояния модели, либо продолжить.
Dukobpa3
03.03.2011, 18:50
Могу пример привести из моего любимого Toribash.
Физика там вся в клиенте, во вьюхе.
На сервак отправляются просто команды следующего хода - согнуть коленку, выпрямить локоть.
Сервак пересылает клиенту номер рас команды от клиента номер два, а клиенту номер два команды от клиента номер рас.
Потом оба клиента получив оба пакета команд у себя это отрисовывают, независимо от сервера (модели).
Как-то так. Такую же картину вижу и в бильярде. Если это мультиплей то координаты х.у. модели не нужны, (под моделью в данной ситуации я понимаю модель игры на сервере), в модели хранится только последний удар. Кто ударил по какому шару, и в какой точке. А дальше обе вьюхи оппонентов без проблем могут по серии этих ударов воссоздать всю партию. Так как физика в обоих вьюхах одинаковая.
Dukobpa3, ну да, примерно так. Только физику надо округлять, чтобы точно было одинаково.
Dukobpa3
03.03.2011, 23:39
Немного не флешовый вопрос.
Рисую архитектуру сервера на питоне. Прошу поглядеть и поправить.
Заранее спасибо.
26134
И второй вариант:
26133
Я слегка запутался))
terbooter
04.03.2011, 09:50
Про бильярд.
Вьюха которая гоняет шары, это уже полноценный модуль, который я бы тоже строил по архитектуре МВЦ.
То есть есть большое МВЦ - это весь проект клиента. Там команды выполняют бизнес-логику своего уровня (счет, победа, новая игра). И вот одна из вьюх большого МВЦ тоже устроена по схеме МВЦ - это маленькая МВЦ. Там есть своя модель, которая хранит координаты шариков, и свои команды, которые по enter frame гоняют шарики.
Если мы захотим сделать минимэп бильярдного поля - нет проблем, делаем в Большом МВЦ команду, которая будет спрашивать убольшой вьюхи координаты всех шаров. А большая вьюха хранит эти координаты в маленькой модели.
Dukobpa3
04.03.2011, 09:54
terbooter, ну вообще тут страниц пять обсуждения мусолили то что каждый элемент триады может в свою очередь быть триадой :)
terbooter
04.03.2011, 09:54
Мне очень нравится сравнение конструирования ПО со строительством. (Шаблоны проектирования вначале появились именно в архитектуре зданий=))
Так вот если мы строим город, то применяем некоторый шаблон. У нас есть спальные районы, бизнес-районы, парки отдыха. Если увеличить масштаб, то можно увидеть повторение этого же шаблона - в каждом районе есть столовая, детсад и школа. Если еще увеличить, то в каждой квартире есть спальня, кухня, рабочий кабинет. Опять тот же шаблон.
Так почему в проекте один шаблон ДОЛЖЕН быть применет ТОЛЬКО ОДИН раз?
Добавлено через 4 минуты
Dukobpa3, не сомневаюсь. Я внимательно читаю эту тему, как и все остальные темы в которых я пишу.
Потому и еще раз напомнил, про вложенность. А то про это как то забывается у многих
Вот меня сильно интересует вложенность
предположим
/***********************************************
** класс главной вьюшки **
***********************************************/
package
{
public class View extends Sprite
{
private var _model:Model;
public function View(model)
{
_model = model;
this.addListener(MouseEvent.MOUSE_CLICK, onMouseClickAddNewMVC);
}
private function onMouseClickAddNewMVC(e:MouseEvent):void
{
var cController:CarController = new CarController(this);
}
}
}
/***********************************************
** класс КарКонтроллер **
***********************************************/
package
{
public Class CarController
{
private var _host:View;
public funcrion CarController(parentView)
{
_host = parentView;
var cModel:CarModel = new CarModel();
var cView:CarView = new CarView(cModel);
_host.addChild(cView);
}
}
}
так верно или я путаю тёплое с мягким?
Psycho Tiger
04.03.2011, 15:35
Dukobpa3, terbooter, фух, вы меня успокоили =) Да, у меня каждый элемент тоже триада. etc мне говорил про самую "большую" структуру приложения, а я больше углублялся именно в "мелкие". Теперь всё укладывается в моё понимание, всем спасибо.
Добавлено через 1 минуту
@cr0w312, да, правильно.
Но лично мне приятней чтобы контроллер создавал контроллер и никто больше.
gloomyBrain
04.03.2011, 15:42
я бы так делал
/***********************************************
** класс КарКонтроллер **
***********************************************/
package
{
public Class CarController
{
private var _view:CarView;
private var _model:CarModel;
public funcrion CarController()
{
_model:CarModel = new CarModel();
_cView:CarView = new CarView(cModel);
}
public function get view():CarView
{
return _cview;
}
public function get view():CarView
{
return _cview;
}
public function get model():CarModel
{
return _model;
}
}
}
Ну и по клику по главной вьюшке - главная вьюшка сообщает главному контроллеру, что мы хотим создать еще машинку.
Главный контроллер смотрит - можно это сделать или нельзя и, если можно - создает новый контроллер машинки.
Затем главный контроллер получает у созданного контроллера вюшку машинки и добавляет ее в главную вьюшку
@cr0w312, да, правильно.
Но лично мне приятней чтобы контроллер создавал контроллер и никто больше.
эээ... вью слушает клик - рапортует контроллеру, тот в свою очередь создает младшийКонтроллер и пихает в него вью. младшийКонтроллер создает маладшуюМодель и младшуюВью, пихает в младшуюВью маладшуюМодель и цепляет младшуюВью к главнойВью. далее контроллеры выполняют каждый свои функции и следят за своими вьюхами через свои модели.
Psycho Tiger
04.03.2011, 15:55
Ага, примерно так.
Zebestov
26.03.2011, 15:54
http://ru.wikipedia.org/wiki/Model-View-Controller
Конкретно раздел "Наиболее частые ошибки". Я уже писал здесь ранее, что склоняюсь к тонкой прокладке (Controller) между логикой (Model) и ее отображением (View).
Вот такой вопрос в разрезе MVC. Предположим использую я в программе какой-то внешний, по отношению к программе объект. Он также имеет структуру MVC. В моей программе он отображает содержимое, которое моя программа ему сообщила ранее и изменяет его, специф. образом, по сигналу моей программы. Так как же их завязывать? Какая часть этого, внешнего, объекта будет выражать его самого, что мне экземпляры контролов создавать что ли? Тогда не странно ли будет создавать контролл а добавлять на сцену переданную им ссылку, а общаться опять же через контролл? Что будет интерфейсом этого объекта? Ведь мы привыкли создавая объект, нами он написан или нет неважно, общаться с ним же, а не с его контролом. Не создается впечатления черезголовуштанынадевания?
Если это внешний объект, то у него должен быть интерфейс модуля и работать мы с ним должны как с view если он таковым является.
А как это "интерфейс модуля"?
Подумал, подумал... В этом случае "фасад" подходит, который является DisplayObjectContainer-ом. Приложение общается с ним думая, что он и есть объект, а он сообщает контролу всё необходимое, в тоже время использует преимущества InteractiveObject-а (подписка на события и пр.). То есть мы можем его и "пощупать" и сказать ему что нибудь, вместо того, чтобы "щупать" одного, а говорить другому.
Как такой вариант?
Ещё один момент есть... Сам с собой разговариваю ... :). Смущает то, что контролл зачастую просто транслирует данные через свои сеттеры в сеттеры модели получается дубляж переменных в обоих классах.
Насколько плохим тоном является размещение в сеттере контролла сеттера модели? Без промежуточных переменных, когда они никак не используются в контролле, конечно. То есть получается конструкция типа:
public class Controll() extends EventDispatcher
{
...
private var _model:Model = new Model();
...
public function get param():Object { return _model.param; }
public function set param(obj:Object):void
{
if ( _model.param === obj ) return;
_model.param = obj;
}
...
Dukobpa3
09.06.2011, 15:35
Эмммм... я хз конечно но в моем представлении контролу сеттеры вообще нафиг не надо, это жеж обсервер чистой воды.
Всех слушает через события, а сам рулит моделью (а вьюха слушает модель и рулится согласно купленным билетам)
(может это я разбаловался pureMVC и Robotlegs просто, но там есть система нотификейшенов, через которую контроллеры между собой общаются, потому там нет нужды главному контроллеру что-то дергать в дочернем, и главный контроллер просто шлет нотификейшен)
роботлегс не читал, а в pureMVC нотификешен - это объект-событие с именем и данными, так кажется?
можно так и так. при ветвлении контроллов лучше обсервер, у меня другой случай - здесь целесообразней сеттеры.
а там в методе-слушателе сразу дергается сеттер модели? если конечно цель - только передать в модель новые данные.
Dukobpa3
09.06.2011, 18:57
ну суть в том что нотификейшен имеет имя и данные и это впринципе всё что надо знать.
Это просто инструмент а как его использовать уже вопрос левый. Я зачастую шлю нотификейшены даже без данных, такое себе глобальное событие просто. А когда с данными то опять же два варианта, часто просто достаточно в контроллере разобрать эти данные и сделать выводы, а иногда и запушить эти данные в модель.
Но как я сказал выше - я стараюсь делать так чтоб контроллер напрямую вьюхой не рулил, поэтому практически каждый нотификейшн ведет к тому что контроллер что-то меняет в модели.
Но опять же по ситуации))) Панацеи нету :)
Добавлено через 6 минут
Тут еще стоит понимать что контролер получивший нотификацию может быть каким-то высокоуровневым контроллером на уровне всего приложения, а не рулящий каким-то маленьким модулем, тогда получив нотификацию он ничего никуда не записывает а просто посылает уже другую нотификацию, так сказать адресную.
пример:
- коннектор к серверу (делаю его обычно контролером, но без модели и вью, по сути просто обсервер в этой глобальной системе нотификаций) получает данные с сервера
- коннектор посылает нотификацию "я получил вот такие данные"
- хостКонтроллер получает эту нотификацию, видит данные, парсит
- хостКонтроллер отправляет нотификацию в зависимости от полученных данных, эта нотификация уже адресная в конкретный модуль. На эту нотификацию подписаны уже не все кому не лень, а кто-то один.
- тот кто-то один получает эту нотификацию и уже он пишет в модель новые данные полученные с сервера.
...
- коннектор посылает нотификацию "я получил вот такие данные"
- хостКонтроллер получает эту нотификацию, видит данные, парсит
...
Вот в этом месте может же быть сеттер? Ведь это рассылка точно не многоадресная, и не может предназначаться нескольким модулям, значит событийную модель обмена можно не использовать здесь.
Или "уж если все так, то и этот пусть будет как все"? Или, просто, через фреймворк по другому не получится?
А... или это, чтобы удерживать уровень абстракции?
В этом случае дочерние контроллеры должны знать класс родительского. зачем?
Да и удобнее читать такой код(событийный).В хост контроллере прописали карту событий - смотрим хэндлеры. Типа деклартивно описываешь логику.
А тут нужно погружаться в дочерние контроллеры чтобы узнать что они что-то там вызвали у родителя.
Dukobpa3
09.06.2011, 22:14
Вот в этом месте может же быть сеттер? Ведь это рассылка точно не многоадресная, и не может предназначаться нескольким модулям, значит событийную модель обмена можно не использовать здесь.
Или "уж если все так, то и этот пусть будет как все"? Или, просто, через фреймворк по другому не получится?
А... или это, чтобы удерживать уровень абстракции?
Это просто удобно. Да, у родительского контроллера есть ссылки на дочерние. Но нотификация может предназначаться не дочернему а внучатому какому-то, или еще глубже. Во избежание танцев с бубном "потом" вокруг внуков и правнуков (на которые у главного контроллера ссылок может и не быть) - делаю нотификацию "сейчас".
Та и как Котяра говорит проще ведь сделать список нотификация - хентлер, чем помнить адреса каждого внука и дергать напрямую детей сеттерами.
А вдруг я в дитяти поменяю внутреннею структуру и этого сеттера либо вообще не станет, либо начнет устанавливать что-то другое? - это еще один аргумент в пользу нотификаций-событий.
И не путайте нотификации с событиями. Нотификация это глобальная муть, там своя схема, вникал как-то, но на пальцах долго объяснять. Есть глобальный контейнер в котором регистрируются все контроллеры, и эти контроллеры говорят глобальному контейнеру какие нотификации им удобнее слушать. А контейнер потом получает все нотификации и растусовывает по тем кто на них подписывался.
Т.е. никаких ссылок друг на друга не надо чтоб подписаться на нотификации. Контролер даже может не знать кто ее послал, просто есть факт - получена нотификация - ее надо обработать, всё.
Да... Спасибо. Надо будет посмотреть как это сделано. Интересно стало :)
Dukobpa3
09.06.2011, 22:53
в роботлегсах вообще много интересного)))
Там к примеру еще один паттерн знатный используется Dependency Injection кажись называется))
Суть в том что есть глобальный контейнер, в нем регистрируются все вьюхи, и потом любой контроллер по-умолчанию видит все вьюхи без всяких там импортов, ссылок и прочей хрени. Меня такая схема слегка коробит, но работает на ура.
Там к примеру еще один паттерн знатный используется Dependency Injection кажись называется))
Суть в том что есть глобальный контейнер, в нем регистрируются все вьюхи, и потом любой контроллер по-умолчанию видит все вьюхи без всяких там импортов, ссылок и прочей хрени. Меня такая схема слегка коробит, но работает на ура.
Суть Dependency Injection как бы не в этом. Суть в том, что обычно класс в конструкторе цепляет к себе всякую фигню какую сам захочет, а в случае DI он создается весь такой счастливый и свободный, а кто-то снаружи сразу же напихивает ему всяческую фигню во все свободные отверстия. Можно и без глобального контейнера.
Нотификация это глобальная муть, там своя схема, вникал как-то, но на пальцах долго объяснять. Есть глобальный контейнер в котором регистрируются все контроллеры, и эти контроллеры говорят глобальному контейнеру какие нотификации им удобнее слушать. А контейнер потом получает все нотификации и растусовывает по тем кто на них подписывался.
Ну не люблю я синглтоны - не люблю. И глобальные вещи всякие - тоже.
Не вижу смысла нагружать контроллер всякой чушью:
public class Controll extends EventDispatcher
{
...
private var _model:Model = new Model();
...
public function get param():Object { return _model.param; }
public function set param(obj:Object):void
{
if ( _model.param === obj ) return;
_model.param = obj;
}
...
}
Разве не будет правильно, работать с данными модели через ссылку на нее саму?
public class Controll extends EventDispatcher
{
...
///
private var _model:IModel = new Model();
/// Model getter
public function get model():IModel { return _model; }
...
}
ну и далее уже как:
var myControl:Controll = new Controll();
myControl.model.someParam = "lalala";
trace(myControl.model.someParam);
myControl.model.someParam = "lalala";
Не забываем про Law of Demeter (http://en.wikipedia.org/wiki/Law_of_Demeter)
Dukobpa3
11.06.2011, 00:55
var myControl:Controll = new Controll();
myControl.model.someParam = "lalala";
trace(myControl.model.someParam);
Я не знаю, но мне такая структура претит. Кто бы ни был владелец этого майКонтрола, но какое он право имеет лезть в его модель? Для этого есть тот самый контрол который знает как с его моделью общаться. Я против управления внуками и правнуками вот такими методами.
Другой вопрос что тот кто имеет ссылку на майконтрол может дернуть какой-то из его методов типа: myControl.setParam();
Но не напрямую в модель. Как вариант этот setParam - может быть публичным сеттером на одно кокретное свойство модели, но не на всю модель. Аргументация - в сеттере можно прописать какие-то проверки, а если получили ссылку на модель, то пихаем данные в обход всего и даже без ведома непосредственного руководителя. Я за четкую субординацию.
Dukobpa3, Control не хранит данные и не должен их выдавать композицией на модель.
Dukobpa3
12.06.2011, 23:21
Dukobpa3, Control не хранит данные и не должен их выдавать композицией на модель.
Так я собственно про то же самое и говорю. Просто раз уж так охота рулить моделью чужой то лучше так.
Склонен думать о неправильной архитектуре если есть такая нужда.
Вы сами себе противоречите :)
Не должно быть какой-то внутренней модели, доступ к ней публичный.
Вы сами себе противоречите :)
Не должно быть какой-то внутренней модели, доступ к ней публичный.
ого! а, тогда, какой смысл в контролле вообще?
ого! а, тогда, какой смысл в контролле вообще?
Ну он может быть базовым по отношению к дочернему, которому нужны данные из модели.
Не должно быть какой-то внутренней модели, доступ к ней публичный.
Публичный для кого и для каких целей?
Dukobpa3
13.06.2011, 13:01
Та я вот что-то тоже ниче не понял... Прошу прояснить. Я как-то старался обособить каждый контрол с его моделью и вью от остальных.
Но если вью мог всунуть как дочерней к какой-то там главной вью (ну например таблица - главная вью, а строка таблицы дочерняя), или модель составная из нескольких (опять же та же таблица, в главной модели допустим заголовки колонок, плюс массив строк, каждая строка привязана к какой-то вьюхе строки).
В таком случае я не лазил в модели через дочернние контролы, а просто менял строки из главного контрола, так как главная модель это модель главного контрола.
Правда пример плохой, в данной ситуации у меня скорее всего был бы только один контрол на всё это дерево моделей и вьюх. Что-то умнее щас не придумалось:)
Crazy, для других контроллеров, очевидно.
И да, контрол — это обыкновенный вью, он — не контроллер. И модель ему приходит извне, от того же контроллера, например. Модель же принадлежит контроллеру (основному) и доступна для других контроллеров.
Crazy, для других контроллеров, очевидно.
Если им нужна эта модель -- почему они не получили ее явно, а ходят за ней к некоторому третьему объекту? А если после изменений системы этому третьему объекту эта модель будет не нужна и ее там уберут -- будем всех переписывать?
Откуда такой странный дизайн?
Почему странный, модель принадлежит основному контроллеру, у дочернего есть ссылка на этот контроллер. При желании, он может взять у основного контроллера как модель, так и другие интересующие данные. Какие данные нужны будут дочернему, основной не знает и знать не хочет, поэтому модель у него в паблике.
Почему странный, модель принадлежит основному контроллеру, у дочернего есть ссылка на этот контроллер. При желании, он может взять у основного контроллера как модель, так и другие интересующие данные. Какие данные нужны будут дочернему, основной не знает и знать не хочет, поэтому модель у него в паблике.
Это называется blob antipattern -- когда систему пронизывают хаотичные связи типа "захотел и взял публичные данные". И внесение изменений в одной части вызывает непредсказуемые эффекты по всей системе.
Я озвучил рекомендуемый способ: при создании контроллера давать ему те модели, которыми он должен пользоваться. Способ, который не создает проблем на ровном месте. Вы предлагаете вместо этого внести хаос в дизайн, но пока совершенно непонятно, что мы получаем взамен. Ну, кроме "ни о чем не надо думать заранее -- все как-нибудь рассосется само".
Я этого не предлагаю, об основном контроллере и основной модели все дочерние контроллеры знают и у них и так и так есть ссылка на этот контроллер. Модель у них может и своя, но также доступна по ссылке, как у всех контроллеров.
Это всё описание вот этой модели (http://www.flasher.ru/forum/showpost.php?p=860254&postcount=2).
Я этого не предлагаю, об основном контроллере и основной модели все дочерние контроллеры знают и у них и так и так есть ссылка на этот контроллер.
Отлично. Пусть знают, если это им нужно. Зачем, кстати?
Модель у них может и своя, но также доступна по ссылке, как у всех контроллеров.
Если у них уже есть нужные им данные -- зачем они лезут в чужую модель? Если в их модели нет нужных им данных -- ее неправильно спроектировали. Нужно исправить, пока не поздно.
Это всё описание вот этой модели (http://www.flasher.ru/forum/showpost.php?p=860254&postcount=2).
Какое конкретное свойство этого дизайна не позволяет реализовать описанным мной способом, не лазая в чужие модели? BTW, неоправданное использование нестандартных нотаций мягко говоря не способствует коммуникации.
Отлично. Пусть знают, если это им нужно. Зачем, кстати?
Основной контроллер как минимум фасад, общающийся с сервером. Ну заодно и основную модель держит.
Если у них уже есть нужные им данные -- зачем они лезут в чужую модель? Если в их модели нет нужных им данных -- ее неправильно спроектировали. Нужно исправить, пока не поздно.
Это понятно, только речь о связи дочерний->основной. Дочерний к дочернему прямого доступа не имеют.
Конкретные данные для обработки само собой придут в аргументах, а не будут вытягиваться из модели.
Какое конкретное свойство этого дизайна не позволяет реализовать описанным мной способом, не лазая в чужие модели? BTW, неоправданное использование нестандартных нотаций мягко говоря не способствует коммуникации.
Никакое, можно и так, просто нет смысла настолько абстрагировать контроллеры. Это касается только лишь линков на основной контроллер и основную модель, конкретные данные, как я уже говорил, приходят аргументами.
Никакое, можно и так, просто нет смысла настолько абстрагировать контроллеры.
Смысл состоит в следовании Law of Demeter для минимизации зависимостей. Однако это возвращает нас к моему вопросу, который был фактически проигнорирован:
Вы предлагаете вместо этого внести хаос в дизайн, но пока совершенно непонятно, что мы получаем взамен.
Если ничто не мешает нам сделать в соответствии с нормальной практикой, то какие же преимущества мы получаем, отказавшись от минимизации зависимостей? Каковы плюсы помимо "я уже сделал именно так"?
Не является ли недостатком такой схемы необходимость хранить в контроллере линки зависимых моделей, а прогеру помнить все закоулки данной, конкретной, архитектуры? Может реализация где контролл - обсервер имеет преимущество в том, что головная (ные) модель(дели) может просто кидать нужное сообщение, а контроллы зависимых уровней уже сами решают интересует их подопечную модель данная информация или нет?
Эта схема у меня есть (сохранил когда то), но вместо схемы, на странице, у меня это:
Crazy, хаоса никакого, просто в 90% случаев контроллеру нужна так или иначе основная модель, для получения прототипов или иной ерунды, поэтому она по умолчанию идёт линком у родительского контроллера и всё тут. Я опираюсь на собственный опыт (а я считаю, что он уже достаточен) и минимизация зависимостей вот как раз в таких случаях — простое помешательство на MVC, выливающиеся в геморрой по передаче 100500 параметров, вот и всё. Да, можно всё сделать по фен-шую, только незачем и никому это не нужно.
Резюмирую: никаких плюсов мы взамен не получаем.
Спасибо за дискуссию.
Dukobpa3
14.06.2011, 00:34
У меня для этих целей есть обычно два синглтона:
1. Для каких-то статичных данных (Это например грузим что-то с сервера пачкой, там базовые настройки системы и в таком духе, и вот реально всем они нужны в той или иной мере)
2. Для динамических (У меня это банально bulkLoader)
Феншуй при этом абсолютно не страдает как мне кажется, если не считать нелюбовь некоторых адептов к синглтонам. Но как по мне это как раз тот случай когда один синглтон спасает от кучи лишних связей.
Резюмирую: никаких плюсов мы взамен не получаем.
Спасибо за дискуссию.
Если вам не влом передавать каждый раз ссылки на очевидные вещи, то да, никаких плюсов.
Если вам не влом передавать каждый раз ссылки на очевидные вещи, то да, никаких плюсов.
Простите, смысл этой меткой фразы прошел мимо моего сознания. Нельзя ли переформулировать?
Простите, смысл этой меткой фразы прошел мимо моего сознания. Нельзя ли переформулировать?
К сожалению, нет, потому что я уже всё объяснил.
Не хватает конкретики для понимания. Тему осилил процентов на 90, а также статьи и другие подобные темы.
Несколько вопросов:
1) Модель диспатчит Event.CHANGE и вьюшка сама разбирается, что конкретно поменялось в модели, или модель генерит конкретное событие "яблоки подорожали", а вьюшка уже отображает новую цену?
2) Вьюшка, слушает события от действий юзера, определяет, что нажата кнопка Play и отсылает контроллеру событие "начало просмотра" (как здесь: http://www.flasher.ru/forum/blog.php?b=348), или вьюшка отсылает событие "меня тут где-то нажали", а контроллер по таргету уже определяет, что раз нажата кнопка с id1, а это кнопка Play, и значит пользователь хочет начать просмотр?
3) Есть таймер. Слушается событие TimerEvent.TIMER, по нему преобразуются значения таймера в понятные юзеру минуты/секунды и отображаются на экране. Отображает понятно вьюшка, а кто должен заниматься преобразованием? Контролер в котором создается таймер и слушается же событие меняет вью (минуя модель), модель в которой слушается событие от таймера созданного в контроллере, а потом диспатчится Event.CHANGE при каждом тике таймера, или вьюшка должна сама слушать от контроллера, преобразовывать и отображать (минуя модель)?
В каком случае более правильное классическое MVC или есть еще варианты? =)
1) Обычно конкретное, если модель сложносочиненная;
2) Вьюшка шлёт конкретное событие PLAY_CLICK;
3) Событие таймера слушает модель, в себе содержит время в timestamp, например, при изменении шлёт событие. Вьювер ловит и через форматтер выводит время.
Dukobpa3
10.08.2011, 13:22
3) Событие таймера слушает модель, в себе содержит время в timestamp, например, при изменении шлёт событие. Вьювер ловит и через форматтер выводит время.
У меня обычно один из двух вариантов:
1. таймер в контроллере. По таймеру контроллер пихает в модель неформатированное время. Модель говорит что ее изменили. Вьюха форматирует время так как ей надо.
2. опять же таймер в контроллере. Контроллер пихает Форматированное время в модель. Вюшка просто берет готовую строку и отображает.
Первый вариант правильнее, так как одно и то же самое системное время(число) можно показать по-разному. А это как раз дело вьюхи.
Dukobpa3, а я сую таймер прямо в модель, как правило он статический и вещает на все экземпляры моделей.
Нагружать контроллер этой ерундой не вижу смысла, не говоря уже о том, что у меня нет какого-то специального контроллера модели, который занимается её изменением.
Dukobpa3
10.08.2011, 13:52
Мой MVC не совсем академический, так как модель как правило выполняет роль БД, а вся логика в контроллере, и частично во вью (но разделение логики контроллера и вью четкое: контроллер решает те вопросы в которых требуется изменение модели, а так же коммуникации с другими контроллерами, а вью сугубо то что нужно менять визуально).
Хотя в случае конкретно с таймерами - то в контроллере потому, что на одном таймере как правило висит не только запись в модель текущего времени, а еще пару-тройку действий, к модели не относящихся.
Добавлено через 6 минут
А то что статический то да, но вот к примеру в текущем проекте у нас есть синглтон с данными пользователя.
Там пара: модель + контроллер.
Соответственно контроллер запускает таймер, а модель хранит в себе неформатированное время. Плюс это время периодически синхронизируется с сервером.
А все вьюхи уже берут эту цифру и показывают кому как надо.
прикольная тема, осилил-таки наконц полностью, хоть и не за один присест. Много идей интересных.
etc, я так понял, что в твоих проектах может быть несколко триад, в том числе и вложенные. Кто занимается добавлением вьюшек в дисплей лист? Контроллер? Если да, то как ты определяешь, куда контроллер должен добывить свою вью, ведь очень часто ее надо засунуть не просто в документ класс, а в какой-то определенный контейнер, о котором контроллер нечего не знает, а знает только более старшая вьюха.
Dukobpa3
31.10.2011, 11:31
Если можно я отвечу, хоть вопрос и не ко мне)) Так же под шумок возможно кто-то укажет и на мои ошибки в понимании данного вопроса:)
В общем, кроме дерева триад/контроллеров/моделей есть еще и дерево хостов. Каждый контроллер имеет свой хост (дисплейОбжектКонтейнер) В который он добавляет свою вьюху. Этот хост к этому контроллеру пристегивает родительский контроллер(в моем случае сразу в конструкторе). Соответственно структура остается четкой и древовидной без всякого рода мешанины и одноуровневых пулов.
Хотя есть вариант реализации и слегка иной, в частности он используется в роботлегс, советую посмотреть. Там все контроллеры на одном уровне и все вьюхи. В момент использования просто берется то или иное из общего пула и вуаля. С самим фреймворком общался сугубо в ознакомительных целях потому тонкостей не знаю, но в целом вроде так.
прикольная тема, осилил-таки наконц полностью, хоть и не за один присест. Много идей интересных.
etc, я так понял, что в твоих проектах может быть несколко триад, в том числе и вложенные. Кто занимается добавлением вьюшек в дисплей лист? Контроллер? Если да, то как ты определяешь, куда контроллер должен добывить свою вью, ведь очень часто ее надо засунуть не просто в документ класс, а в какой-то определенный контейнер, о котором контроллер нечего не знает, а знает только более старшая вьюха.
Старшая вьюха и создаёт.
Dukobpa3
31.10.2011, 11:32
Дерево растет из мейна. Мейн - это хост мейн контроллера. Ну и дальше аналогия с дисплейлистом идет. Хосты друг в друга добавляются согласно места в дереве.
Старшая вьюха и создаёт.
создает да, а добавляет кто (addChild)? контроллер? откуда у него ссылка на какой-то из внутренних displayobject container-ов?
Создаёт — это и есть new с addChild. Контроллер построением интерфейса не занимается.
Если это компонент (окно, например), то связыванием контроллера с компонентом занимается какой-нибудь менеджер компонентов. Или же контроллер компонента им же самим и создаётся.
crazyone
31.10.2011, 13:32
Раз уж пошла такая пьянка, расскажите мне пожалуйста, как организовывается многокнопочный интерфейс.
Ну, вот если есть панель управления, на которой 100500 кнопок типа загрузить картинку, загрузить документ, загрузить музыку, загрузить видео и т.д. Кто слушает все эти кнопочки и решает что дальше делать?
В голову просится ответ, что вьюшка слушает детей на предмет MouseEvent.CLICK, а потом диспатчит кастомное событие InterfaceEvent.LOAD_FILE с соответствующими свойствами.
Точно так же - если мы захотим повесить хоткеи на эти кнопки, то вьюшка будет слушать KeyboardEvent.KEY_DOWN и вещать те же самые события.
Но что-то внутри меня подбивает сделать обработку изначальных MouseEvent.CLICK и KeyboardEvent.KEY_DOWN уже в контроллере, т.к. это какбе уже принятие решения - как реагировать на действия пользователя. И даже если не пихать эту обработку в основной контроллер, то сделать для этой вьюшки своего личного контролерчика.
Это что-то внутри нужно безжалостно давить, или холить и лелеять?
Ну на самом деле можно и так и так.
Если вьюшка обрабатывает сама события своих детей - то она в рамках этого модуля - контроллер.
Если мы говорим о иерархической MVC с древовидным ветвлением. Если мы не принимаем такое ветвление, то Всё это должен решать контроллер.
Есть ещё промежуточный вариант.
PresentationModel (http://blogs.adobe.com/paulw/archives/2007/10/presentation_pa_3.html).
Выбирать архитектуру теюбе. Нельзя сказать, что вот делай именно так. Всё зависит от контекста.
crazyone
31.10.2011, 18:40
Вот оно как, оказывается. Спасибо за пояснения.
ЗЫ Я кстати понял, почему мне древовидное ветвление в MVC тяжело дается. Пытаюсь думать кодом. А если нарисовать диаграмку, сразу так легко и понятно все становится.
tofflife
12.12.2011, 20:29
MVP/MMVC больше подуше.
Spicelib, parsley нам в помощь.
В любом MVC ни при каком раскладе и ни на каком этапе выполнения приложения входной точкой не должен становиться view, для которого все же существует controller. У меня он тоже "тонкий", но входная точка на каждом этапе приложения — именно контроллер. Именно он всех инициирует, собирает докучи и запускает в нужном порядке. Если не поздно — подумай над реорганизацией.
Т.е. как концептуально это выглядит? Примерно так?
import flash.display.MovieClip;
import org.flashdevelop.utils.FlashViewer;
///Host
class Main extends MovieClip
{
public function Main()
{
new Controller( this );
}
}
///Controller
import flash.events.EventDispatcher;
class Controller extends EventDispatcher
{
public function Controller(scene:Main, target:IEventDispatcher = null)
{
var model:Model = new Model();
var view:Viewer = new Viewer(model);
scene.addChild( view );
}
}
///Model
class Model extends EventDispatcher
{
public const READY_DATA:String = "ready data";
public function Model()
{
...
}
}
///View
import flash.display.Sprite;
class Viewer extends Sprite
{
public function Viewer(model:Model)
{
model.addEventListener( Model.READY_DATA, init);
}
private function init():void
{
///start
}
}
А кто представляет объект снаружи? Контроллер? Ну в данном случае, если напр. мейн захочет обратиться
к вьюеру.
Можно какой то мин. примерчик? Или пруф.
Zebestov
23.12.2011, 16:44
Т.е. как концептуально это выглядит? Примерно так?
Примерно так.
Ну в данном случае, если напр. мейн захочет обратиться к вьюеру.
Что он там забыл? Main создал контроллер и ушел на заслуженный отдых. Отец семейства теперь — твой главный контроллер. И он может всегда дотянуться до своей вьюхи. А потом приложение должно перейти в другую стадию. Тот же контроллер создаст новый контроллер, тот в свою очередь полностью возьмет на себя новый этап приложения, создаст новый view и будет с ним работать сам. По окончании просто приберет за собой и сообщит "папе", что все закончено. Главный контроллер будет с нетерпением ждать этого сообщения, чтобы решать, куда идем дальше.
В общих чертах.
Psycho Tiger
23.12.2011, 17:09
По сути, Main - контейнер для вьюшек и инициализатор контроллера.
Controller в принципе не должен знать, что такое Main.
Константы имён событий надо объявлять в самих событиях.
Controller в принципе не должен знать, что такое Main.
Да, конечно. Это пример написанный наспех. Контроллер может воспринимать Main как просто DOC, но мне все равно не нравится - не должен объект сам себя куда-то добавлять.
Константы имён событий надо объявлять в самих событиях.
Имеется в виду так?
[Event( name="some event" type="com.somepack.SomeClass" )]
Мне удобнее традиционным способом - видно перечень констант в панели Outline.
Psycho Tiger
25.12.2011, 01:53
Имеется в виду так?
Нет, имеется ввиду определение этих констант в наследнике Event.
Да, конечно. Это пример написанный наспех. Контроллер может воспринимать Main как просто DOC, но мне все равно не нравится - не должен объект сам себя куда-то добавлять.
Кто куда кого добавляет? DOC, да, это логичнее.
Имеется в виду так?
[Event( name="some event" type="com.somepack.SomeClass" )]
Мне удобнее традиционным способом - видно перечень констант в панели Outline.
И [Event()] тоже, как раз в аутлайне и появится (это в FB во всяком случае). Тигра выше написал, что имелось ввиду.
Кто куда кого добавляет?
В примерном коде, у меня, где "точка входа - контроллер" возможны два варианта:
- контроллер получает ссылку на контейнер и добавляет туда вьюер,
- контроллер отдает ссылку на свой вьюер (другому контроллеру, или контейнеру).
Оба варианта мне не нравятся, потому, что контроллер должен иметь дело с сигналами объектов, а не с манипуляцией объектами.
Нет, имеется ввиду определение этих констант в наследнике Event.
И [Event()] тоже, как раз в аутлайне и появится (это в FB во всяком случае). Тигра выше написал, что имелось ввиду.
Создание объекта расширяющего Event, с определением перечня каст. набора событий -
в результате мы получаем возможность подписываться на события инициализируемые другим объектом, даже не находящимся в области видимости подписчика? Это имеется в виду?
В примерном коде, у меня, где "точка входа - контроллер" возможны два варианта:
- контроллер получает ссылку на контейнер и добавляет туда вьюер,
- контроллер отдает ссылку на свой вьюер (другому контроллеру, или контейнеру).
Оба варианта мне не нравятся, потому, что контроллер должен иметь дело с сигналами объектов, а не с манипуляцией объектами.
По мне так контроллер на то и контроллер, чтобы манипулировать.
Создание объекта расширяющего Event, с определением перечня каст. набора событий -
в результате мы получаем возможность подписываться на события инициализируемые другим объектом, даже не находящимся в области видимости подписчика? Это имеется в виду?
Нет, имелась ввиду лишь первая часть про создание кастомного события. Остальная часть за гранью понимания.
Нет, имелась ввиду лишь первая часть про создание кастомного события
Ну, а в чём бонус то? В этом случае.
Так принято. Не надо подписчику иметь импорт диспетчера (если ты там определяешь константы)
Ну, а в чём бонус то? В этом случае.
В том, что мы не тащим за собой конкретный класс-вещатель при подписке на такие события, в том, что мы заведомо знаем тип приходящего события (указывая оный в обработчике), в том, что будет корректно работать автокомплит (большинство IDE построено именно на такой схеме объявления событий), а также в том, что в автокомплите будут перечислены именно типы событий, а не всё статическое барахло диспетчера.
@Котяра, @_etc. Почитал, подумал... вы совершенно правы. Спасибо.
Ах да, я забыл, ещё такие события не всегда отсылает единственный диспетчер.
Ах да, я забыл, ещё такие события не всегда отсылает единственный диспетчер.
Вот насчет этого я хотел бы уточнить. Как на твой, несомненно более опытный взгляд, если в качестве диспетчера таких событий использовать специально для этого созданный объект (естессно расширяющий EventDispatcher)? Видимый глобально он мог бы сделать доступными сигналы объектов не находящихся в прямой или глобальной видимости. Но, тогда не наступит хаос в программе? Не слишком ли это сильное
разделение связей между объектами? Вроде бы так вообще легко потерять контроль над взаимосвязями объектов в программе.
Глобальный — зло. Через него кто хочет и как хочет шлёт, в итоге отледить, что и откуда, невозможно.
Но многие таки используют. См. Spring и EventBus.
HardCoder
15.01.2012, 21:15
Здравствуйте. Если подобное уже здесь обсуждалось, приношу извинения, ибо после 10 страниц чтения топика - перестал понимать о чем идет речь.
И так вопрос. Контроллер обработал некую информацию. В соответствии с этой информацией нужно провести изменения в представлении. Но дело в том, что эти изменения модели не касаются. Что делать? Напрашиваются такие варианты:
1. В контроллере есть же ссылка на представление, значит мы можем вызвать метод этой вьюшки прямо из контроллера. Но речь идет об "Хорошее MVC", согласно которому контроллер не должен изменять представление.
2. Через модель диспатчить событие, и ловить його в представлении. С точки зрения MVC - это хорошо, но с точки зрения программирования - корове седло. Зачем лишний посредник (модель) в этом случае?
Как грамотнее поступить?
Dukobpa3
15.01.2012, 21:19
То что контроллер обрабатывает информаию уже не совсем академический мвц. Логика должна быть в модели если так чтоб совсем правильно.
Но у меня тоже мозг в контроллере:)
И если контроллер обрабатывает нечто что важно для вью - значит нужно это нечто выносить в модель, а дальше уже модель по накатанной схеме диспатчит что мол: "я поменялась отрендерись там" во вьюху.
Это если в общем, хотя ситуации разные бывают. Лучше конкретный пример приведи.
HardCoder
15.01.2012, 21:38
Конкретный пример: Игра, изометрический плиточный мир, разные юниты в этом мире... Это все в контейнере - вьюхе. Контролер получает известие от одного юнита, что этот юнит переместился на другую плитку. Значит надо передать вьюхе что нужно отсортировать экранные обьекты. В модели есть массив этих экранных обьектов. Но в ней нигде нет информации на каком уровне глубины в дисплей-листе эти обьекты расположены. Значит в модели нечего менять, так как ей до фонаря как эти обьекты расположены по глубинам, на ход игры это не влияет. Контроллеру тоже до фонаря - его интересуют лишь x, y и пр. свойства. Единственный кому не наплевать - это представление, так как оно беспокоется о том чтобы пользователь правильно воспринимал происходящее.
Добавлено через 3 минуты
То что контроллер обрабатывает информаию уже не совсем академический мвц. Логика должна быть в модели если так чтоб совсем правильно.Но если модель будет и хранить данные и обрабатывать их - зачем тогда нужен вообще контролер? Просто чтобы быть ненужным посредником между моделью и вьюхой?
Dukobpa3
15.01.2012, 21:42
Ну координаты объекта ведь поменялись, значит очевидно же что надо отсортировать.
Следовательно мы организовываем вьюху таким образом чтобы каждый раз, как меняются координаты объекта всё что нужно - сортировалось. И контроллер тут ни при чем, равно как и модель.
Zebestov
15.01.2012, 21:47
Значит в модели нечего менять
В модели изменятся X и Y юнита. Кто даст команду на перемещение — контроллер или отображение — в данном случае несущественно. Я бы делал это из контроллера.
Контроллеру тоже до фонаря - его интересуют лишь x, y и пр. свойства
Контроллеру неинтересны эти свойства, если он не заведует логикой (которой хорошо бы быть в модели).
Значит надо передать вьюхе что нужно отсортировать экранные обьекты
Отображение само узнает о необходимости перерисовки, когда модель сообщит, что юнит переместился.
Dukobpa3
15.01.2012, 21:47
Но если модель будет и хранить данные и обрабатывать их - зачем тогда нужен вообще контролер? Просто чтобы быть ненужным посредником между моделью и вьюхой?
Ну если говорить о таком МВЦ как в вики пишут, типа правильном то это всё должно выглядеть примерно как в макдаке.
заказчик - вью
официант - контроллер
модель - кухня и прилавок
заказчик-вью подошел, заказал.
контроллер-официант правильно интерпретировал заказ (на входе может может быть что-то типа: "мне вот такую вот хрень, я у вас когда то был, но не помню как называется"), передал на кухню.
кухня приготовила, выставила результат на прилавок.
вью видит что на прилавке стоит ее поднос - идет забирает.
HardCoder
15.01.2012, 22:05
Представление:
Берет из модели массив юнитов. Размещает их в дисплейлист. Она не знает на какие координаты их размещает. Координаты уже заранее предписаны каждому юниту во время их создания в контроллере. Но! она знает на какие глубины их размещать. Не важно откуда знает. Знает и все. Это ее дело заниматься сортировкой (удобным отображением), потому что именно она вызывает addChild-ы а не кто-то другой из триады.
Контроллер:
Получает известие от вьюшки что пользователь выбрал юнита, кликнул на карту и надо этот юнит переместить на место, куда кликнул пользователь. Контроллер лезет в массив юнитов (в модели) вытаскивает оттуда нужного юнита и говорит ему: "двигайся туда". Юнит покорно, при каждом шаге высчитывая новые координаты, двигается. То что он перемещается знает только он сам и юзер, который видит на экране перемещение. Когда юнит пришел на место - он сообщает конролеру, что тот прибыл. Контроллер знает что раз тот прибыл - значит положение изменилось и надо пересортировать карту. Что делать?
Бежим к модели - та курит в сторонке - ей вообще по барабану. Она знает что юнит никуда не делся из ее массива. Переместился? ну и что? Координаты можно узнать от самого юнита.
Так кто же должен сообщить вьюхе, которая понятия не имеет что произошло - что юнитов надо отсортировать?
Добавлено через 3 минуты
PS: повешать слушатель во вьшке на юнита мы не можем. Это может сделать только контроллер. Потому что вьюшка передает контроллеру что был произведен клик, а тот уже определяет с помощью сотен строк что дальше с ним делать (перемещать, атаковать, умирать) и отдает ему команды. Представление заранее не может знать что конкретный юнит будет перемещен.
Dukobpa3
15.01.2012, 22:11
всё плохо:)
Модель: содержит набор абстрактных данных таких как координаты, имена и прочее. Без всяких визуальных объектов.
Представление: Содержит визуальную интерпретацию абстракций заложенных в модели. Например в модели у нас некий Object{type:type, x:x, y:y} - а вьюха уже знает что такой тип выглядит так, и находится по таким координатам.
Контроллер: получает от вью событие клика. Вносит в модель новые координаты объекта. На этом всё.
Вью: слышит маяк от модели что ее поменяли. Смотрит что поменяли координаты такого-то объекта, а текущие координаты то отличаются. И вот вью покорно начинает двигать объект с точки на точку с анимашками и прочими свистелками.
HardCoder
15.01.2012, 22:12
Конечно, спасибо за ответы. Я понял что мой алгоритм - изначально не MVC. :) Буду учиться.
Dukobpa3
15.01.2012, 22:16
PS: повешать слушатель во вьшке на юнита мы не можем.
в контроллере достаточно повесить слушатель на всю большую вью, а из юнитов диспатчить события с bubbles=true - тогда они будут насквозь пролетать аж до контроллера, и контроллер сможет их поймать и обработать. В большой вью делать ничего не нужно для этого.
HardCoder
15.01.2012, 22:37
Короче говоря - надо все переписывать. Я как-бы понимаю что такое MVC, и понимаю что моя стратегия написания неправильна. Но в то же время не понимаю как мне полностью абстрагировать вьюшку от всего происходящего, как организовать работу их троих... Конечно, каждый случай уникальный, правила игры уникальные, поэтому мне самому нужно думать. Но может, если кто-то делал хотя бы похожее, подскажите, пожалуйста, как вы строили эту структуру.
PS: все делается без сервера.
Dukobpa3
15.01.2012, 22:42
Ну переписывать это кардинальное решение)
Как сделать я тебе уже ответил, чуть выше. Если хочешь можешь в личку/скайп стучаться.
Контроллер: получает от вью событие клика. Вносит в модель новые координаты объекта. На этом всё.
Вью: слышит маяк от модели что ее поменяли. Смотрит что поменяли координаты такого-то объекта, а текущие координаты то отличаются. И вот вью покорно начинает двигать объект с точки на точку с анимашками и прочими свистелками.
Модель не должны интересовать координаты объекта, для неё объект - некая статистическая единица, с набором соотв. информации (кол-во жизни, патронов и пр.), ИМХО, конечно (на классика пока не тяну )).
Думаю, что контроллер должен трансформировать данные из вью-типа в данные модель-типа, что собсно
и является его прямой обязанностью.
И так вопрос. Контроллер обработал некую информацию. В соответствии с этой информацией нужно провести изменения в представлении. Но дело в том, что эти изменения модели не касаются. Что делать? Напрашиваются такие варианты:
Если говорить не о "хорошем" MVC, а о классической реализации, то контроллер интерпретирует данные
и при необходимости изменяет вьюер (не знаю конкретики, но звено "контроллер", почти всегда лишнее, если события порождают информацию касающуюся только вьюера).
Dukobpa3
15.01.2012, 22:57
Модель не должны интересовать координаты объекта,
В данном случае координаты это часть модели карты, поэтому они в модели быть должны.
Вообще задача модели хранить всю информацию, которая позволит воссоздать картину происходящего с какой-нибудь другой вьюхой например. Если речь идет о карте то координаты с ней неразрывно связаны.
Если же это будут координаты какой-то там звездочки которая выпадает откуда-то как некий эффект, то конечно ее координаты никому кроме вью не понадобятся.
HardCoder
15.01.2012, 23:16
Значит, я так понял, что: классы юнитов это всего лишь каркасы, которые не должны нести графического представления? Они должны лишь иметь ссылку на класс графического обьекта который они представляют (король, солдат, дом...). А вьюха должна создавать не новые юниты и добавлять их на сцену, которыми оперирует контроллер, а новые анимашки (король, солдат...). Ой-ой-ой сколько же работы предстоит!!!
Dukobpa3
15.01.2012, 23:24
Нет.
Каждый юнит это тоже моделька МВЦ, маленькая.
У каждого юнита есть модель
Есть вью
И возможно есть отдельный контроллер, а может и нет. Скорее всего контроллером всех юнитов будет этот главный контроллер.
Массив моделей юнитов хранится в модели, ни о каких ссылках на спрайты или мувики там речи быть не может.
Массив вьюх в свою очередь хранится в главной вьюхе.
Вьха когда рендерится она смотрит в массив моделек, и создает у себя аналогичный массив визуальных штук, пользуясь данными из этих самых моделек.
Но это одна из частных реализаций, может быть и иначе.
В данном случае координаты это часть модели карты, поэтому они в модели быть должны.
Вообще задача модели хранить всю информацию, которая позволит воссоздать картину происходящего с какой-нибудь другой вьюхой например. Если речь идет о карте то координаты с ней неразрывно связаны.
Не знал, что классические принципы MVC уже изменились.
Задача модели, вообще-то, хранить логику независимо от вьюера, то есть ваше приложение должно одинаково работать и с вьюером, и с двумя (выполненными в разных масштабах, например) и вообще без него, напр. в консольном режиме...
Dukobpa3
16.01.2012, 02:46
Комент ради комента.
Я не то же самое сказал?
Комент ради комента.
нет
Я не то же самое сказал?
нет
/всё - 6 знаков, хотя оно того не стоило/
Zebestov
16.01.2012, 21:11
fish_r, ты действительно не сказал ничего, что оспаривал бы Dukobpa3. Особенно легко в этом убедиться, прочитав пропущенный тобой комментарий (http://www.flasher.ru/forum/showpost.php?p=1057129&postcount=397) прямо над твоим возражением.
Вы об одном и том же разными словами :)
Я его и не пропустил. Мы обсуждали другую частность:
Модель не должны интересовать координаты объекта.
В данном случае координаты это часть модели карты, поэтому они в модели быть должны.
Zebestov
16.01.2012, 21:47
Ясно. И как это
координаты это часть модели карты, поэтому они в модели быть должны
противоречит этому
Задача модели, вообще-то, хранить логику независимо от вьюера, то есть ваше приложение должно одинаково работать и с вьюером, и с двумя (выполненными в разных масштабах, например) и вообще без него, напр. в консольном режиме...
Координаты юнита на карте разумеется должны храниться/изменяться в модели (вы оба придерживаетесь схемы, где модель — это данные и логика по их обработке). Вьюха может быть чем угодно (2D, 3D, забавным мультиком, диаграммой посещаемости "храма" юнитами за отчетный период, и т.д.). И модели до этого нет никакого дела. Она живет своей жизнью.
А вот это действительно лишнее:
Модель не должны интересовать координаты объекта.
А вот это действительно лишнее:
Вот это вот действительно лишнее.
Хорошо. Предположим вы делаете не игру, а польз. интерфейс заносите ли вы координаты кнопок в модель?
Zebestov
17.01.2012, 01:29
Хорошо. Предположим вы делаете не игру, а польз. интерфейс заносите ли вы координаты кнопок в модель?
Ну и на этот вопрос тебе Dukobpa3 уже давал ответ, с которым я согласен
Если же это будут координаты какой-то там звездочки которая выпадает откуда-то как некий эффект, то конечно ее координаты никому кроме вью не понадобятся.
Юнит — не кнопка. Юнит — фигурант логики приложения. Кнопка — кликабельный кусок монитора.
Dukobpa3
17.01.2012, 02:07
@Zebestov - Спасибо, наверное))) Мои слова поняты верно и с первого раза, плюс за поддержку.
@fish_r - Слушай что тебе старшие говорят ;-Р
HardCoder
17.01.2012, 02:15
Интересует взаимосвязь модели с вью. Вьюшка не может изменять модель. Но у нее есть ссылка на модель, соответственно... сами понимаете что. Акцессоры здесь не подходят, так как контроллер должен изменять те же свойства, которые читает вью. В отдельный пакет вьюшку тоже не закинешь. Понятно, я не собираюсь в представлении как-то менять модель :). Но интересно на будущее, просто чтобы уж "совсем правильно", как здесь быть?
Если создать событийный класс для событий модели (имею в виду "пользовательское событие" по К.Муку). В этот класс при диспатче из модели передавать все доступные параметры для вьюшки. Это будет правильно?
Добавлено через 2 минуты
Или лучше создать несколько таких событийных классов, погрупировав в них лишь те свойства, которые непосредственно будут нужны при поимке этого события в представлении?
Zebestov
17.01.2012, 02:19
...при диспатче из модели передавать все доступные параметры для вьюшки. Это будет правильно?
Не правильно. Вьюшка просто услышит про изменения и сама пойдет к модели выяснять, что там поменялось. Ей даже не важно, кто и каким образом поменял эти значения (модель сама там что-то насчитала, контроллер что-то там вызвал, с сервера данные подоспели).
Dukobpa3
17.01.2012, 02:21
Вьюшка не может изменять модель. Но у нее есть ссылка на модель
да
Если создать событийный класс для событий модели
Как вариант прокатит, и даже более того это будет один из самых правильных вариантов но сложен в реализации. Сложно будет сделать адекватный рендер с обработкой всех событий и слишком легко запутаться.
Акцессоры здесь не подходят
Очень даже подходят. Просто вью ничего не меняет в модели, только читает всё что ей нужно. А контроллер может еще и менять. Технически это разделить сложно, хотя можно, там придется неймспейсы прикручивать. Я на практике просто сам сознательно не трогаю модель из вью и всё.
Т.е. получается модель продиспатчила - меня изменили. Вью полезла посмотрела нужные данные и всё.
Добавлено через 3 минуты
Не правильно. Вьюшка просто услышит про изменения и сама пойдет к модели выяснять
Если вью массивная, то лучше события из модели разделить и диспатчить если не совсем уж разные то хотя бы как-то сгруппировано.
Например большая изокарта. События в модели могут быть разные. Поменялся статус в каком-то домике, просто надо в нем показать хинт, или же поменялась позиция домика, тогда нужно отсортировать элементы. Вот эти два изменения лучше как-то разделить чтоб вьюха понимала какой рендер запускать.
Добавлено через 8 минут
Ей даже не важно, кто и каким образом поменял эти значения
А вот это действительно несущественно. У вьюхи есть ее модель и ее основная задача с одной стороны отображать во внятном а не абстрактно-циферном виде состояние этой самой модели, чтоб пользователю понятно было. А с другой стороны передавать действия пользователя контроллеру чтобы тот мог принимать какие-то решения или давать модели команды.
HardCoder
17.01.2012, 02:31
Ей даже не важно, кто и каким образом поменял эти значения (модель сама там что-то насчитала, контроллер что-то там вызвал, с сервера данные подоспели).Это понятно. Я же не говорю что она должна знать кто что менял.Не правильно. Вьюшка просто услышит про изменения и сама пойдет к модели выяснять, что там поменялось.Жаль что не правильно. Яхотел просто вьюшку подписать на события модели и больше модель в ней вообще не трогать. Что-то типа этого:model.addEventListener(ModelEvent.UNIT_ACTIVATED, activateUnit);
private function activateUnit(e:ModelEvent):void {
trace(e.activeUnit);
}То есть, чтобы за свойством activeUnit не лезть в модель с которой по-пьяни можно сделать что-то, а получить его прямо из событийного обьекта ModelEvent.
Что же, будем делать "правильно". Спасибо :)
Добавлено через 8 минут
Сложно будет сделать адекватный рендер с обработкой всех событий и слишком легко запутаться..Не совсем понял. У меня какбэ все просто. Есть класс ModelEvent, на события которого подписываются две вьюшки, вернее одна вью - и компьютер(АI). Они получают такие события от модели. Отправляют в контроллер события OpponentEvent.
Dukobpa3
17.01.2012, 02:42
model.addEventListener(ModelEvent.UNIT_ACTIVATED, activateUnit);
private function activateUnit(e:ModelEvent):void {
trace(e.activeUnit);
}
Это только одно событие получается. Юнита активировали. А будет еще пачка, юнит походил, юнит атакует, юнит копает, юнит в доме.
И это в итоге может разрастись на пачку всего остального.
К тому же если юнита активировали то подсветится те клетки куда можно пройти, а юнит не может ходить по камням к примеру. Так вот в каждом таком событии передавать всю карту нецелесообразно, нужно чтоб вью сама полезла в модель и прочитала параметры карты и потом нарисовала подсвеченные клетки.
HardCoder
17.01.2012, 02:46
Так вот в каждом таком событии передавать всю карту нецелесообразно, нужно чтоб вью сама полезла в модель и прочитала параметры карты и потом нарисовала подсвеченные клетки.То что я и хотел узнать!!!
@fish_r - Слушай что тебе старшие говорят ;-Р
Так уж получилось, что я старше вас обоих и не исключено, что вместе взятых.
Но, вероятно мы должны сказать спасибо вашим родителям за ваше воспитание.
Dukobpa3
17.01.2012, 03:24
Никогда не оценивал возраст по годам, сорри.
Ну и на этот вопрос тебе Dukobpa3 уже давал ответ, с которым я согласен
Юнит — не кнопка. Юнит — фигурант логики приложения. Кнопка — кликабельный кусок монитора.
А теперь предположим, что вы делаете польз. интерфейс с помощью которого несколько пользователей, одновременно управляют неким процессом и местоположение кнопок определяет последовательность
каких либо действий. Т.е. если один изменил местоположение кнопки, то и у других оно должно изменится.
Являются ли в этом случае координаты кнопки частью модели?
Добавлено через 1 минуту
Никогда не оценивал возраст по годам, сорри.
Блин, а как его ещё можно оценивать? Вы просто непрерывно открываете для меня "новые горизонты".
Dukobpa3
17.01.2012, 03:28
Т.е. если один изменил местоположение кнопки, то и у других оно должно изменится.
ключевые слова вот.
Да, тогда координаты или какое-то представление координат должно быть в модели (возможно даже не двумерное, а линейное "что за чем в каком порядке").
Добавлено через 58 секунд
Блин, а как его ещё можно оценивать? Вы просто непрерывно открываете для меня "новые горизонты".
Сложный философский вопрос, не для этого форума.
Изначально про возраст как бы шутка была. Но если уж так серьезно то так.
Вадим не отписался, предположу, что он и в этом, вашем ответе с вами солидарен.
Так вот:
Да, тогда координаты или какое-то представление координат должно быть в модели (возможно даже не двумерное, а линейное "что за чем в каком порядке").
Не "координаты", и не "какое то представление", а именно измененный порядок действий должен быть получен моделью (интерпретированный контроллером), и вью интерфейса "на другой стороне", который возможно и выглядит-то иначе (ну скажем оппонент - араб, или японец и т.д.), интерпретирует полученные данные (а именно порядок действий) в нужную последовательность расположения виз. элементов.
Таким образом мы и получаем правильное взаимодействие элементов: вью интерпретирует данные модели,
контроллер интерпретирует данные вью - получаем обособленность, независимость модели от представления (но не обратную, что MVC и не предусматривает).
И, вот что... устал я что то от этого, с вашего позволения закроем прения по этому вопросу.
"Имеющий уши да услышит, имеющий глаза да увидит..."
Dukobpa3
17.01.2012, 23:47
Ни к чему ведь прения.
Вы опять же привели один из частных случаев.
Одни и те же шахматы можно сделать как с сохранением истории - тогда ключевым моментом будет порядок действий. А можно хранить только текущее состояние. Тогда достаточно будет только координат фигур на доске.
Оба варианта имеют место быть и на определенном уровне абстракции абсолютно идентичны.
Прение - это спор. В этом нет ничего страшного )
Ну, ладно. А почему именно координаты вам нужно сохранять (про шахматы)? Можно ведь сохранить в
двухмерном массиве вида x\y, где каждый эл-т это клетка шах. поля. Так нельзя сделать?
Конечно, в случае с юнитами всё может быть намного сложнее, но MVC и не гарантирует простоты, он гарантирует лишь одно - независимость представления от логики.
Dukobpa3
18.01.2012, 00:05
двухмерном массиве вида x\y, где каждый эл-т это клетка шах. поля. Так нельзя сделать?
Да как угодно можно. Главное принципы соблюсти.
Касательно шахмат зачем мне целый двумерный массив из 64-х клеток если я обойдусь одномерным массив на 32 значения. Экономия на спичках, в данном конкретном случае, но всё же. И даже если это будет не 8х8, а некое произвольное поле то вьюхе будет достаочно узнать размерность(два значения) и опять же один одномерный массив юнитов.
И разговор наш начинался с карты и юнитов. Тут абсолютно та же ситуация - координаты минимальное чем можно обойтись для воссоздания текущей ситуации.
А вот например есть игра Торибаш. Физика трехмерная, две регдольных куклы файтинги устраивают. Так вот тут нужен именно порядок действий с самого начала боя, так как тут играет роль физика, и очень влияет на исход боя не только текущее положение, а еще и инерция которую мы получили в предыдущих ходах.
Еще может быть какая-то стратегия, чтоб риплеи сохранять и прочее. Ну так ведь это уже другая задача совершенно. К ней и подход другой. Да и тут можно кучу вариантов найти. Либо порядок действий каждого пользователя, либо же набор "скриншотов" модели.
Да как угодно можно. Главное принципы соблюсти.
Вот именно "как угодно" нельзя именно потому, что надо принципы соблюсти.
Касательно шахмат зачем мне целый двумерный массив из 64-х клеток если я обойдусь одномерным массив на 32 значения. Экономия на спичках, в данном конкретном случае, но всё же. И даже если это будет не 8х8, а некое произвольное поле то вьюхе будет достаочно узнать размерность(два значения) и опять же один одномерный массив юнитов.
MVC не решает задачу - упросить приложение, оно решает задачу - отделить представление от логики. Так
что если вам понадобится в 50 раз больше усилий приложить, будьте добры приложите их. Иначе не "крестите" свою конструкцию MVC, только и всего.
И разговор наш начинался с карты и юнитов. Тут абсолютно та же ситуация - координаты минимальное чем можно обойтись для воссоздания текущей ситуации.
А вот например есть игра Торибаш. Физика трехмерная, две регдольных куклы файтинги устраивают. Так вот тут нужен именно порядок действий с самого начала боя, так как тут играет роль физика, и очень влияет на исход боя не только текущее положение, а еще и инерция которую мы получили в предыдущих ходах.
Еще может быть какая-то стратегия, чтоб риплеи сохранять и прочее. Ну так ведь это уже другая задача совершенно. К ней и подход другой. Да и тут можно кучу вариантов найти. Либо порядок действий каждого пользователя, либо же набор "скриншотов" модели.
2Dukobpa3. А кто вам вообще сказал, что непременно должна быть реализована MVC? Что других способов
писать приложение уже не осталось? Это единственный возможный вариант строения приложения? Да, наплюйте, как наплевали на это больше половины (наверняка) игроделов.
Да. Реализация этой парадигмы может привести к значительному усложнению приложения, росту нагрузки,
замедлению быстродействия и пр. Ещё раз - MVC не решает эти проблемы, она решает совершенно другое, так, что взвесьте, подумайте нужно ли вам в очередном приложении такая реализация? Может дешевле будет переделать логику когда потребуется переделывать отображение? Если вообще потребуется.
Но если вы ставите логику в зависимость характеристик отображения, то это не MVC.
Dukobpa3
18.01.2012, 23:16
MVC не решает задачу - упросить приложение, оно решает задачу - отделить представление от логики.
Зато я, как программист, решаю задачу упростить приложение и сократить кол-во трафика и внутреннего и наружного. И если я могу это сделать, не нарушая принципов - то я сделаю. Сократить кол-во информации вдвое просто потому что записал не клетки, а юнитов - да запросто. Использовать обратную польскую запись чтобы отказаться от скобок и лишнего форматирования - опять же только за?
Логика от этого не страдает абсолютно, равно как и парадигма МВЦ, а идти заведомо каким-то сложным путем, если можно проще, смысла не вижу никакого.
И вы мне покажите хоть один источник информации в котором указано каким именно образом должны записываться данные в модель? Формулы какие-то? Правила? Их нету.
incvizitor
28.06.2012, 17:05
Crazy, хаоса никакого, просто в 90% случаев контроллеру нужна так или иначе основная модель, для получения прототипов или иной ерунды, поэтому она по умолчанию идёт линком у родительского контроллера и всё тут. Я опираюсь на собственный опыт (а я считаю, что он уже достаточен) и минимизация зависимостей вот как раз в таких случаях — простое помешательство на MVC, выливающиеся в геморрой по передаче 100500 параметров, вот и всё. Да, можно всё сделать по фен-шую, только незачем и никому это не нужно.
А каким образом лучше организовать получение прототипов из основной модели? И еще, как лучще всего получать их в дочерних моделях?
А каким образом лучше организовать получение прототипов из основной модели? И еще, как лучще всего получать их в дочерних моделях?
Реализовать промежуточный класс с ленивым геттером основной модели. Так называемый ассет основной модели. Всё, кто в неё попадает, может получить на неё ссылку. Ну а оттуда уже к коллекции прототипов и т. д.
Dukobpa3
28.06.2012, 17:15
Я в базовый класс модели вставляю сылку статическую на основную(серверную) модель.
Psycho Tiger
28.06.2012, 17:20
А что такое "прототипы" в этом контексте?
А что такое "прототипы" в этом контексте?
Прототип — описание характеристик сущности. Своего рода класс сущности.
incvizitor
28.06.2012, 17:28
Ага, спасибо. Только что такое "ленивый геттер" ? :rolleyes:
А еще вот в swiz, была такая фишка, всё что попадает на сцену проижектывается автоматом. С этой фичей мы избавляемся от маппинга, но за то приобретаем плюся ДИ. Может быть такую систему можно заюзать для того что бы дочерние модели получали то что нужно?
Ага, спасибо. Только что такое "ленивый геттер" ? :rolleyes:
А еще вот в swiz, была такая фишка, всё что попадает на сцену проижектывается автоматом. С этой фичей мы избавляемся от маппинга, но за то приобретаем плюся ДИ. Может быть такую систему можно заюзать для того что бы дочерние модели получали то что нужно?
Ну прям выдерну пример ленивого геттера:
/**
* @private
*/
private var _user:UserData;
public function get user():UserData {
if (!this._user || !this._user.contains(this)) {
this._user = null;
var parent:DataContainer = super.parent;
while (parent) {
if (parent is IUserAsset) {
this._user = (parent as IUserAsset).user;
break;
}
if (parent is UserData) {
this._user = parent as UserData;
break;
}
parent = parent.parent;
}
}
return this._user;
}
Хотя в случае с глобальной моделью, уже инжект:
/**
* @private
*/
private var _universe:UniverseData;
public function get universe():UniverseData {
return this._universe;
}
[Exclude]
public function set $universe(value:UniverseData):void {
if (this._universe == value) return;
if (!value) this.removedFromUniverse();
this._universe = value;
if (value) this.addedToUniverse();
if (this is DataContainer) {
var dc:DataContainer = this as DataContainer;
var num:int = dc.numChildren;
while (num --> 0) {
var child:Data = dc.getChildAt(num);
if (child is IUniverseAsset) child['$universe'] = value;
}
}
}
Зачем this._user = null?
if (!this._user || !this._user.contains(this)) {
this._user = null;
incvizitor
28.06.2012, 17:50
1 - Понял, спасибо.
2 - А почему бы просто не слушать DataBaseEvent.ADDED?
И еще. Можно вышестоящим родителем сеттить user, если он у него есть, конечно. Т.е. не обращаться к родителю, а он все сам сделает. Аха, да, это инжект и есть.
Psycho Tiger
28.06.2012, 17:53
Прототип — описание характеристик сущности. Своего рода класс сущности.
А для чего он может понадобится?
Зачем this._user = null?
if (!this._user || !this._user.contains(this)) {
this._user = null;
Я от тебя такого вопроса не ожидал :)
Добавлено через 55 секунд
А для чего он может понадобится?
Для хранения общих свойств, типа названия предмета, ссылки на картинку и т. п. Т. е. если у тебя есть однотипные предметы в инвентаре, у них всех ссылка на один и тот же прототип.
Добавлено через 1 минуту
А почему бы просто не слушать DataBaseEvent.ADDED?
А зачем тратить на это время, если никто не обращается к геттеру?
Добавлено через 2 минуты
И еще. Можно вышестоящим родителем сеттить user, если он у него есть, конечно. Т.е. не обращаться к родителю, а он все сам сделает.
Можно, но опять же, зачем тратить на это время, если юзер прям вот щас не нужен.
incvizitor
28.06.2012, 18:02
Хм, разве это дорогостоящая операция?
Хм, разве это дорогостоящая операция?
Вполне себе да, особенно учитывая, что оно всплывающее.
if (!this._user...
this._user = null;
Он вроде и так null;
incvizitor
28.06.2012, 18:11
@dimarik, не обязательно.
@etc, ок спасибо.
Зачем this._user = null?
if (!this._user || !this._user.contains(this)) {
this._user = null;
А если выполняется вторая часть условия?
Можно, но опять же, зачем тратить на это время, если юзер прям вот щас не нужен.
Ну а если юзер сменится? Нужен апдейт по детям тогда.
Ну а если юзер сменится? Нужен апдейт по детям тогда.
Не сменится :)
А если и сменится, это в любом случае произойдёт в результате ADDED/REMOVED, т. е. заведомо более важного события. Самим ассетам отслеживать момент смены не нужно, просто незачем.
UserData вполне себе может быть IUserAsset, кстати. И UserData#user может указывать, например, на персонажа текущего пользователя. Лишняя проверка убирается.
Добавлено через 1 минуту
ADDED/REMOVED еще продиагностировать нужно, от кого пришло. А если глубина вложенности большая, то только и будешь определять target.parent с currentTarget
UserData вполне себе может быть IUserAsset, кстати. И UserData#user может указывать, например, на персонажа текущего пользователя. Лишняя проверка убирается.
Персонаж это персонаж, а юзер это юзер. Последний ассетом самого себя не может быть.
ADDED/REMOVED слушают и диагностируют те, кому это нужно, просто в любом случае смена юзера означает изменение контейнера, а значит в представлении точно также поменяется отображаемый контейнер и это будет уже другой вьювер.
this._user.contains(this) при глубоком (IUserAsset находится в энном колене) и широком (обладатель этого ленивого геттера находится на тысячной позиции) дереве будет чутка тормозить.
this._user.contains(this) при глубоком (IUserAsset находится в энном колене) и широком (обладатель этого ленивого геттера находится на тысячной позиции) дереве будет чутка тормозить.
В модели таких вложенностей не бывает.
Psycho Tiger
28.06.2012, 18:37
Для хранения общих свойств, типа названия предмета, ссылки на картинку и т. п. Т. е. если у тебя есть однотипные предметы в инвентаре, у них всех ссылка на один и тот же прототип.
А, для экономии памяти, понятно.
Реализовать промежуточный класс с ленивым геттером основной модели. Так называемый ассет основной модели. Всё, кто в неё попадает, может получить на неё ссылку.
А чем плохо сразу тянуть ссылку на основную модель, без этих заморочек?
Персонаж это персонаж, а юзер это юзер. Последний ассетом самого себя не может быть.
ADDED/REMOVED слушают и диагностируют те, кому это нужно, просто в любом случае смена юзера означает изменение контейнера, а значит в представлении точно также поменяется отображаемый контейнер и это будет уже другой вьювер.
А я разве сказал, что this._user ассет самого себя? Он ассет кого надо ассет. Какого-то юзеря. Может текущего персонажа. Удобно с текущим пером меряться. Он под рукой всегда.
Ну поменяется отображаемый контейнер, если ты сверху вниз на стадии смены контейнера пересеттишь этот ассет. Я не вижу смысла тут пользоваться прослушиванием ADDED/REMOVED
В модели таких вложенностей не бывает.
Это по стандарту так?
А, для экономии памяти, понятно.
Нет, просто копировать свойства в каждый новый экземпляр замучаешься и сравнивать их потом сложно.
А чем плохо сразу тянуть ссылку на основную модель, без этих заморочек?
Тем и плохо, что надо тянуть и не забыть.
А я разве сказал, что this._user ассет самого себя? Он ассет кого надо ассет. Какого-то юзеря. Может текущего персонажа. Удобно с текущим пером меряться. Он под рукой всегда.
Димка, я чето не понимаю, на каком языке ты разговариваешь. Юзер — это пользователь. Всё, что к нему относится — его ассеты и ему на него ссылку и вообще находятся в нём. В том числе и персонажи. Но как может быть юзер ассетом персонажа, я не очень понимаю.
Ну поменяется отображаемый контейнер, если ты сверху вниз на стадии смены контейнера пересеттишь этот ассет. Я не вижу смысла тут пользоваться прослушиванием ADDED/REMOVED
Речь шла о том, что отслеживать смену юзера самому ассету незачем, т. к. есть более важные события, которые следуют в результате смены юзера, например тот же ADDED/REMOVED. И если их слушают во вьювере, этого достаточно, чтобы обновить данные в соответствии с новыми условиями и юзером.
Это по стандарту так?
В контексте модели, обсуждаемой в этой теме, да. А в целом, при такой вложенности я не уверен, что вообще необходимо делать такие элементы ассетами кого-либо, если вообще имеет смысл держать такое в модели.
Psycho Tiger
28.06.2012, 19:09
Тем и плохо, что надо тянуть и не забыть.
Главная модель для меня всегда находится в вершине иерархии. Если композит моделей перенести на дисплей обджект, то это stage / root, ссылка тянется самой структурой.
Главная модель для меня всегда находится в вершине иерархии. Если композит моделей перенести на дисплей обджект, то это stage / root, ссылка тянется самой структурой.
А, я думал про «тянуть» имелось ввиду передавать вниз по иерархии. Если имеется ввиду сразу дергать линк, то ничего плохого в этом нет, кроме бесполезно потраченного времени.
incvizitor
28.06.2012, 19:17
Psycho Tiger, ну тогда получится что DataBase придется экстэндить, и все потомки (которые хотят обращатся к прототипам) будут знать тип нашей БД. А если использовать ленивый геттер, то мы не знаем что в иерархии является IPrototypeHolder у которой можно забрать прототипы.
Psycho Tiger
28.06.2012, 19:23
А, я думал про «тянуть» имелось ввиду передавать вниз по иерархии. Если имеется ввиду сразу дергать линк, то ничего плохого в этом нет, кроме бесполезно потраченного времени.
Вниз - это от предка к потомкам?
Когда контейнеру делают addChild у него автоматом устанавливается parent и root. Когда нужен root - сразу дёргают root, без поиска его по ленивым геттерам. Где тут бесполезно потраченное время, не понимаю?
@Инквизитор: тебя я тоже совсем не понимаю )
Можно на пальцах?
incvizitor
28.06.2012, 19:30
Зачем сразу устанавливать рут? Разве его нельзя забрать рекурсивно?
На пальцах:
public function getPrototypeHolder():IPrototypeHolder{
var parentNode:DataContainer = parent;
while(parentNode){
if(parentNode is IPrototypeHolder){
return parentNode as IPrototypeHolder;
}
parentNode = parentNode.parent;
}
throw new Error("not found");
}
Мы не знаем что это именно ДБ явлеятся (ведь может быть и нет) IPrototypeHolder, мы просто знаем что он есть среди родителей.
Димка, я чето не понимаю, на каком языке ты разговариваешь. Юзер — это пользователь. Всё, что к нему относится — его ассеты и ему на него ссылку и вообще находятся в нём. В том числе и персонажи. Но как может быть юзер ассетом персонажа, я не очень понимаю.
А, все! Я вроде андерстенд! У тебя персонажи и пользователи разделены. По той причине, что у одного пользователя может быть несколько персов. Я же, каюсь, в силу привычки к своему проекту, в котором один пользователь — один персонаж, не сразу догнал, о какой UserData идет речь.
Но этот посыл ровным счетом ничего не меняет. Все будет зависеть от глубины и ширины модели. Вот я к чему.
Пуш/пуль. Вот в чем камень преткновения! Когда push становится быстрее pull и наоборот? Никакие остальные рассуждения о конкретике реализации не имеют смысла. Вполне возможно, что эта величина вычислима на основе количества объектов, агрегируемых другим.
Вниз - это от предка к потомкам?
Когда контейнеру делают addChild у него автоматом устанавливается parent и root. Когда нужен root - сразу дёргают root, без поиска его по ленивым геттерам. Где тут бесполезно потраченное время, не понимаю?
Да хотя бы взять дерево, не добавленное в рут изначально, с толпой детей. Добавили в рут, посидели и покурили, пока оно раздаст руты всем киндерам. Но зачем? Геттер тупит единственный раз и явно меньше по времени, чем раздача рута абсолютно всем.
Добавлено через 50 секунд
Но этот посыл ровным счетом ничего не меняет. Все будет зависеть от глубины и ширины модели. Вот я к чему.
Пуш/пуль. Вот в чем камень преткновения! Когда push становится быстрее pull и наоборот? Никакие остальные рассуждения о конкретике реализации не имеют смысла. Вполне возможно, что эта величина вычислима на основе количества объектов, агрегируемых другим.
Это всё можно реализовать гибридным способом, где-то push, где-то pull. Но сомневаюсь, что когда-нибудь этим займусь.
Добавлено через 1 минуту
Зачем сразу устанавливать рут? Разве его нельзя забрать рекурсивно?
В предложенном варианте будет пробегать всякий раз при обращении к геттеру. Это не есть гут.
Позвольте все эти вышеозначенные вопросы свести все-таки к пушпулю. Итак, все рассуждения сводятся к тому, как красивше в дереве прокидывать ссылки на листья/ветки к другим листьям/веткам. Никто не находит это логичным?
incvizitor
29.06.2012, 00:02
В предложенном варианте будет пробегать всякий раз при обращении к геттеру. Это не есть гут.
ну да, можно добавить кеш и чистить его на REMOVED_FROM_DATABASE.
ну да, можно добавить кеш и чистить его на REMOVED_FROM_DATABASE.
Нет смысла, если только нет подписки на какие-либо события.
incvizitor, etc
Вы как смотрите на мою локализацию проблемы?
incvizitor
29.06.2012, 00:20
что именно, создавать кеш или чистить его, или и то и другое?
Добавлено через 52 секунды
@dimarik, ок, ща про кеш договорим только =)
что именно, создавать кеш или чистить его, или и то и другое?
Занулять ссылку при удалении из базы.
incvizitor
29.06.2012, 00:34
Занулять ссылку при удалении из базы.
ясно, спасибо.
Psycho Tiger
29.06.2012, 00:58
Да хотя бы взять дерево, не добавленное в рут изначально, с толпой детей. Добавили в рут, посидели и покурили, пока оно раздаст руты всем киндерам. Но зачем? Геттер тупит единственный раз и явно меньше по времени, чем раздача рута абсолютно всем.
Тут уже вопрос, что чаще - дёргается root или делается addChild толпой. Но мысль уловил, спасибо.
incvizitor
19.08.2012, 17:30
А если есть такая структура:
http://www.flasher.ru/forum/attachment.php?attachmentid=28353&stc=1&d=1345396959
Стоит задача отобразить красным ресурсы которых не достаточно для покупки предмета. Как лучше протягивать баланс юзера в модельку shopItem?
Dukobpa3
19.08.2012, 18:04
скрин улетел
incvizitor
19.08.2012, 18:16
скрин улетел
http:// *************/ s / 2dGQj
Добавлено через 1 минуту
блин, и на клип2нет линк вырезается..
Dukobpa3
19.08.2012, 18:55
вставь вложение
Как лучше протягивать баланс юзера в модельку shopItem?
Никак, в примере на скрине вариант лучший имхо только один :
Либо DB должна при запросе создания shop должна отсылать вам кеш , а создавать итем будете уже передавая в него кеш. Либо есть более изящный вариант :
В итеме подписываемся на событие добавления на сцену, из итема диспатчим событие шопу ( или чего у вас там вьюха) , ну а в шопе имеем баланс уже ( надеюсь ) , от него и рассылаем итемам задачу сменить цвет
Как лучше протягивать баланс юзера в модельку shopItem?
Я сделал коллекции Condition и ComparisonObject. Первый по сути требования, условия. Второй -- то, что будем сравнивать с условиями. Сравнивать можно любые объекты, поддерживающие IComparator и IComparable.
ShopItem имплементит IComparator, с его методом compare. Метод принимает список ComparisonObject и возвращает Boolean (подошло/не подошло). У каждого магазина, его коллекции ShopItem'ов, самого ShopItem есть ссылка на User. User поддерживает интерфейс IComparable, метод которого getComparisonList(глагол):Vector.<ComparisonObject>, возвращает список доступных для сравнивания ComparisonObject;
getComparisonList извлекает предварительно подготовленные списки ComparisonObject. Их формированием и обновлением занимается сам IComparable, правила для этого находятся в нем.
Сама проверка можно ли купить предмет, с учетом скилов User и количества требуемой валюты сводится к одной строке
const canBuyItem:Boolean = shopItem.compare( shopItem.user.getComparisonList(покупать) );
Коллекция ShopItem -- ShopItemCollection тоже поддерживает интерфейс IComparator;
Достаточно накидать в нее некоторое количество shopItem, а затем и с ней провести сравнение.
const canBuyItems:Boolean = shopItemCollection.compare( shopItemCollection.user.getComparisonList(покупать) );
При этом будет учитываться количество, например денег, чтобы хватило на покупку всех айтемов. MoneyComprasionObject -> ChangeableComparisonObject -> ComparisonObject будет последовательно, с каждой проверкой уменьшать value. А вот, например, CharacteristicComparisonObject -> ComparisonObject и поэтому сравниваемая характеристика есть константа. Метода похожа на шаблон посетитель.
Итак, можно сравнивать все и вся, лишь бы была коллекция условий и то, с чем сравниваем. Можно померяться скилами UserData с коллекцией UserCollection.
userCollection.compare( userCollection.user.getComparisonList(меряться_скилами) );
Вот как-то так я это сделал.
Sintesis
05.11.2012, 22:01
А если приложение не связано с сетью и есть класс в который встроена вся графика и XML с некоторыми данными этот класс можно считать Model и по команде от Controller - View будет брать у него графику через геттер? Или вся графика сразу должна встраиваться во View?
Dukobpa3
06.11.2012, 01:04
хмл - модель.
графика - вью.
В хмл могут быть ссылки на аасеты к примеру, тогда в модели будут урлы по которым вьюха сможет достать нужный ассет.
Или если графика заэмбежена - то бы сделал некий манагер, а в модели бы хранил ид-ы по которым вьюха сможет из манагера достать ассет.
Как-то так. А вообще по ситуации смотреть надо. В идеале должно быть так чтоб модель ничего не знала об ассетах. Чтобы можно было на одну модель повесить несколько вьюх, которые одни и те же данные по-разному отображают.
Sintesis
06.11.2012, 01:44
Наверное тогда класс в котором встроены все ресурсы будет каким-то хранилищем, а в модели будут храниться id. Условие такое, что скомпилиная флешка должна быть самодостаточной, то-есть в неё всё должно быть встроено и хочется, чтоб всё встроенное было в одном месте. В XML храняться данные о вершинах которые нужно парсить и больше ничего.
Dukobpa3
06.11.2012, 01:49
думаю норм будет.
Sintesis
08.11.2012, 21:49
И ещё вопросик, если есть кнопки, то они располагаются в View и диспетчат событие контроллеру или они публично открыты для контроллера и слушаются в нём?
Dukobpa3
08.11.2012, 21:54
Контроллер не знает про внутренности вьюхи, он слушает только ее.
А там уже вьюха шарит какое событие выпускать наружу при клике на кнопку.
Варианты могут быть разные.
Можно из кнопки бабблить транзитом через вьюху.
А можно во вьюхе слушать кнопку "открыть профиль" и например клик по аватаре, и на оба этих внутренних события в контроллер выпускать только одно событие: "покажи профиль".
Sintesis
08.11.2012, 22:05
Понятно, значит во вьюхе диспатчить буду.
Контроллер не знает про внутренности вьюхи
Но методы вьюхи контроллер может же вызывать? В примере ПсихоТайгера например: _view.updateSquares(); вызывается в контроллере. Или ты имеешь ввиду, что глубже заходить нельзя, например вот так
_view.updateSquares().someElse; ?
Dukobpa3
09.11.2012, 00:06
Но методы вьюхи контроллер может же вызывать? В примере ПсихоТайгера например: _view.updateSquares(); вызывается в контроллере. Или ты имеешь ввиду, что глубже заходить нельзя, например вот так
_view.updateSquares().someElse; ?
_view.updateSquares(); - это уже плохо. Только ивентами, но иногда не гнушаюсь и сам дернуть какой-то паблик метод вьюхи, хотя и очень стараюсь избегать. Я предпочту поменять что-то в модели чтоб вьюха увидела изменения и просто перерисовалась.
А то что вьюха постоянно слушает модель на предмет изменений и согласно этому рендерится вроде как вопросов вызывать не должно?:)
Sintesis
09.11.2012, 00:38
_view.updateSquares(); - это уже плохо.
А то что вьюха постоянно слушает модель на предмет изменений и согласно этому рендерится вроде как вопросов вызывать не должно?:)
Так это-ж ужас какой-то если она будет рендериться от событий модели, а если в контроллере Энтерфрейм событие меняет какие-нибудь данные положения объекта в модели, модель должна диспатчить событие для вьюхи 30 раз в секунду?
Dukobpa3
09.11.2012, 00:40
Тебе на первую страницу и читать сначала в таком случае....
Добавлено через 2 минуты
* Во-перых какие это данные в моделях должны с частотой раз в кадр меняться?
* Во-вторых что энтерфрейм делает в контроллере.
* В третьих кто сказал что рендер во вьюхе должен быть целиком - получил маяк - целиком перерисовалась.
Из модели шлются микросообщения: "поменялось такое вот данное" а вьюха меняет "такое вот поле". Одно поле, а не вся перерисовывается.
Sintesis
09.11.2012, 00:44
Тебе на первую страницу и читать сначала в таком случае....
Да не, толку не будет, потому, что мне в глаза сразу бросается _view.updateSquares(); который всё это решает. Можно тут объяснить?
Dukobpa3
09.11.2012, 00:45
И в модели изначально должны быть те данные которые влияют на состояние системы. То что мы должны будем восстановить при перезапуске допустим, или же закрыв и открыв окно.
Вьюха удаляется, но потом восстанавливает нужную картинку по данным из модели.
Так вот если это допустим текущая страница в магазине, скорее всего ее хранить нигде не надо, и можно листать страницы не сохраняя индекс страницы в модель. Ну и в таком духе.
Добавлено через 4 минуты
Можно тут объяснить?
Так че тут обьяснять. Должно быть четкое разделение прав и обязанностей между контроллером моделью и вьюхой.
Модель - логика и математика и данные. Она всё считает.
Вью - красивая, но тупая, умеет только рисоваться согласно данным в модели. При чем на одной модели может висеть несколько разных вьюх. Например есть профиль пользователя, это модель. А у него три вьюхи - инвентарь, кукла персонажа в бою, оконо распределения скилов.
А контроллер
случает события из вьхи.
может каким-либо методом общаться с другими контроллерами
при получении сообщения из вью или другого контроллера - поменять некие данные в модели.
При этом всём вью постоянно слушает модель на предмет изменений и перерисовывается, поддерживаяч картинку в актуальном состоянии.
И вот чтоб вью слишком часто не рисовалась наша задача подумать как и что должна диспатчить модель и как часто.
Ну это мое видение мвц. С ним некоторые наверное не согласятся. А спорить я не хочу.
Добавлено через 6 минут
И да, контроллер это чисто как связующее звено. Он сам решений не принимает. Все таймера и периодические события возникают в моделях, либо же во вью - если это не требует выхода наружу (ну типа локально во вью подписались на энтерфрейм, но ольше никто об этой подписке не знает и не должен. Если должен - то лучше крутить что-то в модель, пусть она рендер дергает.)
Sintesis
09.11.2012, 00:53
* Во-вторых что энтерфрейм делает в контроллере.
Об этом ничего не написано, почему-то посчитал, что ентерфрейм должен быть в контроллере, но раз уж он в вьюхе, тогда _view.updateSquares(); не потребуется.
Dukobpa3
09.11.2012, 00:58
Контроллер не может быть инициатором никакого действия.
Инициатор всегда либо модель если это данные с сервера новые, либо что-то периодическое типа таймера. Либо же вью - если это какое-то действие пользователя.
Ну это грубо. Вцелом то так и есть, но бывает по-разному.
Так вот исходя из этого - никакая логика не может допустить наличие энтерфейма в контроллере, ибо в таком случае он станет инициатором какого-то непотребства.
Добавлено через 3 минуты
Нужно изначально понять саму идею разделения ролей на М В Ц. Тогда путаницы не будет.
Когда четко осознаешь обязанности каждого - половина вопросов сами отпадут.
Sintesis
09.11.2012, 01:02
Добавлено через 6 минут
И да, контроллер это чисто как связующее звено. Он сам решений не принимает. Все таймера и периодические события возникают в моделях, либо же во вью - если это не требует выхода наружу (ну типа локально во вью подписались на энтерфрейм, но ольше никто об этой подписке не знает и не должен. Если должен - то лучше крутить что-то в модель, пусть она рендер дергает.)
Ага, ну вот так вот уже понятней, первые посты немного в заблуждения вводят. Ещё стрелочка на рисунке от контроллера к вьюхе вводит в заблуждение, кажется буд-то контроллер может делать с вьюхой что хочет.
Dukobpa3
09.11.2012, 01:04
Он имеет ссылку на вью, но это не значит что он может делать с ней всё что хочет. Ему ссылка нужна банально для того чтобы подписаться на события. В идеале этим нужно ограничиться.
Sintesis
09.11.2012, 01:06
Вот что пишет ПсихоТайгер
C - Controller. Контроллер. Он занимается логикой всей триады. Именно он обрабатывает нажатие клавиш и меняет данные в модели, записывая туда новые координаты игрока. Именно он разрешает игроку стрелять и меняет у него оружие.
Вот цитата с твоего поста:
Контроллер не может быть инициатором никакого действия.
Инициатор всегда либо модель если это данные с сервера новые, либо что-то периодическое типа таймера. Либо же вью - если это какое-то действие пользователя.
Что-то не сходится, если контроллер обрабатывает "нажатие клавиш" то как он "не может быть инициатором никакого действия"?
Dukobpa3
09.11.2012, 01:11
Я не считаю что тигер был прав.
Он в этих суждениях допускает стандартную ошибку всех начинающих работать по мвц - думает что контроллер всему голова, а модель - тупо набор данных.
Это не так. Логика в модели. А контроллер может ей сказать: Ану-ка подруга, обнови-ка свои данные об вот этом вот контакте. И она обновит, а вьюшка увидит и нарисует этот контакт.
Но не так что контроллер говорит: модель, вот этот контакт заблокировать, поставить ему аватару вот такую, и поставить ему друзей вот таких вот. Модель сама знает откуда информацию черпать. Контроллер манагерит чисто на уровне команд.
Sintesis
09.11.2012, 01:20
думает что контроллер всему голова, а модель - тупо набор данных.
Жесть, да там всю статью об этом говориться, что контроллер всему голова и etc это подтверждает, а тут вдруг оказывается... Где истина?
Контроллер что и клавиши не слушает? Чем он вообще будет заниматься если приложение не серверное?
Dukobpa3
09.11.2012, 01:25
in vino veritas
Я таки рекомендовал бы прочесть весь этот флуд 50 страниц. Тут много умного и вариантов так же много. Я свое видение высказал. И я к нему шел два года, раньше тоже контроллер мозгами был, а модель просто набором данных. Но за два года я таки понял что удобнее логику в модели хранить. Гораздо удобнее.
Удобнее это значит: требуется меньше кода, меньше времени, меньше усилий на поддержку.
Добавлено через 6 минут
И что самое крутое: роли таки получаются четко разделены. МОдель перестает быть тупой пачкой геттеров-сеттеров и начинает выполнять какие-то функции. И контроллер не раздувается до вселенских неконтролируемых масштабов.
Sintesis
09.11.2012, 01:34
У тебя много противоречий например ты говоришь:
* Во-перых какие это данные в моделях должны с частотой раз в кадр меняться?
имеешь в виду, что никакие данные не меняются в модели 30 раз в секунду.
а дальше
Все таймера и периодические события возникают в моделях
данные меняются 30 раз в секунду только в модели.
What? Я так не могу...
Dukobpa3
09.11.2012, 01:36
В моделях у меня таймера. Самый частый из них - раз в секунду. А это реже чем раз в кадр в целых 30 раз (у меня в проектах вообще обычно 60).
Добавлено через 5 минут
И это как правило вообще один глобальный теймер с частотой раз в секунду. В нем добавляются/удаляются коллбеки которые собственно на каждый тик дергаются.
Если нужна рекция чаще чем раз в секунду - есть еще одна глобальная штука - глобальный ентерфрейм. Ситема та же. Добавить/убрать коллбек и дернуть каждый - раз в кадр.
Коллбеки в основном в моделях находятся. Но бывают варианты.
Ну и ентерфрейм вот в текущем проекте реально только в одном модуле используется.
Dukobpa3, а как на счет ветвления контроллеров? В этом случае ничего раздуваться не должно. Может "пассиваная" модель и считается не правильным подходом, но при этом про ветвление этой структуры в той же википедии умалчивается (если где есть - дайте почитать, поделитесь ссылкой, интересно), а это предотвращает раздувание контроллера. При этом имеем четкое "разделение власти". Все же считаю, что программа не должна зависеть только от данных (как это может пропагандироваться), но и, к примеру, от "состояний". Где должно храниться "состояние"? Возможно в модели. Да, несколько озадачивает. В чем тогда предназначение контроллера? Список интерактивных объектов с подписанными слушателями и обработчиками и все?
Sintesis
09.11.2012, 01:45
Хоршо, глобальный энтерфрейм где длжен находиться в MVC? И не разрушит ли его глобальность ооп принципы и сам паттерн?
Dukobpa3
09.11.2012, 01:46
Ветвление моделей и вьюх - пожалуйста, ветвление контроллеров я стараюсь избегать.
У меня есть мейнКонтроллер, который содержит пачку дочерних контроллеров (все что есть в системе) и собственно их инициализирует.
В итоге все модули получаются на одном уровне, и ими легко управлять при любой сложности. Легко включить выключить любой из них. А если ветвить ссылками то призрачный "контроль" конечно вырастет, но и связанность тоже, и это уже обрубит модульную структуру на корню.
Добавлено через 1 минуту
Хоршо, глобальный энтерфрейм где длжен находиться в MVC? И не разрушит ли его глобальность ооп принципы и сам паттерн?
А вот хз))))
Я всунул туда же где и глобальный таймер. Просто в один и тот же синглтон можно добавить либо коллбек на таймер либо на ентерфрейм. И этот синглтон только этим и занимается - дергает периодические коллбеки с заданным интервалом. Иногда синхронизируя текущую дату с сервером.
Добавлено через 4 минуты
В чем тогда предназначение контроллера? Список интерактивных объектов с подписанными слушателями и обработчиками и все?
Связующее звено.
- слушает вью
- слушает другие контроллеры
- по командам от вью либо от других контроллеров может попросить модель поменять данные
- либо передать какую-то команду другим контроллерам.
- всё.
В нем вполне достаточно будет логики и кода для обработки разных команд от вьюх и других контроллеров. На этом его функция как для меня и заканчивается.
У меня есть мейнКонтроллер, который содержит пачку дочерних контроллеров (все что есть в системе) и собственно их инициализирует.Примерно это и имел ввиду.
ветвить ссылкамиКакое это имеет отношение к роли модели? В любом случае модуль - не один файл, а группа из M, V и C. К тому же не забываем про интерфейсы.
Добавлено через 2 минуты
Dukobpa3, так кто все-таки меняет данные? Вью или контроллер? Получается, что оба. Получается, что мы можем не знать кто именно, хотя это один из основополагающих моментов.
Dukobpa3
09.11.2012, 01:56
В любом случае модуль - не один файл, а группа из M, V и C.
Ну с моим подходом "Модуль" это всегда означает контроллер.
Иногда там есть и модель и вью, иногда только модель, иногда только вью, иногда по парочке каждых.
И тыкнув пальцем в контроллер можно сказать - вот модуль, от него всё пляшет.
А тыкнув пальцев во вью или модель придется еще поковыряться и найти к какому модулю она относится. (это решается грамотной группироовкой пакетов и иенами, но если абстрактно - дело именно так и обстоит)
Ну и получается контроллеры это типа как стартовые точки модулей.
Добавлено через 40 секунд
Dukobpa3, так кто все-таки меняет данные?
что значит "меняет данные" ?
Добавлено через 2 минуты
Вью ВПРИНЦИПЕ ничего не меняет. Она может попросить контроллер их поменять, а контроллер может и не согласиться.
И контроллер не меняет данные, он просит модель АКТУАЛИЗИРОВАТЬ ДАННЫЕ согласно текущего состояния системы. А модель уже сама вкурсе где взять конкретные цифры и куда их вписать.
Sintesis
09.11.2012, 02:02
Связующее звено.
- слушает вью
- слушает другие контроллеры
- по командам от вью либо от других контроллеров может попросить модель поменять данные
- либо передать какую-то команду другим контроллерам.
- всё.
В моём случае, например нужно перемещать главного героя нажатием клавиш, при твоём подходе вьюха самодостаточная - имеет весь функционал для данного действия, она сама прослушает нажатие, сама переместит в ентерфрейме объект и отрисует его. Зачем нужен контроллер и модель?
Dukobpa3
09.11.2012, 02:11
Чуток не так.
Переместить героя - скорее всего нужно будет помнить его последнюю позицию, значит она должна оказаться в модели.
Т.е.:
- тыкаем в клетку на карте
- вью диспатчит: "пытаемся походить"
- контроллер получает событие, дергает паблик в модели: "походитьГероемТуда-то" (координаты пришли в событии)
- модель в этом паблик методе делает проверку. Можем походить, не можем и если можем то меняет координаты героя, и диспатчит: "координаты героя поменялись"
- вью слышит что координаты поменялись, переставляет героя в новые координаты.
Проблемы начинаются там где нужно анимированное перемещение. По сути до этого модели дела нету. Она координаты куже поставила. А вот во вью уже будут твинеры или ентерфреймы, необходимые блокировки екрана чтоб пользователь не тыкал в екран пока герой идет и в таком духхе. Но в математике у героя координаты уже новые. (опять же по ситуации. Это лишь один из вариантов)
А теперь другой вариант. Всё это должно синхронизироваться с сервером. Тогда:
- тыкаем в клетку на карте
- вью диспатчит: "пытаемся походить"
- контроллер получает событие, посылает команду контроллеру сервера: командаПоходитьВТочку(х, у)
- сервер обрабатывает, присылает ответ ок/неОк.
- какой-то серверКонтроллер кричит контроллеру карты мол тут команда пришла поменять координаты
- наш контроллер получает эту команду
- дергает паблик в модели: "походитьГероемТуда-то" (координаты пришли в событии)
- модель в этом паблик методе меняет координаты героя, и диспатчит: "координаты героя поменялись"
- вью слышит что координаты поменялись, переставляет героя в новые координаты.
Добавлено через 4 минуты
Т.е. Если модели нужно знать новые координаты то надо диспатчить в контроллер, а контроллер просит модель проверить можно ли и если можно - сделать.
Если модели знать не обязательно - то вью может быть "самодостаточной" как ты и сказал.
А теперь самое главное.
Как понять когда же модели нужно знать а когда не нужно:
- если на это новое состояние будет опираться математика - нужно.
- если это чисто визуальная плюшка - пофиг.
Например мы идем героем и на нас в люббой момент может накинуться враг, и результаты атааки могут зависеть от того где герой находится. Тогда понятночто модель ждолжна знать как это всё считать и координаты героя ей важны.
И другой вариант. Мы управляем не самим героем а просто кликаем в шкаф в комнате, герой к нему подходит и открывает. Тут собственно пофигу, сам по себе герой в данной ситуации где-то там наравне с партиклом летящим за указателем. Суть не в том куда он идет, а в том что он пытается открыть. Тогда само перемещение героя может остаться во вьюхе, а вот открытие чемодана - уже надо продиспатчить контроллеру, чтоб он подумал что с этим делать.
Sintesis
09.11.2012, 02:16
Нет ни один из примеров не подходит у меня игра без сервера и не пошаговая, а реалтайм, ходим по событию клавиш, вид сбоку и физика Box2D. MVC для такой игры не подходит?
Так нужно ещё интернет порыть об этом паттерне. Хотя вариант ПсихоТигра убедительней. Расскажите кто нибудь кроме Дикобраза кто как поступает в MVC с ентерфреймом?
Dukobpa3
09.11.2012, 02:19
Не за что:)) Лол)
Добавлено через 44 секунды
Самое обидное что какой-то мудак даже в вики переписал правильный паттерн на тот который ты называешь: "вариант тайгера".
А раньше там было примерно то о чем я тут вещаю.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2025, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.