Laravel Чем вызван взрывной интерес к Лярве?

artoodetoo

великий и ужасный
Обычный инджект
PHP:
function(User $user) {
    return $uesr->find(1);
}
При этом можно даже на уровне роутоу заиндить модель
https://laravel.com/docs/5.2/routing#route-model-binding
это, что правда здо́рово? помоему магия с автоподсовыванием по тайпхинту нужна больше как демонстрации крутости )))
а если кроме User нужны другие данные, их тоже придется как-то передать.
почему фреймворк будет за меня решать, что передать просто как инстанс указанного интерфейса, а что (как в примере выше) связать с параметром роута и добыть по подразумеваемому ID?!

это путь боли, ящитаю.
 
Последнее редактирование:

Adelf

Administrator
Команда форума
@artoodetoo, я скорее всего с тобой согласен, но давай критикуй вежливо. Т.е. рассказывай какой путь считаешь правильным и почему.
 

artoodetoo

великий и ужасный
Моё ИМХО:
1) Неявную инъекцию объектов надо ограничить самим DIC. То есть когда мы командуем $service = $container->get('Ololo'), мы соглашаемся с тем, что контейнер знает как его создать, какой конкретный класс использовать и что подставить в конктрутор. Вот на этом и стоило бы остановиться. Не надо тотально "автоматически" инжектить всё и везде. Не надо магии.
2) Вполне допустимо в некоторой области, назовём её Application layer, явно тянуть объекты из контейнера, т.е. использовать его в роли Service Locator.
В эту область входят контроллеры и всё что служит для начальной загрузки приложения.
 

artoodetoo

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

Adelf

Administrator
Команда форума
А моё имхо - нигде в пользовательском коде не должно быть $container->get('Ololo') или \App::make(...).
Везде constructor injection или, для послабления в контроллерах, controller action parameter injection.
 

hell0w0rd

Продвинутый новичок
А моё имхо - нигде в пользовательском коде не должно быть $container->get('Ololo') или \App::make(...).
Везде constructor injection или, для послабления в контроллерах, controller action parameter injection.
а если нужно lazy инстанцирование сервиса?
 

Вурдалак

Продвинутый новичок
А моё имхо - нигде в пользовательском коде не должно быть $container->get('Ololo') или \App::make(...).
Везде constructor injection или, для послабления в контроллерах, controller action parameter injection.
В некоторых инфраструктурных штуках использовать контейнер для lazy loading вполне OK. К примеру: https://github.com/symfony/event-dispatcher/blob/master/ContainerAwareEventDispatcher.php

Но нужно понимать, что DI иногда попросту не нужен или бессмысленен, как в примере с User::find(), когда DI используется для внешнего прикрытия проблемы, но никак ее не решает. Не нужен также регистрировать сущности и VO в контейнере. Я уже не раз замечаю за некоторыми товарищами непонимание этого вопроса, когда static воспринимается как что-то плохое.
 

MiksIr

miksir@home:~$
а если нужно lazy инстанцирование сервиса?
Фабричный метод или прокси ;) Хотя сам в реальности все же в контроллере c контейнером работаю. Но это вопрос тонкости контроллера. Если там несколько строчек всего с подготовкой объекта формы... то почему бы и нет.
 

Adelf

Administrator
Команда форума
определение "пользовательского кода", можно? тогда наверное будет понятно почему нельзя. или ззя.
Твой код. Не фреймворковый.

В некоторых инфраструктурных штуках использовать контейнер для lazy loading вполне OK. К примеру: https://github.com/symfony/event-dispatcher/blob/master/ContainerAwareEventDispatcher.php
Ну это сложно назвать пользовательским кодом ;-)
 

AmdY

Пью пиво
Команда форума
это, что правда здо́рово? помоему магия с автоподсовыванием по тайпхинту нужна больше как демонстрации крутости )))
а если кроме User нужны другие данные, их тоже придется как-то передать.
почему фреймворк будет за меня решать, что передать просто как инстанс указанного интерфейса, а что (как в примере выше) связать с параметром роута и добыть по подразумеваемому ID?!

