Update: There is a version 2 of this that I consider better, but you should read this before reading version 2

Intro

When programming in OO Perl I prefer to keep everything, including configuration options, accessible via a method rather than directly accessing the objects data structure. The sometimes tedious part is adding all the methods as the configuration file grows. I don't want to hard code my accessor methods and I certainly don't want to modify my API modules everytime a new configuration option is added. What follows is a method for keeping both the API developer and the application developer happy and providing flexibility without complete loss of control. This was in part was started after I saw that many of the WWW::Search::X modules were directly accessing the object data structure and felt that level of access was "dirty."

A Good API

The purpose of an API is to provide building blocks for application developers. API modules once deployed are expanded, but the base functionality has to remain. These modules remain in use for a long time hopefully lasting for months or years without major revision once deployed. So how can we achieve this goal and keep an OO interface while expanding configuration options at the developer level and keeping the developer from creating their own accessors?

The Concept

We start off with the Class::Accessor module. Class::Accessor creates accessor methods within your class by passing a list of the method names you want generated into its mk_accessors method.

If you combine the Class::Accessor module with a configuration module such as Config::Auto you get a combination that makes it easier to add options to your applications as well as maintain and extend. It also puts some power (with limited danger) back into the hands of the developer. Any Config::* module could be used I use Config::Auto because it has the ability to use different formats of configration files with modifying our core module. Using plain text configuration files make it easier for installers to adjust the application to their needs and allows for reuse of the same configuration values between languages if needed. This all makes our applications decoupled because they rely on less and less language specific values.

Creating Our "Base" Class

We are going to create an initial module named Base.pm for this OO project. We use Class::Accessor within the Base module and from an application level the usage of OurApp::Base class is hidden. The Base module is for the API or object creator not the person writing applications based on it.
We decide on our module name first, the one we want people to use.
Lets call it OurApp
So inside of OurApp.pm we do:

Now if we run this the configuration file keys will be come accessor methods with the values as assigned in the conf file, but we can also set them to new values using the accessor method.

This gets rid of a lot of typing and makes it easy to add new options to the application without hard coding and without rewriting the Base class.

Now say you want to set up a phone_number method, you simply add:
phone_number=555 1212
to your configuration file. The method is automatically added to your application the next time it runs.

This is also helpful for when you know the parameters are going to change on something or you decide in the future to move something into the business logic. Your config key equals your method name so you can look up the names of methods in that file. It is also useful to set values between the development and production server.

Further Exercises/Thoughts

Add values to the configuration and you see there is no need to modify the API level modules, this allows you make your application more decoupled because you can add variable elements at the configuration/development level and developers can create new client/need defined methods so the application keeps an OO interface as much as possible.

This technique can be extended to allow for separate configuration files that can override the master configuration, that is at the end user level they may have their own configuration files that can be loaded to override the master configurations file default. If needed the _make_accessors method could be overridden in OurApp.pm to assign values based on system default or user preferences.

This technique has helped me greatly when running a code set in a development environment and then moving it to a production server.

There should be more flexibility built into the new method that allows for passing data structures that can be used for the configuration, such as a hash ref for method and defaults values as well as array or array ref to provide empty method creation. Another nice feature is to have a default/fallback configuration file specified in the _make_accessors method. Ultimately it would be nice to allow a database based configuration option that doesn't require the application developer to create all the DBI code.

Caveats

There are some hidden and not so hidden dangers to this technique. One danger is repeating a configuration variable (key) names or colliding with built in real methods, but naming conventions and guidelines can help avoid that. The technique I have adopted is to name the configuration variables conf___, which will likely not occur directly in the API at any point. Another hidden danger is that there is no way to document the accessors efficiently since they are often added by the developer and never moved into the core, but then that is reasonable to some extent since the API has served it's purpose. The end developer has the responsibility to adequately document their specific needs.

There is most likely a cost in terms of speed at some level, but that cost would vary depending on several factors:

I see a few strange things, but it could be because I don't completely understand what kind of objects these are supposed to be. Are they just an OOP wrapper API to these config files, or do they have other purposes? It seems like you're trying to have accessors defined on a per-object basis (you (re)generate the accessors every time the new method is called). But you create these accessors on a per-class basis, and all of your objects are of the same class. Do you only ever instantiate one of these OurApp objects per execution of your app?

Wouldn't you want $obj1->bar and $obj2->foo to give an error like Can't locate object method "bar" via package "OurApp"? It won't happen if the OurApp namespace has been given both methods. Of course, if you don't plan on having multiple OurApp objects around this isn't a problem.