do I need command chaining?
Hi there,
just getting started with RobotLegs over the last few days. I'm repeatedly gobsmacked when I come across a totally awesome solution of RobotLegs to a problem I've tackled in the paste without MVCS.
Afraid I'm struggling up the learning curve though! Steeeeeeep! I've a few Qs, hope that's ok:
-I load default settings for my app from an XML file via a LoadXMLService, driven my 'LoadDefaultSettingsCommand'. When the given XML file does not exist, my LoadDefaultSettingsCommand is told this and responds by running my 'CreateDefaultSettingsXMLService'. My issue is that it seems a waste of memory to load up the CreateDefaultSettingsXMLService as a singleton in my Context file before hand given and pass it to my Command via [Inject], given that it will only be used once in a while. Should I just create an instance of this service in my CreateDefaultSettingsXMLService and then destroy it after I have used it? Googling, it seems that command chaining is used in this scenerio but afraid I am not sure.
-it also seems a waste to keep code related to loading default settings in memory after the settings have been loaded. Is there a way to kill Services and commands once they are done with?
Thanks!
Andy.
Cheers,
Andy.
-
Comments are currently closed for this discussion. You can start a new one.
Support Staff 2 Posted by Ondina D.F. on 29 Jun, 2012 01:15 PM
Hi Andy,
Of course you can create an instance of CreateDefaultSettingsXMLService where you need it and destroy it when you don’t need it anymore.
But, you can also do something like this:
-Context mappings:
injector.map(ISomeService).toSingleton(SomeService);
commandMap.mapEvent(SomeEvent.LOAD_SOMETHING, SomeCommand, SomeEvent);
-In SomeCommand :
[Inject] public var someService: ISomeService;
then access someService.loadSomething()
After SomeService has finished its job, it dispatches an event triggering an
-UnmapSomeServiceCommand, which will do:
injector.unmap(ISomeService); // ==> SomeService gets gc-ed
And, if you want, you can unmap the commands as well:
commandMap.unmapEvent(SomeEvent.LOAD_SOMETHING, SomeCommand, SomeEvent);
But, as you probably already know, commands won’t be kept in memory after their execute() has run.
HTH
Ondina
3 Posted by andytwoods on 29 Jun, 2012 02:30 PM
Thanks! Super quick reply too :)
I ended up with something similar to what you suggest.
In my Context:
injector.mapSingleton(SaveDefaultsService);
and
commandMap.mapEvent(DefaultsEvent.CREATE_DEFAULTS, CreateFreshDefaultsCommand,DefaultsEvent);
I am guessing that it's overkill to use a command in my above code when a service can just call another service. Guessing to it is better practice not to make my singleton 'accessible to all' and just accessible to what needs it. I'll update to your code :)
Slowly things are becoming more understandable to me. Cheers!
Support Staff 4 Posted by Ondina D.F. on 29 Jun, 2012 02:57 PM
No problem, Andy:)
Maybe my first statement was a bit misleading.
I should have warned you that creating an instance of CreateDefaultSettingsXMLService in another service may be problematic.
How will you know when to destroy it, in case of an asynchronous response, and where are you intending to destroy it? Or are both services disposable after running them?
Besides, it’s not quite “nice” to call a service from another service, if you want to strictly follow the best practices ;)
But, if you really need to do it like that, just do it. You can decide later whether it’s a good approach or not.
5 Posted by andytwoods on 02 Jul, 2012 05:47 AM
Hi there,
afraid it's me again :)
Digesting this part of your first message:
"-Context mappings: injector.map(ISomeService).toSingleton(SomeService);
commandMap.mapEvent(SomeEvent.LOAD_SOMETHING, SomeCommand, SomeEvent);
-In SomeCommand : [Inject] public var someService: ISomeService; then access someService.loadSomething()"
You've probably guessed it but I've a Q or 2!:
-does RobotLegs only instantiate a service when it is called? Most likely this is a stupid question :-) -regarding "injector.map(ISomeService).toSingleton(SomeService);" Why use ISomeService and not just injector.mapSingleton(SomeService)? Is there a memory benefit of not referring to the 'full fat' class and referring to it's interface?
Thanks!
6 Posted by andytwoods on 02 Jul, 2012 06:08 AM
Hi,
another quick Q:
" injector.map(ISomeService).toSingleton(SomeService);" guessing this is robotlegs 2? map method not available to me (robotlegs 1). cheers,
Andy.
7 Posted by andytwoods on 02 Jul, 2012 06:58 AM
OMG This is so amazingly incredibly awesome:
[PostConstruct]
For anyone reading this and wondering, calls any function after everything has been loaded.
https://github.com/robotlegs/robotlegs-framework/wiki/Robotlegs-Int...
Support Staff 8 Posted by Ondina D.F. on 02 Jul, 2012 02:10 PM
Hey Andy,
Right, this is rl 2 syntax. My bad, I was working on an rl2 project by the time I answered your question, and the more intuitive syntax used in rl2 was still fresh in my mind.
For rl1 the mapping would look like this:
injector.mapSingletonOf(ISomeService, SomeService);
Regarding the question about interfaces:
It’s impossible for me to cover all the benefits of “Programming to an interface, not an implementation“ in this post. The topic is too complex, and besides there are a multitude of in-depth articles and books on the subject, written by experts. So I’ll just mention a few things (rather keywords that can be used for further research) that come to mind:
using interfaces enables code reuse, which can minimize duplicate and repetitive code, the code becomes flexible, managing dependencies is easier, your application is easily maintainable
using interfaces makes it possible to follow the SOLID principle of OOP and OOD
interfaces are used in several design patterns
interfaces as APIs
interfaces keep the coupling minimal
encapsulating the implementation is a good thing
you can be sure that a certain functionality will work in a standardized way
type safety
you get compiler errors when the class that implements an interface does not implement all the methods declared in the interface, and that’s good when building an application that will be extended by another developer or used by third parties
it is easier to test classes in isolation and to use mock objects when real objects are not available
generalization is a good thing, in OOP ;)
polymorphic capabilities
allows the use of interchangeable behaviors, variation of implementation
using an interface allows a service to be swapped for another one that implements the same interface, i.e., if IAssetsLoader is implemented by SQLAssetsLoader , XmlAssetsLoader, MockAssetsLoader , all you have to do is replace
injector.mapSingletonOf(IAssetsLoader, SQLAssetsLoader);
with
injector.mapSingletonOf(IAssetsLoader, XmlAssetsLoader);
or
injector.mapSingletonOf(IAssetsLoader, MockAssetsLoader);// a dummy class used to mimic services’ behavior – used in unit testing
This way your Application doesn’t have to care where the data comes from.
Sorry, if you already know all of this, or if the random listing was confusing! :)
9 Posted by andytwoods on 02 Jul, 2012 03:18 PM
thanks for all your help! I'm still very much a newbie at this sort of thing :-)
Support Staff 10 Posted by Ondina D.F. on 02 Jul, 2012 04:46 PM
You’re welcome, Andy!
And don’t worry, compared to the design patterns gods and geniuses out there (GoF, Fowler and many others) we, ordinary (mortals) coders, will be Noobs Forever;) No matter how advanced we get, they’ll be always ahead of us, unless the best practices and design patterns change over time…
Besides, being a perpetual newbie in a programming/platform field or another is our fate as developers, am I right?
You can close the discussion, in case your original problem has been solved. Please open new threads for new issues.
Thank you :)
Ondina D.F. closed this discussion on 05 Jul, 2012 10:08 AM.