Как стать автором
Обновить

Комментарии 62

К слову, у меня пример на чистом perl работает, если приписать
use feature ':5.10';
Вот выйдет Perl6 и будет всем счастье.
Совершенно недавно начал работать с ООП в Perl, жесть конечно ещё та, но если делать, то уж делать на чистом перле, ибо если писать большие проекты, то из за всяких этих Moose::* производительность упадёт в разы!
Я не наблюдал падения производительности в разы. На моих тестах производительность может упасть на проценты, но никак не в разы. У меня так же есть достаточно большие скрипты (5000 строк), которые используют Moose и заметным падением производительности не страдают. Я даже через профайлер их проганял как-то. Другое дело когда используешь MooseX::Declare. Но причина такого поведения MooseX уже известна: нужно сторониться пакета MooseX::Method::Signatures.
Хочу добавить, что злоупотреблять ООП в Перле, конечно не стоит. Но в разумных пределах, почему бы и нет.
Ну не знаю, если оно есть, почему бы и не злоупотребить, если надо.
Половина модулей CPAN на ООП и ничего.
Да и такие гиганты как MogileFS и Perlbal тудаже, вот если б их на Moose писали, тогда бы и был возможно ответ на ваш первый комментарий.
А в целом решение одно — опять же — официальный выход Perl6, хотя чем дальше, тем всё мутнее история с его выходом.
Пока он выйдет все уже сбегут на Питон, Ruby и NodeJS.
А разве уже не сбежали?
хм… кажется нет, и даже проекты новые на Perl начинаем
Кстати, разве нода это ЯП?
Я думал это просто фреймворк для асинхронного программирования. А также такой фреймворк имеется во всех тобой упомянутых ЯП, а так же и в перле.
В 2001 году многие тоже так думали :) Но что-то счастье не приходит.
Хех… Вспоминается тот разброд, который был в Tcl до 8.6, когда не было стандартной объектной системы, но благодаря расширяемости языка она легко дописывалась, и каждый тиклер если не считал своим долгом, то просто по необходимости писал свою собственную. Собственно, разброд и продолжается, просто теперь есть одна «стандартная» система, которая рекомендуется к использованию — теперь нет нужды писать новые системы, ну только разве ради самообразования.
s/Moose/Mouse/g — и результат вас приятно удивит
Относительно Moose. Примеры, которые Вы привели, вообще к Moose отношение конечно имеют, но они без него ничуть не хуже могут быть реализованы, зато гораздо быстрее. А вот когда начинаем использовать Moose на полную катушку — тут и вылезают все его недостатки. Это и замедление работы — вызов метода до 6-ти раз может быть замедлен, и проблемы с отладчиком и профайлером, и невозможность форматировать стандартным perltidy модули, написанные на MooseX::Declare (да и редакторы от него дуреют).

Плюсы Moose для традиционного программирования — можно приблизить перл к нормальным типизированным языкам, организовать контроль типов в процедурах (хотя опять же и без него это можно сделать). Но то, что простая ООП модель перла превращается в кучу чёрных ящиков, которые страшно тронуть, все плюсы перечёркивает.

Я остановился на модулях ниже, и дальше не захожу — не окупается.

use Moose;
use Moose::Autobox;
use MooseX::Params::Validate;
use MooseX::StrictConstructor;
Примеры, которые я привел, были чисто иллюстративного характера. Конечно, они не имеют непосредственного отношения к реальному коду. Но это более менее то, что я потом использовал в тестах на производительность.

Насчет замедления вызова методов в 6 раз, это нужно уже на конкретном коде выяснять, что у вас там было. При описании методов с помощью Method::Signatures у меня такого не было. Но как вариант, Moose может сильно просесть если забыть написать make_immutable в конце пакета.

