100

一段时间以来,我一直在考虑配置文件及其与代码的关系,并且根据日期和风向,我的观点似乎会发生变化。尽管我越来越多地回到我在学习 Lisp 时最初的认识:数据和代码之间几乎没有区别。这对于配置文件来说似乎是双重的。从正确的角度来看,Perl 脚本只不过是 perl 的配置文件。这往往会对 QA 和分工(例如谁应该负责更改配置文件)等任务产生相当严重的后果。

从配置文件到成熟语言的转变通常很慢,并且似乎是由拥有通用系统的愿望驱动的。大多数项目一开始看起来很小,只有一些配置项,比如在哪里写日志、在哪里查找数据、用户名和密码等。但随后它们开始增长:功能开始能够打开或关闭,操作的时间和顺序开始被控制,并且,不可避免地,有人想要开始添加逻辑(例如,如果机器是 X,则使用 10,如果机器是 Y,则使用 15)。在某个时刻,配置文件变成了一种特定领域的语言,而且是一种写得很糟糕的语言。

既然我已经开始着手搭建舞台,以下是我的问题:

  1. 配置文件的真正目的是什么?
  2. 是否应该尝试保持配置文件简单?
  3. 谁应该负责对他们进行更改(开发人员、用户、管理员等)?
  4. 它们是否应该受到源头控制(见问题 3)?

正如我之前所说,我对这些问题的回答不断变化,但现在我在想:

  1. 允许非程序员快速改变大量行为
  2. 是的,任何不是粗粒度的都应该在代码中
  3. 用户应该对配置文件负责,程序员应该对配置文件和代码之间的配置层负责,它可以对应用程序进行更细粒度的控制
  4. 不,但更细粒度的中间层应该是
4

18 回答 18

42

非常有趣的问题!

我倾向于将我的配置文件限制为非常简单的“key=value”格式,因为我完全同意您的看法,配置文件可以很快成为成熟的程序。例如,任何曾经尝试“配置” OpenSER 的人都知道您所说的感觉:这不是配置,而是(痛苦的)编程。

当您需要您的应用程序以您今天无法想象的方式非常“可配置”时,您真正需要的是插件系统。您需要以其他人可以编写新插件并在将来将其挂接到您的应用程序的方式来开发您的应用程序。

所以,回答你的问题:

  1. 配置文件的真正目的是什么?

    我想说,为了让安装您的应用程序的人能够调整一些与部署相关的参数,例如主机名、线程数、您需要的插件的名称以及这些插件的部署参数(检查出FreeRadius的配置这个原理的例子)等等。绝对不是表达业务逻辑的地方。

  2. 是否应该尝试保持配置文件简单?

    确实。正如您所建议的,配置文件中的“编程”是可怕的。我认为应该避免。

  3. 谁应该负责对他们进行更改(开发人员、用户、管理员等)?

    一般来说,我会说部署应用程序的管理员。

  4. 它们是否应该受到源头控制(见问题 3)?

    我通常不对配置文件本身进行源代码控制,但我会对模板配置文件进行源代码控制,其中包含所有参数及其默认值,以及描述它们作用的注释。例如,如果配置文件名为database.conf,我通常对名为 的文件进行源代码控制database.conf.template。现在我当然是在谈论我作为开发人员所做的事情。 作为管理员,我可能想要对我为每次安装选择的实际设置进行源代码控制。例如,我们远程管理数百台服务器,我们需要跟踪它们的配置:我们选择使用源代码控制来做到这一点。


编辑: 虽然我相信以上对于大多数应用程序都是正确的,但当然也有例外。例如,您的应用程序可能允许其用户动态配置复杂的规则。大多数电子邮件客户端允许用户定义管理其电子邮件的规则(例如,“所有来自 'john doe' 并且在收件人:字段中没有我的电子邮件都应该被丢弃”)。另一个示例是允许用户定义新的复杂商业报价的应用程序。您还可以考虑像 Cognos 这样的应用程序,它允许用户构建复杂的数据库报告。电子邮件客户端可能会为用户提供一个简单的界面来定义规则,这将生成一个复杂的配置文件(甚至可能是一些代码)。另一方面,商业报价的用户定义配置可能以结构化方式保存在数据库中(既不是简单的键=值结构也不是代码的一部分)。一些其他应用程序甚至可能允许用户使用 python 或 VB 或其他一些具有自动化功能的语言进行编码。换句话说...您的里程可能会有所不同。

于 2009-03-15T18:15:08.623 回答
11

行。您将有一些用户想要一个非常简单的配置,您应该将其提供给他们。同时,你会不断的请求“你能添加这个吗?我在配置文件中怎么做?”,我不明白为什么你不能同时支持这两个组。

我目前正在处理的项目使用 Lua 作为其配置文件。Lua 是一种脚本语言,它在这种情况下工作得很好。有一个我们默认配置的示例。

你会注意到它主要是 key=value 语句,其中 value 可以是 Lua 的任何内置类型。最复杂的是列表,它们并不复杂(只是语法问题)。

现在我只是在等待有人问他们每次启动时如何将服务器的端口设置为随机值......

于 2009-03-15T18:34:39.247 回答
8

最近我正在做一个项目,我意识到我想在我的配置文件中包含条件 - 以前只是一个非常简单的形式:


key = val
key2 = val
name = `hostname`

我不想编写迷你语言,因为除非我非常小心地这样做,否则我不能允许有用的灵活性。

相反,我决定我有两种形式:

  1. 如果文件以“#!”开头 并且是可执行的,我会解析运行它的结果。

  2. 否则我会按原样阅读

这意味着我现在可以允许人们编写如下所示的“配置文件”:

 #!/usr/bin/perl
if ( -x /bin/foo ) 
{
   print <<EOF;
foo=me
bar=you
EOF
}
else
{
   print <<EOF;
foo=bar
bar=foo
EOF
}

这样,如果用户想要使用它,我就可以获得动态配置文件的强大功能,并且不必编写自己的迷你语言。

于 2009-03-15T20:30:34.273 回答
5

每个(足够长的)配置文件模式最终都会成为一种编程语言。由于您描述的所有含义,配置文件设计者最好意识到她正在编写一种编程语言并相应地进行计划,以免她给未来的用户带来不良遗产。

于 2009-03-15T18:15:25.017 回答
3

我对配置文件有不同的理念。关于应用程序应该如何运行的数据仍然是数据,因此属于数据存储,而不是代码(配置文件 IMO 是代码)。如果最终用户需要能够更改数据,那么应用程序应该提供一个接口来做到这一点。

我只使用配置文件来指向数据存储。

于 2009-03-15T20:03:20.157 回答
3

您可以求助于计算理论来定义什么才是编程语言。如果您的配置文件格式是图灵完备的,那么它可以合理地算作一种编程语言。根据这个定义,描述推箱子级别的文件格式算作一种编程语言(参见此处)。低于图灵完备的其他复杂程度也可能计算在内,例如常规语法下推自动机

另一种看待它的方式是,许多配置文件只能进行数据标记,而适当的编程语言必须能够实现算法。例如,JSON 是一种配置文件格式,而 ECMA 脚本是一种编程语言。

于 2009-03-16T07:29:19.773 回答
2

这是我的想法:

  1. 允许轻松修改应用程序的运行时行为。这可以由程序员或非程序员根据需要进行。这可以在开发过程中进行,但我经常将配置文件视为有助于使程序在任何时候更加灵活的一种方式。

  2. 是的。我认为配置文件应该尽可能简单,因为您可能需要各种选项来控制运行时的不同行为。我更喜欢对配置设置进行分组,并尽可能简化它们。

  3. 取决于进行更改的内容和原因。如果用户要对其进行更改,则应制作前端以隐藏细节。一般来说,非开发人员通常也是如此。

  4. 我经常对“默认”配置进行源代码控制,但有一种方法可以在实际运行时覆盖每个系统。

至于向配置文件添加逻辑 - 我会避免这种情况。我认为最好只在应用程序中的逻辑上切换配置文件。根据我的经验,配置文件中的行为导致缺乏可维护性和理解力。我强烈希望使配置文件尽可能简单。

于 2009-03-15T18:12:53.543 回答
2

