A Simple Pattern for Configuration in Perl
In order to be flexible and provide more widely applicable functionality, code should be configurable, right? But ask perl programmers how best to pass configuration data to their programs and you'll likely get many different answers.
Here is an example of a very simple pattern that allows specification of configuration data at the level of:
- the command-line
- a configuration file
- built-in defaults
The priority is CLI > file > built-in.
I originally wrote this for handling config for connecting to a database, which explains the example. Obviously, this pattern is not only pertinent for database config data.
There are various reasons why I have chosen to write it this way; I'm sure there are also various reasons why this is _not_ a good solution for certain needs.
One aspect that I like is that I can be granular about the configuration data; in the config file, I can separate by stanza heading, '[database]', and since each stanza hash is separate, I can give different parts of the config to different parts of my code. Minor, but it helps my keep things cleaner and simpler in my mind.
I'm using 2 non-core perl modules, both of which are likely available in your distribution's software repositories: Config::Tiny and Hash::Merge. Use your distro's package repositories unless you have a good reason not to; and even then consider packaging into a local repository.
#!/usr/bin/env perl use strict; use warnings; use Config::Tiny; use Getopt::Long; use Hash::Merge qw( merge ); my %dbconfig_defaults = ( dbtype => 'Pg', # This should be the name of the DBD; probably one of :'Pg','MySQL','SQLite' dbhost => 'localhost', # Encourage a unix domain socket connection dbname => 'example_db', dbuser => 'example_user', dbpass => 'GuessMeEasily', ); my $config = Config::Tiny->new; $config = Config::Tiny->read( '/etc/myconfig.conf'); my(%dbconfig_cli,$otherconfig_cli); GetOptions( "dbtype=s" => $dbconfig_cli{'dbtype'}, "dbhost=s" => $dbconfig_cli{'dbhost'}, "dbname=s" => $dbconfig_cli{'dbname'}, "dbuser=s" => $dbconfig_cli{'dbuser'}, "dbpass=s" => $dbconfig_cli{'dbpass'}, "dbport=i" => $dbconfig_cli{'dbport'}, "help|h" => $otherconfig_cli{'help'}, "verbose|v" => $otherconfig_cli{'verbose'}, ); my %db_config = %{ merge(\%dbconfig_cli, $config->{'database'}) }; %db_config = %{ merge(\%dbconfig,\%dbconfig_defaults) };
I can list all the configuration items that are in the file's stanza called 'section' with:
keys(%{$config->{'section'}})
For reference, here is a configuration file which replicates the behaviour of the built-in defaults:
[database] dbtype=Pg dbhost=localhost dbport=5432 dbuser=example_user dbpass=GuessMeEasily dbname=example_db