
Dmitry
27.09.2017
11:40:50
имя методу? у тебя нет метода

Sergey
27.09.2017
11:41:08
а еще это очень простой способ заставить разработчиков делать классы только с одним публичным методом)

F01134H
27.09.2017
11:41:29

Google

$iD
27.09.2017
11:41:34

Sergey
27.09.2017
11:41:55
которое ухудшает читаемость

$iD
27.09.2017
11:42:05
но не handle, а что-то типа BlaBlaHandler :)

Dmitry
27.09.2017
11:42:57
с invoke у тебя действие это имя переменной

Sergey
27.09.2017
11:43:05
приведи пример того что ты считаешь "плохо"
и я тебе переименую это что бы было хорошо)

Alexander
27.09.2017
11:43:21
__invoke позволяет в качестве агрумента передать как обычный колбэк, так и объект класса, это очень удобно когда делаешь стратегии, и некоторые стратегии не помещаются в обычный колбэк, а некоторые состоят всего из одной строки. аргумент?

Dmitry
27.09.2017
11:44:00
ну так... глагол определяет не объект, а использующий его код

Sergey
27.09.2017
11:44:23
с invoke у тебя действие это имя переменной
я не делаю разделения на "имена методов" и "имена переменных" и то и то должно быть со смыслом. А когда я говорю "хэндлер хэндлит" или "регистратор регистрирует" - я чувсвую себя имбицилом

Dmitry
27.09.2017
11:45:33
мда? ты в русском говоришь только "регистратор"? или только "регистрирует"?

Google

Oscar
27.09.2017
11:46:18
ну если бы в пхп использовался русский язык, то методы действия описывались бы глаголами в абсолютной степени

Sergey
27.09.2017
11:46:22

Oscar
27.09.2017
11:46:30
инфинитивы же называются вроде

Dmitry
27.09.2017
11:47:08
пример чего? твой пример достаточен

Sergey
27.09.2017
11:47:17

Oscar
27.09.2017
11:47:51
почему нет?
Пользователь -> создать, удалить, зарегистрировать, заблокировать
Запрос -> принять, перенаправить

Dmitry
27.09.2017
11:48:01
Когда ты передаешь интерфейс и потом аргумент вызываешь как функцию

Sergey
27.09.2017
11:48:04
как и "удалить"

Oscar
27.09.2017
11:48:36
Удалить пользователя, создать пользователя
я про это говорю и примеры абстрактны

Sergey
27.09.2017
11:48:54
а еще - если у тебя есть опыт с другими языками
https://www.typescriptlang.org/docs/handbook/interfaces.html

Dmitry
27.09.2017
11:50:38
т.е. давай все классы с одним методом публичным переделаем на invoke?

Sergey
27.09.2017
11:50:42
в python чуть интереснее конечно - Callable(...args, returnType)
профит:
- удобно
- расширение интерфейсов уже будет вызывать массу вопросов так как будет выглядеть мягко скажем странно
так что если у тебя есть цель ограничить разработчиков в том сколько они в интерфейс пихают публичных методов - почему бы и да

Google

Dmitry
27.09.2017
11:52:44
можешь дать чёткое определение?

Alexander
27.09.2017
11:53:41
всё ж самое большое удобство и самый большой профит в том, что можно вместо таких классов напихать разных callable и наоборот, вместо громоздких callable напихать классов

Mikhail
27.09.2017
11:54:03
Я, кстати, как и @fes0r использую __invoke для хэндлеров команд и прочих функции, просто из-за ущербности автозагрузки php использовать просто функцию без класса нецелесообразно. Но команда должны быть готова к магии $handler($args)

Sergey
27.09.2017
11:54:35
вместо класса-мока пишешь анонимку и все счастливы
это к слову один из способов уменьшить колиество моков в тестах - больше полагаться на лямбды

Mikhail
27.09.2017
11:55:46

Alexander
27.09.2017
11:56:03
во-во, либо наоборот, если анонимка грозится вырасти за пределы экрана можно классом заменить

Sergey
27.09.2017
11:56:34

Mikhail
27.09.2017
11:57:07
Т.е. сервисы инжектишь по callable? и настраиваешь все в контейнере?

Sergey
27.09.2017
11:57:27

Mikhail
27.09.2017
11:57:44
Ну вот я и удивился
Вот я и спрашиваю

Sergey
27.09.2017
11:59:06
public function changePassword(string $oldPassword, string $newPassword, callable $hashOf)
{
if ($hashOf($oldPassword) !== $this->password) throw new InvalidPassword();
$this->password = $hashOf($newPassword);
}

Alexander
27.09.2017
11:59:30

Sergey
27.09.2017
11:59:31

Google

Sergey
27.09.2017
11:59:51
а где ты их определяешь?

Alexander
27.09.2017
12:02:03
в самом начале разработки я пишу их прямо в index.php, позже уже выношу отдельно, группирую в классы и т.д., некоторые так там и остаются, потому что состоят из одной строки

Sergey
27.09.2017
12:02:08
или ты на всяких там люменах/сайлексах?

Mikhail
27.09.2017
12:02:41
Ну для маленьких приложений ок

Alexander
27.09.2017
12:02:58
я чаще просто беру набор пакетов из композера и всё

Mikhail
27.09.2017
12:03:00
Для больших — мешанина, нет ясности где искать хэндер
либо в index.php он заинлайнен или еще где

Alexander
27.09.2017
12:04:22

Mikhail
27.09.2017
12:04:54
А классы ты инициализируешь заранее?

Alexander
27.09.2017
12:05:34
контейнер это делает за меня

Admin
ERROR: S client not available

