configuration文件在什么时候成为编程语言?

我一直在研究configuration文件和它们之间的关系,现在编码一段时间,取决于风的日子和方向,我的意见似乎改变了。 我越来越多地回到我刚刚学习Lisp的时候,数据和代码之间几乎没有区别。 这对于configuration文件来说似乎更加真实。 当在正确的光照下看Perl脚本只是一个perl的configuration文件。 这对于诸如QA和劳动分工这样的任务往往具有相当严重的后果,比如谁应该负责更改configuration文件。

从configuration文件到完全成熟的语言的蠕变通常是缓慢的,并且似乎由具有通用系统的愿望驱动。 大多数项目似乎都是从less量configuration项开始的,比如在哪里写日志,在哪里查找数据,用户名和密码等等。但随后他们开始增长:function开始能够打开或closures,操作的时间和顺序开始被控制,并且不可避免地有人想要开始添加逻辑(例如,如果机器是X,则使用10,如果机器是Y,则使用15。 在某一点上,configuration文件成为一个领域特定的语言,并写在一个不好的。

现在我已经漫步上台了,这里是我的问题:

  1. 什么是configuration文件的真正目的?
  2. 应该试图保持configuration文件简单吗?
  3. 谁应该负责对其进行更改(开发人员,用户,pipe理员等)?
  4. 他们是否应该被源代码控制(见问题3)?

正如我刚才所说,我对这些问题的答案不断变化,但现在我在想:

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

非常有趣的问题!

我倾向于将我的configuration文件限制为非常简单的“key = value”格式,因为我完全同意你的意见,configuration文件可以很快成为完整的程序。 例如,曾经试图“configuration”OpenSER的任何人都知道你正在谈论的感觉:这不是configuration,而是(痛苦的)编程。

当你需要你的应用程序非常“可configuration”的方式,你今天无法想象,那么你真正需要的是一个插件系统 。 您需要以其他人可以编写新插件的方式开发您的应用程序,并将其挂载到您的应用程序中。

所以,要回答你的问题:

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

    我想说的是,允许安装应用程序的人能够调用一些与部署相关的参数,例如主机名,线程数,所需插件的名称以及这些插件的部署参数(检查FreeRadius的configuration就是这个原理的一个例子)等等。绝对不是expression业务逻辑的地方。

  2. 应该试图保持configuration文件简单吗?

    当然。 正如你所build议的,configuration文件中的“编程”是可怕的。 我相信应该避免。

  3. 谁应该负责对其进行更改(开发人员,用户,pipe理员等)?

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

  4. 他们是否应该被源代码控制(见问题3)?

    我通常不会自行控制configuration文件,但是我使用所有参数及其默认值以及描述他们所做的注释来源控制模板configuration文件。 例如,如果configuration文件名为database.conf ,我通常会源代码控制一个名为database.conf.template的文件。 当然,我正在谈论我作为开发人员的工作作为pipe理员 ,我可能需要源代码控制我为每个安装select的实际设置。 例如,我们远程pipe理几百台服务器,我们需要跟踪他们的configuration:我们select使用源代码控制来实现这一点。


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

好。 你会有一些用户想要一个非常简单的configuration,你应该把它给他们。 同时,你会不断请求“你可以添加这个吗?我该怎么做在configuration文件?”,我不明白为什么你不能支持这两个组。

我目前正在使用的项目使用Lua的configuration文件。 Lua是一种脚本语言,在这种情况下效果很好。 有一个我们的默认configuration的例子。

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

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

最近我正在做一个项目,我意识到我想在我的configuration文件中有条件 – 以前只是一个非常简单的forms:

key = val key2 = val name = `hostname`
key = val key2 = val name = `hostname` 

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

相反,我决定我有两种forms:

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

  2. 否则,我会按照原样阅读

这意味着我现在可以让人们写下如下所示的“configuration文件”:

  #!的/ usr / bin中/ perl的
如果(-x / bin / foo) 
 {
   打印<< EOF;
富=我
酒吧=你
 EOF
 }
其他
 {
   打印<< EOF;
富=酒吧
条= FOO
 EOF
 }

这样,如果用户想要使用它,就可以获得dynamicconfiguration文件的强大function,而且不需要编写自己的迷你语言。

每个(足够长的)configuration文件模式最终都会成为一种编程语言。 由于你所描述的所有含义,configuration文件devise者明智地认识到她正在编写一种编程语言并作出相应的规划,以免给未来的用户带来不好的遗产负担。

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

我只使用configuration文件指向数据存储。

你可以转向计算理论来定义什么是一种编程语言。 如果你的configuration文件格式是Turing Complete,那么它就可以算作一种编程语言。 通过这个定义,用于描述推箱子级别的文件格式可以算作一种编程语言(参见这里 )。 在Turing Complete以下还有其他一些复杂性,也可能会被计算在内,比如Regular Grammars和Pushdown Automata 。

另一种看待它的方式是许多configuration文件只能够进行数据标记,而恰当的编程语言必须能够实现algorithm 。 例如,JSON是一种configuration文件格式,而ECMA Script是一种编程语言。

这是我的想法:

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

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

  3. 取决于什么和为什么改变正在做。 如果用户将要改变它,应该做一个前端来隐藏他们的细节。 一般来说,非开发者也是如此。

  4. 我经常将源代码控制为“默认”configuration,但是有一种方法可以在实际运行时针对每个系统重写此configuration。

至于添加逻辑到configuration文件 – 我会避免这一点。 我认为最好是在应用程序的逻辑上打开configuration文件。 根据我的经验,configuration文件中的行为导致缺乏可维护性和理解。 我非常希望保持configuration文件尽可能简单。

这取决于你同意团队中的其他开发人员。 你是否像configuration文件一样使用configuration文件,或者你正在创build一个模型驱动的应用程序。

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

  • 名称=值对开始相互依赖
  • 你觉得有必要有stream量控制(例如, 如果(这个)比
  • configuration文件的文档变得必不可less,为了做进一步的发展(而不是仅仅使用应用程序)
  • 在从configuration值读取之前,它需要有一些上下文(即值取决于外部configuration文件本身的东西)

configuration文件总是成为丑陋的,不合逻辑的“完全成熟的编程语言”。 devise好的编程语言需要艺术和技能,而configuration语言变成编程语言往往是可怕的。

一个好的方法是使用一个devise良好的语言,比如python或ruby,并用它来为你的configuration创build一个DSL 。 这样,你的configuration语言可以保持简单的表面,但实际上是一个完整的编程语言。

我相信你的问题是非常相关的,因为移动到“stream畅的接口”。 许多开发人员已经对XMLconfiguration的应用程序“看得见”了。 使用XML可能非常冗长,难以正确编辑(特别是如果没有提供架构)。 stream畅的界面允许开发人员通过纯文本configuration文件(或者命令行参数)中的某些键值对的帮助,以特定于域的语言configuration应用程序。 这也使得它很容易设置和configuration应用程序的新实例进行testing等等。

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

  • 什么是configuration文件的真正目的?

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

  • 应该试图保持configuration文件简单吗?

理想情况下,我认为configuration文件应至less补充一个stream畅的界面来configuration程序(这在很多方面是有用的)。 如果你需要一个configuration文件,那么它应该保持非常简单,除了键 – 值对之外。

  • 谁应该负责对其进行更改(开发人员,用户,pipe理员等)?

我认为这个答案取决于你的组织。 部署软件的人员应负责确保其configuration正确。

  • 他们是否应该被源代码控制(见问题3)?

我会偷别人的这个答案:)我喜欢在源代码控制中存储模板configuration的想法,并根据每个本地用户的需要修改它。 机会是一个开发人员的configuration文件是另一个开发人员的噩梦,所以最好留下来源于控制的用户不同的东西。 有一个模板也是让部署应用程序(或其他开发人员)的人确切地看到configuration文件有效的值的一个好方法。

我倾向于同意这个问题的前提。 我避免让自己陷入麻烦,预测这种情况将会发生,因此不要推出我自己的configuration系统。

  • 我可以使用操作系统的configurationfunction(比如plist,gconf或其他适合的),
  • 或者是一个简单的平面文件,可以像现成的INIparsing器那样处理。
  • 硬着头皮插上一个轻量级的语言parsing器,通常是lua,有时候tcl进入应用程序,
  • 或者将数据存储在SQLite或类似的关系数据库中。

并且自to生自己做的任何决定,或者如果我不能,重构使用更好的适合应用程序的上述select之一。

要点是,没有任何理由使用本土configuration解决scheme。 首先,用户难于学习新的,特定于应用程序的configuration格式。 另一方面,您可以从使用现成解决scheme时免费获得的所有错误修复和更新中受益。 最后,Feature蠕变被搁置了,因为,实际上你不能只是增加一个特性而不做真正的大修,因为configuration系统并不在你手中。

是的,configuration文件应该很简单。 它们本身不应该包含“逻辑” – 将它们看作是if语句中的expression式列表,而不是整个条件语句。

他们在那里允许用户决定在应用程序中编码哪些选项,所以不要试图让它们变得复杂,最终会导致自我毁灭 – 你最终可能会写简单的configuration文件来控制如何configuration原始configuration文件!

微软“奥斯陆”工作的目的之一就是允许(虽然不要求)解决这个问题。

  1. 一个应用程序可以装载它包含的任何新组件的模型。 它也会使用现有的模型。 例如,它可能包含一个Web服务,所以它可以重用Web服务的系统模型。
  2. 这些模型将包括描述它们的元数据,包括用于工具访问它们的足够信息,无论是文本还是graphics。
  3. 部分型号将对应“configuration”

这意味着相当于今天的configuration文件可能足够丰富,以支持其configuration的文本和graphics编辑。 graphics工具将提供“奥斯陆”(代号“象限”)。

我将成为逆向投资者,只有当它体现的不仅仅是可以用XML来表示的时候,它才会是一种语言; 否则当XML被认为是一种语言。

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

最终,“语言”是一个软弱的抽象,但是,边缘是模棱两可的。

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

我们必须编写更好的代码来处理这个复杂的环境,所以我们的应用程序代码变得更加重要。

我见过的configuration文件代码的Python程序。 如果你不需要做任何特殊的事情(条件等),那么和其他的configuration风格看起来并没有什么不同。 例如我可以使用如下的东西来创build一个文件config.py

 num_threads = 13 hostname = 'myhost' 

和INI文件相比,用户唯一的负担就是他们需要在string周围放置“。 毫无疑问,你可以在其他解释语言中做同样的事情。 它给你无限的能力,在必要时使你的configuration文件变得复杂,可能会吓到你的用户。

我非常喜欢使用Python程序作为configuration文件,尤其是守护进程。 除了“configuration端口”之外,我喜欢把守护进程完全清空。 然后,python程序连接到守护进程,并继续在守护进程中创build对象并将它们连接在一起以创build所需的configuration。 一旦设置好了,守护进程就可以自行运行了。 当然,好处是你得到了一个完整的编程语言来编写你的configuration文件,因为你已经有了一个方法来跟另一个程序中的守​​护进程交谈,所以你可以用它来debugging和获取统计信息。 主要的缺点是不得不处理来自另一个程序的消息。