package or not? it’s a problem
Erlang 的 maillist 这几天有这么一个帖子:
Time to update programming rules?
7.7 Module names
Erlang has a flat module structure (i.e. there are not modules within modules). Often, however, we might like to simulate the effect of a hierarchical module structure. This can be done with sets of related modules having the same module prefix.
If, for example, an ISDN handler is implemented using five different and related modules. These module should be given names such as:
isdn_init
isdn_partb
isdn_…We have packages! http://www.erlang.se/publications/packages.html
是的,这的确是一个看上去似乎是故意要让人迷糊的问题。一方面 erlang 允许使用 abc.bcd.cde 这样的 module 名称,另一方面 erlang 的 program rule 文档又建议大家在 module 上使用 flat name ,对于初学者而言,想不晕恐怕都很难。
name space 或者说 package 机制对于有 java 背景的人来说,是再熟悉也没有的了。它的好处就是“命名的自由”,“从前”的命名是一件很让人很苦恼事,又要担心“冲突”,又想足够“简洁”,常常让人挠破头皮而不得要领。但在 java 的世界里,这件事就变得异常简单——只要建了一个自己的 com.company.application 的 package,然后你就想怎么命名就怎么命名。想叫 String 也没有关系,大致不会冲突(只能是大致如此,仍有特殊情况)。而且,有了 eclipse 强大的 refactor 功能,你甚至还有了“随时改主意的自由”,又想出了更加牛叉的名字?直接改就是了。一个命令,全部自动搞定。……诸多好处不一而足,而所有这些荣耀,尽皆归于伟大的 name space 。
但从我个人的经验而言, erlang 的 package 虽说已经有了(雏形),但仍算不上成熟。回帖中的一个举例相当切中要害。
We can, and should, do MUCH MUCH better.
For example, if a module is going to be referred to elsewhere as a.b.c, and if we compile a module M by invoking “erlc M.erl”, then erlc a.b.c.erl should work. (It doesn’t.) Certainly if a module announces itself as “-module(a.b.c)” then compiling it should not produce a simple c.beam. (It does.)
就目前的状况而言,erlang 的 package 仍然只是“允许在 module name 中使用句点的 hack”而已,远远还谈不上“全面的 package 支持”。从 erlang/otp 自己的 souce code tree 来看,其代码的组织方式也并非“基于 package”,而是“基于 application”。在 package 这个问题上,现在的 best practice (到目前为止)仍然是“建一个 application 目录”然后在其中采用 flat module name 即 app_sys_module 这样的命名方式以避免命名冲突。
package 机制对于语言的应用繁荣非常关键(至少是大有裨益) —— cean 项目的诞生也许正是有感于此 —— 多个应用不再需要为了彼此之间有可能产生命名冲突而心存顾忌。这更利于代码重用,比较容易产生“多个应用彼此引用”的叠加效应(比如 mochiweb+couchdb 能重用 json 模块),而不是目前的“独立应用+runtime”模式。希望 erlang team 能够关注和改善这个问题。


Comments
更进一步,erlang 的 release 也可以分成两个部分:erlang vm 和 erlang lib 。
前者可以用 binary 方式来发布一个体积很“sexy”(大约 3m 就足够了)的运行核心,后者则以 source code/application 的方式来发布(下载源码到本地再编译),配以一个良好的“依赖管理”+“按需下载”系统(就像 MooTool 那样),就可以实现一个“mini size runtime”,而这恰好就是 java 正在努力追求的“瘦身”目标。
Package层次并不需要复杂
Smalltalk就一层分类(参考Squeak)
东西同样也很丰富
package 层次无关丰富。这个层次主要是对“第三方库的开发者”以及“多个项目的整合”有利。
假如 couchdb 和 mochiweb 都有自己的 json 模块(这只是一个比方,实际这两个项目共用了 json 模块),从“库的开发者”角度,都希望能“不受限”的将自己的模块命名为 json.erl 。但是不行,因为在有人想要整合两个项目时,就会出现重名问题。因而,目前比较好的实践方式是分别命名为 mochi_json.erl 和 couch_json.erl —— 各自带上不同的前缀,这能很好的解决问题。但实际上,这样的命名就是“flat package name”了之后的名字。只是目前的这个 flat 的过程要靠“手工+自觉”。
package/name space 的要义就是“命名的自由”,这个自由主要来自“不需要顾忌会和其他人的 module 发生冲突”。实现起来并不困难,对于 erlang team 来说,只是想不想做的问题。
Write a Comment