command bus !== ООП?

Обсуждаем, как правильно строить приложения
Bio man
Сообщения: 609
Зарегистрирован: 2013.07.22, 10:40

Re: command bus !== ООП?

Сообщение Bio man » 2018.01.16, 14:28

Может глупый вопрос задам, но все-же.
К какому слою относится шина (интерфейс)? К прикладному?

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: command bus !== ООП?

Сообщение zelenin » 2018.01.16, 14:31

Bio man писал(а):
2018.01.16, 14:28
Может глупый вопрос задам, но все-же.
К какому слою относится шина (интерфейс)? К прикладному?
к слою приложения/сервисному слою. оркестратор всего что происходит в приложении.

Bio man
Сообщения: 609
Зарегистрирован: 2013.07.22, 10:40

Re: command bus !== ООП?

Сообщение Bio man » 2018.01.16, 14:34

Но реализация шины может быть в инфраструктуре или презентационном (если в шине используем \Yii)?

Bio man
Сообщения: 609
Зарегистрирован: 2013.07.22, 10:40

Re: command bus !== ООП?

Сообщение Bio man » 2018.01.16, 14:37

А как поступить, если в хендлере мне нужен логгер?
1. Делать свой адаптер и прокидывать в хендлер или
2. реализовать хендлер в инфраструктуре и прокинуть йиишный логгер?

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: command bus !== ООП?

Сообщение zelenin » 2018.01.16, 14:47

Bio man писал(а):
2018.01.16, 14:34
Но реализация шины может быть в инфраструктуре или презентационном (если в шине используем \Yii)?
презентационный - это адаптер приложения во внешний мир, принимает реквесты, отдает респонсы.
Реализация шины может быть в приложении или в инфраструктуре. Я предпочитаю такие вещи выносить в отдельные модули, а непосредственно в слое оставлять только фабрику.

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: command bus !== ООП?

Сообщение zelenin » 2018.01.16, 14:48

Bio man писал(а):
2018.01.16, 14:37
А как поступить, если в хендлере мне нужен логгер?
1. Делать свой адаптер и прокидывать в хендлер или
2. реализовать хендлер в инфраструктуре и прокинуть йиишный логгер?
хэндлер же ваш? отредактируйте его.

Аватара пользователя
ElisDN
Сообщения: 5015
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: command bus !== ООП?

Сообщение ElisDN » 2018.01.16, 17:14

Bio man писал(а):
2018.01.16, 14:37
А как поступить, если в хендлере мне нужен логгер?
Принять Psr\ Log\LoggerInterface и в инфраструктуре сочинить адаптер для Yii-шного.

Bio man
Сообщения: 609
Зарегистрирован: 2013.07.22, 10:40

Re: command bus !== ООП?

Сообщение Bio man » 2018.01.16, 23:36

Не хочу создавать новую тему, спрошу тут.
App слой может знать об инфраструктуре?

Мои команды лежат в app слое, но шина валидации лежит в инфраструктуре (и все интерфейсы относящиеся конкретно к этой шине).
Так вот, команды и валидаторы знают, что в инфраструктуре есть некие интерфейсы для шины валидации (CommandValidatorAwareInterface, CommandValidatorInterface).
Нужно ли перенести эти интерфейсы в app слой? Или как-то по другому их распределить? Или все в порядке?

Bio man
Сообщения: 609
Зарегистрирован: 2013.07.22, 10:40

Re: command bus !== ООП?

Сообщение Bio man » 2018.01.16, 23:41

Код: Выделить всё

// infrastructure
abstract class BaseCommandValidator implements CommandValidatorInterface
{
    protected $errors = [];

    public function getErrors(): array
    {
        return $this->errors;
    }
}

Код: Выделить всё

// application
class LoginValidator extends BaseCommandValidator
{
    /**
     * @var LoginCommand
     */
    private $command;

    public function __construct(LoginCommand $command)
    {
        $this->command = $command;
    }

    public function validate(): bool
    {
        return true;
    }
}

Код: Выделить всё

// application
class LoginCommand implements CommandHandlerAwareInterface, CommandValidatorAwareInterface
{
    /**
     * @var string
     */
    public $email;
    /**
     * @var string
     */
    public $password;
    /**
     * @var int
     */
    public $expirationTime;

