Upload
raimundas-banevicius
View
11.041
Download
0
Embed Size (px)
DESCRIPTION
Join Raimundas (author of mvcExpress frameworks) as he presents his vision of next step in AS3 MVC framework evolution. Writing maintainable software fast – was never a trivial task, but MVC frameworks are here to help us! In this session you will see short reminder of MVC framework history, comparison of coding convenience and performance benchmark results for PureMVC, robotlegs and mvcExpress frameworks. For those who does not enjoy seeing code or statistic tables as much as running applications, Raimundas will show dungeon editor/crawler to demonstrate mvcExpress modular programming features, designed to save even more time and headaches while developing games and applications.
Citation preview
The Next Step in AS3 Framework Evolution
02.2013
About me
Senior AS3 Developer
Working with Flash from 2001
Author of open source AS3 framework – mvcExpress
Twitter : @Deril
About this presentation
● AS3 framework evolution ● Modular programming in mvcExpress
● mvcExpress live
AS3 framework evolution
AS3 framework history
●PureMVC (2006)●Cairngorm (2007?) [flex only]●Springactionscript (2007)●Parsley(2008)●Mate(2008) [flex only]●Robotlegs(2009)●Swiz(2009) [flex only]
●MvcExpress(2012)●Robotlegs 2 (2012) (in beta)
(ActionScript 3.0 released in 2006)
AS3 framework history
●PureMVC (2006)●Cairngorm (2007?) [flex only]●Springactionscript (2007)●Parsley(2008)●Mate(2008) [flex only]●Robotlegs(2009)●Swiz(2009) [flex only]
●MvcExpress(2012)●Robotlegs 2 (2012) (in beta)
(ActionScript 3.0 released in 2006)
PureMVC
● Organize your code is small units
● Let those units communication
● Standardize your code
● Focus on app instead of architecture
● Ported to many languages
● Slightly hurts performance
● Built on static classes
● Lot of boilerplate code
Can't it be done simpler?
The good The bad
The good The bad
robotlegs
● All PureMVC goodness.
● Removed most boilerplate code
● Introduces dependency injection
● Hurts performance a lot!
Can't it be done simpler...
and run fast?
The good The bad
robotlegs 2 (beta)
● Highly configurable
● Modular
● Guards ,hooks, rules.
● Adds some boilerplate code
● Code less standardized
● Hurts performance a lot (and more)
I meant faster! Not slower...
The good The bad
mvcExpress
● All PureMVC and robotlegs goodness.
● Focus on modular development
● Simplifies code even more
● Hurts performance the least
● Young framework
Simplest and fastest MVC framework!
package {public class PureMvcMediator extends Mediator implements IMediator {
public static const NAME:String = "PureMvcMediator"; public function PureMvcMediator(initViewComponent:ViewComponent) { super(NAME, initViewComponent); } // cast view for convenient local use. public function get view():ViewComponent { return super.getViewComponent() as ViewComponent; } // listen for framework notices override public function listNotificationInterests():Array { return [ // DataNote.STUFF_DONE // ]; } // handle framework events override public function handleNotification(notice:INotification):void { switch (notice.getName()) { case DataNote.STUFF_DONE: // do stuff… break; }
}}
pureMVC mediator
package {public class PureMvcMediator extends Mediator implements IMediator {
public static const NAME:String = "PureMvcMediator"; public function PureMvcMediator(initViewComponent:ViewComponent) { super(NAME, initViewComponent); } // cast view for convenient local use. public function get view():ViewComponent { return super.getViewComponent() as ViewComponent; } // listen for framework notices override public function listNotificationInterests():Array { return [ // DataNote.STUFF_DONE // ]; } // handle framework events override public function handleNotification(notice:INotification):void { switch (notice.getName()) { case DataNote.STUFF_DONE: // do stuff… break; }
}}
pureMVC mediator
package {public class PureMvcMediator extends Mediator implements IMediator {
public static const NAME:String = "PureMvcMediator"; public function PureMvcMediator(initViewComponent:ViewComponent) { super(NAME, initViewComponent); } // cast view for convenient local use. public function get view():ViewComponent { return super.getViewComponent() as ViewComponent; } // listen for framework notices override public function listNotificationInterests():Array { return [ // DataNote.STUFF_DONE // ]; } // handle framework events override public function handleNotification(notice:INotification):void { switch (notice.getName()) { case DataNote.STUFF_DONE: // do stuff… break; }
}}
pureMVC mediator
package {public class PureMvcMediator extends Mediator implements IMediator {
public static const NAME:String = "PureMvcMediator"; public function PureMvcMediator(initViewComponent:ViewComponent) { super(NAME, initViewComponent); } // cast view for convenient local use. public function get view():ViewComponent { return super.getViewComponent() as ViewComponent; } // listen for framework notices override public function listNotificationInterests():Array { return [ // DataNote.STUFF_DONE // ]; } // handle framework events override public function handleNotification(notice:INotification):void { switch (notice.getName()) { case DataNote.STUFF_DONE: // do stuff… break; }
}}
pureMVC mediator
package {public class MvcExpressMediator extends Mediator { [Inject] public var view:ViewComponent; override public function onRegister():void { // listen for framework events addHandler(DataMessage.STUFF_DONE, handleStuffDone); } // handle framework events private function handleStuffDone(params:DataChangeParamsVO):void { view.showStuff(params.dataParam1); }}}
mvcExress mediator
package {public class MvcExpressMediator extends Mediator { [Inject] public var view:ViewComponent; override public function onRegister():void { // listen for framework events addHandler(DataMessage.STUFF_DONE, handleStuffDone); } // handle framework events private function handleStuffDone(params:DataChangeParamsVO):void { view.showStuff(params.dataParam1); }}}
mvcExress mediator
package {public class MvcExpressMediator extends Mediator { [Inject] public var view:ViewComponent; override public function onRegister():void { // listen for framework events addHandler(DataMessage.STUFF_DONE, handleStuffDone); } // handle framework events private function handleStuffDone(params:DataChangeParamsVO):void { view.showStuff(params.dataParam1); }}}
mvcExress mediator
package {public class MvcExpressMediator extends Mediator { [Inject] public var view:ViewComponent; override public function onRegister():void { // listen for framework events addHandler(DataMessage.STUFF_DONE, handleStuffDone); } // handle framework events private function handleStuffDone(params:DataChangeParamsVO):void { view.showStuff(params.dataParam1); }}}
mvcExress mediator
Speed test datamvcExpress pureMVC robotlegs robotlegs 2
Command creation and execution: 0.00087 0.00219 0.00866 0.01894
Proxy inject into command: 0.00037 0.00024 0.00491 0.00247
Mediator create: 0.02100 0.02100 0.05100 0.13600
Mediator remove: 0.01700 0.10300 0.01850 0.05550
Communication 1 to 1: 0.00030 0.00060 0.00153 0.00141
Communication 1 to 10: 0.00073 0.00788 0.00670 0.00629
Communication 1 to 100: 0.00480 0.06897 0.05746 0.05071
1.0 /2.5 /10.0 /21.8
1.0 /0.7 /13.2 /6.6
1.0 /1.0 /2.4 /6.5
1.0 /6.1 /1.1 /3.3
1.0 /2.0 /5.0 /4.6
1.0 /10.9 /9.2 /8.7
1.0 /14.4 /12.0 /10.6
https://github.com/MindScriptAct/as3-mvcFramework-performanceTest
https://github.com/MindScriptAct/as3-mvcFramework-performanceTest
Command runs /1ms
pureMVC robotlegs robotlegs 2 mvcExpress mvcExpress(pooled)
Command with nothing: 495.0 109.3 55.3 1010.1 1754.4
Command with 1 inject: 487.5 70.4 49.6 961.5 1694.9
Command with 2 injects: 458.7 58.6 47.2 724.6 1724.1
Command with 4 injects: 340.1 44.1 42.7 480.8 1783.3
Command performance
Command runs /1ms
pureMVC robotlegs robotlegs 2 mvcExpress mvcExpress(pooled)
Command with nothing: 495.0 109.3 55.3 1010.1 1754.4
Command with 1 inject: 487.5 70.4 49.6 961.5 1694.9
Command with 2 injects: 458.7 58.6 47.2 724.6 1724.1
Command with 4 injects: 340.1 44.1 42.7 480.8 1783.3
Command performance
Command runs /1ms
pureMVC robotlegs robotlegs 2 mvcExpress mvcExpress(pooled)
Command with nothing: 495.0 109.3 55.3 1010.1 1754.4
Command with 1 inject: 487.5 70.4 49.6 961.5 1694.9
Command with 2 injects: 458.7 58.6 47.2 724.6 1724.1
Command with 4 injects: 340.1 44.1 42.7 480.8 1783.3
Command performance
Command runs /1ms
pureMVC robotlegs robotlegs 2 mvcExpress mvcExpress(pooled)
Command with nothing: 495.0 109.3 55.3 1010.1 1754.4
Command with 1 inject: 487.5 70.4 49.6 961.5 1694.9
Command with 2 injects: 458.7 58.6 47.2 724.6 1724.1
Command with 4 injects: 340.1 44.1 42.7 480.8 1783.3
Command performance
Command runs /1ms
pureMVC robotlegs robotlegs 2 mvcExpress mvcExpress(pooled)
Command with nothing: 495.0 109.3 55.3 1010.1 1754.4
Command with 1 inject: 487.5 70.4 49.6 961.5 1694.9
Command with 2 injects: 458.7 58.6 47.2 724.6 1724.1
Command with 4 injects: 340.1 44.1 42.7 480.8 1783.3
Command performance
Command runs /1ms
pureMVC robotlegs robotlegs 2 mvcExpress mvcExpress(pooled)
Command with nothing: 495.0 109.3 55.3 1010.1 1754.4
Command with 1 inject: 487.5 70.4 49.6 961.5 1694.9
Command with 2 injects: 458.7 58.6 47.2 724.6 1724.1
Command with 4 injects: 340.1 44.1 42.7 480.8 1783.3
Command performance
Communication performance
Direct communication:
Indirect communication:
Communication performance
Direct communication:
Indirect communication:
Overview
Overview
Overview
Modular programming in mvcExpress
Modular programmingfeatures
● Aggregation● Communication● Dependencies(data)
● Permission control (v1.4)
Aggregation
mediatorMap.mediate(moduleB);
var moduleB:ModuleB = new ModuleB();
view.addChild(moduleB);
Module communication
Module communication
Module communication
sendScopeMessage("scopeName", "messageType", new ParamObject());
addScopeHandler("scopeName", "messageType", scopedMessageHandrlerFunction);
Module data sharing (data dependencies)
Module data sharing (data dependencies)
Module data sharing (data dependencies)
proxyMap.scopeMap("scopeName", myProxyObject);
[Inject(scope="scopeName")]public var myProxy:MyProxy;
Scope permissions
registerScope(scopeName:String, messageSending:Boolean = true, messageReceiving:Boolean = true, proxieMapping:Boolean = false):void
Dungeon viewer example
Modular programming pitfalls
● Planning is needed
● Good module should be able to stand as application on its own
– Chat window
– Stand alone tutorial● Worst case scenario: extracting
module/reintegrating module refactoring.
MvcExpress live
mvcExpress live
● mvcExpress live = mvcExpress + game engine
– Continuous logic execution– Dynamic animations– Breaking execution in parts. (batching)
● Compatible with mvcExpress
mvcExress live diagram
mvcExress live diagram
mvcExress live diagram
mvcExress live diagram
mvcExress live diagram
mvcExress live diagram
mvcExress live diagram
Process examplepackage com.mindscriptact.testProject.engine {public class GameEngineProcess extends Process {
override protected function onRegister():void { addTask(MoveHeroTask); addTask(MoveEnemiesTask); addTask(HeroCollideEnemiesTask); addTask(EnemySpawnTask); addTask(ShowHeroTask); addTask(ShowEnemiesTask);
addHandler(Message.PAUSE_GAME, handleGamePause); }
private function handleGamePause(isPaused:Boolean):void { if (isPaused) { disableTask(MoveHeroTask); disableTask(MoveEnemiesTask); } else { enableTask(MoveHeroTask); enableTask(MoveEnemiesTask); } }}}
Task example
package com.mindscriptact.testProject.engine.tasks {
public class ShowEnemiesTask extends Task {
[Inject(constName="com.mindscriptact.testProject.constants.ProvideIds.ENEMY_DATAS")]
public var enemyDatas:Vector.<EnemyVO>;
[Inject(constName="com.mindscriptact.testProject.constants.ProvideIds.ENEMY_VIEWS")]
public var enemyImages:Vector.<EnemySprite>;
override public function run():void {for (var i:int = 0; i < enemyDatas.length; i++) {
enemyImages[i].x = enemyDatas[i].x;enemyImages[i].y = enemyDatas[i].y;enemyImages[i].rotation = enemyDatas[i].rotations;
}}
}}
mvcExpress live testingpackage com.mindscriptact.testProject.engine.tasks {
public class ShowEnemiesTask extends Task {
[Inject(constName="com.mindscriptact.testProject.constants.ProvideIds.ENEMY_DATAS")]public var enemyDatas:Vector.<EnemyVO>;
[Inject(constName="com.mindscriptact.testProject.constants.ProvideIds.ENEMY_VIEWS")]public var enemyImages:Vector.<EnemySprite>;
override public function run():void {for (var i:int = 0; i < enemyDatas.length; i++) {
enemyImages[i].x = enemyDatas[i].x;enemyImages[i].y = enemyDatas[i].y;enemyImages[i].rotation = enemyDatas[i].rotations;
}}
}}
[Test]public function showEnemiesTask_enemyViewAndDataCount_isEqual():void {
assert.equals(enemyDatas.length, enemyImages.length, "Enemies data and view count must be the same!");}
[Test(delay="500")]public function showEnemiesTask_enemyViewAndDataPosition_isEqual():void {
for (var i:int = 0; i < enemyDatas.length; i++) {assert.equals(enemyImages[i].x, enemyDatas[i].x, "Enemy x is damaged. enemyId:" + enemyDatas[i].id);assert.equals(enemyImages[i].y, enemyDatas[i].y, "Enemy y is damaged. enemyId:" + enemyDatas[i].id);
}}
Process run speed
● Best case:
– Runs 1000000 empty Task's in 17 ms– 58823 empty tasks in 1 ms
● Worst case:
– 13300 empty tasks in 1 ms
MvcExpress live overview
● Designed with games in mind but can be used in any application than has repeating logic to run.
● Processes and Task's are decoupled
● Convenient communication with MVC
● It is possible to break Model and View decoupling rules, but gives tools to detect it.
● It is fast!
● It just works!
On learning curve
On learning curve
● MVC framework initial learning curve is steep...
● But if you learned one – learning another is easy!
http://mvcexpress.org/documentation/
https://github.com/MindScriptAct/mvcExpress-examples
Also I do workshops.
http://mvcexpress.org/documentation/
https://github.com/MindScriptAct/mvcExpress-examples
Also I do workshops.
MvcExpress logger
Links
http://mvcexpress.org/
https://github.com/MindScriptAct/mvcExpress-frameworkhttps://github.com/MindScriptAct/mvcExpress-exampleshttps://github.com/MindScriptAct/mvcExpress-downloads
http://puremvc.org/
http://www.robotlegs.org/
Twitter : @Deril
Thank you for your time!
http://mvcexpress.org/
https://github.com/MindScriptAct/mvcExpress-frameworkhttps://github.com/MindScriptAct/mvcExpress-exampleshttps://github.com/MindScriptAct/mvcExpress-downloads
http://puremvc.org/
http://www.robotlegs.org/
Twitter : @Deril