如何从概念上处理程序中的大量配置参数? [英] How to handle large number of configuration parameters across a program conceptually?
问题描述
想象一个软件系统,其中您有大约 100 个参数,每个参数都可以更改(在我的情况下,这是一个用于机器学习的研究系统).显而易见的解决方案是将所有参数存储在一个配置文件中,以便系统易于处理和查看.
Imagine a software system where you have like 100 parameters, each of which is sensible to change (in my case this is a reasearch system for machine learning). The obvious solution is to store all parameters in a config file, so that the system is easy to handle and see through.
哪种方法更好:
- a) 在程序入口点加载配置文件,并通过代码中的每个方法传递大量配置变量
- b) 在程序入口点加载配置文件,并通过代码中的每个方法传递相关的配置变量集合
- c) 在需要的地方直接加载配置变量
- d) 加载配置并将其设为全局
我愿意接受特定实现的建议或示例.目前我正在试验嵌套配置变量,每个嵌套对象在代码中存储不同模块的配置.
I'm open for suggestions or examples of a particular implementation. At the moment I'm experimenting with nested config variables, each nested object storing config of different modules in the code.
推荐答案
我建议您执行以下步骤.
I recommend you do the following steps.
首先,使用支持多节/范围概念的配置文件语法,最好是可嵌套范围.例如,在我所说的意义上,一个 XML 元素是一个可嵌套的范围,而.ini"文件提供了不可嵌套的部分.Java 属性文件不提供对作用域的直接支持,但您可以通过使用语法 xyz
来表示在作用域 y中的变量
z
来模拟这种支持code>,依次嵌套在作用域 x
中.Config4*(我开发的)为嵌套作用域提供直接支持.
First, use a configuration file syntax that supports the concept of multiple sections/scopes, and preferably nestable scopes. For example, an XML element is a nestable scope in the sense I am talking about, while a ".ini" file provides non-nestable sections. A Java properties file does not provide direct support for scopes, but you can emulate such support by using the syntax x.y.z
to denote variable z
, in scope y
, which in turn is nested in scope x
. Config4* (which I developed) provides direct support for nested scopes.
其次,编写一个可配置的Foo
类的构造函数,如下伪代码所示:
Second, write the constructor of a configurable Foo
class as shown in the following pseudocode:
Foo(Configuration cfg, String scope) {
_x = cfg.lookup(scope + ".x");
_y = cfg.lookup(scope + ".y");
_z = cfg.lookup(scope + ".z");
_bar = new Bar(cfg, scope + ".bar");
}
在上面的伪代码中,我使用_
前缀来表示一个实例变量,并且我假设Configuration
类有一个lookup()
使用范围名称的操作,例如 cfg.lookup("foo.bar.abc")
将返回 abc
变量在 foo.bar
作用域.
In the above pseudo code, I use the _
prefix to denote an instance variable, and I assume the Configuration
class has a lookup()
operation that takes a scoped name, for example, cfg.lookup("foo.bar.abc")
will return the value of the abc
variable in the foo.bar
scope.
第三,你的应用程序的main()
函数可以写成如下伪代码:
Third, the main()
function of your application can be written as shown in the following pseudocode:
main(...) {
String configFileName = ...; // obtain from command-line argument
String scope = ...; // obtain from command-line argument
Configuration cfg = parseConfigurationFile(configFileName);
Foo foo = new Foo(cfg, scope + ".foo");
... // create other configured objects
doRealWork(foo, ...);
}
最后,应用程序的命令行参数应指定:(1) 配置文件的名称,以及 (2) 包含用于运行应用程序的配置变量的顶级范围(在配置文件中).例如,假设 example.cfg
的结构如下:
Finally, command-line arguments to your application should specify: (1) the name of a configuration file, and (2) a top-level scope (within the configuration file) that holds configuration variables for running the application. For example, let's assume example.cfg
is structured as follows:
instance1 {
foo {
x = "a value";
y = "another value";
z = "yet another value";
bar {
...
}
}
... # configuration for other objects
}
instance2 {
foo {
x = "...";
y = "...";
z = "...";
bar {
...
}
}
... # configuration for other objects
}
您可以将应用程序作为 myApp.exe -cfg example.cfg -scope instance1
运行.
You might run your application as myApp.exe -cfg example.cfg -scope instance1
.
上述建议具有以下好处:
The above advice provides the following benefits:
- 您的应用程序可以创建多个
Foo
对象,每个对象都可以进行不同的配置,只需将不同的scope
参数传递给每个对象的构造函数即可. - 用户可以根据需要灵活地将多组配置变量存储在单个配置文件中.例如,用户可能有不同的配置变量集: (1) 不同的单元测试;(2) 开发、UAT 和生产环境;(3) 复制的服务器应用程序的多个实例.
- 随着时间的推移,您可以编写一个遵循上述设计原则的可配置类库.该可配置类库可以在多个应用程序中重复使用.
- Your application can create multiple
Foo
objects, each of which can be configured differently, simply by passing a differentscope
parameter to the constructor of each object. - Users have the flexibility of being able to store multiple sets of configuration variables inside a single configuration file, if they want. For example, a user might have different sets of configuration variables for: (1) different unit tests; (2) development, UAT and production environments; (3) multiple instances of a replicated server application.
- Over time, you can write a library of configurable classes that follow the above design principle. That library of configurable classes can be reused across multiple applications.
我已经在我编写的几个基于 C++ 和 Java Config4* 的应用程序中使用了上述方法,并且它对我来说效果很好.如果您使用的语言具有内置的反射支持(例如 Java),那么另一种方法是使用依赖注入框架.如果您不知道那是什么,那么请在互联网上搜索依赖注入"、控制反转"或Spring 框架".
I have used the above approach in several C++ and Java Config4*-based applications that I wrote, and it has worked well for me. If you are using a language that has built-in support for reflection (such as Java), then an alternative approach is to use a dependency injection framework. If you don't know what that is, then do an Internet search for "dependency injection", "inversion of control" or "Spring Framework".
这篇关于如何从概念上处理程序中的大量配置参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!