Там, кстати, магии и черных ящиков не много. По крайней мере в Moose написано, что он не использует source re-writing. Иллюзия раширения синтаксиса происходит за счет создания функций типа has, role, method.
6 раз — это использование всех прелестей оболочек вокруг функций — согласно документации. Конечно, это экстремальный случай.
>Там, кстати, магии и черных ящиков не много. По крайней мере в Moose написано, что он не использует source re-writing. Иллюзия раширения синтаксиса происходит за счет создания функций типа has, role, method.

Например, для обычного перла я могу вызвать caller() и получить вменяемый стек. А для Moose получается куча прокладок. Это, кстати, к вопросу о замедлении вызова методов — должно быть более заметно, чем у Вас в тестах получилось, мне кажется.
а как же
use MooseX::FollowPBP;
?
За MooseX::StrictConstructor спасибо, ага.
А расскажите, чем именно Вам так не угодил вариант использования чистого перла? Неужели написать тривиальную new() сложнее описания полей класса на птичьем языке Moose? Неужели тупо добавлять my $self = shift; в каждый метод насколько лениво?

Что касается тестов, то смущает незначительная разница в скорости на «доступ к свойству» — дайте я угадаю, вероятно Вы для тестирования чистого перла тоже написали getter/setter-функции для поля? Попробуйте сравнить скорость доступа к обычным ключам хеша, без getter/setter-ов. Нет, я понимаю, что из соображений «а если нам в будущем потребуется перехватить чтение/запись этого свойства для реализации какой-то функциональности» доступ ко всем полям должен быть только через getter/setter, но на практике для 98% полей это абсолютно не нужно — ни писать код getter/setter-ов, ни валидировать значения при записи, ни тратить лишнее время на вызов функции там, где можно было просто работать с хешем.

И, да, любопытно было бы увидеть аналогичные тесты с Mouse вместо Moose, как уже написал johnny_bee — Mouse вроде значительно по-легче будет.

Лично я считаю, что грузить в свой проект те дикие количества сложного чужого кода, которые тянет за собой Moose — довольно глупо. По крайней мере ради замены одного простого синтаксиса на другой, с добавлением кучи ненужных фич и дополнительных тормозов. Баги есть везде, и чем больше кода, тем больше в нём багов. А Moose это дикий монстр — попробуйте как-нибудь на системе, где активно используют perl, поставили немало CPAN-модулей, но не сильно увлекаются ООП, запустить установку Moose, и посмотрите сколько модулей он потянет за собой как зависимости и зависимости зависимостей… так вот все эти модули, может не сразу, но когда-нибудь подгрузятся таки в Ваш проект!
прелесть moose/mouse не в «птичьем» языке, а в meta — это очень мощный и удобный инструмент для метапрограммирования, с помощью которого можно творить очень классные вещи. плюс трейты, плюс не надо выдумывать свой велосипед для lazy_build. ну и всякий сахар их Moose::Exporter и Moose::Util
ну и остальное по мелочи

сеттеры-геттеры реально нужны — во-первых, некошерно лазить грязными рукими внутрь класса, во-вторых, они упрощают наследование. опять же coercion, хоть это и тормоз, но если отдавать себе отчет, что ты делаешь, можно аккуратно использовать.

но moose да, тормоз. в продакшен только mouse
Тут ключевое слово «себе» — 'если отдавать СЕБЕ отчет'. Вопрос — поймёт ли кто-то кроме себя любимого что происходит в программе.
не такой уж moose и тормоз. Использую его в довольно крупных проектах, ощутимо медленнее только старт приложения, на скорости работе практически не сказывается. В общем что уж говорить, Catalyst написан на moose.
и как только его переписали на Moose, тут же появился Mojolicious.
интересно добавить в сравнение Mouse, Object::Tiny, Moo и Mo
И M.
и o )
Да, Mouse я и сам хотел протестировать. Про Object::Tiny, Moo и Mo раньше не слышал. Как будет время, можно посмотреть.
Добавил ссылку на исходный код, кому интересно.
Хороший обзор, но!
черт побери, за вот это
sub make_noise {
my $self = shift;
say $self->{name}, " says: ruff-ruff!";
}

