views:

195

answers:

2

I am working on an application that consists of several modules which in turn will be used in other applications as well. Each of these modules needs some configuration options, but should not be aware of the options of other modules, and also should not require other modules to exist. Some settings are shared between modules.

Lets say Module A requires settings x and y, Module B requires settings y and z.

Settings are stored either in the registry or in one or more .ini files.

So far I have considered the following approaches:

  1. Have a global unit ("global.pas") that is included in all modules and contains global variables with the settings. I don't like this approach very much because it would require all applications to have such a unit and it is bound to collect lots of additional code that has nothing to do with the original purpose. So eventually each application will have its own incompatible global unit.
  2. Have configuration classes for each module that contain all the settings required for that module. These are passed into the module from some central point in the application which also handles reading and writing them to some permanent form (e.g. use JvAppStorage). This requires some synchronisation between the modules because some options will be shared between them, so if the option is changed in one module, this change must somehow be reflected in the configuration of another module (not necessarily in real time but the next time the module is initialized).
  3. Have a generic configuration class that is passed to each module and that contains the settings for all modules as properties. Each module accesses only those settings it knows about. The problem here might be that name clashes can occur whithout being noticed. Also I don't like the idea of passing configuration options around that are not necessary for a module. In addition, every application will contain a different subset of modules but would end up containing the same configuration class with the options for all possible modules. (This isn't very different from the global unit approach above.)
  4. Have a generic configuration class that is passed to each module, like above. But instead of having properties, the modules access their settings by name (in the easiest case this could be a TCustomIniFile). This avoids having settings for all modules available in all applications, but introduces possible type compatibility problems and again, name clashes may become an issue (unless each module prefixes its options with its name, but then they can no longer share options).

I guess everybody who wrote a modularized system has faced this issue and found some solutions they later on were stuck with, whether they still liked them or not. I have been there too, several times and am still looking for the golden bullet.

Maybe somebody else has already found the ideal solution?

(This is Delphi 2007 in case it matters. I am already using the JCL / JVCL.)

A: 

I once had application like that (written in C++Builder). I had one basic module (BaseClass.BPL) that all others (like Payment.BPL) inherited from . So you can use base class to read the common parameters and overwrite the inherited modules to read specific settings.

void PaymentForm::Readsettings()
{
   BaseClass::ReadSettings(); //to read common stuff
   IniFile->ReadString("Payment Module", "setting1,...); //read specific stuff
}

I kept settings in INI file - much easier to handle that registry. To avoid clashes with similar names each module used different section in INI.

[Common]
Datapath=...
Server=...

[MainModule]
setting1=..

[Payment module]
setting1=....
setting3=....
Riho
+2  A: 

I would probably create a generic configuration class, and have each module depend on one or several concrete configuration classes that are singletons. A module depends on a configuration class instance with settings that are significant for that module only, and optionally on one or more other configuration class instances with settings that pertain to more than one module. Due to the fact that the configuration objects are singletons the modules that share configuration objects automatically get the same settings.

You would create the configuration classes according to functionality, not according to module usage. The functionalities a module uses implicate which configuration objects it will need.

Every module that gets added to an application adds all the needed configuration classes as dependencies, other configuration classes are not added. The singleton configuration objects add themselves to a list (or registry if you will) of such objects on application startup. The application itself does not need to know about details, just loading and saving the settings from and to persistent storage is enough. It can OTOH make use of the same infrastructure if it needs to.

Generally I would implement everything in terms of interfaces, and leave the persistence mechanism outside. Thus you would be free later on to have configurations in INI files, the registry, or even a database (which would give you a simple way of implementing a history of configuration changes). I have found that I have not locked myself that much into a way of doing things since I started programming against interfaces instead of hierarchies of classes.

mghie