Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > Котяра

Оценить эту запись

Проблемы использования MVC

Запись от Котяра размещена 13.01.2010 в 13:12
Обновил(-а) Котяра 14.01.2010 в 12:44 (добавил ссылки)

Проблемы использования MVC
(Черновик)

Концепция MVC очень привлекательна, и до некоторого временя я был ярым её приверженцом, и даже, мягко сказать, фанатом)
Но, переводя старые проекты на этот паттерн, и проектируя новые, я столкнулся с некоторыми проблемами, которые я попробую описать и формализовать.
Часть примерных решений проблем я опишу, часть остаётся открытыми. Прошу помочь!


Целью статьи является ФОРМАЛИЗАЦИЯ проблем при разработке архитектуры проекта, если вдруг пришло в голову использовать MVC (готовый или самописный)


В статье попробую описать проблемы конструирования проекта и реализации MVC для ActionScript3, с которыми сталкивался лично, хотя многие проблемы не связаны напрямую с языком, и, скорее являются проблемами архитектуры в чистом, незамутнённом реализациями, виде, или, что более вероятно, проблемами моего восприятия концепции MVC)
Я пока не знаком со всеми реализациями MVC, ссылки на которые указал ниже, возможно, в некоторых из них многих проблем не существует.

И вообще, как сказал wvxwv:
Цитата:
MVC - это инструкция как писать свой код, но ее нельзя отделить от какого-то конкретного кода, положить в библиотеку и использовать по новой, ну, примерно так же, как нельзя выделить написание только гласных букв из процесса написания кода
Хотя использовать по новой в ОДНОТИПНЫХ проектах можно и нужно.

Вводная:
TODO: описание MVC - примеры реализаций, ссылки.
Существует множество реализаций MVC, как для pure AS3, так и для Flex.
вот некоторые из них:
TODO: добавить краткий обзор каждого, и ссылки на документацию.

* Cairngorm
http://opensource.adobe.com/wiki/dis...gorm/Cairngorm

* PureMVC
http://puremvc.org/

* Mate
http://mate.asfusion.com/

* HydraMVC - A rewrite of the PureMVC API exclusively for Flex
http://www.hydramvc.com/


* Slide
http://code.google.com/p/flex-slide/

* Guasax
http://www.guasax.com/

* Parsley
http://www.spicefactory.org/parsley/

* FlashMVC - A flexable lightweight framework engine for AS3.
http://www.flashmvc.com/

* Hive - A state-based MVC framework for AS3.
http://code.google.com/p/as-hive/

* Soma and SomaUI - An AS3 MVC framework and software to generate an AS3 flash site based on it.
http://www.soundstep.com/blog/downloads/somaui/


Самая основная проблема:
0. А нужен ли MVC вообще в этом, конкретном проекте:
TODO - плюсы и минусы MVC, проекты где без MVC не обойтись/ проекты где MVC лучше не использовать.


Проблемы отделения:

1.Отделение контроллера от вида
Отделить контроллер от представления обычно легко - в качестве контроллера у меня часто выступает некий parent - это может быть документ класс или составной VC (подмодуль).Фанаты явно отделяют контроллер от основного вида используя композицию.
На самом деле Фасад (F)- по сути является контроллером, хотя с другой стороны является видом более высоко порядка. В иерархическом MVC я не вижу смысла отделять Фасад

2.Отделение модели(M) от вида(V).
Собственные данные вида, такие как x,y - очень часто выглядаят как данные модели, и возникает соблазн не заводить их в модели и менять напрямую из контроллера. После таких конструкций более логично выглядит и остальные данные привязать напрямую с видом. Этого делать нельзя, но очень хочется - значит можно.
Пример:
добавляем вид слушающий x,y модели. но модель не изменяется, соответственно нет события изменения.
Решение 1: вызов view.init() - > самостоятельное взятие данных из модели..
Вроде хорошое решение, но из этого решения вытекает проблема №7