в приличном обществе можно схлопотать по шапке.
даже маленький тестовый пример не повод плевать на MVC.
Чего?
Спасибо за статью и в особенности за упоминание модуля Method::Signatures — не знал о нем.

По моему опыту, писать на Perl в ООП стиле без дополнительных модулей не представляет собой большой проблемы. Фактически — единственная сложность заключается в необходимости написать 3 строчки кода для конструкора, показав тем самым, что наш пакет написан в объектно-ориентированном стиле, а не в процедурном (любой package в Perl фактически является классом). По сути вы делаете то же самое с помощью строк use Moose; use Method::Signatures;. Стоит ли экономия одной-двух строк кода потери производительности?

ЗЫ. А в этой заметке показано, почему не годятся модули типа Class::InsideOut и иже с ним. То есть, как вы и отметили, фактически у нас две альтернативы — чистый perl и Moose.
> По моему опыту, писать на Perl в ООП стиле без дополнительных модулей не представляет собой большой проблемы.

Разница в том, что без дополнительных модулей для каждого класса нужно писать некоторое количество boilerplate кода. С модулями это количество сводится к минимуму. Когда пишешь код, например, для прототипа, то чем меньше этого ненужного boilerplate кода, тем лучше. С MooseX можно легко делать классы даже без создания для них отдельных *.pm файлов, и это очень удобно. (Конечно без модулей можно тоже *.pm не создавать, но тогда код будет выглядеть как нагромождение packages в одном файле.)

Практически с дополнительными модулями можно достигнуть удобности Питона, сохраняя при этом всю мощь Перла.
>> тогда код будет выглядеть как нагромождение packages в одном файле

Тут следует сделать оговорку, что можно писать примерно так: pastebin.com/Geg2znee Если не ошибаюсь, в perl 5.14 даже не нужна точка с запятой в первой строчке.
Забавляют реакции из серии «лишний код», «зависимости» и тэдэ.
Когда вы начинаете писать реально сложное приложение, которое должно быть расширяемым, управляемым и предсказуемым в процессе «жизненного цикла», то в итоге приходишь к сеттерам\геттерам, контролю и валидации данных объекта, исключеним, ролям, аспектам, инверсии зависимостей и всему остальному «монструозному».
Задумайтесь на минуточку — «монструозная» Java — чуть ли не стандар de facto для большого бизнеса.
Ширее надо смотреть на вещи, и не заниматься субоптимизацией прототипов.
С другой стороны, если подумать — Method::Signatures все же overkill. ИМХО пакет = класс, так к чему плодить сущности и упихивать все внутря, раздувая кавычечки?
Да, Вы абсолютно правы. Но есть предложение смотреть на вещи ЕЩЁ ширее, и реально сложных приложений не писать вообще! Keep It Simple. Простым приложениям зачастую ООП вообще нафиг не нужно.

Любое большое сложное приложение можно (и нужно!) разбить на кучу маленьких и очень простых, связанных между собой максимально тривиальными интерфейсами. И не важно, как эти маленькие приложения в конечном счёте будут оформлены — как независимые утилиты, сетевые сервисы, файл-сервера, модули/библиотеки, отдельные нити/группы нитей, или даже классы внутри цельного приложения. Это довольно непростая задача в плане разработки архитектуры, но оно того стоит — лучше когда сложность проявляется в процессе продумывания системы, а код остаётся очень простым и небольшим.

