如何为不与内置或 CPAN 包名称冲突的自定义 Perl 模块选择包名称?
Posted
技术标签:
【中文标题】如何为不与内置或 CPAN 包名称冲突的自定义 Perl 模块选择包名称?【英文标题】:How do I choose a package name for a custom Perl module that does not collide with builtin or CPAN packages names? 【发布时间】:2010-10-14 02:57:58 【问题描述】:我已阅读perldoc on modules,但我没有看到关于命名包的建议,因此它不会与内置或 CPAN 模块/包名称冲突。
以往为了开发本地的Session.pm模块,我用我公司的名字创建了一个本地目录,比如:
package Company::Session;
... Session.pm 将在目录 Company/ 中找到。
但我只是不喜欢这种命名约定。我宁愿将包层次结构命名为更接近代码的功能。但这就是在 CPAN 上的一般做法......
我觉得我缺少一些基本的东西。我还查看了 Damian 的 Perl 最佳实践,但我可能没有找对地方......
关于以正确的方式避免包命名空间冲突的任何建议?
更新相关问题:如果存在包名冲突,Perl 如何选择使用哪一个?谢谢大家。
【问题讨论】:
附带说明,这正是 Java 命名空间首先使用域名完成的原因(内置类除外,它以 java. 或 javax. 开头)。 .NET 也有同样的问题... 【参考方案1】:为你的包选择一个你喜欢的名字然后谷歌搜索“perl the-name-you-picked”有什么问题?
【讨论】:
我正在寻找一种解决方案,它可以防止我的系统管理员安装 future CPAN 模块,该模块随后会与我的碰撞......【参考方案2】:如果您需要最大程度地确定您的模块名称不会与其他人的名称冲突,您可以从 Java 的书中获取一页:使用公司域的名称命名模块。因此,如果您为 Example, Inc. 工作并且他们的域名是 example.com,您可以将您的 html 解析器模块命名为 Com::Example::HTML::Parser 或 Example::Com::HTML::Parser。第一个的好处是,如果您有多个子单元,它们都可以有自己的命名空间,但模块仍然会一起排序:
Com::Example::Biz::FindCustomers Com::Example::IT::ParseLogs Com::Example::QA::TestServer但乍一看确实很奇怪。
【讨论】:
我没有说我会这样做,只是它给了你最好的保护。当我在 Capital One 时,我们使用 CapOne::*,因为我们有理由确定不会发生冲突,但如果另一个部门在同一台机器上并认为同样的事情,那么可能会发生不好的事情。【参考方案3】:以你的公司命名你的内部模块并没有错;我总是这样做。我的 90% 的代码最终都在 CPAN 上,所以它有“正常”的名称,但内部的东西总是以 ClientName::
开头。
我相信其他人也这样做。
【讨论】:
那个或项目的名称。 PITA 当营销决定更改名称时。 ;)【参考方案4】:命名空间Local::
已为此目的而保留。 CPAN 或核心不会接受以该前缀开头的任何模块。或者,您可以在***名称中使用下划线(例如 My_Corp::Session
或只是 My_Session
)。所有带下划线的类别也已保留。 (这在perlmodlib 中提到,在“为模块选择名称”下。)
请注意,这两个保留仅适用于***名称。例如,有名为 Time::Local
和 Text::CSV_XS
的 CPAN 模块。但是Local::Time
和Text_CSV::XS
是保留名称,不会被CPAN 接受。
以您的公司命名模块也可以。 (好吧,除非你为一些听起来很一般的公司工作。)使用反向域名可能是矫枉过正,除非你打算将你的模块分发给其他人。 (但在这种情况下,您可能应该注册一个普通的模块名称。)
Perl 如何解决冲突:
Perl 在@INC
中的目录中搜索具有指定名称的模块。找到的第一个模块就是使用的模块。因此@INC
中的目录顺序决定了将使用哪个模块(如果您在不同位置安装了同名模块)。
perl -V
将报告@INC
的内容(优先级最高的目录首先列出)。但是也有很多方法可以在运行时操作@INC
。
顺便说一句,Raku 可以handle multiple modules with the same name by different authors,甚至在一个程序中使用多个。这是一个不同的解决方案。
【讨论】:
据我所知,这是非常确定的,谢谢一百万。【参考方案5】:(我知道这篇文章很旧,但由于过去几个月我不得不整理一下,我想我会权衡一下)
在工作中,我们认为“Local::”感觉过于地域化。 CompanyName:: 我们也遇到了一些与开发无关的问题,我会跳过这些问题,不过我会说 CompanyName 很长,因为您必须输入数十次。
所以我们选择了“Our::”。当然,我们不是“CPAN 安全”的,因为可能有一天我们想使用带有 Our:: 前缀的 CPAN 模块。不过感觉不错。
Our::Data 是我们的 Class::DBI 模块 Our::App 是我们的通用应用程序框架,它执行配置处理和 Getopt 内容
读起来很舒服,打字也很好。
【讨论】:
我几乎认为 'Our' 应该为此添加到保留的命名空间中。三个字符不能被击败。可能感觉有点类似于我/我们的变量作用域,但是......也许这个比喻足够好。【参考方案6】:@INC
变量包含要在其中查找模块的目录列表。它从第一个条目开始,如果没有找到请求模块,则转到下一个条目。 @INC
有一个在 perl 编译时创建的默认值,但是您可以使用 PERL5LIB
环境变量、lib
pragma 更改它,并直接在 BEGIN
块中操作 @INC
数组:
#!/usr/bin/perl
BEGIN
@INC = (); #no modules can be found
use strict; #error: Can't locate strict.pm in @INC (@INC contains:)
【讨论】:
一位同事告诉我他是这样解决这个问题的,方法是将他的本地模块目录添加为第一个 @INC 条目。以上是关于如何为不与内置或 CPAN 包名称冲突的自定义 Perl 模块选择包名称?的主要内容,如果未能解决你的问题,请参考以下文章
如何为方法 MongoDB.Bson.Serialization.BsonSerializer.Deserialize 自定义映射字段名称或类型
如何为我的自定义 UICollectionViewCell 设置属性