2017-01-06 7 views
4

Чтение все больше и больше о Perl, у меня возникают сомнения в том, как я организовал свои модули в своем текущем проекте.Иерархия и состав модулей Perl

У меня есть основное пространство имен - назовем его «MyProject».

В этом проекте базовые данные представляют собой графики, в которых каждый объект имеет класс. объекты связаны с отношениями. Оба объекта и отношения могут иметь атрибуты.

Существует часть проекта, где я использую модель для проверки этих графиков. Итак, у меня есть класс Model, который состоит из объектов класса Class, Relation и Attribute.

Классы Класс, связь и атрибутов используются классом модели только, так что имело смысл для меня, чтобы организовать модули следующим образом:

  • MyProject :: Модель
  • MyProject :: Модель :: Class
  • MyProject :: Модель :: связь
  • MyProject :: Модель :: Атрибут

Но я начинаю думать, что это будет мак Для меня смысл только в том случае, если я когда-нибудь осмелюсь передать часть моего проекта в CPAN. Я думаю, что люди будут полагать, что Class, Relation и Attribute наследуют модель и не составляют ее.

Итак: я должен реорганизовать мои модули таким образом:

  • MyProject :: Модель
  • MyProject :: Класс
  • MyProject :: Отношение
  • MyProject :: Атрибут

Или, может быть, указать, что класс, отношение и атрибут являются частями модели, добавляя их имена?

  • MyProject :: Модель
  • MyProject :: ModelClass
  • MyProject :: ModelRelation
  • MyProject :: ModelAttribute

Мой вопрос: Что в настоящее время считается наилучшей практики для организации модуля и обозначения, когда дело касается композиции?

Cross-posted at Perlmonks

+0

Действительно. Позвольте мне изменить свой вопрос с фактическими классами. –

+0

Под _композицией вы подразумеваете, что он использует объекты этих классов? – simbabque

+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 :: Магазин :: Session под капот. Основное приложение даже не знает, какой движок используется. Возможно, у вас нет Redis на вашей машине разработки, поэтому вы используете простые файлы.

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

Оба они есть, они принадлежат :: Session, но они не привыкают какой-либо другой части системы, поэтому мы подать их прочь, где они принадлежат.

Наследование

Мы также имеем продукты . Базовый класс продукта может быть таким.

OurCompany::Shop::Product 

И для этого есть файл.

OurCompany/Shop/Product.pm 

Просто, что это базовый продукт никогда не будет использоваться непосредственно в магазине, кроме проверки, что некоторые вещи должны иметь :: продукт в своем дереве наследования (это isa чек). Так что это отличается от :: Session, который используется напрямую.

Но, конечно, мы продаем разные вещи, и у них разные свойства. Все они имеют цены, но обувь имеет размеры и жесткие диски имеют емкость. Поэтому мы создаем подклассы.

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

И у них есть свои собственные файлы.

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

Мы могли бы также проводить различие между механической Жёсткий и SSD, поэтому мы делаем подкласс :: SSD.

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

OurCompany/Shop/Product/HardDrive/SSD.pm 

Так в основном вещи ставятся в том же пространстве имен, если они принадлежат друг другу. Вот древовидное представление нашей библиотеки.

. 
└── 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) Может быть, у нас также есть приложение BackOffice, который также использует одни и те же классы продуктов. В этом случае мы можем использовать их как OurCompany :: Product, и они будут использоваться двумя разными проектами: OurCompany :: Shop и OurCompany :: BackOffice.

+1

Это кристально чистое, спасибо! Но последнее беспокойство: предположим, что у меня есть компьютеры из дисков, процессора и бара (это глупый пример). Было бы разумно иметь класс Computer.pm. Но я все равно хочу группировать элементы компьютера в выделенном пространстве имен. В этом случае следует: 1- создать другое пространство имен для хранения компонентов: ComputerComponent :: Disk, ComputerComponents :: RAM, ComputerComponents :: CPU 2. Использовать пространство имен компьютеров, которое противоречит вашим рекомендациям? –

+0

@ Давид хм. Если ваше главное - это компьютер, тогда компьютер Computer: CPU, Computer :: Disk and Computer :: RAM имеет смысл.Но если помимо физических компонентов у вас также есть классы, которые делают что-то еще, то, возможно, компьютер, компьютер :: Component :: CPU, Computer :: Component :: Disk, Computer :: Role :: Portable. Если компоненты предназначены только для компьютера, разделите его так. Они не нужны для всех _ship с дистрибутивом Computer, поэтому они могут быть в разных репозиториях кода, но если вы хотите создать новый modul Computer :: Component :: Disk :: SSD и выпустить его, то root будет содержать пучок пустых папок сначала – simbabque

+0

ОК, поэтому в композиции я могу просто добавить пространство под-имен, которое будет использоваться для хранения компонентов. это имеет смысл, спасибо! –