В плане решения проблемы сложности очень сильно прочищает мозг и открывает глаза изучение OS Inferno (думаю, и Plan9 тоже) — и в плане используемых архитектурных подходов к решению проблем, и в плане исходного кода (который крайне полезно почитать просто хотя бы ради повышения своей квалификации). Они умудрились порешать кучу сложных проблем невероятно просто и элегантно.
ммм… идеально, но не получится. В программировании нет ничего простого, а разрезание на кучу маленьких частей не упрощает итоговое приложение, сложность просто «размазывается» + накладные расходы на взаимодействие (в сложностном смысле, не трогаем производительность).
Кроме того не будем забывать, что приложения пишутся не сферическими программистами в ваккуме для самовыражения, а, в основном, по требованию бизнеса.
А для бизнеса: быстрее и надежнее лучше, чем дешевле.

с точки зрения бизнеса лучше гарантировано терять 5 штук баксов на еще один сервер, потому что медленно, чем неожиданно 50 штук, из-за того что внедренная фича все сломала или 500 штук, потому что требование не может быть реализованно архитектурно вообще.
Если лично Вы с чем-то не сталкивались, это ещё не означает, что оно не существует в принципе. Смешно, когда тебе рассказывают, что то, что ты (и многие другие) много лет делаешь, невозможно в принципе. :)

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

С точки зрения бизнеса, быстрее и надёжнее написать 10 маленьких и простых приложений чем одно сложное. Ибо маленькие проще понимать, быстрее писать, легче тестировать, поддерживать, в них меньше багов, и их дешевле заменить/переписать в случае совсем уж критических проблем. И дополнительное время и деньги потраченные на разработку архитектуры окупаются реально сторицей.

А насчёт «требование не может быть реализованно архитектурно вообще» — такое случается с любой архитектурой, вне зависимости от стиля исполнения. Но если система состоит из кучи мелких независимых приложений с простыми интерфейсам, то после глобального переделывания архитектуры под новые требования Вы с удивлением обнаружите, что в новой архитектуре можно использовать 90% старых уже готовых приложений вообще без переделок, как есть. Так что стоимость и время полного изменения архитектуры тоже сильно уменьшается.
хм. оффтоп конечно, но что из приличной литературы по архитектуре ПО на русском посоветуете?
Уж больно похоже на то, что в теме вы очень плотно, глупо не воспользоваться ситуацией и не спросить :)

И еще один вопрос, если позволите — инверсия контроля и создание объекта-можордома, который строит и возвращает нам любые иные объекты (не совсем абстрактная фабрика, но что-то типа) — плохая идея? Что-то меня в ней смущает, а без нее никак не пойму правильного применения Bread::Board.

PS. трехтомник Кнута для меня невкуряем.
С литературой сложно. Я мало чего действительно хорошего находил. Из книжек с ходу вспоминается разве что дядя Боб (на русский вроде их переводили, но я читал на английском). Как я уже говорил, лично я большую часть действительно ценных знаний по разработке архитектуры получил изучая архитектуру и исходники OS Inferno.

Что касается объекта — любые объекты и паттерны полезны в определённых ситуациях, как и оператор goto. Так что абстрактно заявить что он плох — я не рискну, не зная ситуации в которой он применяется. Но в общем такие объекты обычно плохи своей универсальностью. Универсальный код, как правило, прилично добавляет сложности в систему. А очень универсальный код, который вообще делает почти что угодно, обычно ещё и не делает ничего полезного.

В той же Inferno активно используется копипаст — вместо того, чтобы написать чуть более универсальную функцию и засунуть её в библиотеку, они тупо копируют её из одной программы в другую, иногда с мелкими изменениями. Когда я впервые _такое_ увидел, у меня был просто шок — и это написали «те самые монстры из Bell Labs!!!!111адинадин». А потом я заставил себя перестать давать оценку тому, что я вижу, и просто изучать как оно устроено… В результате через некоторое время у меня выработалось довольно отрицательное отношение к идее code reuse в целом, и в своих проектах у меня тоже появилась куча копипаста. И, что интересно — никаких минимально-серьёзных проблем из-за этого не возникает, а многие вещи сильно упростились.
Вообще дублирование — это зло, с которым лучшие умы от программирования воюют уже пол века :) Если вы докажите обратное, быть вам по меньшей мере новым Фаулером :)
Нередко лекарство оказывается хуже болезни. Дублирование бывает разное, и далеко не всегда оно уместно, но и точно так же далеко не всегда это зло. Это как с goto — новичку им лучше не пользоваться, будет эффект обезьяны с гранатой; но опытный профи вполне способен с помощью goto иногда заметно упростить код.