我倾向于同意这个问题的前提。我通过及早预测这将会发生来避免让自己陷入麻烦,因此从不推出我自己的配置系统。

  • 我要么使用操作系统的配置工具(例如 plist、gconf 或任何合适的),
  • 或者一个简单的平面文件,可以由现成的 INI 解析器之类的东西处理。
  • 咬紧牙关,在应用程序中插入一个轻量级语言解析器,通常是 lua,有时是 tcl,
  • 或者将数据存储在 SQLite 或类似的关系数据库中。

并让自己接受我做出的任何决定,或者如果我不能,重构以使用上述更适合应用程序的选择之一。

关键是,没有任何理由使用本土配置解决方案。一方面,您的用户很难学习一种新的、特定于应用程序的配置格式。另一方面,您可以从使用现成解决方案时免费提供的所有许多错误修复和更新中受益。最后,特性蠕变被搁置,因为,实际上,你不能只添加一个特性而没有真正进行大修,因为配置系统一开始并没有真正掌握在你的手中。

于 2009-03-15T22:11:25.293 回答
1

这取决于您与团队中其他开发人员达成的共识。您是在使用配置文件作为配置文件还是在创建模型驱动应用程序。

配置文件成为编程语言的症状:

  • 名称=值对开始相互依赖
  • 您觉得需要进行流量控制(例如if (this) than that
  • 为了进行进一步的开发(而不仅仅是使用应用程序),配置文件的文档变得必不可少
  • 在读取配置中的值之前,它需要有一些上下文(即值取决于配置文件本身的外部内容)
于 2009-03-15T18:28:01.587 回答
1

配置文件总是逐渐变得丑陋、不合逻辑的“成熟的编程语言”。设计好的编程语言需要艺术和技巧,而配置语言变成编程语言往往是可怕的。

一个好的方法是使用设计精美的语言,例如 python 或 ruby​​,并使用它为您的配置创建DSL。这样,您的配置语言表面上可以保持简单,但实际上是成熟的编程语言。

于 2009-03-15T18:39:24.930 回答
1

鉴于转向“流畅的界面”,我相信您的问题非常相关。许多开发人员已经“看到了曙光”关于 XML 配置的应用程序。使用 XML 可能非常冗长且难以正确编辑(尤其是在未提供模式的情况下)。拥有流畅的界面允许开发人员在纯文本配置文件(或者可能是命令行参数)中的一些键值对的帮助下,以特定领域的语言配置应用程序。它还使得设置和配置应用程序的新实例以进行测试或其他任何事情变得非常容易。

以下是我对您的问题的回答:

  • 配置文件的真正目的是什么?

配置文件是一种允许用户在运行时自定义其程序行为的方法。

  • 是否应该尝试保持配置文件简单?

理想情况下,我认为配置文件至少应该辅以流畅的界面来配置程序(这在很多方面都很有用)。如果您确实需要一个配置文件,那么它应该保持非常简单,除了键值对之外别无其他。

  • 谁应该负责对他们进行更改(开发人员、用户、管理员等)?

我认为这个问题的答案取决于您的组织。部署软件的人应负责确保软件配置正确。

  • 它们是否应该受到源头控制(见问题 3)?

我会从其他人那里窃取这个答案:) 我喜欢将模板配置存储在源代码管理中并根据每个本地用户的需要对其进行修改的想法。一个开发人员的配置文件很可能是另一个开发人员的噩梦,因此最好将因用户而异的内容排除在源代码控制之外。拥有模板也是让部署应用程序的人员(或其他开发人员)准确了解配置文件的有效值的好方法。

于 2009-03-15T19:50:53.510 回答
1

我见过配置文件代码的python程序。如果您不需要做任何特殊的事情(条件等),它看起来与其他配置样式没有太大区别。例如,我可以使用以下内容制作文件config.py

num_threads = 13
hostname = 'myhost'

与(比如说)INI 文件相比,用户的唯一负担是他们需要将 '' 放在字符串周围。毫无疑问,您可以在其他解释语言中做同样的事情。它使您可以无限地在必要时使配置文件复杂化,但可能会吓到您的用户。

于 2009-03-16T03:09:07.700 回答
0

是的,配置文件应该很简单。它们本身不应包含“逻辑”——将它们视为 if 语句中的表达式列表,而不是整个条件语句。

它们的存在是为了让用户决定应该使用应用程序中编码的哪些选项,所以不要试图让它们变得复杂,它最终会弄巧成拙——你最终可能会编写简单的配置文件控制原始配置文件的配置方式!

