Perl模块的层次结构和组成

Dav*_*din 4 perl module hierarchy

阅读越来越多关于Perl的内容,我对如何在当前项目中组织模块表示怀疑.

我有一个主命名空间 - 让我们称之为"MyProject".

在此项目中,基础数据是每个对象都有一个类的图形.对象与关系相关联.对象和关系都可以具有属性.

项目的一部分我使用模型来验证这些图.所以我有一个Model类,它由Class,Relation和Attribute类的对象组成.

类Class,Relation和Attribute仅由类Model使用,因此我有必要按如下方式组织模块:

  • MyProject的型号::
  • MyProject的::型号::类
  • MyProject的::型号::关系
  • MyProject的::型号::属性

但是我开始认为只有当我敢于在CPAN中重新部分我的项目时才对我有意义.我认为人们会相信Class,Relation和Attribute是继承Model而不是编写它.

所以:我应该这样重新组织我的模块:

  • MyProject的型号::
  • MyProject的::类
  • MyProject的关系::
  • MyProject的::属性

或者可以通过附加名称来表明Class,Relation和Attribute是Model的一部分?

  • MyProject的型号::
  • MyProject的:: ModelClass
  • MyProject的:: ModelRelation
  • MyProject的::的ModelAttribute

我的问题:在组合方面,目前被认为是模块组织和命名的最佳实践是什么?

在Perlmonks交叉发布

sim*_*que 9

你的顾虑是正确的.通常,包由包含继承命名.我将编写一个更现实的例子.假设我们正在建立一个在线商店.

入选

首先为项目选择一个命名空间.在商业世界中,您经常首先看到具有公司名称的命名空间,以区分专有模块和CPAN模块.所以项目的命名空间可以是:

OurCompany::Shop
Run Code Online (Sandbox Code Playgroud)

那么应用程序的主类或模块可能被称为相同,所以我们有一个

OurCompany/Shop.pm
Run Code Online (Sandbox Code Playgroud)

我们将有一堆东西,我们需要在网上开店.如果我们的项目是MCV,那么有控制器和模型以及类似的东西.所以我们可能有这些东西:

OurCompany::Shop::Controller::ProductSearch
OurCompany::Shop::Controller::Cart
OurCompany::Shop::Controller::Checkout
OurCompany::Shop::Model::Database
Run Code Online (Sandbox Code Playgroud)

所有这些都直接映射到模块.

OurCompany/Shop/Controller/ProductSearch.pm
OurCompany/Shop/Controller/Cart.pm
OurCompany/Shop/Controller/Checkout.pm
OurCompany/Shop/Model/Database.pm
Run Code Online (Sandbox Code Playgroud)

但是没有OurCompany::Controller基类.该名称只是用于对事物进行排序的命名空间.

然后有一些东西就在那里,并被OurCompany :: Shop使用,就像Session引擎一样.

OurCompany::Shop::Session
Run Code Online (Sandbox Code Playgroud)

除非它们非常具体,否则在项目结束后进入第一级.

当然,会话系统背后有一些引擎.假设我们很喜欢并使用Redis参加我们的会议.如果我们自己实施通信(我们不会因为CPAN已经这样做了),我们会坚持实施

OurCompany::Shop::Session::Engine::Redis
Run Code Online (Sandbox Code Playgroud)

唯一使用此模块的是引擎盖下的OurCompany :: Shop :: Session.主应用程序甚至不知道使用什么引擎.也许你的开发机器上没有Redis,所以你使用普通文件.

OurCompany::Shop::Session::Engine::File
Run Code Online (Sandbox Code Playgroud)

它们都在那里,它们属于:: Session,但它们不会被系统的任何其他部分使用,所以我们将它们归档到它们所属的位置.

遗产

我们还将提供产品1.基础产品类可以是这个.

OurCompany::Shop::Product
Run Code Online (Sandbox Code Playgroud)

并且有一个文件.

OurCompany/Shop/Product.pm
Run Code Online (Sandbox Code Playgroud)

只是这个基础产品永远不会被商店直接使用,除了检查某些东西必须在其继承树中有:: Product(这是一个isa检查).所以这与:: Session不同,后者直接使用.

但当然我们卖不同的东西,它们有不同的属性.所有这些都有价格,但鞋子有尺寸,硬盘有容量.所以我们创建子类.

OurCompany::Shop::Product::Shoe
OurCompany::Shop::Product::HardDrive
Run Code Online (Sandbox Code Playgroud)

那些有自己的文件.

OurCompany/Shop/Product/Shoe.pm
OurCompany/Shop/Product/HardDrive.pm
Run Code Online (Sandbox Code Playgroud)

我们也可能区分机械HardDrive和SSD,因此我们制作了:: SSD子类.

OurCompany::Shop::Product::HardDrive::SSD

OurCompany/Shop/Product/HardDrive/SSD.pm
Run Code Online (Sandbox Code Playgroud)

所以基本上,如果它们彼此属于同一个命名空间,那么它们就被置于同 这是我们的lib的树视图.

.
??? OurCompany
    ??? Shop
    ?   ??? Controller
    ?   ?   ??? Cart.pm
    ?   ?   ??? Checkout.pm
    ?   ?   ??? ProductSearch.pm
    ?   ??? Model
    ?   ?   ??? Database.pm
    ?   ??? Product
    ?   ?   ??? HardDrive
    ?   ?   ?   ??? SSD.pm
    ?   ?   ??? HardDrive.pm
    ?   ?   ??? Shoe.pm
    |   ??? Product.pm
    ?   ??? Session.pm
    ?   ?   ??? Engine.pm
    ?   ?       ??? File.pm
    ?   ?       ??? Redis.pm
    ??? Shop.pm
Run Code Online (Sandbox Code Playgroud)

总结一下:

  • 对于主模块,文件名是项目包名的最后一部分.其他一切都在那里.
  • 属于一起的东西被分组在一个名称空间下.
  • 继承自某事物的东西属于某个东西的命名空间.
  • 只被某个特定事物使用的东西归于那个东西.

永远不要像MyProject :: AB那样将事物附加在一起,以表明它属于MyProject :: A.始终使用命名空间分隔符来组织命名空间.考虑一下,这看起来很简单:

OurCompany::ShopProductShoe
Run Code Online (Sandbox Code Playgroud)

1)可能我们还有一个后台应用程序也使用相同的产品类.在这种情况下,我们可能将它们作为OurCompany :: Product,它们被两个不同的项目,OurCompany :: Shop和OurCompany :: BackOffice使用.