Refactoring a current project to include robot legs

npearson99's Avatar

npearson99

09 Mar, 2012 12:44 AM

I'm trying to refactor a current, semi large project to use robot legs.

My first task is to load a configuration settings file (AIR) and make it available inside the app.

So I can get that going fine. I have a service read in the data and populate a model. I have a singleton mapped and I'm ready to go.

Now my existing code base follows some bad practices. I have a controller that is about 1500 lines long that runs most of my app. It extends EventDispatcher and dispatches events.

The controller also holds some data and references to models. It's some whacky hybrid of a monolithic controller/model :).

I pass that controller around to different parts of the app, mostly view components to interact with it. I know..bad practice..that's why I'm here.

I'd like to switch this controller over to an actor and start to divide and conquer this sucker. My problem is that this controller dispatches events. I'm not sure how to keep dispatching events with this class and change it to an actor. I see there's an IEventDispatcher on it. Should I create an instance of EventDispatcher and populate that? I think that's wrong because I'm guessing it will be fulfilled when I inject it.

Any tips on going about this? I'd like to takes bites of my elephant than try to refactor the whole thing at once.

Thanks!

-Nate

  1. Support Staff 1 Posted by Ondina D.F. on 10 Mar, 2012 11:02 AM

    Ondina D.F.'s Avatar

    Hi Nate,

    My problem is that this controller dispatches events. I'm not sure how to keep dispatching events with this class and change it to an actor. I see there's an IEventDispatcher on it. Should I create an instance of EventDispatcher and populate that? I think that's wrong because I'm guessing it will be fulfilled when I inject it.

    I assume you have something like this in your controller:
    dispatchEvent(new SomeCustomEvent(SomeCustomEvent.SOME_CUSTOM_TYPE, value));

    If you’d extend Actor you’d only have to replace dispatchEvent with dispatch in your code:
    dispatch(new SomeCustomEvent(SomeCustomEvent.SOME_CUSTOM_TYPE,value));

    But, if you want to use “dispatchEvent” instead of “dispatch”, you can create your own „Actor“ like this:

    
    import flash.events.Event;
    import flash.events.IEventDispatcher;
    
    public class BaseDispatcher
    {
    [Inject]
    public var eventDispatcher:IEventDispatcher;
    
    protected function dispatchEvent(event:Event):void
    {
    if (eventDispatcher.hasEventListener(event.type))
    eventDispatcher.dispatchEvent(event);
    }
    }
    

    Then:
    public class SomeDispatcher extends BaseDispatcher

    dispatchEvent(new SomeCustomEvent(SomeCustomEvent.SOME_CUSTOM_TYPE, value));

    As you know, you can inject the IEventDispatcher wherever you need it:

    
    public class SomeDispatcher
    {
    public function SomeDispatcher()
    {
    }
            
    protected var _eventDispatcher:IEventDispatcher;
    
    
    public function get eventDispatcher():IEventDispatcher
    {
        return _eventDispatcher;
    }
    
    [Inject]
    public function set eventDispatcher(value:IEventDispatcher):void
    {
        _eventDispatcher=value;
    }
    public function doDispatch(value:String):void
    {
    eventDispatcher.dispatchEvent(new SomeCustomEvent(SomeCustomEvent.SOME_CUSTOM_TYPE, value));
    }
    }
    

    Does this help?

    Ondina

  2. 2 Posted by Nate on 12 Mar, 2012 08:57 PM

    Nate's Avatar

    I'm a little confused.

    If I change my "controller" class to an actor and replace dispatchEvent with dispatch, this breaks all event listeners on that class. If I did this, i would have to re-write my app to use the RL event dispatching.

    Is this correct?

  3. Support Staff 3 Posted by Ondina D.F. on 13 Mar, 2012 12:56 PM

    Ondina D.F.'s Avatar

    Hey Nate,

    I thought your intention was to refactor your “controller” so you can take advantage of the shared even dispatcher provided by robotlegs. I think changes to other parts of your app are unavoidable, if you want to do it à la robotlegs :)

    A temporary solution, until you define your new classes, that should replace the huge controller:

    SomeDispatcher (from my previous post) would be your “controller” class. You provide it with an IEventDispatcher, so you can communicate with other rl classes. Have 2 methods: addEventListener and dispatchEvent, so you can add event listeners to it.

    Mapping:
    injector.mapSingleton(SomeDispatcher);

    SomeDispatcher.as

    
    import flash.events.Event;
    import flash.events.IEventDispatcher;
    
    public class SomeDispatcher
    {
    protected var _eventDispatcher:IEventDispatcher;
    
    public function SomeDispatcher()
    {
    }
    
    public function get eventDispatcher():IEventDispatcher
    {
        return _eventDispatcher;
    }
    
    [Inject]
    public function set eventDispatcher(value:IEventDispatcher):void
    {
        _eventDispatcher=value;
    }
    
    public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
    {
        eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
    }
    
    public function dispatchEvent(event:Event):void
    {
        eventDispatcher.dispatchEvent(event);
    }       
    }
    

    Now, you can inject SomeDispatcher in SomeMediator and let someDispatcher dispatch an event on the shared event dispatcher.

    SomeMediator.as

    
    [Inject] public var view:SomeView;
    [Inject] public var someDispatcher:SomeDispatcher;
    
    override public function onRegister():void
    {
        view.someDispatcher=someDispatcher;
    }
    
    protected function onSomethingHappened():void
    {
        someDispatcher.dispatchEvent(new SomeCustomEvent(SomeCustomEvent.SOME_CUSTOM_TYPE, "from SomeMediator");        
    }
    

    AnotherMediator.as has registered a listener for the event dispatched by someDispatcher:

    
    override public function onRegister():void
    {
        eventMap.mapListener(eventDispatcher, SomeCustomEvent.SOME_CUSTOM_TYPE, onSomeCustomEvent);
    }
    protected function onSomeCustomEvent(event:SomeCustomEvent):void
    {
        trace(event.someMessage);//would trace "from SomeMediator"
    }
    

    I pass that controller around to different parts of the app, mostly view components to interact with it.

    As you can see above, SomeMediator passes the injected someDispatcher to SomeView.
    In SomeView:

    
    public var someDispatcher:SomeDispatcher;
    
    private function initView():void
    {
        someDispatcher.addEventListener(SomeCustomEvent.SOME_CUSTOM_TYPE, actionHandler);
    }
    private function someViewList_changeHandler(event:IndexChangeEvent):void
    {
        someDispatcher.dispatchEvent(new SomeCustomEvent(SomeCustomEvent.SOME_CUSTOM_TYPE, "from SomeView"));   
    }
    private function actionHandler(event:SomeCustomEvent):void 
    {
        trace(event.type+"  "+event.someMessage);//traces from SomeView
    }
    

    As you can see, you can use the old syntax someDispatcher.dispatchEvent and someDispatcher.addEventListener.
    But, as a side effect, the events dispatched by someDispatcher in SomeView will be heard by AnotherMediator as well, which is not exactly how rl-MVCS should work. Therefore that should be just a temporary solution!!!
    Does that help?
    Others may chime in with a better solution(?)

    Ondina

  4. Ondina D.F. closed this discussion on 30 Mar, 2012 09:01 AM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac