【问题标题】:Problem with Either and errors types incompatibilityEither 和错误类型不兼容的问题
【发布时间】:2022-07-25 05:24:13
【问题描述】:

我遇到了 Either 错误类型不兼容的问题。

创建Account实体的方法:

static Either<AccountError,Account> create(
String userNameCandidate,
UserNameUniquenessValidator userNameUniquenessValidator,
String passwordCandidate,
PasswordEncoder passwordEncoder) {

   return UserName
            .create(userNameCandidate,userNameUniquenessValidator)
            .flatMap(correctUserName -> Password
                    .create(passwordCandidate,passwordEncoder)
                    .map(correctPassword -> new Account(correctUserName,correctPassword)));
}

用户名和密码值对象:

@Embeddable
final class UserName implements Serializable {

public static final Integer MIN_USER_NAME_LENGTH = 3;

public static final Integer MAX_USER_NAME_LENGTH = 15;

@Column
private final String userName;

UserName(String userNam) {
    this.userName = userNam;
}

//For JPA only.Don't use!
public UserName() {

    this.userName = "default";
}

static Either<WrongUserNameFormatError,UserName> create(
        String userNameCandidate,
        UserNameUniquenessValidator userNameUniquenessValidator) {

    if (userNameCandidate.isEmpty()) {

        return Either.left(new WrongUserNameFormatError("Empty user name."));
    }

    var isUserNameCandidateLengthWrong =
            userNameCandidate.length() < MIN_USER_NAME_LENGTH &&
            userNameCandidate.length() > MAX_USER_NAME_LENGTH;

    if (isUserNameCandidateLengthWrong) {

        return Either.left(new WrongUserNameFormatError(
                    "Wrong user name length: " + userNameCandidate.length() +
                            ".Min: " + MIN_USER_NAME_LENGTH +
                            ".Max: " + MAX_USER_NAME_LENGTH));
    }

    if (!userNameUniquenessValidator.isUnique(userNameCandidate)) {

        return Either.left(new WrongUserNameFormatError("Not unique user name: " + 
userNameCandidate));
    }

    return Either.right(new UserName(userNameCandidate));
}

public String getUserName() {
    return userName;
  }
}

@Embeddable
final class Password implements Serializable {

public static final Integer MIN_PASSWORD_LENGTH = 5;

@Column
private final String password;

private Password(String password) {
    this.password = password;
}

//For JPA only.Don't use!
public Password() {

    this.password = "default";
}

static Either<WrongPasswordFormatError,Password> create(String passwordCandidate, PasswordEncoder passwordEncoder) {

    if (passwordCandidate.length() >= MIN_PASSWORD_LENGTH) {

        var encodedPassword= passwordEncoder.encode(passwordCandidate);

        return Either.right(new Password(encodedPassword));
    }
    else {

        return Either.left(new WrongPasswordFormatError(
                    "Wrong password length: " + passwordCandidate.length() +
                            ". Min: " + MIN_PASSWORD_LENGTH));
    }
}

public String getPassword() {
    return password;
}

}

我得到错误:必需的 Either,提供了 Either,不兼容的约束:AccountError 和 WrongUserNameFormatError,即使所有错误都扩展了 AccountError。

【问题讨论】:

  • 无关评论:您可以将 VO 的构造函数设为私有,JPA 将使用它们。无关推荐 2:放弃 vavr 并使用 Kotlin 或其他支持函数式构造的 JVM 语言,您的生活质量将显着提高:D.

标签: java functional-programming either vavr


【解决方案1】:

我会在这里使用Validation,因为您可以在那里收集(验证)错误。 :

由于我没有您示例的对象类型,所以我想出了这个:

Validation<Seq<? extends Number>, String> c = Validation.invalid(io.vavr.collection.List.of(1L));
Validation<Seq<? extends Number>, String> d = Validation.valid("x");
    
final Validation<Seq<? extends Number>, String> result = c.flatMap(s -> d);

验证基本上是 Either 的一种特殊情况(在 Validation 对象上还有一个 .toEither)。

cUserName.created Password.create 的结果

“诀窍”是在这里使用Seq 而不是直接使用 Object 类型。我无法解释原因(所以我意识到这听起来可能是个坏建议)。

在我们的项目中,我们广泛使用这种结构,因为我们的流程中经常会出现多个验证错误,然后左侧总是相同的并且很容易转移到其他流程中。

【讨论】:

    【解决方案2】:

    问题是Either&lt;WrongUserNameFormat, ...&gt; 不会扩展Either&lt;AccountError, ...&gt;,即使WrongUserNameFormat 可以扩展AccountError。这是因为Java 对type parameter variance 没有很好的支持。 VAVr 认识到了这个问题,因此它为包括Either 在内的许多类型提供了narrow 方法。所以你可以用Either.&lt;AccountError, Account&gt;narrow(...) 包装Account.create 的返回值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-23
      • 2011-07-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多