跳到内容

TOML 有什么问题?

# This is a TOML document.

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00 # First class dates

TOML 是一种配置,被设计为一种“改进”的 INI 文件。 它类似于这个项目 - StrictYAML,这是对 修复 YAML 缺陷 的类似尝试

# All about the character
name: Ford Prefect
age: 42
possessions:
- Towel

我不会在这里争论 TOML 是最糟糕的文件格式 - 如果你在小型简单文件上不经常使用它,它可以正常工作。

但这是一个警告:随着你使用它的范围扩大,许多不好的缺点就会开始出现。

PyTOML 的作者 Martin Vejnár 正好提出了这一点。 他最初出于对这种新格式的热情构建了一个 TOML 解析器,但后来放弃了。 当被问及是否希望将他的库作为 PEP-518 的一部分用于 pip 的依赖项时,他说不 - 并解释了为什么他放弃了这个项目

TOML 是一种糟糕的文件格式。 它乍一看很好,对于真正非常琐碎的事情,它可能很好。 但是,当我开始使用它,配置模式变得更加复杂时,我发现语法很丑陋,很难阅读。

尽管如此,PyPA 仍然继续使用 TOML 用于 PEP-518。 幸运的是,pyproject.toml 确实 非常琐碎,并且每个项目只出现一次,因此他提到的问题并不那么明显。

相比之下,StrictYAML 被设计为一种语言,用于编写 可读的“故事”测试,其中每个项目将有许多文件,具有更复杂的层次结构,在这种情况下,TOML 开始变得非常糟糕。

那么,当你将 TOML 的使用范围扩大时,它到底有什么问题?

1. 它非常冗长。 它不 DRY。 它的语法很嘈杂。

这个 StrictYAML 故事的示例它等效的序列化 TOML 中,后者最终 花费多 50% 的字符来表示完全相同的数据。

这主要是因为设计决策,要求每个键的完整名称都与每个值相关联,这**不是**DRY的。

这也部分归因于大量的语法冗余 - 引号和方括号在 TOML 文档中占主导地位,而在 StrictYAML 示例中则不存在。

在其他条件相同的情况下,缩短程序长度(和 DRY 代码)显着减少了错误数量,因为维护变得更容易,并且从代码中推断意图变得更加清晰。对于图灵完备代码,同样适用于配置代码。

2. TOML 的层次结构很难仅从语法中推断出来

TOML 中的映射层次结构由点确定。这对解析器来说足够简单,可以读取和理解,但仅凭这一点就难以感知数据之间的关系。

这一点已被许多 TOML 编写者所认识到,他们采用了对许多程序员来说非常熟悉的方法 - 解析器忽略的缩进。

Non-meaningful indentation

这类似于在具有括号等语法标记的许多编程语言中添加缩进的方式 - 例如,JSON、Javascript 或 Java 通常都使用未解析的缩进来使人类更容易理解它们。

但 Python 不是。

Python 长期以来一直是其设计方式的突出例外 - 语法标记不是推断程序结构所必需的,因为缩进确定程序结构的标记。

关于 Python 中有意义缩进优点的争论已经持续了几十年,而且并非所有人都同意这一点,但它通常被认为是一个好主意 - 通常是出于此堆栈交换问题中提出的原因

  1. Python 从(现已过时的)前身语言 ABC 继承了重要的缩进。ABC 是极少数使用可用性测试来指导设计的编程语言之一。因此,虽然关于语法的讨论通常归结为主观意见和个人偏好,但选择重要缩进实际上有更坚实的基础。

  2. Guido van Rossum 遇到了缩进与语法分组不一致的细微错误。有意义的缩进修正了这类错误。由于没有 begin/end 括号,因此解析器和人类读者感知的分组之间不会出现分歧。

  3. 使用符号分隔块和缩进违反了 DRY 原则。

  4. 它消除了典型的 C 语言宗教辩论,即“将大括号放在哪里”(尽管 TOML 还不足以流行到引发关于缩进的宗教战争...... 然而)。

3. 过度复杂:与 YAML 一样,TOML 的功能过多

有些讽刺的是,TOML 的创建者非常正确地批评 YAML 没有以简洁为目标,然后自己也陷入了同样的陷阱 - 虽然没有那么深。

它这样做的一种方式是尝试包含日期和时间解析,这引入了与日期和时间相关的所有内在复杂性。

日期和时间,正如许多更有经验的程序员可能意识到的那样,是一个意外的深奥的复杂性和古怪、意外、令人头疼且容易导致错误的边缘情况 的兔子洞。TOML 因为这一点而遇到了许多这些边缘情况

处理这类基本复杂性 的最佳方法是解耦,隔离复杂性并将其委托给擅长处理特定问题的专业工具,你可以在需要时进行更换。

这就是 JSON 所采用的方法(可以说是一个很好的决定),也是 StrictYAML 所采用的方法。

StrictYAML 库(而不是格式)有一个验证器,它使用Python 最流行的日期/时间解析库,尽管开发人员不需要也不必鼓励使用它。StrictYAML 默认情况下将所有内容解析为字符串,任何后续验证都被认为不在其范围内。

4. 语法类型化

与大多数其他标记语言一样,TOML 具有语法类型 - 标记的编写者决定是否将某些内容解析为数字或字符串,例如。

flt2 = 3.1415
string = "hello"

程序员在维护这一点时会感到宾至如归,但非程序员往往发现“1.5”和 1.5 之间的区别毫无必要地令人困惑。

StrictYAML 不需要在任何值周围加上引号来推断数据类型,因为模式被假定为类型信息的单一事实来源。

flt2: 3.1415
string: hello

在上面的示例中,它只是删除了两个字符,但在包含更复杂数据的较大型文档中,将类型解析决策推送到模式(或假设字符串)中会消除大量的语法噪音。

缺少语法类型以及使用缩进而不是方括号来表示层次结构,使等效的 StrictYAML 文档缩短了 10-20%,更简洁,最终更易读。

TOML 相比 StrictYAML 仍然具有的优势

目前仍然有一些

  • StrictYAML 目前没有“官方规范”。规范目前只是“YAML 1.2 与删除的功能”。这有一些优势(例如,编辑器中的 YAML 语法突出显示工作正常),但也有一些缺点(某些文档的呈现方式会有所不同)。
  • StrictYAML 还没有除了 Python 之外的其他语言的解析器。如果你想为你的语言编写一个(如果你不进行验证,实际上并不复杂),请联系我,我很乐意尽我所能帮助你 - 包括进行测试套件和文档编制。
  • 流行度。