Alexander
27.09.2017
12:05:44
для этого PHP-DI юзаю
ну а так да, про размер приложений замечание верное: для маленьких такое подходит
а большие приложения я стараюсь из маленьких собирать)


Борис
27.09.2017
12:07:24
поддерживаю мнение, что __invoke костыль для совместимости с callable, и его юзать только если других вариантов нету (например его юзают в php-react/promises и получаются нормальные такие js like промисы). То что @fes0r ты сегодня вызываешь свой хендлер с реквестом, завтра другой вызовет с хуй пойми чем..... имхо интерфейсы лучше и нагляднее, потому что ты соблюдаешь контракт функции. Плюс тупо поиском по проекту сможешь найти в коде кто еще использует(именно вызывает) такой же интерфейс. (полезно при рефакторинге).
Опять же, хорошо что у тебя ловко получается писать сервисы. А если завтра тебе нужно будет добавить аргумент к функции (true\false флаг посылки емейла) например. Есть хорошее правила рефакторинга - открытый для добавления но закрытый для изменения. Чтобы поддержать обратную совместимость. Что ты будешь делать? Вынесешь в парент и сделаешь два класса вместо одного? ... ну хз, "принцип наименьшего удивления" очень хреново работает в таких __invoke командах


Pavel
27.09.2017
12:14:02
Почему "принцип наименьшего удивления" не работает с __invoke, если это поведение четко определено?

Mikhail
27.09.2017
12:14:38
__invoke($arg, bool $arg = false) не подойдет? Тут трэйдофф просто чтобы не создавать интерфейс ради одной имплементации.
Хотя насчет отсутствия способа зафиксировать сигнатуру при callable — разумно.

Sergey
27.09.2017
12:16:11

Google

Sergey
27.09.2017
12:17:18
и это не кастыль - это способ вызывать объекты как callable
ну то есть я не вижу тут ничего кастыльного.
юзать не юзать - по ситуации и в зависимости от контекста

Борис
27.09.2017
12:18:13

Sergey
27.09.2017
12:18:31
ты всеравно веришь наслово разработчику что если ты берешь две штуки которые реализуют один интерфейс их поведение будет одинаковым

Борис
27.09.2017
12:19:27

Sergey
27.09.2017
12:19:45

Alexander
27.09.2017
12:20:20
вы сегодня выходные?

Sergey
27.09.2017
12:20:23
ты не можешь в них выделить общий интерфейс как минимум потому что так говорит бабушка Лисков
поведение важнее сигнатур
короч спор на пустом месте... там где нужны интерфейсы я юзаю интерфейсы, там где мне нужна по сути анонимка с зависимостями я лучше буду юзать __invoke

Anton
27.09.2017
12:26:55
уже 3-ю минуту пишет

Борис
27.09.2017
12:27:44
ты не можешь в них выделить общий интерфейс как минимум потому что так говорит бабушка Лисков
Так ты сам себе злой буратино. Ты юзаешь __invoke только потому что он есть у каждого класса (считай ObjectInterface говорящий тебе, что метод __invoke существует, но с неопределенной сигнатурой).
А завтра если у тебя есть ComandOneService в который ты передаешь __invoke(AType a) и ComandTwoService в который ты передаешь __invoke(BType b) то привет полные штаны удивления, потому что теперь каждому разрабу нужно знать реализацию, чтобы точно разобраться что куда можно передать.
Лисков тебе говорит, что если ты реализуешь интерфейс, то не будь идиотом, и пиши реализацию так, чтобы она не ломала то, куда ты запихнешь эту реализацию.
В принципе я все, согласен что каждый решит для себя сам.


Pavel
27.09.2017
12:29:36
Мне вот например не понятно, почему __invoke вызывает затруднения
class SearchAccountAction extends Controller
{
public function __invoke(Request $request, AccountRepository $repository)
{
return $this->json(['result' => $repository->search($request->get('search'))]);
}
}


Sergey
27.09.2017
12:36:37
Так ты сам себе злой буратино. Ты юзаешь __invoke только потому что он есть у каждого класса (считай ObjectInterface говорящий тебе, что метод __invoke существует, но с неопределенной сигнатурой).
А завтра если у тебя есть ComandOneService в который ты передаешь __invoke(AType a) и ComandTwoService в который ты передаешь __invoke(BType b) то привет полные штаны удивления, потому что теперь каждому разрабу нужно знать реализацию, чтобы точно разобраться что куда можно передать.
Лисков тебе говорит, что если ты реализуешь интерфейс, то не будь идиотом, и пиши реализацию так, чтобы она не ломала то, куда ты запихнешь эту реализацию.
В принципе я все, согласен что каждый решит для себя сам.
почему им надо что-то там знать? что куда передается - происходит вполне явно. В моем случае информация о типах не скрывается и все вполне трекается штуками вроде phpstan.
> Лисков тебе говорит, что если ты реализуешь интерфейс, то не будь идиотом, и пиши реализацию так, чтобы она не ломала то, куда ты запихнешь эту реализацию.
именно так. И если у меня реализации подразумевают то что они не разные реализации одного поведения а разные поведения - то между ними нельзя выделить общий интерфейс.
короч да, закрываем тему


Patrik
27.09.2017
12:41:09
На тему __invoke все таки один минус есть, например в тестах, если допустим в setUp каждый раз создается экземпляр такого класса и помещается в проперти тестового класса, то в тестовых методах его уже не вызвать как $this->invocableClass(), будет фатал, приходится делать не совсем красиво $this->invocableClass->__invoke()

Mikhail
27.09.2017
12:44:34
($this->invocavleClass)()

Patrik
27.09.2017
12:45:59
не поможет, синтакс еррор

Pavel
27.09.2017
12:46:07
php 5?