C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Design idiom for application configuration

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Peter Jones
Guest





PostPosted: Thu Jan 15, 2004 10:36 am    Post subject: Design idiom for application configuration Reply with quote



Does anyone have a good design idiom for application configuration
information?

Most of the systems that I have worked on have a "config" class. The config
class will pull configuration information from some source, for example, an
XML file. The other classes in the system that need this configuration
information take a reference to a config object in their constructor.

This of course means that a lot of the system has a dependency on the config
class. What I think is worse is that you can't unit test some of the classes
without having to create a config class and pass it to the class that is
to be unit tested.

The singleton pattern seems to be a good match for this config object. But
there is still the dependency problem, where most of the system depends on
the config class. There may not be a way around that though.

I am just curious how other people are implementing a system that has a
large number of configuration variables used throughout the system.

--
Peter Jones [http://pmade.org/]
Warning: [email]cxx (AT) pmade (DOT) org[/email] is a spam trap.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Ivan Vecerina
Guest





PostPosted: Thu Jan 15, 2004 3:22 pm    Post subject: Re: Design idiom for application configuration Reply with quote



"Peter Jones" <cxx (AT) pmade (DOT) org> wrote

Quote:
Does anyone have a good design idiom for application configuration
information?

Most of the systems that I have worked on have a "config" class. The
config
class will pull configuration information from some source, for example,
an
XML file. The other classes in the system that need this configuration
information take a reference to a config object in their constructor.

This of course means that a lot of the system has a dependency on the
config
class. What I think is worse is that you can't unit test some of the
classes
without having to create a config class and pass it to the class that is
to be unit tested.

The singleton pattern seems to be a good match for this config object. But
there is still the dependency problem, where most of the system depends on
the config class. There may not be a way around that though.

I am just curious how other people are implementing a system that has a
large number of configuration variables used throughout the system.

Don't create a class for the global configuration object -- keep it as
a text-based hierarchical structure, such as an XML document loaded in
memory.
Let each module of your application access and decode its own config
entries,
located in a sub-path of the root document.
Try to have working defaults if an entry is missing in the document -
consider
even generating the default entries automatically and updating the
config file automatically (by inserting values for future customization).

By the way:
http://xmlsucks.org/but_you_have_to_use_it_anyway/does-xml-suck.html


Regards,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ross Smith
Guest





PostPosted: Fri Jan 16, 2004 2:58 am    Post subject: Re: Design idiom for application configuration Reply with quote



Peter Jones wrote:
Quote:

The singleton pattern seems to be a good match for this config object.
But there is still the dependency problem, where most of the system
depends on the config class. There may not be a way around that
though.

Don't hard-code the configuration variables into the config class;
instead, have them retrieved at run time, identified by name.

So instead of something like this:

class Config {
private:
int width_;
int height_;
string title_;
public:
int width() const { return width_; }
int height() const { return height_; }
string title() const { return title_; }
};
...
create_gui(conf.width(), conf.height(), conf.title());

Do it like this instead:

class Config {
private:
typedef map<string, string> StrMap;
StrMap data_;
public:
template <typename T> T get(string key) const {
StrMap::const_iterator i(data_.find(key));
if (i == data_.end())
throw invalid_argument("Unknown config key");
// ... or return a default value
return boost::lexical_cast<T>(i->second);
}
};
...
create_gui(conf.get<int>("width"), conf.get<int>("height"),
conf.get<string>("title"));

--
Ross Smith ......... [email]r-smith (AT) ihug (DOT) co.nz[/email] ......... Auckland, New Zealand

"This world is like a burnt steak: small, tough, and the chips
are always stacked against you." -- Mike

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Roland Pibinger
Guest





PostPosted: Fri Jan 16, 2004 1:06 pm    Post subject: Re: Design idiom for application configuration Reply with quote

On 15 Jan 2004 05:36:38 -0500, Peter Jones <cxx (AT) pmade (DOT) org> wrote:

Quote:
Does anyone have a good design idiom for application configuration
information?

Most of the systems that I have worked on have a "config" class. The config
class will pull configuration information from some source, for example, an
XML file. The other classes in the system that need this configuration
information take a reference to a config object in their constructor.

This of course means that a lot of the system has a dependency on the config
class. What I think is worse is that you can't unit test some of the classes
without having to create a config class and pass it to the class that is
to be unit tested.

Why is this a bad solution? Classes need some information and you pass
it to them via constructor. Users can configure the the classes
differently (e.g. for test cases) without problems.

Quote:
The singleton pattern seems to be a good match for this config object. But
there is still the dependency problem, where most of the system depends on
the config class. There may not be a way around that though.

Singletons are just global objects with all the disadvantages of
global objects. They severely reduce the (re-)usability of your code
in other programs. Java programmers who use Properties or Preferences
(= config singletons) throughout their programs run into problems.

Best regards,
Roland Pibinger

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Frank Birbacher
Guest





PostPosted: Fri Jan 16, 2004 1:09 pm    Post subject: Re: Design idiom for application configuration Reply with quote

Hi!

Peter Jones wrote:
Quote:
The singleton pattern seems to be a good match for this config object.

That's what I do: use a singleton. This way you do not need to pass
around the reference to the config class.

Quote:
But
there is still the dependency problem, where most of the system depends on
the config class. There may not be a way around that though.

If the system is to be configured, then it depends on the configuration.
There is nothing you could do about this. However the config class
should not depend on the rest of the system. The config class should be
standalone. E.g. don't let the config class be a class Factory at the
same time.

Frank


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Richter
Guest





PostPosted: Fri Jan 16, 2004 1:19 pm    Post subject: Re: Design idiom for application configuration Reply with quote

Hi,

Quote:
Does anyone have a good design idiom for application configuration
information?

Most of the systems that I have worked on have a "config" class. The config
class will pull configuration information from some source, for example, an
XML file. The other classes in the system that need this configuration
information take a reference to a config object in their constructor.

This of course means that a lot of the system has a dependency on the config
class. What I think is worse is that you can't unit test some of the classes
without having to create a config class and pass it to the class that is
to be unit tested.

The idea of having a config class is fine as it is, but then, I would
not hard-code the available configuration entries into the config
class, but would rather let the classes to be configured tell the
config class which configuration item they need. Second, I would not
pass the config class in the constructor. It is sometimes useful to allow
the user to re-configure the system at run time, in which case the
configuration must be re-parsed from alife objects. Therefore, I would
suggest the following:

i) Build a configuration base class ("ConfigParser") that provides
functions like:

long ParseIntegerArgument(const char *configname,long min,long max);
bool ParseBooleanArgument(const char *configname);

and so on.

ii) Implement this class by a specific parser that takes "argc,argv" pointers
from main() and extracts the information from there. Also built a class
that takes a configuration file handle and extracts the information from
there.

iii) Define an abstract interface class "Configurable" that provides
functions to get or set configuration options from the configuration
class, e.g.:

class Configurable {
...
void ParseArgs(ConfigParser &configsource);
void WriteArgs(ConfigParser &configdest);
};

iv) Derive all configurable objects from "Configurable" and implement
the configuration parser there, e.g.:

class MyClass : public Configurable {
...
long option1;
...
void ParseArgs(ConfigParser &configsource);
...
};

void MyClass::ParseArgs(ConfigParser &configsource)
{
option1 = configsource.ParseLong("MyOption",1,10); // integer in range 1..10
...
}

So long,
Thomas


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Roland Pibinger
Guest





PostPosted: Sat Jan 17, 2004 10:57 am    Post subject: Re: Design idiom for application configuration Reply with quote

On 15 Jan 2004 21:58:37 -0500, Ross Smith <r-smith (AT) ihug (DOT) co.nz> wrote:

Quote:
Peter Jones wrote:

The singleton pattern seems to be a good match for this config object.
But there is still the dependency problem, where most of the system
depends on the config class. There may not be a way around that
though.

Don't hard-code the configuration variables into the config class;
instead, have them retrieved at run time, identified by name.

So instead of something like this:

class Config {
private:
int width_;
int height_;
string title_;
public:
int width() const { return width_; }
int height() const { return height_; }
string title() const { return title_; }
};
...
create_gui(conf.width(), conf.height(), conf.title());

Do it like this instead:

class Config {
private:
typedef map<string, string> StrMap;
StrMap data_;
public:
template <typename T> T get(string key) const {
StrMap::const_iterator i(data_.find(key));
if (i == data_.end())
throw invalid_argument("Unknown config key");
// ... or return a default value
return boost::lexical_cast<T>(i->second);
}
};
...
create_gui(conf.get<int>("width"), conf.get<int>("height"),
conf.get<string>("title"));


