Application configuration design patterns

There are two core design patterns for the scope of objects used to configure a Python application:

  • A global property map: A global object can contain all of the configuration parameters. A simple class definition is perhaps an ideal way to provide names and values; this tends to follow the Singleton design pattern ensuring that only one instance exists. Alternatives include a dictionary with pairs of name: value, or a types.SimpleNamespace object of attribute values.
  • Object construction: Instead of a single object, we'll define a kind of Factory or collection of Factories that use the configuration data to build the objects of the application. In this case, the configuration information is used once when a program is started and never again. The configuration information isn't kept around as a global object.

The global property map design is very popular because it is simple and extensible. The first example of this is using a class object, which is defined as follows:

class Configuration: 
   some_attribute = "default_value" 

We can use the preceding class definition as a global container of attributes. During the initialization, we might have something similar to this as part of parsing the configuration file:

Configuration.some_attribute = "user-supplied value" 

Everywhere else in the program, we can use the value of Configuration.some_attribute. A variation on this theme is to make a more formal Singleton class design pattern. This is often done with a global module, as it can be easily imported in a way that provides us with an accessible global definition.

The second example involves using a module for the configuration. We might have a module named configuration.py. In that file, we can have a definition like the following:

settings = {
"some_attribute": "user-supplied value"
}

Now, the application can use configuration.settings as a global repository for all of the application's settings. A function or class can parse the configuration file, loading this dictionary with the configuration values that the application will then use.

In a Blackjack simulation, we might see the following code:

shoe = Deck(configuration.settings['decks']) 

Alternatively, we might possibly see the following code:

If bet > configuration.settings['limit']: raise InvalidBet() 

Generally, we'll try to avoid having a global variable for the configuration. Because a global variable is implicitly present everywhere, it can be misused to carry stateful processing in addition to configuration values. Instead of a global variable, we can often handle the configuration relatively more neatly through object construction. In the next section, we will look at examples of constructing objects as a way to implement the configuration changes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset