Save 10% off ANY FITC event with discount code 'slideshare'
See our upcoming events at www.fitc.ca
OVERVIEW
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.
2. About me
Raimundas Banevicius
Senior AS3 Developer
Working with Flash from 2001
Author of open source AS3 framework – mvcExpress
Blog : http://www.mindscriptact.com/
Twitter : @Deril
E-mail : raima156@yahoo.com
3. About this presentation
● AS3 framework evolution
● Modular programming in mvcExpress
● mvcExpress live
5. AS3 framework history
(ActionScript 3.0 released in 2006)
●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)
6. AS3 framework history
(ActionScript 3.0 released in 2006)
●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)
7. AS3 framework history
(ActionScript 3.0 released in 2006)
●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)
8. PureMVC
The good The bad
● Organize your code in small units ● Slightly hurts performance
● Let those units communicate
● Built on static classes
● Standardize your code
● Focus on app instead of architecture ● Lots of boilerplate code
● Ported to many languages
Can it be done simpler?
9. robotlegs
The good The bad
● All PureMVC goodness. ● Hurts performance a lot!
● Removed most boilerplate
code
● Introduces dependency
injection
Can it be done simpler...
and run fast?
10. robotlegs 2 (beta)
The good The bad
● Highly configurable ● Adds some boilerplate code
● Modular ● Code less standardized
● Guards, hooks, rules. ● Hurts performance a lot
(and more)
Can it be done simpler...
and run fast?
11. mvcExpress
The good The bad
●
All PureMVC and robotlegs ● Hurts performance the least
goodness.
● Young framework
● Focus on modular development
● Simplifies code even more
Simplest and fastest MVC framework!
12. package { pureMVC mediator
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;
}
}}
13. package { pureMVC mediator
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;
}
}}
14. package { pureMVC mediator
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;
}
}}
15. package { pureMVC mediator
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;
}
}}
16. 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);
}
}}
17. 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);
}
}}
18. 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);
}
}}
19. 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);
}
}}
20. Speed test data
mvcExpress pureMVC robotlegs robotlegs 2
Command creation and execution: 0.00087 0.00219 0.00866 0.01894
1.0 /2.5 /10.0 /21.8
Proxy inject into command: 0.00037 0.00024 0.00491 0.00247
1.0 /0.7 /13.2 /6.6
Mediator create: 0.02100 0.02100 0.05100 0.13600
1.0 /1.0 /2.4 /6.5
https://github.com/MindScriptAct/as3-mvcFramework-performanceTest
Mediator remove: 0.01700 0.10300 0.01850 0.05550
1.0 /6.1 /1.1 /3.3
Communication 1 to 1: 0.00030 0.00060 0.00153 0.00141
1.0 /2.0 /5.0 /4.6
Communication 1 to 10: 0.00073 0.00788 0.00670 0.00629
1.0 /10.9 /9.2 /8.7
Communication 1 to 100: 0.00480 0.06897 0.05746 0.05071
1.0 /14.4 /12.0 /10.6
35. 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.
45. package com.mindscriptact.testProject.engine { Process example
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);
}
}
}}
46. Task example
package com.mindscriptact.testProject.engine.tasks {
public class ShowEnemiesTask extends Task {
[Inject(name="enemyDatas")]
public var enemyDatas:Vector.<EnemyVO>;
[Inject(name="enemyViews")]
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;
}
}
}}
47. mvcExpress live testing
package com.mindscriptact.testProject.engine.tasks {
public class ShowEnemiesTask extends Task {
[Inject(name="enemyDatas")]
public var enemyDatas:Vector.<EnemyVO>;
[Inject(name="enemyViews")]
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);
}
}
}}
48. 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
49. 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!
51. 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.