What is the advantage of the second solution?
- you need a global Config object in both cases
- you trade compiletime errors for runtime errors in case of typos,
e.g. conf.widt() vs. conf.get<int>("widt")
- and you introduce a maintainace problem by using template code,
especially boost::lexical_cast, which probably produces incredible
error messages if the wrong type for T is used. Your coworkers will
not use your code and each will write his/her own class ...

Best wishes,
Roland Pibinger

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ross Smith
Guest





PostPosted: Sat Jan 17, 2004 11:54 pm    Post subject: Re: Design idiom for application configuration Reply with quote

Roland Pibinger wrote:

Quote:
On 15 Jan 2004 21:58:37 -0500, Ross Smith <r-smith (AT) ihug (DOT) co.nz> wrote:

Do it like this instead:

class Config {
private:
typedef map<string, string> StrMap;
StrMap data_;
public:
template <typename T> T get(string key) const {
StrMap::const_iterator i(data_.find(key));
if (i == data_.end())
throw invalid_argument("Unknown config key");
// ... or return a default value
return boost::lexical_cast<T>(i->second);
}
};
...
create_gui(conf.get<int>("width"), conf.get<int>("height"),
conf.get<string>("title"));


What is the advantage of the second solution?
- you need a global Config object in both cases

But you don't need to change the Config class every time you add a new
configuration parameter. Which I thought was the whole point of the
exercise.

Quote:
- you trade compiletime errors for runtime errors in case of typos,
e.g. conf.widt() vs. conf.get<int>("widt")

An inevitable tradeoff. I can live with it.

Quote:
- and you introduce a maintainace problem by using template code,
especially boost::lexical_cast, which probably produces incredible
error messages if the wrong type for T is used. Your coworkers will
not use your code and each will write his/her own class ...

Now that's just ridiculous. This is the 21st century for god's sake,
nobody's afraid of templates any more. The solution, in the unlikely
event that that actually happened, is to laugh at your idiot coworkers
and tell them to grow up and quit whining.

--
Ross Smith ......... [email]r-smith (AT) ihug (DOT) co.nz[/email] ......... Auckland, New Zealand

"This world is like a burnt steak: small, tough, and the chips
are always stacked against you." -- Mike

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Grzegorz Jakacki
Guest





PostPosted: Sun Jan 18, 2004 11:26 am    Post subject: Re: Design idiom for application configuration Reply with quote

Peter Jones <cxx (AT) pmade (DOT) org> wrote

Quote:
Does anyone have a good design idiom for application configuration
information?

Most of the systems that I have worked on have a "config" class. The config
class will pull configuration information from some source, for example, an
XML file. The other classes in the system that need this configuration
information take a reference to a config object in their constructor.

This of course means that a lot of the system has a dependency on the config
class. What I think is worse is that you can't unit test some of the classes
without having to create a config class and pass it to the class that is
to be unit tested.


I would first separate configuration interface:

class Configuration
{
public:
virtual int MaxNumberOfErrors() const = 0;
virtual string SectionName() const = 0;
};

class ArgvConfiguration : public Configuration
{
public:
ArgvConfiguration(int ac, char* av[]);
...
};

That way you can define mock confgiguration class for unit tests.
The client code will not be aware, as it will know
the 'Configuration' class only.

class MockConfiguration : public Configuration
{
...
};

If you have many subsystems, each with their own set of configuration
options, you may want to separate Configuration interfaces for these
subsystems, e.g.:

class CoreConfiguration
{
public:
virtual int MaxNumberOfErrors() = 0;
...
};

class CodeGenerationConfiguration : virtual public
CoreConfiguration
{
public:
virtual bool InRegisterPassing() = 0;
...
};

class OptimizationConfiguration : virtual public CoreConfiguration
{
public:
virtual bool Inlining() = 0;
...
};

class ConformanceConfiguration : virtual public CoreConfiguration
{
public:
virtual bool RequireMainIsInt() = 0;
...
};

class ArgvConfiguration
: public CodeGenerationConfiguration
, public OptimizationConfiguration
, public ConformanceConfiguration
{
...
};

