MVC, часть 1: про дубовый стол и сиськи
[Что-то очень глючил редактор, где то возможны нестыковки - текст порой просто удалялся. Замечания пишите в комменты. Спасибо]
...и вот появился на свет гений. Истинный Разработчик. Луч света падает на него, а клавиатура сокрушается под ударами его пальцев... Сейчас он сядет и сделает шедевр, в ритмах Вивальди извлекая звуки от щелчков мышки и ритмичных ударов о клавиатуре...
Думайте это о Вас? Обо мне? Пфф... Это Вам не сага о Горце. Тут придется включить свою голову. Ну или хотя бы сделать вид. Как бы то ни было - купите виски и откиньтесь на спинку кожаного кресла, положив свои ноги в ботинках из крокодиловой кожи на стол из столетнего дуба. Да-да, вы не ослышались. MVC - это действительно круто. Соплякам тут не место )
Мне всегда вот в научных статьях, учебниках по квантовой физике и статьях на википедии не нравилось одно - сухость материала. Ну пришел Шредингер, сказал что нашел универсальное уравнение в материи в целом - и понеслись иероглифы. Ну вот как это следует вообще понимать? Тут тоньше надо. Не спугнуть читателя, объяснять всё простым языком... Тут тренд Дисковери уловил, конечно. Поэтому давайте-ка я расскажу вам о трёх буквах.
Готовы? Отлично, так рад видеть на Ваших лицах заинтересованность - вот оно, "эм вэ цэ" да ещё и языком художественным текстом, где возможно. Только сразу огорчу - про дубовые столы я погорячился. Точнее, не погорячился, а совсем соврал. Это полная чушь, что MVC что-то там даёт. Да-да, я вас сильно обманул, но обещаю, что больше так делать не буду, а вы мне взамен обещайте что будете слушать меня внимательно. Договорились? Договорились. Дак вот, MVC - это просто инструмент, он не сделает из Вас ни "тру-флешера", ни человека способного на что-то большее, чем он умел до этого. Скажу больше, удобство использования вы ощутите... ну после нескольких недель работы. Это как накачать пресс - жирок то родной, булочки вкусные, а тренажеры не манят. Зато потом сверкая прессом перед девочками на пляже... ну вы поняли. Не испугались? Тогда вперёд )
Начнем, пожалуй, с истории среднестатистического флеш-разработчика. Речь, конечно же, пойдёт о человеке растущим на флеше с 0, а не матёрым Java`ером, который решил переквалифицироваться.
Сперва разработчик начинает писать свой код в кадрах/в одном классе. Он не понимает, зачем создавать другие классы, ведь всё можно написать здесь - и оформить функцией - то есть замыканием. Некоторые о приёме замыкания не знают - и слава богу - и пишут в методах.
Наступает момент, когда кода становится слишком много и под давлением общественности человек начинает делать попытки создавать другие классы. И тут же чувствует себя скованным - как же получить глобальную переменную... В следствии чего в конструктор пихает всё что только может. А ещё лучше - ссылку на класс, который его и создал. В итоге Main порождает пятерку других классов. И все знают всё о Main.
Потом человек понимает, что так передавать - крайне неэффективно. И начинает использовать синглтон. Ну как синглтон... Он думает, что это синглтон. На самом деле - просто набор статический методов и переменных. Ну должен же быть глобальный контроль!
И вот наконец человек понимает. Черт возьми, как же неудобно когда всё жутко связанно. Как много кода копируется копипастом... Как неудобно эту полоску жизней делать отдельно и для врагов, и для игрока - выгладят по разному, а работа одна и та же... Как же хочется чтобы можно было просто изменять внешний вид, а логика работы так и оставалась где то далеко... И тут мы у человека происходит озарение. Да-да, мы думаем об одном и том же. Человек начинает использовать наследование.
И вот только потом, через много времени он чувствует себя готовым. Готовым к большим открытиям и большим наградам. И виднеются на горизонте три большие, заглавные буквы - M, символизирующие Молодец разработчику, V, символизирующее пятерку за архитектуру и C - символизирующее Сиськи, которых порой так не хватает рядом во время длительной разработки. Ну, это для меня. MVC - у каждого своё. Вроде бы очевидно, что от MVC со временем не так то просто отказаться.
...Затянулось начало. Перейдём к делу.
Чтобы было сразу понятней - сразу же введем пример. Предположим, у нас есть герой у которого есть 3 вида оружия. Вид игры - сверху.
Рассмотрим отдельно все части:
M - Model. Модель. Хранит данные, которые нужны триаде (MVC). Это - координаты игрока в мире, текущие оружие в руках, количество здоровья, количество боеприпасов. Остальные данные - например количество крови хлыщущее из его вены в модели не хранятся.
V - View. Вьюшка. Отображалка. Занимается всем тем, что видит и слышит пользователь. Хранит в себе как раз количество крови, которое из игрока хлыщет, само изображение игрока, создаёт звуки выстрелов... Ну вы поняли. Это всё, что вообще есть на экране.
C - Controller. Контроллер. Он занимается логикой всей триады. Именно он обрабатывает нажатие клавиш и меняет данные в модели, записывая туда новые координаты игрока. Именно он разрешает игроку стрелять и меняет у него оружие.
Всё понятно? Не пытайтесь проводить грань и понять взаимодействие между ними - просто определитесь, кто что делает.
Сейчас я дам вам картинку, нагло взятую где то из интернета.
Какая прелесть, правда? Давайте разберемся. Сплошными линиями показаны жесткие связи между трио - то есть у контроллера есть прямая ссылка на модель и на вьюшку, а у вьюшки на модель. Штрихованными же показано кто кого слушает - контроллер слушает вьюшку, а вьюшка модель. Что такое "слушает" - ниже, на примере каждого.
Пример с игрой и человечком сверху был удачным для объяснения идеи текстом, но мне кажется для практической реализации нужно взять пример попроще. Давайте сделаем совсем элементарный пример: несколько квадратиков, все разных цветов. При этом есть одна стрелочка, которая указывает на один из квадратов. По клику стрелочка указывает на случайный квадратик, а каждые 3 секунды цвета у квадратов меняются. Это игра будет для детей дошкольного возраста: они должны будут произносить вслух цвет, на который указывает стрелочка, а воспитатель скажет, правильно или нет.
Итак. Сперва мы должны создать Главный контроллер - он всегда самый главный в любом приложении. У нас будет всего один контроллер, одна модель и одна вьюшка - поэтому контроллер главный, и по совместительству единственный. Контроллеру нужно знать, куда добавлять всю прелестную графику? Нужно. Поэтому ему нужен иметь какую-то точку привязки для графики - DisplayObjectContainer. Где её взять? Это - ваш класс Main, который базовый. Как создать главный контроллер? В Main, в конструкторе или в обработчике события Event.ADDED_TO_STAGE нужно написать примерно следующее:
Мы просто создали этот контроллер и передали ссылку на себя - то есть на то место, где будет скапливаться вся графика. Нам даже не нужно сохранять ссылку на главный контроллер!
Код класса BaseController:
package { import flash.display.DisplayObjectContainer; public class BaseController { private var _host:DisplayObjectContainer; private var _model:Model; private var _view:View; public function BaseController(host:DisplayObjectContainer) { super(); _host = host; _model = new Model(); _view = new View(_model); } } }
Давайте напишем модель. Сперва нужно понять, что должно быть в модели. В модели должны быть данные, которые нужны всей триаде. Это - цвета всех квадратов и номер квадрата, на который указывает стрелочка. "А как же графика для стрелочки, размеры квадрата, расстояние между ними и всё остальное?" - воскликнет читатель. Нет, эти данные не должны хранится в модели. Вся графика, все звуки и всё остальное - это забота вьюшки, в этом и прелесть: сегодня у меня на экране человек, а завтра киборг. При этом я переписываю только отображение, не трогая контроллер и модель, тем самым не "ломая" логику. Размер прямоугольников - не нужен в контексте этой задачи - нам плевать на форму, хоть квадратная, хоть скругленная. Нам так же плевать на позиции - хоть синусоидально, хоть по прямой. На логику это не влияет. Нам просто нужно выводить на экран какие-то цветные элементы и помечать их. Отсюда всплывает очередная прелесть - мы можем не сильно заботится о том, что творится на экране, оставив это на "потом". Будь другой контекст - например, если бы нужно было отгадать размер в пикселах этой фигуры - то эти данные попали бы в модель. Аналогично и с формой, и с расположением. Проще говоря, в модели хранятся значимые данные в данной задаче. А на фоне гусей или океана это происходит - программу не колышет.
Итак, нам нужно хранить в модели массив цветов и номер прямоугольника, на который указывает стрелка. При этом при изменении информации в модели неплохо было бы заявить всем желающим, что данные изменились - неплохо бы их обновить. Это означает, что модель должна испустить событие о том, что она изменилась. Делается это GoF паттерном Observer, но не пугайтесь: обычная событийная флешевая событийная модель реализует именно его, поэтому нам совсем не стоит об этом беспокоится. При обновлении информации есть 2 подхода: push и pull. При обновлении информации мы генерируем событие о том, что что-то изменилось. Представим, что это событие кто-то поймал. В событии может содержаться вся информация о том, что же изменилось - такой подход называется push - мы проталкиваем с событием всё что нужно обновить. Другой подход - pull - значит "тяни". В таком случае события носят нотификационный характер - что-то вроде "Эй парень, число народу в игре обновилось.". А сколько теперь онлайн - это событие не скажет. И в таком случае эти данные приходится "тянуть" с модели явно. Я использую оба подхода, оба подхода хороши. Но конкретно сейчас я ограничусь pull-подходом. Кстати, событийное поведение добавляет ещё одно удобство, одно из главных - если у нас в 5 разных местах показывается, например, баланс игрока - то при изменении баланса в одном месте он должен поменяться во всех.
Но тут всплывает проблема: поменяв номер прямоугольника, на который указывает стрелочка вызовется сеттер, который испустит событие об изменении. Но в случае с массивом всё не так: чтобы вызвать сеттер у массива нужно будет переопределить на него ссылку, что недопустимо: нам нужно просто менять элементы массива, но не ссылку на него. Решений у проблемы несколько. Например, самый извращенный - это унаследовать модель от Proxy, определив там поведение для [], попутно реализовав ей IEventDispatcher. Можно, например, сделать метод setElement, в теле которых и генерировать событие об изменении. Можно в модели добавить метод "сделай событие пожалуйста, что ты изменилась" и дёргать его. Но немного подумав вспоминаем, что модель мы меняем в контроллере. А в контроллере мы имеем полный контроль над вьюшкой. Поэтому в этом случае на мой взгляд самым лучшим решением будет явно вызвать метод у вьюшки после того как закончится изменение модели.
Код Model:
package { import flash.events.Event; import flash.events.EventDispatcher; [Event(name="change", type="flash.events.Event")] public class Model extends EventDispatcher implements IReadableModel { private var _pointer:int = 0; public var colors:Array = []; public function Model() { super(); } public function get pointer():int { return _pointer; } public function set pointer(value:int):void { if (_pointer == value) return; _pointer = value; super.dispatchEvent(new Event(Event.CHANGE)); } } }
Итак, теперь View. Как мы поняли ранее, у View есть прямая ссылка на Model, в итоге нам нужно всего лишь визуализировать эти данные.
package { import flash.display.Shape; import flash.display.Sprite; import flash.events.Event; public class View extends Sprite { private var _model:Model; private var _squares:Array; private var _pointer:Shape; public function View(model:Model) { super(); _model = model; //здесь будем хранить ссылки на созданные графические объекты _squares = []; //это типа стрелочка _pointer = new Shape(); _pointer.graphics.beginFill(0x00FF00); //круглая такая стрелочка _pointer.graphics.drawCircle(0, 0, 30); _pointer.y = 100; _pointer.graphics.endFill(); super.addChild(_pointer); //вызываем обработчик как будто-бы модель изменилась. Это нужно чтобы указатель //сразу встал на нужный квадрат onPointerChange(null); //подписались на изменение модели _model.addEventListener(Event.CHANGE, onPointerChange); } public function updateSquares():void { //поменялись цвета - удаляем все старые прямоугольники var i:int = _squares.length; while (i--) super.removeChild(_squares.pop()); //рисуем новые i = _model.colors.length; while (i--) { var shape:Shape = new Shape(); shape.graphics.beginFill(_model.colors[i]); shape.graphics.drawRect(0, 0, 50, 50); shape.graphics.endFill(); shape.x = 100 * i; _squares.push(shape); super.addChild(shape); } } private function onPointerChange(event:Event):void { _pointer.x = 100 * _model.pointer; } } }
Абстрагируемся. Нам сообщают событиями о том, что модель изменилась. Если мы получили такое сообщение - меняем изображение, чтобы быть актуальным каким-то данным, которые есть в модели. Попутно имеем паблик метод updateSquares, который будет вызван кем-то сверху, когда нужно обновить квадраты. Если не думать о трио в целом, а только об одном элементе - всё очень просто.
Резюме. Мы имеем что-то, что предоставляет нам данные и говорит, когда данные поменялись. На основе этого мы строим изображение. Всё просто? Отлично. Теперь связываем в голове модель и вьюшку. Связываем, думаем.
Готовы продолжать? Теперь контроллер.
Задача контроллера - менять модель. Просто писать в неё данные. Абстрагируемся вновь. Мы просто делаем какую-то логику, и пишем её в объект, не задумываясь о том что происходит дальше. Но ещё нам нужно вот что сделать в контроллере: добавить вьюшку в дисплай лист - т.е. просто сделать addChild к тому, что мы передали в конструктор главному контроллеру. По условию задачи менять каждые 3 секунды цвета. Что-ж, ничего сложного! Делаем:
package { import flash.display.DisplayObjectContainer; import flash.events.TimerEvent; import flash.utils.Timer; public class BaseController { private var _host:DisplayObjectContainer; private var _model:Model; private var _view:View; public function BaseController(host:DisplayObjectContainer) { super(); _host = host; _model = new Model(); _view = new View(_model); //создали таймер и запустили var _timer:Timer = new Timer(3000); _timer.addEventListener(TimerEvent.TIMER, onTimer); _timer.start(); //сразу же вызвали обработчик, чтобы сразу при запуске забить массив //случайными квадратами onTimer(null); //добавили в дисплай лист - чтобы мы смогли увидеть работу вьюшки host.addChild(_view); } private function onTimer(event:TimerEvent):void { //забиваем модель случайными цветами var i:int = 5; while (i--) { _model.colors[i] = int(Math.random() * 0xFFFFFF); } //говорим, что мы изменили цвета //это как раз тот момент из за невозможности вызова геттера _view.updateSquares(); } } }
Как это сделать? Наверное вам в голову лезет мысль - в контроллере отлавливать клик и менять модель. Нет, это не совсем правильно: это лепка программы "под конкретный вариант", а это как раз то, против чего создано MVC. Пользователь с чем взаимодействует? Только с вьюшкой. Он не может кликнуть по модели или по контроллеру - он кликает по экрану, что по сути является вьюшкой. Значит клик должна обрабатывать вьюшка. При этом это слишком связано, что именно по клику: сегодня по клику, завтра по нажатию клавиши, а послезавтра вообще по голосовой команде. Вьюшка должна сообщить о том, что надо бы поменять стрелочку - а уж отчего вьюшка так решила знает только она сама. В итоге во View дописываем функционал, что по клику диспатчим какое-то событие, которое слушает контроллер. Я опять буду использовать событие Event.CHANGE - поначалу могут возникнуть сложности - как же так, мы ведь его уже используем в модели - но это здорово развивает абстракцию. В реальных проектах типов событий у меня очень часто больше 30-40, тут, конечно, одним Event.CHANGE не обойтись и я делаю свой класс, расширяющий Event. Однако, какой случай - такой и инструмент, поэтому здесь Event.CHANGE.
package { import flash.display.Shape; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; [Event(name="change", type="flash.events.Event")] public class View extends Sprite { private var _model:Model; private var _squares:Array; private var _pointer:Shape; public function View(model:Model) { super(); _model = model; //здесь будем хранить ссылки на созданные графические объекты _squares = []; //это типа стрелочка _pointer = new Shape(); _pointer.graphics.beginFill(0x00FF00); //круглая такая стрелочка _pointer.graphics.drawCircle(0, 0, 30); _pointer.y = 100; _pointer.graphics.endFill(); super.addChild(_pointer); //вызываем обработчик как будто-бы модель изменилась. Это нужно чтобы указатель //сразу встал на нужный квадрат onPointerChange(null); //подписались на изменение модели _model.addEventListener(Event.CHANGE, onPointerChange); //нам должен быть доступен stage super.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); } private function onAddedToStage(event:Event):void { super.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage); //подписались на заветный click super.stage.addEventListener(MouseEvent.CLICK, onClick); } private function onClick(event:MouseEvent):void { //и выпустили событие super.dispatchEvent(new Event(Event.CHANGE)); } public function updateSquares():void { //поменялись цвета - удаляем все старые прямоугольники var i:int = _squares.length; while (i--) super.removeChild(_squares.pop()); //рисуем новые i = _model.colors.length; while (i--) { var shape:Shape = new Shape(); shape.graphics.beginFill(_model.colors[i]); shape.graphics.drawRect(0, 0, 50, 50); shape.graphics.endFill(); shape.x = 100 * i; _squares.push(shape); super.addChild(shape); } } private function onPointerChange(event:Event):void { _pointer.x = 100 * _model.pointer; } } }
Теперь немного перепишем контроллер:
package { import flash.display.DisplayObjectContainer; import flash.events.Event; import flash.events.TimerEvent; import flash.utils.Timer; public class BaseController { private var _host:DisplayObjectContainer; private var _model:Model; private var _view:View; public function BaseController(host:DisplayObjectContainer) { super(); _host = host; _model = new Model(); _view = new View(_model); //создали таймер и запустили var _timer:Timer = new Timer(3000); _timer.addEventListener(TimerEvent.TIMER, onTimer); _timer.start(); //сразу же вызвали обработчик, чтобы сразу при запуске забить массив //случайными квадратами onTimer(null); //добавили в дисплай лист - чтобы мы смогли увидеть работу вьюшки host.addChild(_view); //подписались на событие, по которому нужно изменить модель _view.addEventListener(Event.CHANGE, onViewChange); } private function onViewChange(event:Event):void { //просто случайная позиция для стрелочки _model.pointer = Math.random() * 5; } private function onTimer(event:TimerEvent):void { //забиваем модель случайными цветами var i:int = 5; while (i--) { _model.colors[i] = int(Math.random() * 0xFFFFFF); } //говорим, что мы изменили цвета //это как раз тот момент из за невозможности вызова геттера _view.updateSquares(); } } }
Теперь пролистните вверх и посмотрите снова на картинку и вновь перечитайте часть, где я рассказывал про связи между M, V и C (Model, View и Controller). Теперь всё куда понятней, не правда ли?
Но и это не всё.
View не может изменять Model, как вы уже поняли, а у нас может. Как это исправить? Вью нужно передавать не саму модель, а только интерфейс, в которым "порезаны" все set методы. Например, в нашем случае такой:
package { public interface IReadableModel { function get pointer():int; function get colors:Array; } }
Однако, мы всё равно можем изменить элемента массива colors. Можно, конечно, придумать метод getElementAt, который бы лез в массив и возвращал элемент на заданной позиции, тем самым запретив изменять элементы массива... однако запрет на изменение модели не имеет другого характера, кроме как "защиты от дурака/запарки", чтобы случайно вы сами не поменяли модель. Мне не было бы стыдно оставить интерфейс в виде, который я привёл чуть выше - если вы не доверяете себе или людям, с которыми работаете - пишите метод. Это - инструмент, и он должен подстраиваться под вас, а не вы под него. Не стесняйтесь смотреть на картинку - она сильно помогает первое время. Если она даже сейчас кажется вам сложной - не смотрите на неё, а читайте текст и рисуйте эту картинку у себя на бумажке. Не ленитесь, это действительно помогает.
На этом я закончу первую лекцию. В следующих мы будем ветвить контроллеры, делать иерархические модели, общаться с сервером. В общем, в следующие разы будет действительно интересно. Stay tuned
Вторая часть.
Всего комментариев 231
Комментарии
02.11.2010 13:51 | |
Цитата:
Из всех вообще мне именно MVC кажется наиболее удачным. Ну и всякие там M + VC, но по той же логике.
Сам часто использовал MVP подход, когда ещё не знал, что он так называется) Т.е. виды обновляются не слушая модель, а по команде контроллера. Например в контроллере бред вроде этого: private function render():void { var i:int; var len = viewArray.length; for (i = 0; i < len; i++) { var view:IView = viewArray[i] as IView ; // тут может быть иерархическая модель var someViewModel:SomeViewModel = model.getSomeViewModel(i); if (!someViewModel.isInvalidated) { view.x = someViewModel.x; view.y = someViewModel.y; } // а тут говорим модели, что всё данные прочитаны, // т.е. устанавливаем её isInvalidated в true - рекурсивно для всех поддмоделей model.isInvalidated = true; } } |
|
Обновил(-а) Котяра 02.11.2010 в 16:10
|
02.11.2010 14:03 | |
Вот честно, я не очень силен в терминологии что-к-чему при разбитии тройки на двойку. Я имел ввиду что-то вроде визуализатора данных.
P.S. ты меня в скайпе игнорируешь? ) |
02.11.2010 15:25 | |
спасибо за статью.
|
02.11.2010 15:49 | |
Все же буду защищать pureMVC !
Во первых фреймовк находится в разработке, у него есть support и необходимая документация. Во вторых его разрабатывают далеко не глупые люди. В третьих его проще интегрировать с другими технологиями. Вы ведь не презентации делать собираетесь, вашему приложению еще каким то образом нужно с сервером общаться. В четвертых появляются специальные плагины для быстрого встраивания компонентов MVC в IDE. А также flash компоненты для мониторинга над кодом. Мне нравится эта связка: pureMVC console + Kap Inspect |
02.11.2010 15:58 | |
+ надстройка fabrication
Вообщем, кто смелый предлагаю объединить усилия в изучении практики программирования на с помощью pureMVC. В дополнение скажу, что на трех собеседований из пяти, которые мне недавно приходилось проходить интересовались MVC практиками. И только на двух, интересовались flex. Есть компании которые вполне осознанно отказываются от этой бурды. В частности mayl.ru (упс забудьте что я только что сказал) |
02.11.2010 16:06 | |
MVC практика это пюре? О как...
|
02.11.2010 16:07 | |
02.11.2010 16:12 | |
MVC практика это пюре? О как...
Напишите что - нибудь рабочее с вашим MVC тогда и поговорим. |
02.11.2010 16:15 | |
Пример совершенно некорректен.
Если в среде, в которой Вы разрабатываете обнаружена дырка - это не Ваша проблема. Если Вы не компетентны сделать проект, потому что выбрали не тот инструмент, что надо - она уже Ваша. 80% флеш сайтов сделаны на коленке в плане кода, где 500 кадров с анимацией на все случаи действия пользователя. Да теймплейт монстер близок к такому. При этом созерцая этот сайт плохих ощущений он не вызывает. Дак что, к черту весь AS3, давайте программировать в кадрах? UPD: Я правильно понял что Вы не желаете вести со мной спор до тех пор пока я не начну приводить примеры своих работ на моём MVC? |
|
Обновил(-а) Psycho Tiger 02.11.2010 в 16:18
|
02.11.2010 16:34 | |
А с чего Вы вообще взяли что pureMVC что-то там даёт? Вы утверждаете что использование pureMVC в моих проектах как-то повлияет на мою ЗП?
|
02.11.2010 16:38 | |
вот читаю я, читаю... и одного понять не могу, куда подевался мозг у программистов ? это риторический вопрос...
|
02.11.2010 17:19 | |
Цитата:
А почему же тогда в открытом космосе он никуда не падает ???!!!
|
02.11.2010 17:23 | |
Цитата:
А я то думал, что на него воздействует сила гравитации. Оказывается все дело только в массе! А почему же тогда в открытом космосе он никуда не падает ???!!!
Сила гравитации F = G * m1 * m2 / (r*r). Теперь думаем. Цитата:
"он упал так же быстро как и взлетел."
Есть доказательства ?! |
|
Обновил(-а) Psycho Tiger 02.11.2010 в 17:25
|
02.11.2010 17:26 | |
Один в поле не воин. Больше не хочу спорить.
Жаль, что мне одному нравится pureMVC ( |
02.11.2010 17:27 | |
например луна падает без перерыва. тока никак не упасть не может
Всему свое время ))) |
02.11.2010 17:30 | |
Цитата:
Всему свое время )))
|
02.11.2010 17:48 | |
программеры - суровые люди..начали со статьи про MVC , закончили падением луны на землю. о_О
|
02.11.2010 17:51 | |
@BlooDHounD, угу, корпускулярно-волной дуализм, соотношение физических величин между волновой теорией и корпускулярной, энергия существует со стороны взгляда на свет как на волну (а значит глядя как на частицу масса есть), тем самым объясняя почему же фотоны всё таки притягиваются к черной дыре. Я знаю, недавно экзамен сдал по квантовой физике. Просто слишком энергия мала чтобы хоть сколько-либо учитывать притяжение к Земле, неопределенности по Гейзенбергу "съедят" куда больше. Короче, сказал крайне неточно, пример плохой.
UPD: кстати. подумал. В случае с фотоном масса определенна, скорость определенна, в итоге координата абсолютно неопределенная. Не очень уверен что в таком случае говорить о теории Гейзенберга вообще имеет смысл. И давайте заниматься флешем. да.) @i.o., расширение вселенной или что там с ней? ) @inozemcev, Вы похоже нас не правильно понимаете. Нравится Вам - пользуйтесь. Мы же пытаемся Вам доказать, что универсального инструмента нету, ровно как и идеального фреймворка. Комментарий по поводу "создания велосипеда" имел бы смысл, если бы Вы говорили - "используйте фреймворки", а не фанатично доказывали, что пюре - панацея. |
|
Обновил(-а) Psycho Tiger 02.11.2010 в 17:59
|
02.11.2010 19:12 | |
Цитата:
закончили падением луны на землю. о_О
|
02.11.2010 19:39 | |
Не переживай - уже доказали, что со временем она и вовсе улетит от Земли
Блин точно. Меня тигренок попутал. Я это знал, но забыл ) |
02.11.2010 20:19 | |
Ну точно, как что - сразу я )
|
02.11.2010 21:35 | |
А мне, например, RobotLegs нравится, после него PureMVC кажется слишком уж топорным.
|
02.11.2010 22:41 | |
почитал вот это и понял одно - выбирать фремворки все равно, что выбирать автомобили. Я видимо из тех, кто любит большой и громоздский как танк.
|
02.11.2010 22:55 | |
Выбирать MVC -фрэймворки - всё равно что выбирать автомобили.. для похода по разной, часто сильно пересечённой местности с горами, магистралями, болотами и звериными тропами.. кое где танк проедет, кое где феррари, но чаще и проще пешочком или на велосипеде).
UPD вот из тех же обсуждений MVC -фрэймворков, подписываюсь на все 100: Цитата:
В "обычной" жизни вам совсем будут ненужны всякие навороты и фичи всех
фреймворков. Как только у вас появляется очень сложный и большой проект то фреймворки в нем ровным счетом ничего не решают. Тут все больше строится на оргинизации комманды и соглашениях принятых в комманде, и правильной организации кода. Вообще ни один из фреймворков не является серебряной пулей и если вы пишите *****код то никакой фреймворк вам не поможет. Если вы пишите хороший код, то любой из фреймворков будет вам помощником, правда, некоторые довольно агрессивны в плане "правил помощи" |
|
Обновил(-а) Котяра 03.11.2010 в 02:19
|
03.11.2010 01:36 | |
Подписываюсь под каждым словом из цитаты Котяры.
Первый здравый комент за все 5ть страниц …* |
03.11.2010 03:45 | |
товарищи, это конечно хорошо, но я так и не понял, представление может менять то модель или нет ? просто в статье один рисунок а вот тут http://outcoldman.ru/ru/blog/show/184
другой. И если таки не может менять, выходит что вью должна слать сообщения, в которых нужно передавать инфу (деласть свой евент) ? |
03.11.2010 05:04 | |
я вот тоже не понял зачем, но есть прямая ссылка на модель в этой схеме, а в другой схеме нету. Вот я и решил уточнить.
спасибо. |
03.11.2010 13:03 | |
спасибо!
|
03.11.2010 15:37 | |
Тигра давай 2 часть)
|
03.11.2010 19:41 | |
Да, вот так вот программисты и становятся писателями.
Колин Мук был программистом? Что то статьи в википедии нет о нем. |
03.11.2010 22:04 | |
Цитата:
Колин Мук был программистом? Что то статьи в википедии нет о нем.
вот например одно из его последних детищ: http://www.unionplatform.com/ а судя по http://www.moock.org/about/ он был у истоков гипертекстых mud игр - прообразов сегодняшних MMO. Кроме того преподавал в универах всяких. а на вид - программер программером) |
|
Обновил(-а) Котяра 03.11.2010 в 23:45
|
04.11.2010 04:09 | |
а есть статейки про просто MC?)
Сейчас делаю игрульку, в ней только 2 из 14 модулей занимаются отображением, остальные только считают или работают с серверами и сетью. |
04.11.2010 15:41 | |
Ну, видимо должен быть главный модуль, который вбирается в себя модулей эдак 5.
|
05.11.2010 00:34 | |
Заранее извиняюсь за некоторый оффтоп. Я вообще считаю MVC не паттерном проектирования, а схемой построения приложения. У GoF, в принципе, в книге и идет описание разных паттернов применительно к такой схеме в Smalltalk. В теории, как и было ранее сказано, есть большее количество вариаций такой схемы, и к тому же конкретные реализации могут отходить тот этой идеологии довольно существенно. Но статья полезна для понимания, бесспорно, равно как и прикрепленная тема, в которой Тигра проводил свои изыскания по поводу данной схемы, поэтому мои респекты ему и ожидания следующих частей! Если будет интересно, у меня есть идея описать на примерах гофовские паттерны применительно к AS3, хотя это не просто, исходя из понимания паттернов вообще и из из того, что они иногда идеологически пересекаются, и не сразу понятно, чем же они отличаются и какие цели преследуют (как пример - топик того же Тигры во флейме). Но, по крайней мере, мне кажется, что попытаться стоит, и в обсуждении можно многое почерпнуть для себя.
|
|
Обновил(-а) Hidest 05.11.2010 в 00:39
|
05.11.2010 01:17 | |
Hidest, спасибо. Ну если напишите про GoF в реальных примерах в АС3, да ещё и с изысканиями что где применить в каком случае и что чем от чего отличается - то респект Вам от меня )
|
05.11.2010 04:42 | |
Все уже написано. Только пока не переведено.
|
05.11.2010 17:09 | |
Вот кстати перевод главы про MVC
Там в комментарии тоже интресные.. Т.е. с авторами можно поспорить. |
13.11.2010 18:13 | |
Раз уж наткнулся на блог, задам фоновый вопрос, который висел иногда
При данном подходе к MVC зачем обязательно во вьюхе данные менять через событие от модели. Если контроллер производит все логические изменения и имеет все ссылки на все вьюхи, почему бы ему самому не вызывать нужную функцию во вьюхах, например по циклу? Чтобы не привязывать вью к конкретным интерфейсам? |
|
Обновил(-а) Сайлас 13.11.2010 в 18:31
|
Последние записи от Psycho Tiger
- Тонкости и трюки ActionScript`а, которые... бесполезны (10.05.2011)
- Vkontakte: как пользоваться wall.post, нужен ли теперь wall.savePost? (05.03.2011)
- А пятый контер-страйк хорош. (19.01.2011)
- Пацаны, гоу Вконтакте? (21.12.2010)
- Давайте начистоту (18.12.2010)