    public function __construct(string $email, string $password, int $expirationTime)
    {
        $this->email = $email;
        $this->password = $password;
        $this->expirationTime = $expirationTime;
    }

    public function getHandlerClass(): string
    {
        return LoginHandler::class;
    }

    public function getValidatorClass(): string
    {
        return LoginValidator::class;
    }
}

Код: Выделить всё

// infrastructure
class ValidationCommandBus implements CommandBusInterface
{
    /**
     * @var CommandBusInterface
     */
    private $next;
    /**
     * @var Container
     */
    private $container;

    public function __construct(CommandBusInterface $next, Container $container)
    {
        $this->next = $next;
        $this->container = $container;
    }

    public function execute($command): CommandResult
    {
        if ($command instanceof CommandValidatorAwareInterface) {
            $validator = $this->container->get($command->getValidatorClass(), [$command]);

            if (!$validator instanceof CommandValidatorInterface) {
                throw new \UnexpectedValueException('Validator must implement CommandValidatorInterface.');
            }

            if (!$validator->validate()) {
                return CommandResult::failed($validator->getErrors())->withScope('validation');
            }
        }

        return $this->next->execute($command);
    }
}

sda
Сообщения: 331
Зарегистрирован: 2013.12.19, 09:29

Re: command bus !== ООП?

Сообщение sda » 2018.01.17, 00:04

Bio man писал(а):
2018.01.16, 23:36
Нужно ли перенести эти интерфейсы в app слой?
нужно

Bio man
Сообщения: 609
Зарегистрирован: 2013.07.22, 10:40

Re: command bus !== ООП?

Сообщение Bio man » 2018.01.19, 12:09

Это нормально, когда app слой использует интерфейсы из инфраструктурного слоя?
О каких интерфейсах речь спросите вы?
В инфраструктуре лежат фабрики хендлеров и валидаторов, которые используются шиной, и, эти реализации фабрик из инфраструктуры используют интерфейсы (CommandHandlerAwareInterface, CommandValidatorAwareInterface), что бы определить класс хендлера и валидотора. Соответственно, комманды должны эти интерфейсы заимплементить. Получается, что app слой зависит от инфраструктуры напрямую.
Норм это или проблема?
P.S. CommandHandlerAwareInterface, CommandValidatorAwareInterface тоже инфраструктурные, лежат рядом с фабриками.

noLogicOnlyWar
Сообщения: 75
Зарегистрирован: 2017.07.04, 20:53

Re: command bus !== ООП?

Сообщение noLogicOnlyWar » 2018.01.19, 12:18

Не норм. App layer об инфраструктуре ничего знать не должен.

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: command bus !== ООП?

Сообщение zelenin » 2018.01.19, 12:20

вики: инфраструктура - комплекс взаимосвязанных обслуживающих структур или объектов, составляющих и обеспечивающих основу функционирования системы

ComamndHandler - это сущность слоя Application. Почему она в инфре?
В инфре только реализации, и то не все. Часть функционала надо выносить в модули.
Вот у тебя есть в приложении модули Blog, Shop, Api. Все три модуля используют шину, шина - сущность уровня приложения, ее надо вынести в модуль MessageBus и создавать в модуле Application, который будет ядром приложения, объединяющим модули. В разных модулях понадобится HttpClient. Надо вынести в модуль HttpClient. Причем модуль может состоять только из одной фабрики, создающей например инстанс GuzzleClient. Можно написать свой интерфейс для клиента, адаптер клиента над газзлом и фабрику. Можно свой клиент написать на чем угодно.

Bio man
Сообщения: 609
Зарегистрирован: 2013.07.22, 10:40

Re: command bus !== ООП?

Сообщение Bio man » 2018.01.19, 12:28

zelenin писал(а):
2018.01.19, 12:20
ComamndHandler - это сущность слоя Application. Почему она в инфре?
Она в app. В инфре фабрики создающие хендлеры.

Получается, фабрики оставить в инфраструктуре, а Aware интерфейсы (которые используются командами и инфраструктурными фабриками) в приложении?

Bio man
Сообщения: 609
Зарегистрирован: 2013.07.22, 10:40

Re: command bus !== ООП?

Сообщение Bio man » 2018.01.19, 12:31

Что бы было наглядно, структура всего на данный момент
Изображение

Ответить