软件工程的配置化思想

简介: 软件工程的配置化思想

为什么需要配置文件?


这个问题好像很白痴。

但我相信还是有很多人答不上来。

程序是现实世界中万物之间规则的映射。但规则并非一成不变的,所以程序需要不停的适配变化。是否能够快速响应变化,是评判程序好坏的一项指标,这需要很强的设计能力。

配置,是一种将程序运行时所以依赖的变量以一种外挂的形式存储,而不需要将配置硬编码到源代码,这样在每次需要修改变量时都不再需要修改源代码。

而配置化思想,是将配置合理运用到程序运行时的一种思想,同时也提高程序扩展能力和自由度的一个重要思想。

我将它归纳为三重境界。


第一重境界:命令行参数


要实现将变量提取到程序外部,最简单的方法当然是通过命令行参数来实现了。

现代编程语言一般是在启动程序的命令脚本后面直接追加变量,每个变量以空格分割。

比如 Go:


go run main.go hello world

比如 Java:


java MainTest hello world

再比如 Node.js:


node test.js hello world

而在程序内部都以一个数组类型的变量来接收传入的配置,并以传入顺序作为下标,这个变量通常叫做 args,arguments 的缩写。

比如 Go:


args := os.Args
for _, arg := range args {
    fmt.Printf("%v\n", arg)
}

比如 Java:


public static void main(String[] args) {
    for (int i = 0; i < args.length; i++) {
        System.out.println(args[i]);
    }
}

再比如 Node.js:


const args = process.argv;
for (let arg of args) {
  console.log(arg);
}


命令行参数的扩展


这种简单的传参方式当然会存在一些问题。

比如配置参数的类型默认都是字符串,需要自行转换。配置参数无法指定名字,必须按照顺序依次传递,如果有一些可选参数很难处理。

比如我需要这样:


node test.js name=hello -help

解决方式有很多,有的语言内置了解决方案,比如 Go 语言基础库的 flag 包。或者使用功能更加强大的第三方包来实现,比如 Node.js 的 commander。


第二重境界:文件


当配置参数过多时,再用命令行参数的形式会很繁琐,因为每次都需要输入一堆配置。

使用文件来持久化的存储配置是一个更优的选择。

实现配置文件的方式有很多,假设现在你忘记你掌握的文件配置手段。从命令行参数的角度继续思考,最简单的实现方案应该是这样的。


node test.js name=hello -help

把上面这段脚本存储到一个 shell 文件中,每次维护这里面的配置就可以了。

这种方式虽然一样可以实现利用文件持久化保存配置,但很明显,它不优雅。它把运行命令与配置耦合在一起了。

优雅的实现方式是将配置文件单独保存。

下面就要选择用何种配置文件存储配置了。常见的配置文件格式有三类,一类是通用型的文件格式,一类是自定义的文件格式,还有一类是脚本配置文件。

通用型的文件格式有很多,比如:ini、env、xml、conf、json、yaml、toml 等等。


INI、ENV 与 XML


这三者最为简单,ini 格式是初始化文件 Initialization File 的缩写,是 Windows 系统所采用的格式;env 是环境变量 Environment 的缩写,在 PHP 中备受欢迎;xml 应用范围极广,在早期的 Java 项目中非常常见,甚至曾被用作 API 的数据交互格式。但目前来说这三者都不再是最佳选择。

ini:


Name=hello

env:


Name=hello

XML:


<name>
  hello
</name>


JSON


由于与 JS 的天然契合性,json 是当之无愧的最流行配置文件格式之首。可惜 json 仍然有缺点,过于冗余,不支持注释。


{
  "name": "hello"
}


YAML 与 TOML


如果只是为了配置文件这个目的,YAML 和 TOML 是比 JSON 更优雅的选择。

两者都极其简洁,而且功能强大,可以非常友好的表示数组与对象。

YAML:


name: 'hello'

TOML:


name = "hello"

不同的是,相比于 13 年才出现的 TOML,YAML 更加成熟,它是在 2001 年诞生的。


自定义文件格式


自定义文件格式是自己拟定的一种格式,本质上与通用型的文件格式没有什么区别。

像 gRPC 的 proto 文件、babel 的 babelrc 文件等,都是自定义的文件格式。

自定义文件格式的实现并不复杂,最基础的无非是提供一种文件格式的解析器。但同时还要考虑在多个环境中配置高亮的问题。


脚本配置文件


当然还有更复杂的场景,比如 Webpack 的配置文件,是一个可以运行的 JS 文件。这是为了拥有更高的扩展能力而设定的。


第三重境界:UI 界面


程序员的世界里曾经流传着一句传说:

一切能用 JavaScript 实现的东西终将会用 JavaScript 实现

我在这里补充一句:

一切能用 UI 操作的东西终将会用 UI 操作

很显然,程序员不会满足于此。

配置文件的高亮、提示以及校验等配套功能是一个简单的文件系统无法提供的。

我们可能会需要在各个编辑器中提供插件来实现这些功能,但编辑器的市场非常庞杂,Sublime Text、VSCode、Intelij 系列...数不胜数。我们不可能为每一个编辑器都提供一个插件,而且用户安装插件的过程也很繁琐。

而校验配置是否正确也是一个麻烦事,我们不能在程序启动时再进行校验。常见的做法比如 Nginx 的 -t 参数。

而这些弊端,都可以通过在线的 UI 界面来帮助我们更好的完成配置编写。

到目前为止,我们讨论的用途主要仍然是在程序启动阶段依赖的配置。实际上,配置的作用不仅仅可以程序启动,在程序运行时依然可以起到作用。

常见的形式,比如 GraphQL Editor 和 Swagger Editor。

image.png

image.png

更甚者,可以通过拖拽的图形化界面来生成配置,以此来影响程序的运行,比如工作流引擎、Node-Red 等。

image.png

image.png


以上是我对现代软件工程配置化的分析与总结,希望对你有所帮助。



相关文章
|
6月前
|
敏捷开发 安全 测试技术
软件工程:从概念到实践
【8月更文第20天】随着信息技术的快速发展,软件在现代社会中扮演着越来越重要的角色。从简单的移动应用到复杂的操作系统,软件已经成为连接人与数字世界的桥梁。为了有效地开发和维护这些软件系统,软件工程应运而生。本文将探讨软件工程的基本概念、目标、原则以及常用的生命周期模型。
341 0
|
9月前
|
测试技术
软件测试概念与基础
软件测试概念与基础
|
运维 监控 架构师
第二章 软件过程与思想 第一节 基础
第二章 软件过程与思想 第一节 基础
|
开发框架 程序员
软件工程概念——是什么?软件工程的过程PDCA?生命周期模型有哪些?
在刚结束完的机房,它就是一个软件,我们如何使这个软件能够供更多人去使用,软件如何更加规范化,就需要使用软件工程的思想啦!
|
前端开发 程序员
引入软件工程的思想
引入软件工程的思想
|
测试技术 数据库 开发者
【总结】 软件工程过程及模型概括
【总结】 软件工程过程及模型概括
【总结】 软件工程过程及模型概括
《软件工程方法与实践》—— 1.4 软件工程的基本原理与基本原则
推迟实现。推迟实现是软件方法学的基本指导思想。软件开发过程应该理性地 “推迟实现”,即把逻辑设计与物理设计清楚地划分开来,尽可能推迟软件的物理实现。对于大中型的软件项目,在软件开发过程中,如果过早而仓促地考虑程序的具体实现细节,可能会导致大量返工和损失。
2310 0