Perl模块的层次结构和组成

时间:2017-01-06 10:37:03

标签: perl module hierarchy

越来越多地了解Perl,我对如何在当前项目中组织模块表示怀疑。

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

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

项目的一部分我使用模型来验证这些图表。 所以我有一个Model类,它由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

我的问题:当谈到合成时,模块组织和命名的最佳实践目前是什么?

Cross-posted at Perlmonks

1 个答案:

答案 0 :(得分:9)

您的担忧是正确的。通常,包由包含继承命名。我要编写一个更现实的例子。我们假设我们正在建立一个在线商店。

<强>夹杂物

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

OurCompany::Shop

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

OurCompany/Shop.pm

我们将拥有制作网上商店所需的一系列东西。如果我们的项目是MCV,那么有控制器和模型以及类似的东西。所以我们可能有这些东西:

OurCompany::Shop::Controller::ProductSearch
OurCompany::Shop::Controller::Cart
OurCompany::Shop::Controller::Checkout
OurCompany::Shop::Model::Database

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

OurCompany/Shop/Controller/ProductSearch.pm
OurCompany/Shop/Controller/Cart.pm
OurCompany/Shop/Controller/Checkout.pm
OurCompany/Shop/Model/Database.pm

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

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

OurCompany::Shop::Session

那些在项目结束后进入第一级,除非它们非常具体。

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

OurCompany::Shop::Session::Engine::Redis

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

OurCompany::Shop::Session::Engine::File

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

<强>继承

我们还将有产品 1 。基础产品类可以是这个。

OurCompany::Shop::Product

并且有一个文件。

OurCompany/Shop/Product.pm

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

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

OurCompany::Shop::Product::Shoe
OurCompany::Shop::Product::HardDrive

那些都有自己的文件。

OurCompany/Shop/Product/Shoe.pm
OurCompany/Shop/Product/HardDrive.pm

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

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

OurCompany/Shop/Product/HardDrive/SSD.pm

所以基本上,如果它们彼此属于同一个命名空间,那么它们就会放在同一个命这是我们的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

总结一下:

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

永远不要像MyProject :: AB一样追加它们以表明它属于MyProject :: A。始终使用命名空间分隔符来组织命名空间。考虑一下这看起来很简单:

OurCompany::ShopProductShoe

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