I have an AccountCreator class with a create method that takes a DTO with the data needed to create an account. At the beginning there is an attempt to create 2 value objects (UserName and Password), then validate the uniqueness of the user name, create the Account entity which takes these 2 value objects in the constructor and save it in the repo. Of course, errors such as incorrect password length, etc. may be returned. I used Eithers for this and now the question is whether this code is ok or maybe it can be written somehow better?
public Either<Error, AccountDto> create(AccountCreateDto accountCreateDto) {
var errorType = ErrorType.ACCOUNT_PERSISTENCE_ERROR;
var errorMessage = "Not unique user name: " + accountCreateDto.userName;
var error = new Error(errorType, errorMessage);
return UserName
.create(accountCreateDto.userName)
.flatMap(userName ->
userNameUniquenessChecker.isUnique(userName.text) ?
Password
.create(accountCreateDto.password)
.flatMap(password -> {
var createdAccount = new Account(
userName,
password,
AccountStatus.OPEN,
LocalDateTime.now(),
new ArrayList<>()
);
var addedAccount = accountRepository.add(createdAccount);
var accountDto = new AccountDto(
addedAccount.userName.text,
addedAccount.password.text,
addedAccount.status,
addedAccount.creationDate,
(long) addedAccount.tasks.size()
);
return Either.right(accountDto);
}) : Either.left(error));
}
The customary FP approach would be to use a
Validationstyle applicative functor - there's one in Vavr called Validation. You can useValidation.combineto combine multiple Validation values into one, e.g.:You can elide the temporaries - validAcc, validAcc2 & validAccDto, however I left them in for clarity.
(caveat emptor - haven't tested that this code works, or even compiles)