3.Отделение модели от контроллера(C)
тут не так всё однозначно.. часто событие обновления данных модели напрямую меняет виды.

Проблемы иерархий:

4. Синглтоны
5. Иерархия вложенных MVC

6. Изменение связанных данных модели поочерёдно.
Поясню проблему примером:
Изменились x,y - вид слушает оба изменения. т.е. ловит два соытия и оба раза изменяет своё состояние..
Решение: связанные данные связывать)) т.е. менять не x,y, а Point.
Другой вопрос, что


Проблемы ссылок:
7. Всегда ли вид должен иметь ссылку на модель, как объект содержащий данные, или только как объект раздающий события?

Цитата:
Сообщение от Nirth
Вообще MVC за исключением Mate не используют событий, если исходить из классического ( GoF ) реализации, то у нас будет использоватся обсервер, и все три компонента ( Model + View + Controller ) будут подписанны, к Обсерверу.

Далее например модель посылает DataUpdated сообщение через Обсервер, и подписанный Вид на это сообщение будет обновляться.

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

А если вид, контроллер или модель друг на друга ссылаются, весь смысл использования MVC улетучивается моментально.
Управление сложностью:
8. Создание множества лишних классов.
концепция MVC плодит множество классов и соответствеено увеличивает СЛОЖНОСТЬ, как понятие надёжности.

пример: надо сделать движение 10 шариков по экрану. координаты шариков приходят с сервера(имитация в Main.serverOnData).
без mvc : класс Main добавляет 10 шариков Ball. Main вызывает ball[i].move(xArr[i],yArr[i]). всего 2 класса,11 стационарных объектов.
TODO: код,вложения.

mvc: класс Main (FC) создаёт 10 объектов BallView, один MainModel и 10 BallModel. затем связывает каждый ballView и ballModel.
Каждый ballView подписан на событие BallModelEvent.CHANGE_POINT создаваемое в ballModel.
Main изменяет MainModel.ballModelArray
итого:
TODO: код,вложения.

Цитата:
Сообщение от Nitrh
По Hydra/PureMVC нам нужно примерно 6 классов ( Model, View, Controller, ModelAdapter, ViewMediator etc ), если проект большой и длительный (больше 3х месяцев), и есть несколько филиалов, или используются аутсорсеры. То проект обречен на то, что будут забывать или игнорировать классы, и ссылатся напрямую вместо обсерверов. По моему все, что нужно это налаженная кодо-генерация прямо из коробки в Flex Builder. Примерно, как в Ruby on Rails, Merb, Django, где модель, вид и контроллер генерируются сами, а программист уже заполняет функции, и не думает о рутине.
Проблемы взаимодействий интерфейсов
10. ~7+ иерархические модели

..

Проблемы производительности
20. Проблема вызовов.
лучше в одной ф-ции (render) напрямую поменять виды чем изменять модели, и ждать событий изменения.

Проблемы состояний и отложенных действий.
30. Где хранить промежуточные данные? в контроллере?
пример
от сервера приходит действия: шарику двигаться на x1, затем на x2, потом показать табличку, затем плавно поменять счёт.
Всего комментариев 19

Комментарии

Старый 13.01.2010 17:43 Nirth вне форума
Nirth
 
Аватар для Nirth
не в обиду будет сказанно, сложилось впечатление что тебе не совсем понятно как использовать MVC =)
Старый 13.01.2010 17:53 Котяра вне форума
Котяра
 
Аватар для Котяра
Очень даже может быть. Пост будет как раз об этом. То, что пока накидал - примерный планчик проблем - поток сознания. Самая главная проблема - а нужно ли вообще использовать mvc в конкретном случае.
Старый 13.01.2010 18:29 Nirth вне форума
Nirth
 
Аватар для Nirth
Вообще MVC за исключением Mate не используют событий, если исходить из классического ( GoF ) реализации, то у нас будет использоватся обсервер, и все три компонента ( Model + View + Controller ) будут подписанны, к Обсерверу.

