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.
5. 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)
6. 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)
7. 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
8. 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?
9. 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...
10. 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!
11. 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
12. 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
13. 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
14. 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
15. 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
16. 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
17. 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
18. 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
19. Speed test data
mvcExpress 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
42. 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.
52. 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);
}
}
}}
53. 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;
}
}
}}
54. mvcExpress live testing
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;
}
}
}}
[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);
}
}
55. 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
56. 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!
58. 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.