This lets you add/change the configuration options for one subsystem
without affecting other subsystems (you only change iface class for
the subsystem and ArgvConfiguration; other subsytems are isolated by
their respective interfaces, which do not change).

Quote:
The singleton pattern seems to be a good match for this config object. But
there is still the dependency problem, where most of the system depends on
the config class. There may not be a way around that though.

I always find it cumbersome to use Singleton with unit testing, as
usually
you want the "true" singleton object in the application and mock
singleton
object in a unit test.

I usually implement singleton access point as a namespace-level
function
(see "Effective C++"), e.g.:

// TheConfiguration.h
Configuration& TheConfiguration();

For unit testing I do not link with the proper implementation in
TheConfiguration.o, but I write the mock implementation
myself in the unit test file:

Configuration& TheConfiguration()
{
static MockConfiguration configuration_;
return configuration_;
}

If you use per-module configuration iface the singleton apporach
gets trickier, sincce you need per-module singleton
access points, e.g.:

// TheOptimizationConfiguration.h
OptimizationConfiguration& TheOptimizationConfiguration();

and

// TheCodeGenerationConfiguration.h
CodeGenerationConfiguration& TheCodeGenerationConfiguration();

These function can no longer use "Effective C++" static initialization
idiom,
because ech of them have to return a reference to the same one global
configuration object, which in your main application is going to be an
instance of ArgcConfiguration. I would implement those functions as
e.g.

CodeGenerationConfiguration& TheCodeGenerationConfiguration()
{
return TheArgcConfiguration();
};

And have

ArgvConfiguration& TheArgvConfiguration()
{
static ArgvConfiguration configuration;
return configuration;
}

However here surfaces the problem, that you have no way to pass
(argv,argc) to the singleton object ctor. Because of that I would
suggest that the ctor just
gives default or "undefined" values to all options. I usually assume
that
the state of such "created but not filled in" configuration object
should
represent the situation when no configuration options are specified
(e.g. empty configuration file, no arguments on the command line).

To that I would add a member function

class ArgvConfiguration
{
...
void FillIn(int argc, char** argv);
...
};

and have main() call this function at the very beginning of the
program.

Best regards
Grzegorz

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Roland Pibinger
Guest





PostPosted: Mon Jan 19, 2004 12:29 am    Post subject: Re: Design idiom for application configuration Reply with quote

On 17 Jan 2004 18:54:34 -0500, Ross Smith <r-smith (AT) ihug (DOT) co.nz> wrote:

Quote:
Roland Pibinger wrote:

On 15 Jan 2004 21:58:37 -0500, Ross Smith <r-smith (AT) ihug (DOT) co.nz> wrote:

Do it like this instead:

class Config {
private:
typedef map<string, string> StrMap;
StrMap data_;
public:
template <typename T> T get(string key) const {
StrMap::const_iterator i(data_.find(key));
if (i == data_.end())
throw invalid_argument("Unknown config key");
// ... or return a default value
return boost::lexical_cast<T>(i->second);
}
};
...
create_gui(conf.get<int>("width"), conf.get<int>("height"),
conf.get<string>("title"));


What is the advantage of the second solution?
- you need a global Config object in both cases

But you don't need to change the Config class every time you add a new
configuration parameter. Which I thought was the whole point of the
exercise.

- you trade compiletime errors for runtime errors in case of typos,
e.g. conf.widt() vs. conf.get<int>("widt")

An inevitable tradeoff. I can live with it.

- and you introduce a maintainace problem by using template code,
especially boost::lexical_cast, which probably produces incredible
error messages if the wrong type for T is used. Your coworkers will
not use your code and each will write his/her own class ...

Now that's just ridiculous. This is the 21st century for god's sake,
nobody's afraid of templates any more. The solution, in the unlikely
event that that actually happened, is to laugh at your idiot coworkers
and tell them to grow up and quit whining.

Good code is easy to use, easy to read, easy to extend, and easy to
change. These qualities do not apply to template code. Most
programmers who have worked with templates in real-world projects
agree with this statement.
In sum, you advocate a solution that uses a global variable,
hard-coded string literals scattered throughout the program, and at
least questionable template code. Unfortunately there seems to be no
difference between 21st and 20th century code ...

Best wishes,
Roland Pibinger

"I often think that the sole purpose of the STL is to see how many
lines one can use to obfuscate a simple loop." (John Potter)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.