Accessing stored settings in model through out application - best practice

stephenadams1's Avatar

stephenadams1

13 Jul, 2010 11:35 AM

Hi,

I've built an application which at startup loads settings from a xml file, these settings are stored in a value object in my model. When I need to access these settings, I've been injecting the model class, then calling the value out of the value object.

Now I'm wondering if that is the best way to use the model, or is there a better way to do this?

Cheers

Stephen

  1. Support Staff 1 Posted by Shaun Smith on 13 Jul, 2010 01:26 PM

    Shaun Smith's Avatar

    Sounds good to me, though it depends what kind of stuff you're loading from that file - lumping it all into a VO and wrapping it in a single Model (perhaps with a name like SettingsModel) might not be the best approach. Are the values you are loading all related? Do they really belong together?

  2. 2 Posted by stephenadams1 on 13 Jul, 2010 02:26 PM

    stephenadams1's Avatar

    Well these settings are related, they define how where to load data from and how often to reload this data, and when to change a view. So they seem related to me.

    If they are not related would you suggest creating separate models for the different types of settings being stored?

    Would the idea of storing them in a VO in the model and accessing these settings via injection of the model still be a good idea?

    Stephen

  3. Support Staff 3 Posted by Shaun Smith on 13 Jul, 2010 03:57 PM

    Shaun Smith's Avatar

    What I'm suggesting is that the concept of a Settings Model (or a bunch of separate Settings-type Models) is not usually a good one. It sounds like those values don't represent application state, but rather simple settings that will not be altered once the app is running. Perhaps after loading and parsing the settings you could simply pass the values through to relevant application actors as a part of your setup process. For example setting a URL property on a Service. It really depends on the app though.

    To answer your original question though: wrapping a VO in a Model, mapping that Model as a singleton, and injecting that Model into other parts of your system is often a valid usage pattern.

  4. 4 Posted by stephenadams1 on 14 Jul, 2010 09:20 AM

    stephenadams1's Avatar

    Thanks Shaun for both your answer and RobotLegs.

  5. Support Staff 5 Posted by Shaun Smith on 14 Jul, 2010 01:35 PM

    Shaun Smith's Avatar

    My pleasure, hope at least one of them has been helpful.

  6. 6 Posted by Thomas Troelsen on 01 Aug, 2010 08:28 AM

    Thomas Troelsen's Avatar

    I have an additional question related to this discussion:

    I have created a RemoteAct (actor that works as a proxy for my remote services) and a SettingsAct (actor that parses an XML documents and store all settings in a VO).

    When i initialize the RemoteAct I want to acces the SettingsAct in the RemoteAct's constructor to fect eg. the URL of the service. So I inject the SettingsAct in the RemoteAct through an interface:

    public class RemoteAct extends Actor
    {
        [Inject]
        public var settings:ISettings;
    
        private var _endpoint       :String;
        private var _destination            :String;
        private var _source         :String;
    
        /** constructor */
        public function RemoteAct()
                {
            _endpoint       = settings.getSetting("zend_endpoint");
            _destination            = settings.getSetting("zend_destination");
            _source         = settings.getSetting("zend_gateway");
            trace(settings);
                }
    
               (further details omitted)
    }

    The SettingsAct is mapped to ISettings correctly in my MainContext class. I can inject and access the settings (ISettings) in my Mediators, but when I run the above example and initialize my RemoteAct, an exception is thrown.

    The trace(settings) results in null.

    It seems to me the SettingsAct has not yet been initialize when I try to inject it, eventhough I inject it into my startup command before i inject the RemoteAct:

    public class StartupCmd extends Command
    {
        [Inject]
        public var settings:ISettings;
    
        [Inject]
        public var remote:RemoteAct;
    
               (further details omitted)
    }

    1) Is this bad practice to access an application's settings as in the above example?

    2) Why can't I inject and access the ISettings in my RemoteAct actor class, and what should I do instead?

    Thanks!

  7. Support Staff 7 Posted by Shaun Smith on 01 Aug, 2010 11:22 AM

    Shaun Smith's Avatar

    Dependencies injected via setter/property injection are not available until after the instance has been created - it's pretty easy to visualize, just imagine doing it by hand: first you create the new instance and then you set the properties.

    PostConstruct Solution

    The most common solution to this problem is to remove the code from your constructor and place it into a public method with [PostConstruct] metadata placed above it, like so:

    [PostConstruct]
    public function init():void
    {
        // all dependencies have now been satisfied
    }
    

    Constructor Injection Solution

    Instead of using property/setter injection you can use constructor injection, simply define your dependencies as constructor arguments.

    A word of warning about constructor injection: Due to a bug in the Flash Player (pre 10.1), full type information for constructor arguments is only available after the affected class has been instantiated at least once. To work around this bug, SwiftSuspenders (the default DI/IoC framework that Robotlegs uses) checks if type information for the arguments is available when performing constructor injection. If not, SwiftSuspenders will create one throw-away instance of the class. Because of this behavior, it is important not to start any complex processes in constructors of classes that are used with constructor injection.

  8. 8 Posted by Thomas Troelsen on 01 Aug, 2010 10:15 PM

    Thomas Troelsen's Avatar

    Thanks a lot Shaun for both the quick answer and the in-depth explanation - it works perfectly. All theese answers you and your team provide are really great lessons in system architechture and best practices.

    Just a quicik note to my question 1) in the above post. Is it bad practice to inject the ISettings into the RemoteAct class as in my example?

    I make a tight coupling by requiring an ISettings implementation before I can use my remote service, but on the other hand: I would never want to hardcode eg. the server url into the service class, so I thought it was a reasonably solution?

    Keep up the good work! Bye bye PureMVC ;-)

  9. Support Staff 9 Posted by Shaun Smith on 02 Aug, 2010 12:38 PM

    Shaun Smith's Avatar

    Theoretically, yes, it could be considered bad practice: settings, when you think about it, are just dependencies and the whole point of automated dependency injection is that you can flatten out these dependencies so that you don't have to "reach through" other objects to get what you need.

    Another approach would be to simply set these values up as named dependencies and then inject them directly into your RemoteAct (which would more accurately be called a Service). Something like this:

    // In startup, or in a configuration Command:
    injector.mapValue(String, "your_zend_endpoint_value", "ZendEndpoint");
    
    // In your Service:
    [Inject(name="ZendEndpoint")]
    public var endpoint:String;
    

    In general, God-Objects (usually with names like "Manager", "Config" or "Settings") create a lot of coupling in your system and should be avoided.

  10. 10 Posted by Thomas Troelse... on 02 Aug, 2010 03:38 PM

     Thomas Troelsen's Avatar

    Thanks! I will take a closer look at my God-Like-Objects - I have a few thoose in my current application ;-)

  11. 11 Posted by Mark Barton on 09 Aug, 2010 03:08 PM

    Mark Barton's Avatar

    Shaun,

    As a newbie to Robotlegs I have been following all of the tutorials and examples which have been great but I wondered if you knew of an example which utilises a best practice way of dealing with these config settings? Particularly Service endpoints.

    Are you suggesting from your example above that the service endpoint is held in the context file - rather than read in from an external XML file?

  12. Support Staff 12 Posted by Shaun Smith on 09 Aug, 2010 04:15 PM

    Shaun Smith's Avatar

    Hi Mark,

    I don't know of any "best practice" demos that load config settings at runtime unfortunately. Loading from an external XML file would probably be the best way to go for something like service end points - in my example above I was just showing the minimum steps to accomplish that.. the mapValue call could very easily be supplied values from an XML file.

  13. 13 Posted by Mark Barton on 09 Aug, 2010 05:39 PM

    Mark Barton's Avatar

    Thanks for the update Shaun - I will need to lookup how to use that mapValue call a bit more.

    I too was going down the Model / VO God Object which held all of my configuration items.

  14. 14 Posted by Nikos on 20 Aug, 2010 01:28 PM

    Nikos 's Avatar

    I'm with Shaun. Loading the injecter seems like the best way to do it as you can do all this stuff in your context.

    // In startup, or in a configuration Command: injector.mapValue(String, "your_zend_endpoint_value", "ZendEndpoint");

    // In your Service: [Inject(name="ZendEndpoint")] public var endpoint:String;

    In general, God-Objects (usually with names like "Manager", "Config" or "Settings") create a lot of coupling in your system and should be avoided.

  15. 15 Posted by Nikos on 20 Aug, 2010 01:30 PM

    Nikos 's Avatar

    @stephenadams1 I'd be interested to see an example of your settings XML

    also any other exaples would be good, especially if your using zend ;)

  16. 16 Posted by Nikos on 20 Aug, 2010 02:02 PM

    Nikos 's Avatar
    • you should be able to get your endpoints loaded into the context for immediate mapping if you instantiate the context later in as3. Its just a one off to load the xml and then dump that into the context for set up. I dont think you can do it all at once in the contex.
  17. stephenadams1 closed this discussion on 26 Aug, 2010 01:16 PM.

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