Далее например модель посылает DataUpdated сообщение через Обсервер, и подписанный Вид на это сообщение будет обновляться.

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

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

Но моя критика в сторону AS3 MVC на самом деле в другом ракурсе. В теории мне очень нравится юзать MVC, но по Hydra/PureMVC нам нужно примерно 6 классов ( Model, View, Controller, ModelAdapter, ViewMediator etc ), если проект большой и длительный (больше 3х месяцев), и есть несколько филиалов, или используются аутсорсеры. То проект обречен на то, что будут забывать или игнорировать классы, и ссылатся напрямую вместо обсерверов. По моему все, что нужно это налаженная кодо-генерация прямо из коробки в Flex Builder. Примерно, как в Ruby on Rails, Merb, Django, где модель, вид и контроллер генерируются сами, а программист уже заполняет функции, и не думает о рутине.
Старый 14.01.2010 00:28 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Так есть же DCD! Но, помоему хуже чем DCD сделать сложно... Не знаю, мне попытки завернуть в темплейт код на две строчки кажутся, ну, как минимум смешными... и не такими смешными, когда видишь, как код из двух строк перерастает в надцать классов по надцать тысячь строк. За все время моего знакомства с MATE / Cairnogm ни разу не ощутил рекламируемого удобства или скорости в разработке. Постоянное ощущение, что рефакторишь бесконечную массу морально убогого кода, и время от времени просто здаешься и ставишь костыли и затычки, потому что уже просто нет сил с этим бороться...

А по поводу "фреймворков", "паттернов" и "синглтонов" - эти слова уже на столько набили оскомину, что за них четвертовать хочется... Я думаю, что это преходяще, и мода пройдет раньше или позже, и через пару лет мы будем смотреть на MATE / Cairnogm с чувством отвраещния с которым вы бы сейчас смортели на Perl
Старый 14.01.2010 02:10 Nirth вне форума
Nirth
 
Аватар для Nirth
@wvxvw
Ты знаешь, я не ощутил неудобства при использовании Mate / Swiz, вот PureMVC/Cairnogm у меня вызывают стойкое отвращение.
Старый 14.01.2010 02:46 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Ну вот для примера, Мате в самые ранние сроки подисывается к систем менеджеру на все, на что только может на capture фазу (и естественно, на парочку live cycle events - а как же без этого). Это значит что все без исключения дисплей объекты должны диспатчить события с уникальными именами. Как сам можешь догадаться, имена у биндинговых событий отнюдь не уникальные. Когда более-менее сложная флешка поднимается может случится куча непредвиденых вещей, она и проинициализироваться может несколько раз и понасоздавать всякого... Просто биндинг не может жить без ошибок, а кроме этого их еще и подавляет, а с другой стороны всякие dispatchLater() еще свою "изюминку" к этому добавляют. Одна и та же сборка без перекомпиляции может запустится по-разному, и там уже никакой дебаггер не спасет - один хрен не понятно, что происходит.
Т.е. у меня были ситуации, когда одна и та же сборка запускалась 9 раз нормально, а на десятый падал браузер - и пойди угадай почему...

Удобство, да, есть, но только до первой такой ситуации, а потом начинаются мучительные поиски по форумам, джире и т.д. и в 50% случаев заканчиваются тем, что постишь еще один баг в джиру, и понимаешь, что даже если его и пофиксят, то это будет только через несколько билдов, а в них будет что-нибудь "новенькое" и так по кругу. В проекте над которым сейчас работаю мы уже сменили 4 "stable builds" потомучто они совсем не соответствуют своему названию...
Старый 14.01.2010 02:55 Nirth вне форума
Nirth
 
Аватар для Nirth
@wvxvw
Ты знаешь, тут наверное все дело в том, как к фреймворку относишься. Я когда увидел Mate, я решил, что это MVC фреймворк, который просто вместо INotification использует родной (и возможно быстрый) Event.

