Skip to content

Instantly share code, notes, and snippets.

@squeedee
Created January 17, 2011 18:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save squeedee/783251 to your computer and use it in GitHub Desktop.
Save squeedee/783251 to your computer and use it in GitHub Desktop.
Robotlegs Sequencer Actor
package com.visfleet.robotlegs.bootstrap {
import org.robotlegs.core.ICommandMap;
import org.robotlegs.core.IReflector;
import org.robotlegs.mvcs.Actor;
public class AbstractSequencer extends Actor {
private var steps:Array = new Array();
[Inject]
public var reflector:IReflector;
[Inject]
public var commandMap:ICommandMap;
[PostConstruct]
public function postConstruct():void {
configure();
}
virtual protected function configure():void {
throw new Error("Override " + reflector.getFQCN(this) + "#configure and don't call super", 8725414);
}
protected function addStep(commandClass:Class):void {
var classFQN:String = reflector.getFQCN(commandClass);
steps.push(classFQN);
commandMap.mapEvent(classFQN,commandClass,SequenceStepEvent,true);
}
public function step():void {
if (!stepsRemain())
return;
executeNextStep();
}
private function executeNextStep():void {
var classFQN:String = steps.shift();
var event:SequenceStepEvent = new SequenceStepEvent(classFQN, this);
dispatch(event);
}
public function stepsRemain():Boolean {
return steps.length > 0;
}
}
}
package com.visfleet.robotlegs.bootstrap {
import flash.events.Event;
public class SequenceStepEvent extends Event {
public function SequenceStepEvent(classFQN:String, sequencer:AbstractSequencer) {
super(classFQN);
this.sequencer = sequencer;
}
private var sequencer:AbstractSequencer;
public function step():void {
sequencer.step();
}
}
}
public class ConfigureScheduleHeaderViewCommand extends Command {
[Inject]
public var event:SequenceStepEvent;
override public function execute():void {
mediatorMap.mapView(TimelineView, TimelineMediator);
event.step();
}
}
@tschneidereit
Copy link

Can you explain the advantage of listening to and dispatching events based on the FQCN of the commands instead of using ICommandMap#execute?
https://github.com/robotlegs/robotlegs-framework/blob/master/src/org/robotlegs/core/ICommandMap.as#L42 looks like it would work just fine when used in executeNextStep like so:

protected function addStep(commandClass:Class):void {
    steps.push(commandClass);
}

private function executeNextStep():void {
    var commandClass:Class = steps.shift();
    commandMap.execute(commandClass);
}

@squeedee
Copy link
Author

The Sequencer is decoupled from the commands. That is, the commands do not need to know the Sequencer (class OR instance) exists, only that they have an event that lets them show their completion with event.step()

I could remove Command awareness of 'sequencing' completely by doing:
commandMap.execute(commandClass)
executeNextStep();

However this means you cant support asynchrony in your bootstrap. To be honest, I haven't needed to, but the facility is there.

So it's really just an Architectural decision, If your needs are different then go with the event-free solution.

@squeedee
Copy link
Author

Oooh I should also say that I tend to use static mapping of events->commands. If i want state machine behaviour, I use a state machine and a command pattern. That said, I can dump/log the mappings in my module and get the oft desired 'overview' for debugging without letting people get in the habbit of jamming all their command mappings into a single file. Without the mapping in my code, the existance of those commands would be opaque.

@tschneidereit
Copy link

Thanks for the explanation.

I guess the first part could also be solved by directly injecting the sequencer itself and letting the command invoke executeNextStep on it. But I definitely agree about the second argument: Having the ability to get an overview of the mapped commands is very helpful indeed. Also, performance really shouldn't be a concern at this level anyway, so the slight overhead probably isn't an issue, either.

@squeedee
Copy link
Author

God no, performance did not get a look in. I can bootstrap with hundreds of sequence events (across modules) and not even notice it.

@tschneidereit
Copy link

That's what I thought. Thank god the bad old days of the AVM1 are over.

And now I'm back to optimizing the performance of SwiftSuspenders ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment