![]() |
|
||||||||||
|
|||||
|
У меня вопрос по архитектуре модели и принципу поимки факта изменения данных внутри её.
Допустим, есть у нас модель. В ней какие-то приватные свойства, доступ к которым сделан через сеттеры/геттеры. В этом случае, отловить изменения легко - оно происходит в сеттере и мы диспатчим событие изменения. А что если свойство в модели не просто переменная, а например, другой объект. Как в этом случае модель может узнать, произошло чтение данных или их перезапись в этом объекте? Очевидно, модель должна слушать этот объект на событие изменения, который тот должен будет послать ей. А после этого, уже послать своё событие об изменений состояния. Итого, если мы меняем в модели данный на уровень глубже, то-есть например: model.auto.bmw = 0; То произойдет диспетчеризация сразу 2 событий, сначала объект auto уведомит модель об изменений свойства bmw, а затем уже модель пошлет событие изменения состояния. Меня это немного смущает, а что если иерархия вложенности будет ещё больше? Может быть есть другой способ, узнать в модели произошло чтение или запись в дочерних объектах?
__________________
Дети не должны знать о своих родителях |
|
|||||
|
Нуб нубам
модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
|
Да, есть. Не рассматривать модель как свалку хэшей, "базу данных". Приличная Модель не должна давать доступ к своим деткам направо и налево. Все контроллеры должны придерживаться регламента и менять что-то только через специальные методы, предоставляемые моделью, в идеале еще и ограниченные индивидуальными для каждого контроллера интерфейсами.
__________________
Reality.getBounds(this); |
|
|||||
|
Цитата:
Т.е. если есть ребёнок - он сам диспетчит изменения И кому надо - подписывается на ребёнка Максимум - события всплывают до главной модели и кому надо подписываются на неё, ловя события детей. Максимум2 - модель ловит события от детей и просто диспетчит переиначенные свои, но ничего не правит в других частях. А если надо что-то делать при изменении детей с остальными данными - лучше сбоку контроллер навернуть (в модель не лазить!), и лучше чтобы тот кто меняет - сам вызывал метод контроллера меняющий другие части, или вызывал комманду. Просто так проще за всем уследить. Бывает, конечно, что тому, кто меняет лучше не знать, например, о панельке со списком текущих событий в игре (ну в социалках бывает на экране вывешивают список ["созрел фрукт, надо собрать", "здание поломалось надо починить", ...]). Тогда создается контроллер, который слушает модель и правит список этот по необходимости (саму модель слушает, всплывающие изменения детей слушает). Но в основном - события изменения частей модели и самой модели - это для обновления вида (согласовывать обновление вида через модель в разы проще чем вызывать непойми какие методы непонятно в когда появляющихся и исчезающих вьюшек), а не для того, чтобы изменить другие части и что-то пересчитать - иначе с зацикливанием событий не разгребёшь. Цитата:
Не самый плохой способ, даёт больше контроля над диспетчингом, может даже общие объемы кода будут меньше. Недостаток понятен - нужно больше внимания, чтобы не забыть вызвать везде этот метод. Но с другой стороны меньше гемороя с поиском багов в "автоматически" работающем диспетчинге, когда что-то обновляется в неподходящий момент, или того хуже - зацикливается. На практике получается, что половина событий идет автоматом - половина вызвается вручную. Последний раз редактировалось expl; 23.12.2012 в 15:23. |
|
|||||
|
Нуб нубам
модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
|
Цитата:
Исторически сложилось два основных подхода к роли Модели. Один из них — Модель как свалка для хранения всего и вся, а логика приложения пораспихана по ТТУК (Толстые Тупые Уродливые Контроллеры). Это, по всей видимости, то что Вы имеете сейчас. Контроллер как бы логический класс, хранящий свой массив данных не под собственным матрасом, а в банке у Модели. Второй подход (классический MVC) — Модель является не базой данных, а моделью состояния приложения, и содержит в себе всю логику работы с данными. В этом варианте нет места модели как сторожу свалки со свистком. Это то, к чему Вы подсознательно стремитесь. Но это не значит, что Тупой Толстой Уродливой должна быть Модель. Модель может быть композитной. Модели-дети должны быть четко известны главной фасадной модели. Им необязательно пуляться событиями в свою маму, если мама исполняет роль фасада. То есть дети могут получать свои детские сообщения от своих детских контроллеров и либо диспатчить события изменения своим детским вьюхам (по сути просто несколько параллельных MVC), либо вызывать диспатч из модели-фасада (больше порядка / меньше хаоса). Просто не рассматривайте Модель как один единственный класс. Это может быть целый самостоятельный паттерн, одним классом представленный только для слушателей. Просто.. если контроллер ДУМАЕТ, что ему делать с новыми данными, каким моделям-детям их раздавать и т.п., он становится Толстым и Уродливым, ему надо знать слишком много о Модели и о значении этих данных. Контроллер должен не более чем передать по назначению важные действия юзера во вьюхе. Если эти действия интересуют только какой-то один логический блок модели, то лучше именно эту под-модель и передать данному контроллеру для общения сразу при инициализации. Здесь весь смысл в том чтобы сместить логику из контроллеров в модельки — потому что моделям проще обмениваться расчетными данными между собой в своем семейном болоте, чем контроллерам, которые де-юре ничего друг о друге не знают и поэтому сколько-нибудь приличную логику обеспечить не могут (Тупые).
__________________
Reality.getBounds(this); |
|
|||||
|
Цитата:
Как в социалках: изменение данных и способ изменения зависит от того, что за окно открыто, что сервер прислал, какое сегодня число и какой режим редактирования на карте. Т.е пихать это в модель нет смысла. Половина логики - это даже не объекты-контроллеры, которые что-то делают, а просто асинхронные классы-комманды, которые что-то отрправляют на сервер и меняют данные. Есть ещё контроллеры, которые работают во времени и зависят только от состояния данных - т.е. обеспечивают рост растений, появление прибыли и т.д. Их впринципе можно загнать в модель, но они и отдельно нормально живут. Я бы не заявлял что в модель надо пихать логику. Ситуативно всё. |
|
|||||
|
буду краток
модератор форума
Регистрация: Sep 2003
Адрес: Ближайшее Замкадье
Сообщений: 3,110
Записей в блоге: 28
|
Спорить про MVC - бессмысленно)
Добавлено через 56 секунд У каждого он свой, я даже больше скажу, у меня даже для разных проектов он разный. Да и в одном проекте может быть несколько разных mvc.
__________________
Отряд Котовскага |
|
|||||
|
Нуб нубам
модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
|
В таком случае смысл вопроса от меня ускользает — делайте как советовал in4core, пусть контроллер, "меняющий данные", сам и извещает об этом вьюху. Если модель — пассивная БД, то смущаться уже нечего. Можно отложить и все остальное, что Вы читали о классическом MVC.
__________________
Reality.getBounds(this); |
|
|||||
|
Цитата:
Цитата:
Цитата:
А вопрос, насколько я понял (хоть и написал выше стену текста) был в том, что человеку не хотелось писать кучу кода, который только редиспетчит события от детей, тут вызов в ручную - как-бы вариант, реализация универсального баблинга в моделях - тоже вариант, но требующий аккуратности и понимания чего делаешь (это просто делается только при наследовании моделек от Sprite, или композицией с Sprite, чтобы лишние поля от Sprite не мешались, а если самому делать - придётся подключать мозг) Вот вроде и всё. |
|
|||||
|
.
|
Цитата:
|
|
|||||
|
Цитата:
Ресурсы, оно, конечно экономит. Но в модели реализуется не проще, чем редиспетчинг. Плюс в обработчике onRender во вьюхе будет куча if (model.fieldChanged) {...}. Хотя, когда порядок изменений вьюхе известен - их проще держать под контролем - надо взять на вооружение. Но автора, по-моему именно проброска изменений с детей в старшие модели напрягала. Стоп! Код в модели public function set money(value:int) { _money = value; moneyChanged = true; } public var moneyChanged:Boolean = false; public function onRender(event:Event):void { if (_model.moneyChanged) { _moneyTF.text = _model.money + "$"; _model.moneyChanged = false;// А другие модели как будут изменения слушать? } } Просто в ENTER_FRAME всё подрят сбрасывается? Потому что он должен сработать после RENDER? Последний раз редактировалось expl; 23.12.2012 в 22:16. |
![]() |
![]() |
Часовой пояс GMT +4, время: 23:14. |
|
|
« Предыдущая тема | Следующая тема » |
|
|