это путь боли, ящитаю.
Давай по пунктам.
1. Это не магия, это как раз явная передава методу данных, которые ему нужны, а не таскание внутри него из контейнером или явно new и т.д. Думаю причина понятна: прозрачно, легко менять зависимости, тестировать, мокать, менять реализацию...
2.Юзер появляется не волшебным образом, а явно через конфигурацию роутинга, где вы описываете какой параметр и по какому правилу получать. Опустись в доке на пару строк ниже до секции bind.
3. Это точно не дело контроллера. Ты предлагаешь инстанцировать нужный сервис, который знает как получать модель. Получить запрос. Извлечь из запроса нужный параметр. Дёрнуть у сервиса по этому параметру нужный метод и получить таки модель. А может не получить, нужно же ещё и ошибку обработать. В итоге на ровном месте у тебя куча действий и куча зависимостей, даже тест писать страшно.
 

Вурдалак

Продвинутый новичок
3. Это точно не дело контроллера. Ты предлагаешь инстанцировать нужный сервис, который знает как получать модель. Получить запрос. Извлечь из запроса нужный параметр. Дёрнуть у сервиса по этому параметру нужный метод и получить таки модель. А может не получить, нужно же ещё и ошибку обработать. В итоге на ровном месте у тебя куча действий и куча зависимостей, даже тест писать страшно.
А твой сервис, который уже внутри контроллера, никак несуществующую модель не обрабатывает что ли? По-нормальному, он выкидывает исключение типа UserNotFound и по нему и можно отрисовать 404.

Думаю причина понятна: прозрачно, легко менять зависимости, тестировать, мокать, менять реализацию..
Каким образом мокается User::find() (статический метод)? Типа делается в моке-наследнике свой static find()?

Вообще вам самим не противно иметь сервис $user, который непонятно то ли инстанс конкретного юзера, то ли был заинжекчен в качестве репозитория? :)
 

Вурдалак

Продвинутый новичок
Ну это сложно назвать пользовательским кодом ;-)
У меня подобное иногда возникает именно в моём, пользовательском коде. Всякие кастомные штуки, где я собираю по DI-тегами список serviceId, а потом в рантайме подгружаю (фабрики некоторые, например).
 

Adelf

Administrator
Команда форума
@Вурдалак, это твой код, но он чисто служебный. Ты просто дополняешь фреймворк нужными тебе вещами.
 

AmdY

Пью пиво
Команда форума
Каким образом мокается User::find() (статический метод)? Типа делается в моке-наследнике свой static find()?

Вообще вам самим не противно иметь сервис $user, который непонятно то ли инстанс конкретного юзера, то ли был заинжекчен в качестве репозитория? :)
Да это просто фантан.
Я предлагаю инджектить User, чтобы в контроллере было $user->.... , тут врывается Д'артаньян, рассказывает про мои проблемы и что не надо воспринимать статик как что-то плохое, а потом мне ещё и мокать статик метод предлагает.

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

Вурдалак

Продвинутый новичок
Да это просто фантан.
Я предлагаю инджектить User, чтобы в контроллере было $user->.... , тут врывается Д'артаньян, рассказывает про мои проблемы и что не надо воспринимать статик как что-то плохое, а потом мне ещё и мокать статик метод предлагает.
Сорян, я из этого поста:
Если видишь фасады или статические вызовы для AR вроде User::find, то надо сразу бить по рукам.
подумал, что можно писать и просто User::find(), но по каким-то неведомым соображениям ты это запрещаешь.
 

Adelf

Administrator
Команда форума
Я тоже сагрился на это. @AmdY просто не так выразился вероятно. Работая с Eloquent нереально не юзать эти ::find. В контроллере их не должно быть - это да.
 

artoodetoo

великий и ужасный
Давай по пунктам.
давай

1. т.к. настоящий параметр маршрута таки ID, а не инстанс User, то мокать его нетрудно ))) да и вообще юнит-тесты на контроллеры как-то не в ходу.

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

3. не надо утрировать, вся "куча действий" делается в любом случае. твоя магия экономит одно действие на экшн. сам биндинг параметров тоже не бесплатное действие.
 
Последнее редактирование:
Сверху