自动生成数据库文档小工具的诞生

最近我用 Golang 开发了一个可以将数据库每张表的各个列信息转化成文档的小工具。开发的缘由是因为写后端时,经常需要为数据库写说明文档,对于稍微有些规模的项目来说,就动辄几十张上百张数据表,开发人员在文档中不断的写各个列的列名、类型、描述实在是无聊、枯燥和苦不堪言。所以就有了这个小工具的诞生。

项目地址在 这里

工具使用介绍

工具用 golang 开发的,所以直接使用 release 的可执行文件就可以, 无需复杂任何编译安装。

dbdoc -c config.json

在 config.json 文件中,按照格式配置好数据库信息,具体的配置方法如下:

{
  "db_info": {
    "db_type": "mysql",  // required
    "ip_port": "127.0.0.1:3306", // required
    "username": "root", // required
    "password": "", // required
    "schema": "cms" // required
  },
  "includes": [  // optional
  ],
  "excludes": [  // optional
  ],
  "template_path": "", // optional
  "out_path": ""  // optional
}

简单两步,就可以自动生成数据库的说明文档了。如下图
展示图

展示图中的文档模板是使用工具内置的 markdown 模板

开发过程

整个项目的思路其实非常简单,说起来其实就三步

  1. 读取数据库的各个表
  2. 依次读取每个表的列信息
  3. 将列信息转化成 markdown

虽然步骤简单,但是还是有些值得谈的东西。

数据库适配

目前这个小工具支持 MySQL 和 SQL Server, 这俩数据库在 SQL 语句上有着很大的区别。比如
MySQL 的读取当前数据库下的所有表名的语句是 show tables,而 SQL Server 的是 SELECT Distinct TABLE_NAME FROM information_schema.TABLES。除此之外,两个数据库的连接语句,查询列信息的语句,都有很大区别。
所以适配各个数据库,让这个工具支持多个数据库,是件非常复杂的事情。

我目前的做法给每个用到的 SQL 语句做一个工厂方法,给定一个数据库的类型,返回对应的 sql 语句。这种方法虽然复杂繁琐,但是有效。好在我们用到的 SQL 语句也不多,所以效率上也算还好。

目前还在调研各大 ORM 库是怎么实现的这个功能。这个也是以后着重要做的功能。

文档模板

我最初的本意是直接将信息转化成固定的 markdown 格式就可以了,想想既然都提取了表信息为何不做些更自由的做法——用户可以自己定义文档的格式。
比如,这个工具默认生成的格式是这样的:
markdown_preview

但是万一用户不想用这个格式,想给每个表格的标题加个编号,或者给每一列加个编号啥的。那这个工具生成的结果就完全没法用了。
不能将我的喜好强加给用户,那么,可以给用户提供足够自由的接口。

所以我提供了一个扩展的做法, 用户可以在配置文件的 template_path 项,配置一个自己定义的文档模板给工具。如果不提供的话,可以使用默认的模板,如下:

{{- .schema}} Document
{{range .tables -}}
# {{.TableName}}
|column|type|description|
| ------| ------ | ------ |
{{- range .Columns}}
|{{.ColumnName}}|{{.ColumnType}}|{{.Description -}}|
{{- end}}

{{end}}

这个模板的语法直接用的是 golang 标准库的 text/template, 文档在 这里。开始我本来想着随便搜个模板引擎用下,没想到 golang 直接在标准库里自带了。再次感叹下 golang 真是为工业化而生。

有了这个文档模板的功能,这个工具的想象空间变得很大。文档的格式不再局限于 markdown 了,用户可以随便定义文档的格式, html、json 都行。当然 word 的 doc 格式就是另外一个次元的事情了,我也在考虑是否以后加入进去。

以后要加的功能

  • 支持更多的数据库.
  • 支持导出格式为 Word、Excel.
  • 更人性化的命令行接口。目前我为了图省事,就直接传了个 - c。后期打算做成 MySQL 那样直观的接口

谈谈 Golang

这个项目是我用 Golang 做的第一个项目,Golang 在这种跨平台小工具,且完全无需考虑安装依赖的情况下是最好的选择了。Golang 的熟悉之后用起来几乎和 Python 一样快速。我在 文档模板 一节感叹,Golang 真是为工业化而生,把很多在其他语言里是三方库的东西直接做到了标准库。但是另一方面,由于 Golang 中模板和泛型的缺失,有些东西本该内置的又没有了。比如判断一个元素是否在数组中的方法 InArray,String 的 IsBlank 方法,都需要用户在项目中再单独写一遍。实在是无法理解

总而言之,如果以后有类似的小工具的需求,我依然会选择 Golang 或者 Python 作为首选的开发语言。