[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Проверка уникальности сущности в рамках DDD
Страницы: 1, 2, 3, 4, 5
Invis1ble
К примеру, типичное требование - реализовать возможность регистрации пользователей в системе. Имя пользователя в пределах нашей системы должно быть уникально, т.к. по нему юзер будет логиниться.
Где и как делаем валидацию уникальности User::$username?
1. В конструкторе сущности User? Но тогда надо инжектить сервис типа UsernameAlreadyRegisteredChecker, имеющий доступ к репозиторию пользователей (или сразу репозиторий можно передавать, не важно). Может какой-нибудь UserFactory?
2. А может в отдельном сервисе валидацию делать? Но тогда у нас нет уверенности, что клиент не забудет вызвать валидацию. Фактически, мы больше не можем полагаться на аксиому о консистентности модели (invariants).
3. Есть еще вариант типа хранить в памяти "каталог", который сделать корнем агрегата. По-моему, это вообще бред, по крайней мере для php-кода, отрабатывающего по схеме "родился -> немножко потерпел получил запрос -> послал ответ -> умер".
4. ...
...
N. Уникальность юзернэйма - не бизнес-требование, не надо валидировать вовсе. Полагаемся на эксепшн со стороны хранилища. ТС - мудак, ниче не понимает в DDD, Я СКОЗАЛ!!1

Кто как делает?

PS. Валидацию на клиентской стороне (в браузере и т.п.), валидацию DTO в слое presentation/application не рассматриваем, считается, что они и так реализованы. Речь идет о валидации модели в доменном слое.

_____________

Профессиональная разработка на заказ

Я на GitHub | второй профиль

chee
Сходи на phpclub там вурдулак разжует тебе как это решить

По сути если у тебя должен быть метод который проверяет консистентность модели, но это такое.
Есть еще такая штука как передача обязательных параметров модели через конструктор, но тоже такое.

_____________
Люди, имеющие низкий уровень квалификации, делают ошибочные выводы, принимают неудачные решения и при этом неспособны осознавать свои ошибки в силу низкого уровня своей квалификации
Invis1ble
Цитата (chee @ 8.02.2018 - 20:25)
По сути если у тебя должен быть метод который проверяет консистентность модели, но это такое.

Где он должен быть? И какая гарантия, что его не забудут вызвать?

Цитата (chee @ 8.02.2018 - 20:25)
Есть еще такая штука как передача обязательных параметров модели через конструктор, но тоже такое.

Причём здесь передача параметров? Вопрос-то про другое.

_____________

Профессиональная разработка на заказ

Я на GitHub | второй профиль

Игорь_Vasinsky
в Yii2 это в рулесах делается у модели

public function rules()
{
return [
[ [
'unique_var'], 'unique'],
[ [
'email'], 'unique']
[
'email', 'unique', 'targetAttribute' => 'secondary_email'],
[ [
'email', 'secondary_email'], 'unique', 'targetAttribute' => ['email', 'secondary_email'] ],
[ [
'lastname', 'firstname'], 'unique', 'targetAttribute' => ['firstname', 'lastname'] ],
[
'email', 'unique', 'targetAttribute' => ['email', 'secondary_email'] ],
[
'user_name', 'exist', 'targetAttribute' => ['email', 'secondary_email' => 'email'] ],

];

}


_____________
HTML, CSS (Bootstrap), JS(JQuery, ExtJS), PHP, MySQL, MSSql, Posgres, (TSql, BI OLAP, MDX), Mongo, Git, SVN, CodeIgnater, Symfony, Yii 2, JiRA, Redmine, Bitbucket, Composer, Rabbit MQ, Amazon (SQS, S3, Transcribe), Docker
twin
Я хоть и ярый противник доменных моделей, но высказаться же ни кто не запретит? smile.gif
Цитата (Invis1ble @ 8.02.2018 - 09:59)
1. В конструкторе сущности User? Но тогда надо инжектить сервис типа UsernameAlreadyRegisteredChecker, имеющий доступ к репозиторию пользователей (или сразу репозиторий можно передавать, не важно).
Мне кажется это излишняя сложность, ведь модель юзера отвечает не только за регистрацию. Причем это обычно не основной функционал.
Цитата (Invis1ble @ 8.02.2018 - 09:59)
Может какой-нибудь UserFactory?
Я бы использовал билдер, в котором и делал бы всякую валидацию. Фабрика, это немного не из той оперы. Тогда получится компромисс между
Цитата (Invis1ble @ 8.02.2018 - 09:59)
Уникальность юзернэйма - не бизнес-требование, не надо валидировать вовсе. Полагаемся на эксепшн со стороны хранилища
и
Цитата (Invis1ble @ 8.02.2018 - 09:59)
Имя пользователя в пределах нашей системы должно быть уникально, т.к. по нему юзер будет логиниться.
причем без того, чтобы полагаться на хранилище. Свой эксепшен ближе к телу. smile.gif

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

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
Invis1ble
Цитата (Игорь_Vasinsky @ 9.02.2018 - 06:35)
в Yii2 это в рулесах делается у модели

public function rules()
{
return [
  [ [
'unique_var'], 'unique'],
  [ [
'email'], 'unique']
  [
'email', 'unique', 'targetAttribute' => 'secondary_email'],
  [ [
'email', 'secondary_email'], 'unique', 'targetAttribute' => ['email', 'secondary_email'] ],
  [ [
'lastname', 'firstname'], 'unique', 'targetAttribute' => ['firstname', 'lastname'] ],
  [
'email', 'unique', 'targetAttribute' => ['email', 'secondary_email'] ],
  [
'user_name', 'exist', 'targetAttribute' => ['email', 'secondary_email' => 'email'] ],

];

}

Я вижу простой возврат массива. Судя по всему, ничто не мешает создать невалидный объект.

_____________

Профессиональная разработка на заказ

Я на GitHub | второй профиль

Invis1ble
Цитата (twin @ 9.02.2018 - 07:06)
Я бы использовал билдер, в котором и делал бы всякую валидацию. Фабрика, это немного не из той оперы.

Давай уточним, ты бы это сделал в рамках концепции DDD? Потому что если да, то это получается нарушение основных принципов. Билдер предполагает пошаговое создание объекта, а нам нужно атомарно создать валидный объект.

_____________

Профессиональная разработка на заказ

Я на GitHub | второй профиль

twin
Цитата (Invis1ble @ 9.02.2018 - 03:14)
Давай уточним, ты бы это сделал в рамках концепции DDD? Потому что если да, то это получается нарушение основных принципов. Билдер предполагает пошаговое создание объекта, а нам нужно атомарно создать валидный объект.


Свернутый текст
Вот почему я и уточнил, что не люблю DDD. Слишком много ограничений взамен на видимое упрощение проектирования. Одно ORM только чего стоит.... И, как логическое завершение, NoSQL. А тут еще это...


Впрочем я не слышал, что DDD обязывает делать только атомарные объекты. Может чего упустил... Билдер тут, мне кажется, что доктор прописал. Пошел рыть литературу. smile.gif

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
Invis1ble
Цитата (twin @ 9.02.2018 - 07:44)
Одно ORM только чего стоит.... И, как логическое завершение, NoSQL.

ORM и NoSQL не имеют отношения к DDD rolleyes.gif

Цитата (twin @ 9.02.2018 - 07:44)
Впрочем я не слышал, что DDD обязывает делать только атомарные объекты.

Не атомарные объекты, а атомарные операции.

_____________

Профессиональная разработка на заказ

Я на GitHub | второй профиль

twin
Цитата (Invis1ble @ 9.02.2018 - 04:11)
ORM и NoSQL не имеют отношения к DDD
Напрямую нет конечно. Но проектировать доменную модель, используя РСУБД "без изысков" уже априори считается моветоном. И, как следствие, многие начинают смотреть в сторону NoSQL, особенно если нужна масштабируемость, так как рано или позно могут начаться проблемы несоответствия импеданса. Вот это и есть расплата за видимую простоту. Как говорится, а не гнался бы ты поп за дешевизною. :)

Ну да это лирика. А вот тут я запутался:
Цитата (Invis1ble @ 9.02.2018 - 04:11)
Не атомарные объекты, а атомарные операции.
Билдер помоему для того и нужен, чтобы сделать атомарную операцию.

Лучше на коде разобрать, так понятнее будет.
class User
{
protected function setLogin($login)
{
$this->login = $login;
}

protected function setPassword($password)
{
$this->password = $password;
}

protected function registration()
{
// Регистрация
}

protected function enter()
{
// Вход
}
}



class UserRegistrationBuilder extends User
{
public function setLogin($login, $usernameAlreadyRegisteredChecker)
{
if (!$usernameAlreadyRegisteredChecker->checkLogin($login)) {
throw new Exception();
}

parent::setLogin($login);
return $this;
}

public function setPassword($password, $confirm)
{
if ($password !== $confirm) {
throw new Exception();
}

parent::setPassword($password);
return $this;
}

public function registration()
{
parent::registration();
return $this;
}
}


(new UserRegistrationBuilder)->setLogin('login', new UsernameAlreadyRegisteredChecker)
->
setPassword('password', 'password')
->
registration();


Соответственно для других целей (того же входа) - другой билдер.

Сильно наварочено?

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.