Sufir
Я не волшебник, я только учусь
Позволил себе поделиться скромным опытом https://habrahabr.ru/post/321340/
Последнее редактирование модератором:
$client = $builder->setId($id)
->setName($name)
->setGeneralManagerId($generalManager)
->setCorporateForm($corporateForm)
->setAddress($address)
->buildClient();
$client = $factory->createClient(
$name,
$generalManager,
$corporateForm,
$address
);
А что тебе мешает перевести существующую таблицу на sequence? Берешь, увеличиваешь на продакшен таблице AUTO_INCREMENT на 100500, создаешь sequence с id, который был максимальный на момент увеличения. Тут главное, чтобы на время тестов твой sequence не «догнал» AUTO_INCREMENT с прода. Потом после деплоя увеличиваешь sequence как MAX(id) + 100500. Я так не одну legacy-таблицу переводил, потому что с AUTO_INCREMENT работать невозможно.Но иногда возникает необходимость работать с уже существующей структурой БД, в которой таблица хранящая соответствующие данные имеет для идентификатора автоинкрементное поле.
Не хотел перегружать, т.к. тема другая, но теперь тоже думаю, что это ошибка.Твой пример с Client выглядит неубедительно отчасти из-за того, что там вовсе нет логики.
Ну, во-первых потенциально некоторые могут быть опциональными, или стать такими при изменении требований. А во-вторых избавляет от портянки аргументов в одном методе за счет fluent interface. Кто-то здесь на форуме плевался, что мол, пусть лучше будет потенциально невалидный объект, но я его сеттерами построю, чем пол десятка и больше аргументов, а не так давно то же самое и на работе услышал. Вот тут и сеттеры есть и сущность недоделанная не появится. И в общем-то резонно, читабельность повышается, хотя становится не очевидно какие обязательны - диалектика.Касаемо ClientBuilder. Неясно почему именно builder.
Хотел, но что-то утомил он меня к концу уже, нет сейчас мотивации, а потом забуду. Там можно комментировать аккаунтами readonly сейчас, просто такие комменты автор подтвердить должен, напиши. Да и собственно замечания тоже, хоть один коммент напрямую по делу будет, а не по касательной.Тут важно таким людям объяснять различие этих валидацией, они с разных уровней, в определенном смысле — из разных контекстов. И ничего плохого в таком дублировании нет.
Заменяя ловлю статической ошибки (несоответствие аргументов конструктора) на ловлю рантайм ошибки. Ну это как перейти от статической типизации к динамической.А во-вторых избавляет от портянки аргументов в одном методе за счет fluent interface.
Ээ, ну, = null поставишь. Или другой named constructor сделаешь.Ну, во-первых потенциально некоторые могут быть опциональными, или стать такими при изменении требований.
А что плохого в «портянке аргументов», если уж её не избежать? Не очень красиво выглядит?А во-вторых избавляет от портянки аргументов в одном методе за счет fluent interface.
Да, не очень, впрочем лично меня бы это не сильно смутило, но это компромисс в том случае когда у человека непереносимость большого количества атрибутов. Как пример - http://phpclub.ru/talk/threads/infrastructure-vs-domain-или-как-реализовать-правила-предметной-области.81226/#post-735744Не очень красиво выглядит?
По-моему, это просто мнение человека, который недостаточно разобрался в ситуации, но кричит громче всех. Зачем тратить своё время на некомпетентных людей?Да, не очень, впрочем лично меня бы это не сильно смутило, но это компромисс в том случае когда у человека непереносимость большого количества атрибутов. Как пример - http://phpclub.ru/talk/threads/infrastructure-vs-domain-или-как-реализовать-правила-предметной-области.81226/#post-735744
— wat? Мне всегда казалось, что в конструктор нужно передать те данные, которые необходимы для корректного конструирования объекта. Если какое-то поле обязательное, а его не передают, то идите в жопу, у вас невалидные объекты, 3D точка без Y, Z координат.Когда ты создаёшь объект, тебе должно быть необходимо и достаточно передать ТОЛЬКО данные, уникальным образом его идентифицирующие.
— сразу чувствуется знаток сеттеров с требухой и валидацией.Всю остальную требуху - в сеттеры, с валидацией.
Можно просто дать ссылки на похожие мнения:Хотел, но что-то утомил он меня к концу уже
О какой авторизации речь, проверке, может ли выполнить пользователь данную команду или запрос? У меня проект был на Yii2, я использовал их RBAC на уровне приложения, в домен ничего не тащил. Впрочем там система достаточно простая статичная была.Кстати, можете скинуть пример кода, в котором есть авторизация определенных действий в домене
Я обычно выделяю интерфейс, вроде IdentityGenerator, а реализацию тоже к репозиторию цеплял.А кстати, _где_ кто генерирует ID? Я раньше фабрики-аллокаторы делал, а щас просто сую метод allocateId() в репозиторий, не очень эстетично, зато практично
$generator = $container->get(IdentityGenerator::class);
$generator->allocateId();
Можно и не делать, я делал, не в падлу, дело минутное. Это ж ISP. С дженериками было бы приятнее конечно. И в теоретическом случае изменения способа генерации уже несколько странновато будет помещать в репозиторий генерацию UUID к примеру.Насчет интерфейса IdentityGenerator не понял, не вижу смысла в таком при отсутствии дженериков. Делать интерфейсы типа UserIdentityGenerator на каждую сущность, у которой может быть id? А зачем?
Я генерирую до вызова команды:А кстати, _где_ кто генерирует ID? Я раньше фабрики-аллокаторы делал, а щас просто сую метод allocateId() в репозиторий, не очень эстетично, зато практично
$id = $this->sequence->generate('client');
$this->bus->handle(new RegisterClient($id, ...));
$client = $this->clientQueryService->find($id);
Ну да. Т.е. есть требование, допустим, что только менеджер может регистрировать нового клиента. Вроде, должно быть в домене. Значит нужно вводить понятие текущего пользователя/контекста безопасности, и как-то проверять. Или делать отдельный сервис, или спрашивать сущность. Вот такие примеры хочется, кто как делает. Кое-что накопал, но пока мало.О какой авторизации речь, проверке, может ли выполнить пользователь данную команду или запрос? У меня проект был на Yii2, я использовал их RBAC на уровне приложения, в домен ничего не тащил. Впрочем там система достаточно простая статичная была.
Домен домену рознь. Есть понятие контекстов. Есть контекст твоей модели, а есть контекст прав доступа. И контекст прав доступа можно реализовать в виде штатных средств фреймворка. Подобные домены обычно называют generic, т.е. они могут быть в виде библиотеки и переиспользоваться в разных проектах. Обычно нет нужды пилить свои модели а-ля Role. Но нужно сконфигурировать, да.Ну да. Т.е. есть требование, допустим, что только менеджер может регистрировать нового клиента. Вроде, должно быть в домене. Значит нужно вводить понятие текущего пользователя/контекста безопасности, и как-то проверять. Или делать отдельный сервис, или спрашивать сущность. Вот такие примеры хочется, кто как делает. Кое-что накопал, но пока мало.
class Entity
{
private function __construct() {}
static function create($param1, $param2, ...): Entity
{
$new = new static();
...
return $new;
}
static function createSpecial($paramX, $paramY, ...): Entity
{
$new = new static();
...
return $new;
}
}