Тоесть первым делом я:
1) создал класс MateHelper, который является аналого NotificationFactory, тоесть класс который создает события.
2) Сделал базовый класс MateEvent, который просто назначал bubbles = true, для будущих событий.
3) Использовал MateHelper, MateEvent как (I)Notification(Factory), я даже не думал мешать события, которыя я использую для внутренней реализации компонентов, или байндингов, для Матэ.

При таком раскладе, уникальные имена, и байндинги меня мало волновали.
Старый 14.01.2010 12:07 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Не знаю, мое мнение - идея архитектурного фреймворка не имеет права на жизнь, и я еще не встречал ситуации, когда использование такого фреймворка было бы лучше его отсутствия.
Вообще, эти фреймворки напоминают ситуацию в AS2 со слушателями - т.е. если помнишь, там скорее всего в хелпе был пример типа:
Код AS1/AS2:
var listener:Object = {};
Mouse.addListener(listener);
o.onMouseUp = function(){ ... }
И не смотря на то, что это был просто пример где создавался просто объект "для наглядности" - я встречал уйму, даже не то, чтобы уйму, безумное, подавляющее большинство кодеров зачем-то создавали этот "объект для примера" чтобы добавить слушателя.
Т.е. пример массового безумия вызваного какими-то на первый взгляд абсолютно безобидными и вроде как даже не располагающими к тому причинами.
Я к чему - как мне это видится, MVC - это инструкция как писать свой код, но ее нельзя отделить от какого-то конкретного кода, положить в библиотеку и использовать по новой, ну, примерно так же, как нельзя выделить написание только гласных букв из процесса написания кода
Обновил(-а) wvxvw 14.01.2010 в 13:27
Старый 14.01.2010 12:26 Котяра вне форума
Котяра
 
Аватар для Котяра
хы. я сам создавал
Код AS3:
var listener:Object = {};
пока не попробовал вешать на this)))))
по поводу
Цитата:
но ее нельзя отделить от какого-то конкретного кода, положить в библиотеку и использовать по новой
немного не согласен, в более-менее однотипных проектах, повторное использование приветствую, как раз проблемы и возникали у меня когда я MVC либу разработанную для одного проекта прикручивал к совершенно другому.
Старый 14.01.2010 14:08 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Ну вот смотри, для примера две ситуации:
Я использую в проекте nochump либу для работы с ZIP файлами. Она может и не верх совершенства, и как оформлены ее API мне не очень нравится, но, она вцелом не вызывает у меня негативных эмоций, потому что польза от нее на лицо - мне не нужно вникать в подробности как распарсить ZIP файл - т.е. какая-то, довольно большая часть работы сделана за меня, и даже если не на вышшем уровне - меня это не особо смущает, потому что мой код от этого не пострадает.
Но, скажем, используя любой из ныне существующих "MVC фреймворков" мне прийдется вникать в то, как он написан и подстраивать свой код под в 99% случаев ничем не обоснованые прихоти авторов либы. Это занимает кучу времени на изучение и на воплощение. В 99% случаев мне прийдется плодить какие-то абстрактные классы с туманным назначением с одной единственной целью - соответствие требованиям "фреймворка". Как правило добавка над необходимым функционалом во много раз больше самого необходимого функционала, во много - это в десятки а то и в сотни раз.

