Суть: пользователь может бысть зарегистрирован в системе двумя способами: 1) email&password; 2) через oauth Facebook'a. На данный момент использую только один фабричный метод RoomMates\Domain\Model\User::register(...) для обоих способов регистрации, что неминуемо приводит к наличию null-able параметров (так как в разных способах доступны разные данные) и меня это честно говоря напрягает (подругому это смутное чувство объяснить не могу, так как в DDD я новичок ).
Вопросы:
- стоит ли разделять RoomMates\Domain\Model\User::register(...) на два под каждый способ регистрации?
- есть устойчивое желание разделить метод register на 2 и перенести их в UserFactory, насколько это правильно?
Код: Выделить всё
<?php
/**
* Aggregate root User
*/
class User
{
// ...
public function __construct(UserId $id)
{
$this->id = $id;
}
/**
* Register new user
*
* @param EmailAddress $email
* @param null|UserDateOfBirth $dateOfBirth
* @param string $password
* @param string $firstName
* @param string $lastName
* @param string $authKey
* @param null|string $facebookId
* @param null|Gender $gender
*/
public function register(EmailAddress $email,
?UserDateOfBirth $dateOfBirth,
string $password,
string $firstName,
string $lastName,
string $authKey,
?string $facebookId,
?Gender $gender): void
{
$this->setEmail($email);
$this->setPassword($password);
$this->setFirstName($firstName);
$this->setLastName($lastName);
$this->setDateOfBirth($dateOfBirth);
$this->setAuthKey($authKey);
$this->setGender($gender);
$this->setNotificationSettings(new UserNotificationSettings(
true,
true,
true,
true
));
$this->facebookId = $facebookId;
$this->loginCount = 0;
$this->lastLogin = null;
$this->credits = 0;
$this->facebookCredits = 0;
$this->registeredAt = DateTimeHelper::now();
DomainEventPublisher::instance()->publish(
new UserRegistered($this->id())
);
}
// ...
}
Код: Выделить всё
class SignUpService implements ApplicationService
{
/** @var UserRepository */
public $repository;
/** @var AuthManager */
public $authManager;
/** @var PasswordManager */
public $passwordManager;
public function __construct(UserRepository $repository,
AuthManager $authManager,
PasswordManager $passwordManager)
{
$this->repository = $repository;
$this->authManager = $authManager;
$this->passwordManager = $passwordManager;
}
/**
* @param SignUpRequest $request
*
* @return void
* @throws UserAlreadyExistsException
*/
public function execute($request = null): void
{
if ($user = $this->repository->ofEmail($request->email())) {
throw new UserAlreadyExistsException;
}
$user = new User($this->repository->nextIdentity());
$user->register(
new EmailAddress($request->email()),
null,
$this->passwordManager->hashPassword($request->password()),
$request->firstName(),
$request->lastName(),
$this->authManager->generateAuthKey(),
null,
null
);
$this->repository->store($user);
}
}
Код: Выделить всё
class SignUpViaFacebookService implements ApplicationService
{
/** @var UserRepository */
public $repository;
/** @var AuthManager */
public $authManager;
/** @var PasswordManager */
public $passwordManager;
public function __construct(UserRepository $repository,
AuthManager $authManager,
PasswordManager $passwordManager)
{
$this->repository = $repository;
$this->authManager = $authManager;
$this->passwordManager = $passwordManager;
}
/**
* @param SignUpViaFacebookRequest $request
*
* @return void
* @throws UserAlreadyExistsException
*/
public function execute($request = null): void
{
if ($this->repository->facebookUserExists($request->facebookId())) {
throw new UserAlreadyExistsException;
}
if ($user = $this->repository->ofEmail($request->email())) {
throw new UserAlreadyExistsException;
}
// Todo extract to domain service
$dateOfBirth = null;
if (null !== $request->dobDay() && null !== $request->dobMonth()) {
$dateOfBirth = new UserDateOfBirth(
$request->dobYear(),
$request->dobMonth(),
$request->dobDay()
);
}
$password = $this->passwordManager->generatePassword();
$user = new User($this->repository->nextIdentity());
$user->register(
new EmailAddress($request->email()),
$dateOfBirth,
$this->passwordManager->hashPassword($password),
$request->firstName(),
$request->lastName(),
$this->authManager->generateAuthKey(),
$request->facebookId(),
$request->gender()
);
$this->repository->store($user);
}
}
P.S.S. Спасибо заранее!