每个小人物的心中都有一个成为大人物的梦想,配置文件也不例外。
当我们还是编程新手的时候,经常会有一些前辈告诉我们:软件开发中要将一些可能变动的参数放到配置文件中,这样就可以在不改变代码且无需重新部署程序的情况下改变程序行为。
1、软件实践中的配置文件
正如前辈告诫我们的那样,『将一些可能变动的参数放到配置文件中』,可以使得程序更加灵活,适应多种业务场景。于是我们谨遵他们的教诲,在日常的开发过程中,将数据库连接参数,日志路径等线上环境相关的易变值加入配置文件。的确好用,当我们的DB想要扩容,当我们的日志存储想要变更,仅需修改配置文件即可。如此好用,某一天我们可能也会将软件中的某一个功能特性开关移步到配置文件中。不止于此,我们开始将更多的可变参数写在配置文件中,已达到更高的灵活度,更有甚者将一些业务逻辑操作从代码中挪到配置文件中。于是,某一天我们突然发现自己大部分的时间并不是在写代码,而是写配置文件。
2、每一个配置文件都想成为一个DSL
每个工具都想发展成为一个平台,无独有偶,每一个配置文件都想成为一个DSL(Domain Specific Language,领域专用语言)。
正如第一部分描述的那样,起初配置文件中只是一些与代码执行环境有关的参数配置(供系统管理员使用),到最后,随着一些『业务行为』也被加入到配置文件中,它则慢慢地进化成为了一种DSL。但并不是每一个软件系统都需要一套自己的DSL,也不是每一个DSL都会被设计地那么易懂与易用。有些仅仅是增加了复杂度。
有人发明了『配置文件复杂读时钟』的概念来描述配置文件这样的一个发展过程,十分贴切。
- 12点:所有逻辑均是写在代码里,有些甚至是硬编码 - 对应业务起步期。
- 3点:前辈们告诉我们,将一些可能变动的参数放到配置文件中 - 业务发展早期
- 6点:需求快速变化,业务逻辑越来越复杂,配置文件也越来越复杂,引入一些条件判断,异常处理等- 业务发展中期。
- 9点:有一些定制化的需求开始出现,为了应对这种变化,配置文件开始走向大量定义软件行为的方向,并且与业务规则紧密耦合在一起 - 业务发展顶峰期
- 12点:最后的最后又回到原点,所以的业务逻辑均写在配置文件中,包括硬编码 - 业务发展瓶颈期。
于是,软件开发人员从面向代码编程变成了面向配置文件编程。其实,这个时期,配置文件俨然已变成了一种编程语言。
那么回过头来想一想,在业务发展过程中,衍生出了一门配置编程语言,这有必要嘛?
配置文件有时候的确很好用,可以帮助软件开发人员快速应对一些变化。但是如果过度依赖配置文件,却不得不提它带来的缺陷:
- 不通用:配置文件引入了非通用的语法、语义,这对项目项目新人来说,无疑增加了学习难度,也降低了团队的合作效率。
- 调试困难:不像代码,配置文件无法在软件系统发生异常时进行有效地调试,致使无法快速定位问题,修复问题,降低了软件系统的健壮性。
- 可维护性差:每一门编程语言都基本上有一套自身的通用编码规范,并随着开发者社区而得到进一步的完善,而配置文件,大多数软件系统都会定义一套自己特殊的语义。相对而言一份使用通用编程语言编写代码的项目比软件自带配置文件要更好维护。
- 高度耦合:配置文件就如同系统对外API,一旦对外暴露就很难收回。作为模块的API,应该尽可能地小而窄,保持高内聚,低耦合
- 图灵完备性:很多带有『行为』的配置文件根本不是图灵完备的(即无法表达出计算机的所有行为),而基本上所有的编程语言都是图灵完备的。
本质上:配置文件与代码代表了两种编程范式:声明式(Declarative programming)与命令式(Imperative programming)。
当前,几乎所有计算机的硬件工作都是命令式的,也几乎所有计算机的硬件都是设计来运行机器代码,使用命令式的风格来写的。从这点来讲,大部分场景使用代码实现业务逻辑要优于配置文件。
3、代码 OR 配置文件
要回答这个问题,需要对配置文件的目的作出一个定义。
对于大部分的软件系统而言,配置文件是为软件系统的管理员而准备的,方便他们正确而高效地使用软件系统。这样的场景下,应强于代码而弱于配置文件。
这里总结了一些tips,仅供参考:
- 应当仅将简单的key-value配置放到配置文件中。
- 如果允许非开发人员快速改变程序行为,那么可以考虑配置文件。
- 任何涉及业务逻辑的地方都应该放到代码里实现,配置文件不建议加入业务『行为』。
- 如果配置改变需要代码改变,那么需要谨慎使用。
- 如果配置项仅仅是开发者理解的数据结构,那么需要谨慎使用。
- 使用者为配置负责,开发者为代码负责。
凡事终有例外。如这样的一个场景:应用程序需要允许用户(使用者)动态地配置复杂的规则(邮件用户想要定义复杂的邮件过滤规则),另外一些成熟的商业规则系统中也常用配置文件(作为DSL)解决一些特定领域的问题。
REFERENCES
https://stackoverflow.com/que...
https://zh.wikipedia.org/wiki...
https://zh.wikipedia.org/wiki...
https://blog.urth.org/2011/01...
http://mikehadlow.blogspot.co...
https://hackernoon.com/config...
http://taint.org/2011/02/18/0...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。