Т.е. возьмем к примеру ServiceLocator каирнгормовский и типичное его использование во флексовом проекте:
  1. Создается MXML файл, куда складывается порядка десятка RemoteObject (просто хочется взять и убить за такое).
  2. Этот класс скармливается ServiceLocator'у для того, чтобы мы потом могли ServiceLocator.getRemoteObject(name:String):RemoteObject
    (ну да, а как же, самая надежная ссылка на объект - это строка с хз откуда полученым значением! см. п. 1).
  3. Для каждого RemoteObject создается класс Command и Event. Опять изза специфики убогой реализации событий в AS3 мы всюду полагаемся на строковые значения для идентификации объектов, но хуже того - это сильно затрудняет навигацию по коду - go to definition не приведет нас никуда. Весь код приходится расписвывать в духе: а вот эта строчка, если мы ее передадим тому и тому, вернет нам то и то.
  4. Ну и все это сверху полируется моделями с "изюминкой" в виде
    Код AS3:
    [Bindable] class Model implements ModelLocator
    (это значит, что к нашему коду будет добавлено 200% *****кода сгенеренного *****компилятором. Просто мы это не видим, или не хотим замечать. Ну стоит ли на этом фоне вспоминать, что интерфейс ModelLocator пустой, и это просто копия из Java где это имело хоть какой-то смысл, но при этом потеряло всякий смысл в AS3).
  5. Ну и в завершение: так этот же RemoteObject, блин, динамический класс, т.е. даже если мы как-то получим на него ссылку, мы все равно не знаем, что нам можно у него вызывать, а что нет.

Все это гауно в комплекте со своей *****библиотекой добавит так порядка 200К к проекту... ну а может и побольше - зависит от широты мЫшления конкретного исполнителя.

А теперь: ну вот что бы было, если бы вы просто взяли тот же NetConnection, обернули его композитным классом, или отнаследовались - это уже как вам нравится, и добавили бы ему нужные методы для вызова удаленных процедур, ну, можно еще в интерфейсе описать добавленые методы, если этот класс предполагается менять. И все - вы сделали всю ту же работу и для этого вам понадобилось несколько часов и врезультате получили 1 (один) небольшой класс который выполняет все те же функции и делает это лучше, чем куча каирнгормовских классов вместе взятых. При этом вы никому не навредили, ваш код легко читается, изменяется, если нужно и т.д.
Старый 14.01.2010 14:27 alexcon314 вне форума
alexcon314
Я правильно понял мысль?
MVC - суть способ оптимизации подходов к программированию сложных проектов.
Примечание 1. Действует только в рамках одного проекта, притом достаточно большого, чтобы ваш собственный код по весу равнялся с кодом либы.
Примечание 2. Действует только после досконального предварительного изучения либы под микроскопом.
Старый 14.01.2010 16:07 Nirth вне форума
Nirth
 
Аватар для Nirth
@wvxvw
Я вообще предпочитаю Model Delegate, но на Flex они не прижились по каким то причинам, поэтому большинство клиентов сидят на MVC. НО замечу, что по моему ты просто пытаешься выжать из MVC больче чем та готова тебе дать =)

У меня были проблемы с MVC связанные с человеческим фактором (забывали правильно модель описывать, или злоупотребляли байндингами, или дедлайн был, и писали временный спагетти код). Но при правильном использовании самой парадигмы, ничего критического и останавливающего процесс дольше чем на 1-3 человека-часа в неделю не было.

Цитата:
т.е. какая-то, довольно большая часть работы сделана за меня, и даже если не на вышшем уровне - меня это не особо смущает, потому что мой код от этого не пострадает.
Но, скажем, используя любой из ныне существующих "MVC фреймворков"
Дело в том что кроме Swiz и Mate, остальные не являются настоящими фреймворками, они Архитектуры, Парадигмы, Микро архитектуры и тд и тп, тоесть да тебе нужно занть как они работают.
При работе с Матэ, я не вникал, как он работает, мне нужно было просто знать, что есть диспатчер, есть роутинг ( EventMap ), и есть стандартные Action Pattern. Причем куча готовых команд уже написана.
Старый 14.01.2010 17:12 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Нет, я это к тому что на мой взгляд попытка создать архитектурный фреймворк, это как попытка приготовить яйцо в микроволновке, ну можно там пытаться дырочку пропилить или еще какие ухищрения придумывать, но в итоге все равно со стенок соскребать прийдется
Но, скажем, если кроме микроволновки никаких нагревательных приборов больше нет, то ситуация тупиковая, а с "фреймворками" - ну так их в 100 раз проще выбросить и сделать без них. Потому что попытки упростить и без того очень простую вещь ни к чему хорошему не приведут... И это все ложь и клевета, что самописный код будет тяжко поддерживать - не правда, заведомо плохой код ака использующий Cairngorm или DI фреймворки труднее поддерживать чем просто код выполняющий каую-то нужную функцию. Изменение в "своем" функционально нужном коде проще сделать, чем дописать чего-то или рефакторить код созданый с использованием фреймворков, кроме того просто затратнее - гораздо больше всего нужно менять, или добавлять / убирать, если используется фреймворк.

