2011-09-07 16 views
12

Digamos que tengo un programa que tiene una gran cantidad de opciones de configuración. El usuario puede especificarlos en un archivo de configuración. Mi programa puede analizar este archivo de configuración, pero ¿cómo debería almacenar internamente y pasar las opciones?¿Cómo diseñar un programa con muchas opciones de configuración?

En mi caso, el software se utiliza para realizar una simulación científica. Hay alrededor de 200 opciones, la mayoría de las cuales tienen valores predeterminados. Normalmente, el usuario solo tiene que especificar una docena más o menos. La dificultad que afronto es cómo diseñar mi código interno. Muchos de los objetos que deben construirse dependen de muchas opciones de configuración. Por ejemplo, un objeto puede necesitar varias rutas (para donde se almacenarán los datos), algunas opciones que deben pasarse a los algoritmos que llamará el objeto, y algunas opciones que el objeto mismo usa directamente.

Esto lleva a que los objetos necesiten una gran cantidad de argumentos para ser construidos. Además, como mi base de código se encuentra en desarrollo muy activo, es muy difícil pasar por la pila de llamadas y pasar una nueva opción de configuración hasta donde sea necesario.

Una forma de evitar ese dolor es tener un objeto de configuración global que se pueda usar libremente en cualquier parte del código. No me gusta particularmente este enfoque ya que conduce a funciones y clases que no toman ningún argumento (o solo uno) y no es obvio para el lector con qué datos trata la función/clase. También evita la reutilización del código ya que todo el código depende de un objeto de configuración gigante.

¿Alguien me puede dar algunos consejos sobre cómo debe estructurarse un programa como este?

Aquí es un ejemplo de lo que quiero decir para la configuración de estilo opción de paso:

class A: 
    def __init__(self, opt_a, opt_b, ..., opt_z): 
     self.opt_a = opt_a 
     self.opt_b = opt_b 
     ... 
     self.opt_z = opt_z 

    def foo(self, arg): 
     algo(arg, opt_a, opt_e) 

Aquí se muestra un ejemplo del estilo global config:

class A: 
    def __init__(self, config): 
     self.config = config 

    def foo(self, arg): 
     algo(arg, config) 

Los ejemplos están en Python, pero mi pregunta significa cualquier langauge de programación similar.

+0

El objeto de configuración global combina todo el código. Sería bueno que el programa sea más modular. Me gusta la solución que muestra @HYRY. Parece lo mejor de ambos mundos. – qsc

Respuesta

5

matplotlib es un paquete grande, con muchas opciones de configuración. Utiliza un módulo rcParams para administrar todos los parámetros predeterminados. rcParams guarda todos los parámetros predeterminados en un dict.

Cada funciones tendrán las opciones de argurments de palabras clave:

por ejemplo:

def f(x,y,opt_a=None, opt_b=None): 
    if opt_a is None: opt_a = rcParams['group1.opt_a'] 
2

Unos patrones de diseño ayudarán

  • Prototipo
  • fábrica y Abstract Factory

usar estos dos patrones con objetos de configuración. Cada método tomará un objeto de configuración y usará lo que necesita. También considere aplicar una agrupación lógica a los parámetros de configuración y piense en formas de reducir el número de entradas.

pseudo código

// Consider we can run three different kinds of Simulations. sim1, sim2, sim3 

ConfigFactory configFactory = new ConfigFactory("/path/to/option/file"); 
.... 
Simulation1 sim1; 
Simulation2 sim2; 
Simulation3 sim3; 

sim1.run(configFactory.ConfigForSim1()); 
sim2.run(configFactory.ConfigForSim2()); 
sim3.run(configFactory.ConfigForSim3()); 

Dentro de cada método de fábrica que podría crear una configuración de un objeto prototipo (que tiene todos los valores predeterminados "sano") y el fichero de opciones se convierte sólo las cosas que son diferentes de defecto. Esto se combinaría con documentación clara sobre cuáles son estos valores predeterminados y cuándo una persona (u otro programa) podría querer cambiarlos.

** Editar: ** Considere también que cada configuración devuelta por la fábrica es un subconjunto de la configuración general.

2

Pase la clase de análisis de configuración, o escriba una clase que la envuelva y extraiga inteligentemente las opciones solicitadas.

La biblioteca estándar de Python configparser expone las secciones y opciones de un archivo de configuración de estilo INI utilizando el protocolo de mapeo, por lo que puede recuperar sus opciones directamente de eso como si fuera un diccionario.

myconf = configparser.ConfigParser() 
myconf.read('myconf.ini') 
what_to_do = myconf['section']['option'] 

Si desea explícitamente para proporcionar las opciones usando la notación de atributos, crear una clase que anula __getattr__:

class MyConf: 
    def __init__(self, path): 
     self._parser = configparser.ConfigParser() 
     self._parser.read('myconf.ini') 
    def __getattr__(self, option): 
     return self._parser[{'what_to_do': 'section'}[option]][option] 

myconf = MyConf() 
what_to_do = myconf.what_to_do 
0

tener una carga de módulo de los parametros de su espacio de nombres, a continuación, importar y usar donde quiera.
Consulte también la pregunta relacionada here

Cuestiones relacionadas