Use of Services in loading assets
Hej. So I've looked through probably all the topics regarding loading, but still don't get one thing. If I need to load some assets (xmls, images, sounds, etc) — why would I need some Service? Today we all (I believe) use some loading libraries (Matan's AssetLoader, Jack's Greensock LoaderMax, Arthur's BulkLoader, etc...), so why not simply using instance of such loader inside Command to load stuff and populate model or just notify framework? Best practices and Stray keep saying user Services when dealing with outside world, but what's the use of making the Service (and how would it look like? some general wrapper that duplicates custom loader API?) in such cases?
The only way how to have benefit from using Service for me is when dealing with external something like Twitter API (where u could have multiple method for different actions), or saving some model into database (you could switch between local DB and remote service) and so on.. But simply loading assets?
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
Support Staff 1 Posted by creynders on Aug 07, 2011 @ 07:10 AM
I always create some kind of facade/adapter/proxy services for my loading libraries (or other external libraries), because then it's possible to switch libraries if necessary. If you reference those classes in your commands directly you'll be refactoring your commands if for whatever reason you have to swap them. Also, most of the times I prefer having a simple (application-specific) facade for complex/ugly API's of external libraries.
In general my commands never deal with concrete implementations, in other words they only reference interfaces, because it keeps everything loosely coupled which makes it easier to swap implementations if necessary. The only obvious exception to this rule are messaging classes: events/signals and VO's
2 Posted by pavel.fljot on Aug 07, 2011 @ 09:34 AM
@creynders
So if you need in ur app to load, for instance, several config files (XMLs), then at some point thumbnails (images), and then some other images — how much services would you create and theoretical API?
Support Staff 3 Posted by creynders on Aug 07, 2011 @ 12:00 PM
It depends on the complexity of the application, but either ...
I create one Service called LoaderMaxURILoaderService (for example, if I choose to use LoaderMax) and let it implement the various interfaces that will be called by the commands: IApplicationConfigRetrieverService, IMediaPlayerConfigRetrieverService, IMediaPlayerAssetRetrieverService, ...
I create a wrapper/facade class LoaderMaxFacade which implements ILoaderDelegate and then have ApplicationConfigLoaderService which implements IApplicationConfigRetrieverService and MediaPlayerConfigLoaderService which implements IMediaPlayerConfigRetrieverService, etc. All of them using the LoaderMaxFacade instance through separate marker interfaces that extend ILoaderDelegate.
BTW The reason why I use "retriever" instead of "loader" in my interface names is because (for instance) if I decide to embed my assets instead of loading them dynamically, there's very little I need to change, I just create service classes that pull the assets from whatever class they are embedded in and return in the same way as they would when loading them. It makes it extremely easy to swap between implementations that way. And then the "loader" part in the interface name would be misleading
The second option is the better one, but the first one gets you up and running very fast and is easily refactored to the second one if you choose to/must do so. So in general for small applications I use 1 and for larger ones 2.
In fact when using LoaderMax, many times I create a separate loader config xml, which is loaded first. It describes all files that need to be loaded in sequence or in background, however you need them. LM automatically loads all files as described in the loader config xml file but my service classes are unaware of this they request the asset from the LM facade class, which in turn checks whether the asset really has loaded and then fetches the asset from the LM instance(s)
Support Staff 4 Posted by creynders on Aug 07, 2011 @ 12:30 PM
Damn, I attached a diagram to a following post, but I think it has been dumped in spam...
Here's the gist: https://gist.github.com/1130345
This setup allows me the maximum of freedom.
1/ let's say I found out there's a horrible bug in LM and I want to swap it for another bulk loading library, all I need to do is create the corresponding facade class, let it implement ILoaderDelegate and instead of mapping IApplicationConfigRetrieverDelegate, IMediaPlayerConfigRetrieverDelegate to LoaderMaxFacade, I'd map them to the new facade class
2/ If I decide to embed the media player asset files, instead of loading them dynamically I create a MediaPlayerEmbeddedAssetsRetrieverService that implements IMediaPlayerAssetsRetrieverService and change the mapping of IMediaPlayerAssetsRetrieverService from MediaPlayerAssetsLoaderService to MediaPlayerEmbeddedAssetsRetrieverService
3/ If I decide to use a URLLoader instance for my loading my application config because I want to load the greensock library .swc file instead of embedding it, I can write a NativeApplicationConfigLoaderDelegate class which implements IApplicationConfigLoaderDelegate and again change the mapping of IApplicationConfigLoaderDelegate from LoaderMaxFacade to NativeApplicationConfigLoaderDelegate.
(obviously I'll have to add a separate service class for loading the greensock library .swc as well)
5 Posted by pavel.fljot on Aug 07, 2011 @ 07:23 PM
creynders,
Thank you for such detailed explanation of "your way"! I do see the benefits, but still can't get rid of the feeling that it's a huge boilerplate (I guess my projects are much less). And so how the "load" method look like? Do you pass array/vector of urls where to load from? How does your adapter understand which request need which loader? And how could loading/getting-from-embedded switching work out (API-wise)?
Support Staff 6 Posted by creynders on Aug 08, 2011 @ 07:24 AM
Boilerplate code? Not really, if you've got a good IDE, it's actually not a lot more work then option 1. Obviously if you need to create all files by hand it's a lot more work.
I reuse a lot of those helper classes and even services. In fact you can "copy" 90% of those files and just wire them the way you need them in your current application.
Usage varies. It could be I use some kind of URL map with ID's. Some files need to be loaded separately, others in batch. Also adapter usage varies. In case of LoaderMax for instance, as I wrote I have a separate config file which describes the files that need to be loaded and assigns them an ID. The interested actors request them by ID (or URL)
But you could just as well create a factory that creates the appropriate loader for your asset based on a separate
type
argument or on the asset file's extension.I'm not sure I understand your last question. API-wise nothing changes, since both services implement the same interface, the way of retrieving the asset is different that's all.
Support Staff 7 Posted by creynders on Aug 08, 2011 @ 07:33 AM
And obviously if you think this is taking decoupling a step too far, you can ditch the delegate classes all together and simply reference the adapter from the services directly.
Then it's just as option one, but the single service split into several.
Ondina D.F. closed this discussion on Nov 02, 2011 @ 06:01 PM.