文件名:下划线、还是驼峰?

很久之前写了个 jsgf.vim 插件,可以在 js 代码中 gf 两键打开 import 的定义文件。

后来又针对 eggjs 的特性写了个 Vim 插件,可以 gf 两键打开 controllers, service 定义文件,阅读 eggjs 的代码方便多了,例如

1const resp = await ctx.service.mode.name.method();
2                     ^---------------------------

光标在箭头上方的任意位置按 gf 键就可以打开对应的代码定义文件。

image

但是有个问题,就是 eggjs 针对文件名带有下划线或中划线的,会替换成驼峰形式。即文件名为 app/service/path-name/mode_name.js 的路径,Loader 会转换成驼峰形式,在业务代码中必须以驼峰形式调用:

1// file path:      app/service/path-name/mode_name.js
2  const resp = await ctx.service.pathName.modeName.method();
3                                 ^------- ^-------

image

当时 eggjs 做这个目的,估计也说为了支持和顺应当时的文件名命名规范,当时大多数命名规范要求文件名用小写字母、数字、下划线和中划线。

但是,这种命名规范真的好吗?

我的答案是:绝对不好。

  1. 一致性:代码中的名字,和实际文件系统名字不一致。
  2. 确定性:代码中调用的是驼峰的,而实际文件名到底是驼峰,是下划线,还是中划线?这是不确定的。
  3. 唯一性:下划线和中划线都被替换成驼峰,如果同时存在 2 者甚至 3 者,这个定义不是唯一的。

eggjs Loader 要支持这种文件名,一个正则表达式就搞定了。很简单。

是的。但是用户要找到定义它的文件,可就苦了。首先需要知道这种(约定俗成的)替换逻辑(程序员的常识?),其次需要 O(3^n) 的时间复杂度和文件系统查询判断才能 不那么准确的 找到对应的定义文件。

eggjs Loader 加的这个功能,当时不觉得有什么不好,甚至觉得很不错。但是现在细想起来,有点画蛇添足,如果当时不做这个替换,开发者可以用下划线和中划线,下划线也可以在代码中直接使用,中划线你就自己难堪点,用 ctx.servcie['path-name']['mode-name'].method() 也不是不能用。

这样一致性、确定性、唯一性的问题都没有了。少即是多,什么都不做,反而是更好的选择。


随便一提:

有人说,用 vscode 就没这个困扰,确实,用户输入关键字,vscode 通过模糊算法把所有可能性都列出来,让用户判断和选择,长长的待选列表里确实是有你要的的选项,但更多的是你不要的选项,而且首先你得知道这个黑暗的替换逻辑,其次如果文件系统因为不唯一性,出现 2 个甚至 3 个可能的选项,用户是懵的。

排除不确定性,Vim 插件可以 gf 两键准确定位并打开对应文件,不可同日而语。


最后,我不想写个 O(3^n) 复杂度的算法来支持这个东西,然后用了一行命令搞定,业务代码都不用改一行,毫无违和感:

1$ git mv a_b-c aBC

参考


Category: Technology

Published on 2021-09-27

ON THIS PAGE