Т.е. мне например ситуация с RemoteObject и всякими к нему придатками видится примерно такой:
почему-то в Адоби свято верят, что асинхронные операции тяжело осознать, и что для неопытных нужно все сделать так, чтобы оно выглядело "как будто синхронно". Ну и это, "партия сказала 'надо' - комсомол ответил 'есть!'" - и понеслась: биндинги, прокси, динамические классы, анонимные функции и иже с ними... А все потому что, ну просто изначально не подумали, что нельзя это хорошо сделать данным инструментом... вот теперь и имеем специалистов по выпиливанию дырочек в яйцах вместо поваров
Старый 14.01.2010 17:58 Nirth вне форума
Nirth
 
Аватар для Nirth
@wvxvw
Фреймворк фреймворку рознь. Не путай MVC, который выступает в роли Фундамента, над которым строится приложение любой сложности. И узко специализированный фреймворк для работы с Zip, где легко сделать фасаду.

Ты сейчас жалуешься на то, что Toyota Prius не может отвезти 5 тон зерна, не все то что с колесами – грузовик.
Старый 14.01.2010 18:05 Котяра вне форума
Котяра
 
Аватар для Котяра
Вообще основная моя основная идея этого поста рассмотреть создание кастомных MVC архитектур для конкретных проектов:
что-то вроде:
надо чтоб 10 шариков слушали изменение положения 11 шарика , и изменяли своё положение..
хорошо бы сделать так-то.. завести одну модель данные которой позиция 11 шарика, 10 других шариков сделать слушателями изменения..итп..
т.е. основной упор на не использовании конкретного фрэймворка, а на создании архитектуры.
кроме того описать, как это реализовать кастомно или с использованием pureMVC/Mate etc..
В итоге, разобрав ситуации, можно будет приблизиться к требованиям по разработке ИДЕАЛЬНОГО фрэймворка)
Обновил(-а) Котяра 14.01.2010 в 18:12
Старый 14.01.2010 18:06 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Нет, я не жалуюсь, я утверждаю, что автомашины с колесами формы отличной от круга ездят хуже.
Старый 14.01.2010 18:26 Nirth вне форума
Nirth
 
Аватар для Nirth
Цитата:
В итоге, разобрав ситуации, можно будет приблизиться к требованиям по разработке ИДЕАЛЬНОГО фрэймворка)
Стукни мне в скайп если хочешь послушать про случаи с "идеальным" кодом, и сколько людей потом оказывались уволенными =)

Цитата:
Нет, я не жалуюсь, я утверждаю, что автомашины с колесами формы отличной от круга ездят хуже.
Ну я не знаю, что тебе ответить, я тебя не убедил, а ты меня =)
Старый 14.01.2010 19:05 Котяра вне форума
Котяра
 
Аватар для Котяра
это ирония)
Старый 22.07.2010 12:09 terbooter вне форума
terbooter
2 wvxvw,
очень с тобой согласен почти во всем, особенно в том,
что часто проще не использовать фреймворк, а делать свою реализацию MVC для конкретного проекта.
Про политику Адоби касательно асинхронных функций тоже согласен
 

 


Часовой пояс GMT +4, время: 13:01.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2018, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.