tag:robotlegs.tenderapp.com,2009-10-18:/discussions/questions/306-command-queuing-alternativesRobotlegs: Discussion 2018-10-18T16:35:18Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-06T12:52:19Z2010-10-06T12:52:19ZCommand Queuing - alternatives?<div><p>Could I ignore the entire question for now, and just quickly point out that you can use the CommandMap to instantiate and execute Commands (even if they haven't been explicitly mapped):</p>
<p><a href="http://github.com/robotlegs/robotlegs-framework/blob/v1.3.0/src/org/robotlegs/base/CommandMap.as#L160">http://github.com/robotlegs/robotlegs-framework/blob/v1.3.0/src/org...</a></p></div>Shaun Smithtag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-06T13:09:51Z2010-10-06T13:09:51ZCommand Queuing - alternatives?<div><p>Hi Stray,</p>
<p>other alternatives:</p>
<p><a href="http://github.com/Aaronius/robotlegs-utilities-Macrobot">http://github.com/Aaronius/robotlegs-utilities-Macrobot</a></p>
<p>and/or</p>
<p><a href="http://github.com/cbrammer/robotlegs-utilities-CommandLib">http://github.com/cbrammer/robotlegs-utilities-CommandLib</a></p>
<p>I don't know if that's what you need.</p>
<p>Ondina</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-06T13:15:40Z2010-10-06T13:15:40ZCommand Queuing - alternatives?<div><p>You can, and that's a great suggestion... but I need to be backward compatible to 1.0, and that functionality only exists in 1.1+</p>
<p>The shell of the application, which loads all functionality via modules (loaded into the app domain - this is an air app so code not loaded into the app domain is basically impotent), was compiled with 1.0 and the installed user base don't have admin rights to upgrade the shell, so I'm stuck with that version.</p>
<p>But that's ok - 1.0 works good enough! There are a few bits like constructor injection that are busted, but I can still get everything done that I need.</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-06T13:21:16Z2010-10-06T13:21:16ZCommand Queuing - alternatives?<div><p>Thanks Ondina - I had looked at the first, but wasn't aware of the second.</p>
<p>It seems that neither do quite what I'm looking for, though both have some interesting stuff that can inform what I'm doing.</p>
<p>So - I'll put together what I need and then others can grow it from there :)</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-06T14:44:59Z2010-10-06T14:44:59ZCommand Queuing - alternatives?<div><p><a href="http://github.com/joelhooks/robotlegs-utilities-Loadup">http://github.com/joelhooks/robotlegs-utilities-Loadup</a></p>
<p>This fits the bill somewhat, but I never really finished working on it.</p></div>Joel Hookstag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-06T14:55:52Z2010-10-06T14:55:52ZCommand Queuing - alternatives?<div><p>Cheers - I shall look through for stuff that I've missed.</p>
<p>I've just about done with my version - it's surprisingly simple. (2 classes and an interface). And it allows you to use your existing services / events etc without the util dictating anything to them.</p>
<p>It's only the most basic 'get it done' version - I'm sure there would be a ton you could do but I've gone with only implementing behaviour I need for now.</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-06T17:49:34Z2010-10-06T17:49:34ZCommand Queuing - alternatives?<div><p>And another robotlegs utility is born:</p>
<p><a href="http://github.com/Stray/robotlegs-utilities-DeferredCommandQueue">http://github.com/Stray/robotlegs-utilities-DeferredCommandQueue</a></p>
<p>Thanks for all the tips guys. Fork-it if you like it.</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-08T07:00:26Z2010-10-23T09:55:07ZCommand Queuing - alternatives?<div><p>A first problem I see with your util, Stray, is that you can only create one command queue per application, right?<br />
But this could be solved pretty easily I think, just move the code from RunNextDeferredCommand to a executeNextCommand in your DefferedCommandQueu. This would give us something like:<br />
</p>
<pre><code>// set up the mappings for the DeferredCommandQueues
injector.mapSingletonOf( IDeferredCommandQueue, DeferredCommandQueue, 'firstQueue' );
injector.mapSingletonOf( IDeferredCommandQueue, DeferredCommandQueue, 'secondQueue' );
//map the events
commandMap.mapEvent(SomeEvent.SOME_EVENT, RunNextFirstQueueCommand);
commandMap.mapEvent(AnotherEvent.ANOTHER_EVENT, RunNextFirstQueueCommand);
commandMap.mapEvent(SomeOtherEvent.SOME_OTHER_EVENT, RunNextSecondQueueCommand);
commandMap.mapEvent(YetAnotherEvent.YET_ANOTHER_EVENT, RunNextSecondQueueCommand);
//RunNextFirstQueueCommand
[Inject(name = 'firstQueue')] public var queue : IDeferredCommandQueue
override public function execute():void {
queue.executeNextCommand()
}
//RunNextSecondQueueCommand
[Inject(name = 'secondQueue')] public var queue : IDeferredCommandQueue
override public function execute():void {
queue.executeNextCommand()
}</code></pre>
<p>But I'm pretty sure this can be optimized as well, because having 2 classes with almost exactly the same code always smells...<br />
Maybe with some kind of factory pattern?</p></div>creynderstag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-08T07:29:18Z2010-10-08T07:29:18ZCommand Queuing - alternatives?<div><p>Hi Creyenders,</p>
<p>it's not a problem for me - and if it does become a problem then hopefully someone will fork it and add it :)</p>
<p>It's also more like one queue-per-context, so if you're running a multi-context app then you can have a single queue in each context, using it out of the box.</p>
<p>I did give some thought to whether multiple queues in a single context were something I should tackle, but at this stage I only need one, so I figured I'd just build what I needed, and then I might learn more along the path as I use it.</p>
<p>All you would need to do is replace the RunNextSecondQueueCommand with your own commands with named injections - as you've done below. (However, you've moved the execution into the queue, and for lots of reasons I prefer to keep it in the command).</p>
<p>If you don't like named injections then you could put your queues into a VO, and map that as a singleton.</p>
<p>I don't think that having duplicated (but slightly different) code in Commands or Mediators is necessarily a code smell. We repeat small blocks of code (adding listeners for example) all over our application.</p>
<p>I think in this case the transparency of the approach you outline (or one that uses a VO to wrap the queues) is a good tradeoff for a tiny amount of code duplication.</p>
<p>For every refactor there is an equal and opposite refactor :)</p>
<p>Still - fork it, add tests, fix it, push it, and multiple queues can be born...!</p>
<p>Stray</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-08T09:14:31Z2010-10-23T09:55:08ZCommand Queuing - alternatives?<div><p>Could you elaborate why you don't want to move the execution to the Queue? Do you want it to be framework independent, ...or?</p></div>creynderstag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-08T09:45:58Z2010-10-08T09:45:58ZCommand Queuing - alternatives?<div><p>I think it's just Single Responsibility Principle really.</p>
<p>By keeping the execution outside of the queue, the queue only changes if the definition of 'queuing behaviour' changes. If you execute in the queue, it would also be changed if the injector API changed, or the execution protocol changed.</p>
<p>So - that's my starting point.</p>
<p>But then I started to think about it and the separation of execution and queuing allows you to do a bunch of stuff just by switching out the command eg:</p>
<p>1) Add additional logic to an alternative to the command that checks whether something is ready before executing, and maybe skips that command, or pops it back in to the queue with the 'repeat' boolean set to true.</p>
<p>2) Use this queue to do dynamic mappings instead of executions.</p>
<p>and the really useful one:</p>
<p>3) Push payload from the Event that was injected into the RunNext command through to the Commands before they get executed. The commandMap maps the Event that triggered the RunNext command, injects it into the RunNext command, and then unmaps it again. So, if you wanted the payload of that event to reach the queued commands as well, you could either map the event (or the payload) again - do your instantiate - then unmap it, or you could set it manually just by setting the variable.<br />
</p>
<p>You could of course still pass payload by injection even if the queue instantiates the and executes the command... but then the queue needs to drag around the Injector. And the option to pass multiple parameters to a function on the command before it runs is killed off. And the Commands would need to be coupled to the Event when maybe you just want to pass them a couple of VOs.</p>
<p>So, you get more classes having to have knowledge of other classes, and the transparency of what is happening is reduced and the WTF load when it's not what you expect is increased.</p>
<p>So, you don't really have to think of all your use cases - the SRP gives you the nod that the execution shouldn't be bound to the queue - even before you think of the examples of why it would be better to separate queuing and execution.</p>
<p>But... nothing is ever set in stone. So - maybe there's a compelling reason why the queue should do the execution?</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/32446912010-10-08T11:59:24Z2010-10-23T09:55:10ZCommand Queuing - alternatives?<div><p>The compelling reason was: 'because it's easy' :)<br />
But thanks, again, for an excellent explanation.</p></div>creynders