Зарегистрировать UserInterface из секьюрити в контейнере, чтобы потом он мог резолвиться через автовайринг или парам резолвинг. Можно сделать, но это оверинжинеринг
А в чем именно оверинженеринг? Простенькая фэктори + строчка в конфиге
У меня в свое время получилось что-то вроде этого: https://github.com/BoShurik/telegram-bot-example. Отличие в том что я запоминаю не только команду, но и данные которые ввел пользователь, т.о. можно, например, заполнить заявку пошагово
Не скажу за автора, но я отказался из-за странной системы команд: невозможно пробросить свои зависимости в конструктор, как следствие — сложно интегрировать с существующим сайтом/приложением. Это больше похоже на фреймворк для создания бота, чем на библиотеку :)
При вашем подходе все равно придется следить за обновлением безопасности и фиксами ошибок (никто ведь не может быть уверен, что вы выкинули именно ту часть, которая эти ошибки содержит)
Ну и при подходе с композером никто не заставляет ждать цепочку "issue — fix — tag", всегда можете форкнуть и использовать форк до исправления ошибки.
Всё, что вы должны знать о переменных окружения в PHP:
Тенденция иметь только одну переменную, как APP_CONFIG_PATH, и читать её через '%env(json:file:APP_CONFIG_PATH)%' для меня выглядит как заново изобретать старый добрый parameters.yml
kernel.terminate не вызывается в консоле. Конкретно в этом случае это не важно, но если, к примеру, данные будут обновляться по крону из какой-нибудь API, то как тогда?
AwesomeAbility в моем примере далека до God-object, хотя она и правда имеет многовато обязаностей. Но слишком много обязаностей не всегда означатает God-object.
Если сейчас он таким не является, то в будущем — весьма вероятно, "если вдруг еще понадобится влиять на животных"
Но мы ведь говорим сейчас не так о декомпозиции, как о работе с зависимостями. У вас вручную создаются громоздкие конструкторы в вашем классе. И непонятно, кто именно будет создавать все эти листенеры и в них передавать зависимости.
DI контейнер. Если говорить о PHP и Symfony в частности, то даже конфигурировать почти не придется. Думаю в других языках есть аналоги.
Стейт и отображение решил бы так:
Код
class Unit
{
private $abilites;
public function activateStimPack(EventDispatcher $dispatcher)
{
$ability = new StimPackAbility($this, 10 /* seconds */);
$dispatcher->dispatch(Abilities::STIM_PACK_ACTIVATE, $ability);
}
public function deactivateStimPacks(EventDispatcher $dispatcher)
{
$abilities = $this->getAbilities();
foreach ($abilities as $ability) {
$dispatcher->dispatch(Abilities::STIM_PACK_DEACTIVATE, $ability);
}
}
}
class StimPackListener
{
public function __construct(EventDispatcher $dispatcher, GameTimer $timer)
{
}
public function onActivate(StimPackAbility $ability)
{
$ability->getUnit()->addAbility($ability);
// Add other effects
$timer = $this->timer->tick(function() use ($ability){
$ability->decSeconds();
if ($ability->getSeconds() == 0) {
$this->dispatcher->dispatch(Abilities::STIM_PACK_DEACTIVATE, $ability);
}
});
$ability->setTimer($timer);
}
public function onDeactivate(StimPackAbility $ability)
{
$ability->getUnit()->removeAbility($ability);
// Remove other effects
$ability->getTimer()->destroy();
}
}
У вас вместо одной супер-абилити будет множество эвентов, которые просто влияют на юнит
В моем подходе эвент = абилке. Я ее рассматриваю не как объект, а как процесс. В текущем варианте вполне можно их сохранять и выводить.
Кто отвечает за применение эффектов в вашем подходе? Сама абилка или юнит к которому она добавлена?
И как активируются AwesomeAbility из вашего предыдущего примера? Ведь по условию ее эффекты распространяются не только на того, кто ее использовал
На самом деле не претендую на правильность моего подхода. Просто решил посмотреть как он ляжет на вашу задачу. И вроде пока узких мест не вижу.
Я не совсем понял, как вы предлагаете создавать эту комплексную абилку?
$this->getEventDispatcher()->dispatch(Ability::AWESOME, new AwesomeAbilityEvent($subject, $target));
Вместо того, чтобы создать одну AwesomeAbility — создать 5 подабилок? А что это даст?
Это не пять абилок, это пять обработчиков одной абилки. Таким образом решаем проблему Single Responsibility. В вашем варианте у вас получается God-object
И тут мы пришли к тому, что вам писал mayorovp. На один слой больше за счет такой вот обертки.
Либо имеем нарушение принципа единственной ответственности, когда вебсокет сервер у нас еще занимается парсингом вывода и перезапуском упавших процессов.
Судя по источнику перевода, это у автора стиль такой, а не у переводчика
Что вы под этим имеете в виду?
https://github.com/symfony/website-skeleton/blob/4.0/composer.json
https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html
https://symfony.com/doc/current/frontend.html
А в чем именно оверинженеринг? Простенькая фэктори + строчка в конфиге
<?=
— это не short-tag, а алиас на<?php echo
,<?
— вот short-taghttp://php.net/manual/ru/language.basic-syntax.phptags.php
Не рассматриваете вариант выпустить хотфикс, где отключите эту возможность? Все-таки минорный релиз не должен ломать BC
Попытался поставить, но не заработало. Полагаю, потому что APIURL захардкожен (http://grigorov.com/abi/index.php)
У меня в свое время получилось что-то вроде этого: https://github.com/BoShurik/telegram-bot-example. Отличие в том что я запоминаю не только команду, но и данные которые ввел пользователь, т.о. можно, например, заполнить заявку пошагово
Не скажу за автора, но я отказался из-за странной системы команд: невозможно пробросить свои зависимости в конструктор, как следствие — сложно интегрировать с существующим сайтом/приложением. Это больше похоже на фреймворк для создания бота, чем на библиотеку :)
При вашем подходе все равно придется следить за обновлением безопасности и фиксами ошибок (никто ведь не может быть уверен, что вы выкинули именно ту часть, которая эти ошибки содержит)
Ну и при подходе с композером никто не заставляет ждать цепочку "issue — fix — tag", всегда можете форкнуть и использовать форк до исправления ошибки.
Зачем хранить пароли в одном файле/файлах, а не в конкретных переменных окружения?
Хотя бы поэтому: https://twitter.com/o_cee/status/892306836199800836
Увы но так нельзя. Точнее в этом мало смысла, т.к. у нас будет доступ ко всему конфигу сразу, а не к конкретному ключу
https://github.com/symfony/symfony/issues/24674#issuecomment-340267955
kernel.terminate
не вызывается в консоле. Конкретно в этом случае это не важно, но если, к примеру, данные будут обновляться по крону из какой-нибудь API, то как тогда?LuaJit на 7 месте с 8 секундами
Если сейчас он таким не является, то в будущем — весьма вероятно, "если вдруг еще понадобится влиять на животных"
DI контейнер. Если говорить о PHP и Symfony в частности, то даже конфигурировать почти не придется. Думаю в других языках есть аналоги.
Стейт и отображение решил бы так:
В моем подходе эвент = абилке. Я ее рассматриваю не как объект, а как процесс. В текущем варианте вполне можно их сохранять и выводить.
Кто отвечает за применение эффектов в вашем подходе? Сама абилка или юнит к которому она добавлена?
И как активируются
AwesomeAbility
из вашего предыдущего примера? Ведь по условию ее эффекты распространяются не только на того, кто ее использовалНа самом деле не претендую на правильность моего подхода. Просто решил посмотреть как он ляжет на вашу задачу. И вроде пока узких мест не вижу.
Это не пять абилок, это пять обработчиков одной абилки. Таким образом решаем проблему Single Responsibility. В вашем варианте у вас получается God-object
Я бы через Event Dispatcher сделал:
И тут мы пришли к тому, что вам писал mayorovp. На один слой больше за счет такой вот обертки.
Либо имеем нарушение принципа единственной ответственности, когда вебсокет сервер у нас еще занимается парсингом вывода и перезапуском упавших процессов.