Чтобы доказать кому-то пользу от дублирования кода, надо чтобы он сначала осознал, сколько вреда вызывает даже небольшое усложнение кода — а уже дальше продемонстрировать факт усложнения кода из-за code reuse не сложно. Мои наблюдения показывают, что для того, чтобы понять «всю правду о сложности» обычно требуется не меньше 15-20 лет опыта.

Сейчас многие проходят этот этап, так что то тут то там изредка появляются осторожные посты в блогах на эту тему. Осторожные потому, что если заявить эти идеи громко и открыто то сейчас можно заработать не всеми :) желаемую репутацию странного типа с глупыми идеями. Но рано или поздно основная масса дозреет до восприятия этой идеи, и тот, кто в этот момент достаточно громко об этом напишет и станет «новым Фаулером».

А ребята из Bell Labs просто прошли этот этап достаточно давно, в то время они об этом говорили/писали, но практически никто не был готов воспринять эти идеи. Они реализовали эти идеи в Plan9 и Inferno, но эти системы так и не стали популярны т.к. заложенные в них идеи сильно опередили своё время и мало кто их тогда воспринял. А сейчас они тупо устали повторять и объяснять — пока народ не созреет, толку от объяснений мало; в maillist-ах иногда от них проскакивает что-то на эту тему, но мало и с отношением а-ля «кто понимает — тот уже и так понимает, а кто не понимает — пусть разбирается сам, агитировать и объяснять никто не будет». А на вопрос «как разбираться самостоятельно» обычно рекомендуют почитать исходники Inferno/Plan9. Как Вы понимаете, мало кто последует такое рекомендации… но кто последовал — не пожалел. Сейчас вот они предприняли очередную попытку популяризовать хоть часть этих идей, раз в полном объёме их так сложно воспринять — выпустили язык Go. Поглядим, что из этого получится.
Я категорически не согласен с утверждением, что от дублирования кода может быть польза и продолжаю утверждать, что с какой стороны не посмотри — это зло. Но соглашусь с тем, что бывают случаи, когда из двух зол дублирование является меньшим. Например, часто в тестах копипаста позволяет сделать код более читабельным и понятным.
Поздравляю, у Вас все признаки первой стадии — стадии отрицания и неприятия трагического факта. :-)

А если серьёзно, то Ваше заявление не имеет смысла. Всё что угодно можно объявить злом, и в то же время ничто не является злом абсолютным. Я могу (причём вполне искренне) заявить, что добавление любого кода (даже одной строчки) в программу — это зло, т.к. увеличивает её сложность, добавляет багов, etc. Но соглашусь с тем, что бывают случаи, когда зло от отсутствия необходимой фичи больше зла от добавления кода в программу. :)

Речь о том, что идеи, которые на данный момент принято считать «хорошими» — вроде ООП, DRY, code reuse, универсальности — обладают рядом скрытых недостатков (основной из которых увеличение сложности), важность и критичность которых недооценивается. А вещи, которые на данный момент принято считать «плохими» — вроде копипаста кода, goto, процедурной парадигмы — не столь ужасны, как их подают, и при адекватном использовании оказываются вполне «хорошими». И не просто «хорошими», а ещё и позволяющими решить те скрытые недостатки текущих «как бэ хороших» идей.

Возвращаясь к копипасту кода — он позволяет во многих случаях уменьшить сложность программы, и при этом не создать новых проблем (это факт из практики). Для меня это — скорее определения добра, нежели зла.

