如何从概念上处理程序中的大量配置参数?

How to handle large number of configuration parameters across a program conceptually?

想象一个软件系统,您有大约 100 个参数,每个参数都可以合理地更改(在我的例子中,这是一个机器学习研究系统)。显而易见的解决方案是将所有参数存储在一个配置文件中,这样系统易于处理和查看。

哪种方法更好:

我愿意听取特定实施的建议或示例。目前我正在尝试嵌套配置变量,每个嵌套对象在代码中存储不同模块的配置。

我建议您执行以下步骤。

首先,使用支持多个 sections/scopes 概念的配置文件语法,最好是可嵌套范围。例如,XML 元素是我所说的可嵌套范围,而“.ini”文件提供不可嵌套的部分。 Java 属性文件不提供对范围的直接支持,但您可以通过使用语法 x.y.z 来表示范围 y 中的变量 z 来模拟此类支持,其中turn 嵌套在范围 x 中。 Config4*(我开发的)提供对嵌套作用域的直接支持。

其次,编写一个可配置的Fooclass的构造函数,如下伪代码所示:

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 class 有一个 lookup() 操作需要范围名称,例如,cfg.lookup("foo.bar.abc") 将 return foo.bar 范围内的 abc 变量的值。

第三,你的应用程序的main()函数可以写成如下伪代码所示:

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) 包含 [=67] 配置变量的顶级范围(在配置文件中) =]宁应用程序。例如,假设 example.cfg 的结构如下:

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

以上建议具有以下好处:

  • 您的应用程序可以创建多个 Foo 对象,每个对象都可以进行不同的配置,只需将不同的 scope 参数传递给每个对象的构造函数即可。
  • 用户可以根据需要灵活地在单个配置文件中存储多组配置变量。例如,用户可能有不同的配置变量集用于:(1) 不同的单元测试; (2)开发、UAT和生产环境; (3) 复制服务器应用程序的多个实例。
  • 随着时间的推移,您可以编写一个遵循上述设计原则的可配置 classes 库。该可配置 classes 库可以在多个应用程序中重复使用。

我已经在我编写的几个基于 C++ 和 Java Config4* 的应用程序中使用了上述方法,它对我来说效果很好。如果您使用的语言内置了反射支持(例如 Java),那么另一种方法是使用依赖注入框架。如果您不知道那是什么,请在 Internet 上搜索 "dependency injection"、"inversion of control" 或 "Spring Framework".