spurperl has asked for the wisdom of the Perl Monks concerning the following question:

Hello fellow monks,

I have a general OO design meditation...

In my application I have a very important configuration file that defines how the application acts in many ways. The application code is subdivided to many objects that don't interact much, but in most cases are there to encapsulate pieces of functionality. These objects are instantiated from the main flow and do their work.

Now, many of the objects need access to configuration data to do their work - sometimes it's quite a few configuration items for each object. The configuration data is encapsulated in an objects itself - the object reads the configuration data and provides access to it in an easy hash-like fashion.

I am wondering what is the best approach, design wise, to pass the configuration data into these objects. There are a few options:

  1. Pass only the relevant configuration items into each object. Pro: objects don't have to know about the configuration object. Cons: sometimes many items need to be passed into objects and it becomes very cumbersome.
  2. Pass a reference to the configuration object into each object that needs it. Pro: just one reference, and each object knows which items it needs to access. Cons: still feels a little cumbersome to pass the same objects into different objects.
  3. Keep a global singleton configuration object and access it directly from all objects. Pro: most minimal code-wise, no need to pass the object around. Cons: global data, hard to control access.

Now, all this becomes even more complicated when there are more than one configuration files, each with a distinct set of data that is not combinable, and some objects need access to different configuration objects.

Please share your thoughts - I'm sure it's quite a common issue. Is there a "pattern" for it ?

Thanks in advance

Replies are listed 'Best First'.
Re: OO Design question: configuration
by rhesa (Vicar) on May 19, 2007 at 16:36 UTC
    Some other options:
    1. Mixin/Role/Trait. Gives every object that needs it a config method.
    2. Config factory. This is a singleton itself, but it can hand out configuration objects to whoever requests it.

    The mixin is conceptually very simple:

    package My::ConfigMixin; use base qw/ Exporter /; our @EXPORT = qw/ config /; sub config { my $self = shift; somehow_get_config(@_); }
    Which, when used (a simple use My::ConfigMixin; will do), gives your object the method config. Since its first param is your requesting object, you can do all sorts of filtering based on $self (access control, limiting output, etc).

    The main issue here is maintaining state. Pretty much your only option is to use package variables in My::ConfigMixin, which can get messy. I'd be interested to learn more about Traits that need state, but sofar I'm a newbie on the subject.

    The factory might be a better alternative: it can maintain state on its singleton instance.

Re: OO Design question: configuration
by stvn (Monsignor) on May 19, 2007 at 22:36 UTC

    Take a look at IOC it is meant to solve just this kind of problem. We use it at $work for all our larger projects.

    What it basically will do for you is to handle the creation and configuration of all your objects while transparently managing the interdependencies (even circular dependencies as well). You then fetch the objects you need from the IOC::Registry singleton, and they Just Work.

      Huge thanks for pointing me to this. I have never heard of IOC (now it's more popularly called DI - Dependency Injection) before, but it sounds just like the thing I had in mind.
        now it's more popularly called DI - Dependency Injection

        Yeah, I had it called that originally, the it grew into a larger "Inversion of Control" framework with the Proxy objects and such. However, once I started actually using it in practice, I found I had little need for the proxies, but by then it was too late to change the name.

        Plus, IOC was better as a namespace name, whereas DI is just kinda ugly :)

Re: OO Design question: configuration (Encapsulate the knowledge about an object within the object itself)
by mr_mischief (Monsignor) on May 20, 2007 at 07:02 UTC
    I'm far from an authority on OO, but my first instinct would be to encapsulate the knowledge about what each object needs as far as configuration within the object itself.

    Having one object that grabs all the configuration and holds it is a great idea, especially when the storage on disk or eslewhere might change. Having the configuration object know a lot about the insides of the other objects I think violates the encapsulation for which you chose OO in the first place. It's probably best for the configuration object to get and hold the configuration, then make a flexible interface for each other object ask it for what they each need.

    I'd pass a reference to the config object into all the other objects. I know that's a pain, but it's what I'd do out of the alternatives. I'd make sure the configuration object had a nice way to get the values out, either as a hash or as individual key/value pairs. Something like:
    my %conf_val = %{ $conf->values( 'conf_section' ) };
    my $val1 = $conf->value( 'conf_section', 'conf_item' );
    The configuration object then doesn't need to know which objects need which configuration items, let alone how they need them. It just needs to be able to provide what is asked of it, and to do it in a predictable way. The other objects don't need to know how the config object gets or stores the values, or even whether it's eagerly or lazily. This is, as I understand it, one of the biggest advantages to using OO.

    Of course, it's not likely you'd need two or more configurations in a single running program. In this particular situation, a globally accessible object that returns the values it is asked to return may be a good compromise. It'd surely be ahead of making the configuration object aware of each of the other objects on my list. In fact, making the configuration object's behavior depend on the calling object wouldn't even be on my list.

    Christopher E. Stith
Re: OO Design question: configuration
by wjw (Priest) on May 19, 2007 at 16:33 UTC
    Being a long time procedural programmer just breaking into the OO approach to things, I echo spurperl's design query. The question is stated very clearly.

    I have played around with the idea of using inheritance of the config object by the methods objects, but as mentioned, what happens when there is more than one config object? I would think that the method objects need be told which config object they are operating with, which leads me to think that one might just as well hand in a reference to the conifg object to each method object.

    Conversely, perhaps the config object should inherit from all of the method objects?

    The Advanced Perl Programming book talks about this in a couple of chapters. However, it leaves me with my head spinning. Is there a good OO Design book that is Perl centric? One that has a number of examples? I confess that I have not had time yet to do an exhaustive search for such a guide. The tutorials that are pointed to here are very helpfull, but a Perl centric (or better yet, exclusive) OO design book would be very nice to have on my shelf.

    I look forward to the responses to the original posts. Good luck spurperl

    • ...the majority is always wrong, and always the last to know about it...
    • The Spice must flow...
    • my will, and by will alone.. I set my mind in motion
      Is there a good OO Design book that is Perl centric? One that has a number of examples?
      No one ever told you about Object Oriented Perl by Damian Conway? I wonder no one in this thread did so.

      Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

        Thanks for the pointer naikonta... :-)
        • ...the majority is always wrong, and always the last to know about it...
        • The Spice must flow...
        • my will, and by will alone.. I set my mind in motion
      It's good to know that I am not the only one to have run into this problem. However, I want to emphasize that this is a generic OO, non Perl-centric question. It is certainly applicable to all languages.
        I understand your point spurperl. I just happen to program in Perl exclusively which is why I sort of tacked that Perl centric part on. I also have no CS training in my background, which makes me a slow learner. :-) Thanks for the original question.
        • ...the majority is always wrong, and always the last to know about it...
        • The Spice must flow...
        • my will, and by will alone.. I set my mind in motion
Re: OO Design question: configuration
by valdez (Monsignor) on May 21, 2007 at 08:40 UTC

    I think that Class::Singleton is a smart solution for your problem.

    Ciao, Valerio