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

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

Похоже, вы не пометили пост как перевод и не указали источник. А за идеи, обозначенные в статье, благодарю)

Надеюсь что автор просто забыл пометить пост как перевод) На всякий случай я напомню, что оригинал тут http://davidhemphill.com/blog/2016/09/06/presenters-in-laravel/
Тут дело в том, что это публикация из Песочницы, у нас на данный момент нельзя писать в Песочницу «Переводы», только стандартные типы публикаций. Обычно в таких случаях указывают ссылку на оригинал хотя бы обычным текстом в конце публикации.
Мне всегда казалось, что подобную проблему решает ViewModel и DTO, но не Presenter
Очень странная реализация подхода с кучей кода в контроллере.
Давайте теперь добавим отчество, вы будете каждый контроллер править добавляя 'middle_name' => $user->middle_name?
НЛО прилетело и опубликовало эту надпись здесь
Использовали fractal для этих целей
строго говоря, то что Вы сделали, это не паттерн Декоратор, а паттерн Заместитель (Proxy)
ну а в целом да, спасибо, думаю многим будет полезно узнать, что можно изменять/расширять поведение и так
строго говоря, Вы не правы и презентер в статье это именно Декоратор, а не Прокси.
пересмотрел, согласен, всё-таки декоратор, простите мою невнимательность
Нет, вы были скорее правы.
Декоратор предполагает обёртывание объекта с сохранением интерфейса и предпологает обёртывание существующих методов, здесь интерфейса вообще нет, плюс добавляются новые методы. А здесь действительно прокси, так как проктирует обращение на модель, тем более магический __call выполняет функцию паблика морозова, нарушая инкапсуляцию, что недопустимо даже для презентера.
тут на самом деле смесь того и того, с уклоном больше в Декоратор
Вы тоже всё напутали. Именно Proxy дает доступ к внутреннему объекту с сохранением интерфейса но с например выполнением внутри дополнительной логики. А Decorator дает дополнительный функционал, т.е. имеет свой интерфейс.
т. е.
предполагает обёртывание объекта с сохранением интерфейса и предпологает обёртывание существующих методов

Вот это как раз Прокси
Они оба предполагают соблюдение интерфейса, но цель разная. Прокси контролирует объект, а Декоратор предоставляет возможность _динамического_ изменения поведения.
Соблюдение — да. Но как вы сами и сказали Декоратор дает дополнительное поведение.

Если кратко то вот:
Adapter предоставляет к своему объекту другой интерфейс.
Proxy предоставляет тот же интерфейс, управляя обращениями к вложенному объекту.
Decorator предоставляет расширенный интерфейс.
Вот, _расширять_. Потому что наличие интерфейса согласуется с принципом лискоу. При этом слово расширять — лучше понимать как наследовать несколько интерфейсов, соблюдая принцип разделения интерфейсов.
Я сам об это споткнулся пару лет назад, пришлось ставить костыли из-за наличия __call и обратной совместимости вместо нормально интерфейса.
Ну вот так в Ларе это работает. Отойдите вы от понятий php и от конкретной реализации. Для модельки ее возвращаемые поля можно вполне считать интерфейсом. Презентер же берет и добавляет возможность взять еще какие то данные, сохраняя доступ к старым. И возвращаясь к теме ветки обсуждения это как раз Декоратор.
Нет, вам следует убрать магический __call и тогда это будет презентер или viewmodel, а так это паблик морозов, который позволяет делать $object->delete() в слое представления.
А типо, я до этого так сделать не мог? Уж извините это дает мне AR.
Вообще Вы что то мешаете всё в кучу. Начинался диалог с опровержения определения структурного паттерна. Давайте по пунктам.
1. То что в статье (какое бы оно ни было) это Декоратор. Он именно сохранил всё что умел предыдущий объект. И добавил то что тот не умел.
2. Нет это никакой не «паблик морозов» (хотя я вообще не уверен можно ли дискутировать про шуточный антипаттерн). Он не позволит обратиться к закрытым методам внутреннего объекта. Он им был бы если бы враппер (использовано в общем смысле) был бы наследником или того же класса что и внутренний объект.
3. В статье «презентор» не имеет отношения к MVP. Так же как и ваша попытка притянуть сюда архитектурный паттерн MVVM а точнее его часть ViewModel.
4. Стоит ли убрать магический call из конкретно таких презентеров? Да возможно стоит.
Это вы смешали.
1. Нет, это декоратор, он сломал принцип лискоу, так как не сломал интерфейсы и не пройдёт тайпхинтинг.
2. Это паблик морозов, т.к. у вас model — протектид, а __call предоставляет к нему доступ как к публичному.
3. В статье недоразумение, а не паттерн, он нарушает сразу несколько солид принципов, о чём и был смысл данного обсуждения.
4. Обязательно уберите и код из контроллера тоже.
Я мог бы еще с вами спорить (даже писать начал) но мне лень. Я считаю что Вы не правы почти по всем пунктам.
AmdY в общем-то у декоратора и декорируемого один и тот же интерфейс должен быть, но расширять они его могут без проблем
image
Да, декораторы могут наследовать несколько интерфейсов, но не плодить свои. Это всё же динамический паттерн.
Не понимаю зачем добавлять лишний слой абстракции для Laravel когда он сам изначально реализует данный шаблон.
Eloquent: Accessors & Mutators

А если нужно приводить что-то к JSON или массиву — этот механизм тоже имеется у Eloquent.
Eloquent: Serialization

Потому что Так как Модели в Ларе это AR то они и так часто перегружены логикой. И порой хочется чуток их разгрузить. И тут кто во что горазд) Сериализация всё же мне нравится больше через уже упомянутый fractal. А вот презенторы приятно использовать как часть view layer.
Модели в Ларе это AR то они и так часто перегружены логикой

Потому что у фреймворков дебильное понимание MVC. :)
Но мне говорят постоянно, что я работал только с Yii, хотя это касается всех (мейнстримовых) :)
С кем то другим я бы подискутировал на тему AR и хорошо это или плохо, но только не с вами.
public function __call($method, $args)
{
return call_user_func_array([$this->model, $method], $args);
}


Мне тут ребята-фреймворщики рассказывали, что такое делать в самописи нельзя, типа не используем интерфейсы и все такое:
https://habrahabr.ru/company/mailru/blog/308788/

Что ж Вы такое советуете? :)
Я презентеры делаю, но не так. Ваш пример я назову anemic presenter :) по сути набор хелпер-функций.

У меня обычно получается в контроллере что-то вида

return ['fooBar' => $fooBarPresenter->render($foo, $bar)]; // ну или $view...->with(...);

А вся логика представления для данного блока находится в FooBarPresenter.

Презентеры могут внутри создавать другие презентеры — как для комбинаций, так и для коллекций.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории