Pull to refresh

Comments 23

Маленькое дополнение:
>Moose — расширения для Perl 5, позволяющее упростить реализацию ООП.

Правильней было бы
«Moose — расширения для Perl 5, позволяющее усложнить реализацию ООП» — так как самый простой способ использовать ООП в перле — ничего кроме штатных средств не использовать.

А ещё правильней — Moose позволяет превратить Perl в другой язык (даже в несколько разных языков), с неожиданными свойствами, и насколько это оправдано — очень дискуссионный вопрос, есть доводы и за и против.
действительно, я когда изучал классы на перле, то bless довольно долго понимал, а moose — судя по реализации еще более замудренный и для его освоения все-таки нужно знать bless.
по всей видимости moose — это зачаток фреймворка какого-то
1. Moose в разы проще и изящнее чем старый способ ООП
2. Понимание работы ООП каким оно было до Moose не обязательно для работы с ним
1. Спорный момент. Да, в других языках такого нет (ну или по крайней мере я не встречал), но _проще_ ли оно от того? bless — это простое присвоение хешу (или иной сущности) метки — это «объект такой-то и оператор стрелка должна вести себя соответствующим образом ( $obj->f(1,2,3) === Obj::f($obj, 1, 2, 3) )». Во всем остальном работает со старым добрым Perl. Например, объект можно сериализировать обычным encode_json. Куда уж проще и изящнее?
Да, дорогой, он реально проще.
Сравним реализацию класса Person с конструктором, одним атрибутом, сеттером и геттером, ограничением по типу и обработкой ошибок.

Moose

package Person;
use Moose;

has last_name => (
    is  => 'rw',
    isa => 'Str',
);


Pure perl

package Person;
use strict;
use warnings;
use Carp 'confess';

sub new {
    my $class = shift;
    my %args  = @_;
    my $self  = {};

    if (exists $args{last_name}) {
        confess "Attribute (last_name) does not pass the type constraint because: "
                . "Validation failed for 'Str' with value $args{last_name}"
            if ref($args{last_name});
        $self->{last_nane} = $args{last_name};
    }

    return bless $self, $class;
}

sub last_name {
    my $self = shift;

    if (@_) {
        my $value = shift;
        confess "Attribute (last_name) does not pass the type constraint because: "
                . "Validation failed for 'Str' with value $value"
            if ref($value);
        $self->{last_name} = $value;
    }

    return $self->{last_name};
}


И представим, что в сеттере мы опечатались и написали, допустим, $self->{last_mame}…

Я люблю perl, но ооп в нём изначально не было, пришлось костылять.
Ну я вас умоляю. Вы описали только один атрибут. Но ни один нормальный человек не будет описывать в таком стиле 10 атрибутов, он их сгенерит любым удобным для него образом и в целом получит кусок того же самого Mo[ou]se, только без XS-реализации аксессоров, без ненужных в данном конкретном случае наворотов, и с большой вероятностью более компактный по интерфейсу и стилю описания. Да, у сабжа есть одно достоинство — он уже написан и уже умеет многое, и второе достоинство — он (по непонятным лично мне причинам) уже является одним из стандартов разработки. С другой стороны, вот вы выше написали пример аксессора, который (если сделать текст в confess короче) занимает менее 10 строчек, включая закрывающие фигурные скобки. Добавить сюда lazy — это завернуть строчки в еще один простой блок. Добавить билдеры — тоже тривиальное действие, несколько вариантов реализации на любой вкус. Начните писать новый проект — и грошовый по сложности функционал аксессоров довольно быстро и естественным образом осядет у вас в суперклассе, будет понятен и прост для восприятия и не будет иметь никаких космических возможностей, которые пока не нужны. Да и вообще, если речь только про аксессоры — на cpan хватает более простых реализаций. Из всего функционала, описанного в статье, пожалуй только augment не выглядит простой синтаксической надстройкой над тем, что уже есть в перле.
Если честно, я очень хочу поверить в Moose. Он у нас успешно используется, я уже писал с его помощью несложные классы, и разбирал чужие, но как-то без особой радости. Никак не могу понять, где же та граница, когда его использование становится действительно оправданным.
Это вы просто Moose не поняли ещё.
Это другой способ объявлять классы, с кучей удобных возможностей прямо «из коробки».
Чистый ооп в perl понять труднее, а Moose позволяет отвлечься от реализации ооп в perl и сразу делать классы и объекты.
В каком-то смысле это фреймворк, но это ведь не ругательное слово.
За заметку спасибо, НО