于 2009-03-15T18:19:30.577 回答
0

微软“奥斯陆”工作的目的之一是允许(尽管不是必需的)解决这个问题。

  1. 应用程序将附带它包含的任何新组件的模型。它还将使用现有模型。例如,它可能包含一个 Web 服务,因此它可以重用 Web 服务的系统模型。
  2. 这些模型将包括描述它们的元数据,包括足够的信息以供工具以文本或图形方式访问它们。
  3. 部分机型将对应“配置”

这意味着与今天的配置文件相当的内容可能足够丰富以支持对其配置的文本和图形编辑。图形工具将随“Oslo”(代号“Quadrant”)一起提供。

于 2009-03-15T18:20:08.063 回答
0

我将成为逆向者,并认为它只是一种语言,它体现的不仅仅是 XML 所能表示的;或者当 XML 被认为是一种语言时。

或者,大多数配置文件可以被认为是类,但只有属性,没有方法。没有方法,我不认为它是一种语言。

归根结底,“语言”是一种模糊的抽象,但是是的,边缘是模棱两可的。

于 2009-03-15T19:07:10.697 回答
0

我们应用程序的代码变得不那么重要了……有脚本,有各种各样的属性来定义类、方法、方法参数和属性的行为。用户可以定义数据库触发器和数据库约束。可能有非常复杂的配置文件。有时用户可以定义 XSLT 样式表来操作输入和输出,因为我们的系统需要是开放的 (SOA)。还有像 BizzTalk 这样的东西也需要复杂的配置。用户可以定义复杂的工作流程。

我们必须编写更好的代码来处理这种复杂的环境,因此我们应用程序的代码变得更加重要......

于 2009-03-15T19:17:34.293 回答
0

我非常喜欢使用 python 程序作为配置文件,尤其是对于守护进程。除了“配置端口”之外,我喜欢让守护进程完全没有配置。然后,python 程序连接到守护程序并继续在守护程序中创建对象并将它们连接在一起以创建所需的配置。一切设置好后,就可以让守护程序自行运行。当然,好处是您可以使用成熟的编程语言来编写配置文件,并且由于您已经有办法从另一个程序与守护程序对话,因此您可以使用它进行调试和获取统计信息。主要的缺点是必须随时处理来自另一个程序的消息。

于 2009-03-16T20:13:34.180 回答
0

配置文件:“我的目的是什么?”
:“配置黄油。”
配置文件:“好的……”
配置文件:“我的目的是什么?”
:“你配置黄油。”
配置文件:“天哪。” :“是的,欢迎来到俱乐部。”

  1. 配置文件没有“真正目的”。它对您的应用程序有意义。一般来说,机器之间不同(或可能不同)并且在应用程序运行过程中不会改变的东西可能应该在配置文件中。其他服务的默认值、端口和地址都是很好的选择。密钥和秘密也是很好的候选者,但出于安全原因,应与您的正常配置分开处理。我不同意配置文件的目的是允许进行快速更改。目的应该是允许灵活地设置您的应用程序。如果配置文件是一种允许这种灵活性的快速简便的方法,那就更好了 - 但您应该打算频繁更改配置文件。

  2. 是和不是。您是否应该尝试简化应用程序的代码?是的。您应该尝试使您编写的所有内容都简单明了。没有比它需要的更复杂。您的配置也是如此。但是,这是非常特定于应用程序的。硬编码配置中应该包含的内容,因为它会使您的配置“过于复杂”,这是糟糕的设计。事实上,试图“保持简单”就是为什么配置文件最终会变得一团糟。有时最简单的举措是模块化。这就是为什么你的配置文件应该用众所周知的通用编程语言编写——而不是一些糟糕的配置语言(阅读:所有“配置语言”都很烂)。

  3. 同样,谁应该修改配置文件完全取决于应用程序。但我同意 miniquark,部署应用程序的人应该负责配置。

  4. 源代码控制尽你所能。源代码控制很棒。您可以超级轻松地回滚内容,并且您拥有所做更改的完整历史记录以及谁进行了这些更改的记录。那为什么不呢?

于 2018-08-13T22:40:19.430 回答