Ещё один пример того, что меня когда-то шокировало в коде Inferno: активное использование переменных с именами из одного-двух символов. Ещё одна ересь, как же. А на практике, если разобраться, получается не ересь, а ещё одна «ситуация goto». Длинные понятные имена переменных вводили, чтобы увеличить читабельность и ясность кода (и правильно вводили, новички любят создавать глобальные переменные с именем «a»). Но оказывается, что максимальная читабельность и ясность достигается тогда, когда длина имени переменной зависит от её области видимости — если переменная используется всего строчках в ~10, то вариант с именем из одного символа читается и воспринимается легче, чем вариант с длинным именем (на самом деле здесь хватает и других нюансов, но идея, думаю, понятна).
Подскажите мне название книги по теории программирования, в которой дублирование кода не считается проблемой. А еще лучше книги (ну или хотя бы статьи уважаемого автора), в которой дублирование приветствуется и под это подводится теоретическая база. Без этого продолжать дискуссию не вижу смысла ;)
Ок, закрыли тему. Если вдруг когда-нить передумаете, и понадобятся авторитетные источники в процессе переубеждения знакомых — можете ссылаться на меня. :)

Если честно, не люблю авторитеты — слишком много глупостей многие из них несут. «Умное лицо это ещё не признак ума. Все глупости на Земле делаются именно с этим выражением лица.» Так что наличие/отсутствие таких источников не может ничего доказать — надо своей головой думать.

Ну и кроме того, просто для ясности — я никогда не говорил, что дублирование кода это не проблема. Это проблема. Особенно бездумное дублирование в стиле «проще скопипастить эти 10 строк чем вызвать/отрефакторить функцию». Я говорил, что дублирование кода не так ужасно, как принято считать. И что оно позволяет решить некоторые серьёзные проблемы не создавая при этом новых серьёзных проблем из-за факта дублирования кода.
Смотрите на это с другой стороны. Код системы написан. Она использует внешние библиотеки, в которых обнаружены недоработки. Что делать? Править библиотеки нельзя — на них завязаны другие системы и они могут сломаться. Делать себе копию библиотеки и её править? А тогда дублирование возникает.

С другой стороны. Делаем систему, для неё делаем библиотеку. Потом делаем другую систему, библиотеку усложняем. И так далее. В результате получаем монстра, который делает всё что угодно, но каждой системе от него нужен только кусочек. Moose как раз этим и грешит — серьёзно использующие его (её) системы типа DBIX привязываются к конкретной версии, потому что половина функций помечены как нестабильные.

Какой-то компромисс нужен.
Именно. А для компромисса нужны определённые критерии, чувство меры, баланса. Вот чтобы это чувство натренировать, крайне полезно почитать сорцы Inferno, посмотреть в каких случаях они пишут библиотеки (и какие), а в каких дублируют код, etc. Забыть, что ты крутой профи с 15-20-летним стажем, что ты сам знаешь что как правильно и как не правильно делать, и начать снова учиться базовым вещам.
Опыт разработки программ с длительным временем использования показывает вроде бы простую и очевидную, но по факту непонимаемую многими вещь — через 10 лет эксплуатации системы про библиотеки все забыли, система работает как есть, без внешних компонентов, и править можно только по живому. То есть если и использовались внешние библиотеки, то они давно не поддерживаются и стали просто частью системы. Собственно это следствие того, что обычно рассматривается вопрос разработки, но не рассматривается вопрос поддержки.
Вы верно описали распространенную проблему. В качестве решения упомянутый выше Роберт Мартин предлагает использовать принцип открытости / закрытости: класс открыт для расширения, но закрыт для изменения.