«этих знаний должно быть достаточно, чтобы успешно создавать ООП структуры на языке Perl»

Достаточно уметь пользоваться bless. Moose имеет право на жизнь, но bless быстрее и не требует сторонних модулей. И если уж очень хочется синтаксиса, отдаленно напоминающего традиционный, уж лучше использовать Mouse. Насколько я помню, он всего лишь на 40% медленнее blessed хешей.

Ну и, пожалуй, рискну сослаться на свою заметку по теме: eax.me/perl5-oop/
Лопаты тоже достаточно, чтобы выкопать котлован, но экскаватор лучше.
Если писать всё на «чистом» perl, код получается в разы длиннее, соответственно в разы больше вероятность опечататься.
Я сначала сомневался, производительность или удобство. Потом подумал, что проще сервак взять побыстрее, чем мучаться и выискивать, где там опечатка в геттерах и сеттерах… Всё-таки perl изначально не был рассчитан на ООП, отсюда и неудобство.
Я сам и правда остановился на Mouse, как компромиссе. MooseX модули не использую, и бог с ними.
С трудом верю. Пока что, по моим наблюдениям, код на Mouse/Moose получается заметно длиннее, чем без оного. Как Вам удалось сэкономить строчки, да еще в разы?
Стоило бы еще упомянуть, какой огромный оверхед при использовании Moose, я когда писал на Perl последний раз использовал Moo — полегче, побыстрее, понятнее search.cpan.org/dist/Moo/lib/Moo.pm
А насколько огромный оверхед? В документации на Moose, если не ошибаюсь, только про оберточные функции написано в контексте производительности.

Никакого «огромного» оверхеда там нет. Если, конечно, писать грамотно.
Не надо абузить проверки типов и модификаторы методов, делайте все классы неизменяемыми (immutable), и будет вам счастье.
UFO landed and left these words here
Точно так же.
Выше писали, что Moose превращает Perl в другой язык. Я считаю это неправильным и сбивающим с толку. Язык старый, базовые принципы — старые. Moose выдает самые обычные блесснутые хеши в виде объектов, просто у них есть несколько «магических» методов.
А Вы пробовали проходить отладчиком по Moose коду? Похоже нет.
Насчёт нового языка — если под Moose понимать только то, что описано в статье, конечно это не другой язык. Только в таком использовании Moose смысла нет — по сравнению с bless почти нет выигрыша, вся прелесть начинается при использовании дополнительных модулей, при построении своей системы типов, использовании валидации.
UFO landed and left these words here
Ну, если мануал почитать…
Для начала, concepts, classes, attributes.
search.cpan.org/~doy/Moose-2.0602/lib/Moose/Manual.pod

Вот, презентация по-быстрому:
www.houseabsolute.com/presentations/intro-moose-class/index.html

Потом, есть ещё книжка modern perl, легко нагуглить. Там в главе «объекты» просто написано — система в perl очень гибкая, но в ежедневных задачах помощи от неё маловато, поэтому modern perl oop == Moose. И дальше про Moose.
Стал бы я писать, если бы не проходил. Единственное, что реально достает — «джава–стайл» стектрейсы на два экрана. Остальное вполне терпимо, потому что отладчиком надо проходить не по Moose, а по своему приложению. Moose пусть отлаживают его разработчики.
Кстати, я не пытаюсь оправдать использование Moose там, где оно не нужно. Просто говорить, что он превращает Perl во что–то другое — неправильно. Из–за этого люди потом его «боятся».
Если вам надо всего–то генератор аксессоров и конструкторов, то да, есть методы попроще.
Господа, не забывайте про всем известный принцип TIMTOWTDI, особенно актуальный для такого языка как Perl
Не забываем, но как раз для перла это очень актуально — кто-то потом должен будет поддерживать все эти пути.
Sign up to leave a comment.

Articles