Насчет компромисса — с этим сложно спорить. Более того, в случае если требуется небольшой функционал некого монстроподобного модуля разумнее его реализовать самостоятельно / скопировать. Но эта проблема связна как раз тем, что многие сипановские разработчики ничего не знают о хорошей архитектуре и пренебрегают лучшими практиками.С другой стороны, есть паттерны (фасад, адаптер) которые позволяют частично решить и эти проблемы.
Два варианта. 1)Долго тщательно разрабатывать интерфейс класса, чтобы его можно было наследовать, изменять, или 2) сделать только то что нужно сейчас, а в следующем проекте часть переписать, часть дописать, поменять интерфейс под конкретную задачу. Что Вы выберете? А ведь при любом планировании есть риск обнаружить, что врапперы становятся больше класса.

Тщательно разрабатывать интерфейс с расчетом на реюз в другом проекте я не рекомендовал бы, так как это как минимум противоречит YAGNI и KISS-у. С другой стороны, соблюдение SOLID принципов позволяет сходу получать классы, очень пригодные для повторного использования. Так что я за третий вариант :)
Design Patterns (GoF), Patterns of Enterprise Application Architecture (Martin Fowler), Design Patterns Explained (Alan Shalloway), Agile Software Development (Robert C. Martin). В последней книге детально описываются все SOLID принципы, так что она интересна не только в контексте аджайла. Все книги есть на русском.
GoF в основном ценна тем, что дала имена паттернам. Сейчас это уже не так актуально, услышав незнакомое название описание паттерна находится в инете за секунду. Научиться делать хорошую архитектуру по GoF крайне сложно.

Уж простите мне мою искренность, но Фаулер мне не нравится. Очень многие его идеи на мой взгляд достаточно сомнительны.

Третью (Alan Shalloway) не читал.

У Мартина (a.k.a. Uncle Bob) все книжки достаточно интересны, не только эта, но его я уже упоминал выше.
«Design Patterns Explained» как раз доступным языком описывает наиболее важные шаблоны из GoF. По ней можно знакомиться с паттернами, параллельно заглядывая в GoF.

Касательно «Patterns of enterprise application architecture» — это скорее не новаторские идеи, а попытка систематизировать существующие на тот момент лучшие практики. Многие паттерны до Фаулера были описаны в «Core J2EE Patterns» и других публикациях. Хотя тот же Active Record, который так удачно реализовали парни из RoR, и который является наиболее популярной реализацией ORM впервые детально описал именно Фаулер в упомянутой книге.
В целом по инверсии зависимостей рекомендую почитать вот этот материал. А вот здесь о DI контейнерах в перле.
А какая связь между ООП и сложностью приложений? ООП точно так же проповедует принципы слабой связанности, сильного зацепления, единственной обязанности и т.д.
Почти никакой. Если не брать наследование — эта часть ООП в большинстве случаев только добавляет избыточной сложности. Ещё можно добавить тот фактор, что ООП позволяет некоторое время «прятать» сложность, так что если писать одно и то же сложное приложение в процедурной парадигме и объектно-ориентированной, то в случае с процедурной Вы раньше заметите, что сложность программы становится неприличной, и стоит приостановить написание кода и переделать архитектуру для упрощения системы.
Именно поэтому наследование в современном ООП используется не так, как раньше, и заменяется агрегацией. Взять к примеру тот же декоратор.
bless \%self, $class;
return \%self;

а какой тут смысл слова return?
Не знаю, насколько осознанно автор использовал здесь return, но я всегда использую return для явности — чтобы сразу можно было отличить функцию которая что-то возвращает от функции, которая ничего не возвращает (в паскале такие называли процедурами, помнится).
В перле почти невозможно сделать процедуру, которая ничего не возвращает, наверно, на это и намекал NonRealDeveloper.

В случае же с return в new() есть практический смысл — после bless могут быть какие-то операторы, и не ставя на автомате return можно забыть это сделать и потом долго ловить неустойчивую ошибку.

Мне кажется, что автор вообще не очень правильно оформил new() — я бы переписал так:

sub new {
my $class = shift;
my $self = {@_};
bless $self, $class;
return $self;
}
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории