2

次のようなクラスがあるとしましょう。

public class CreateUserRequest {
  ...
  @NotNull
  @Size(min = 4, max = 16)
  @Pattern(regexp = "^[a-zA-Z0-9]+$")
  private final String userName;
  ...
}

ここにあるのは、いくつかの制約があるフィールド「userName」です。そのため、一部の値はOKで、一部はそうではありません。クラスもありますEditUserRequest。あなたuserNameはユーザー識別子としてユーザーを使用しているので、このフィールドEditUserRequestを確実に入力します。

public class EditUserRequest {
  ...
  @NotNull
  @Size(min = 4, max = 16)
  @Pattern(regexp = "^[a-zA-Z0-9]+$")
  private final String userName;
  ...
}

そして確かにあなたはユーザーを削除できるようにしたいです:

public class DeleteUserRequest {
  ...
  @NotNull
  @Size(min = 4, max = 16)
  @Pattern(regexp = "^[a-zA-Z0-9]+$")
  private final String userName;
  ...
}

これらのクラスはすべて、まったく同様の意味と同様の制約を持つフィールド「userName」を持っています。ある日、sでより多くのシンボルを使用できるようにすることを決定しましたuserName。したがって、これら3つのクラスすべてを手動で修正する必要があります。

解決策#1

これらすべてのリクエストの基本クラスを作成します。

public abstract AbstractUserRequest {
  ...
  @NotNull
  @Size(min = 4, max = 16)
  @Pattern(regexp = "^[a-zA-Z0-9]+$")
  private final String userName;
  ...  
}

public class CreateUserRequest extends AbstractUserRequest {
  ... // OK, we have userName here
}

長所

  • これで、制約を一度だけ修正する必要があります
  • 新しいタイプのリクエストを作成するのは非常に簡単です。サブクラスAbstractUserRequest化するだけで機能します。

短所

  • 他の場所が必要な場合userNameは、のサブクラスが必要になりますAbstractUserRequest(例: sのCreateUserGroupRequestリストが必要userNameです。最初にそれらを検証する必要があります)。
  • これを適切にテストする方法が正確にわからない

解決策#2

フィールドのタイプごとに個別のクラスを作成して、「ユーザー名」について話すときに、それが単なるString、制約されていることを知っているようにしStringます。

public class UserNameField {
  @NotNull
  @Size(min = 4, max = 16)
  @Pattern(regexp = "^[a-zA-Z0-9]+$")
  private final String value;
  ...
}

public class CreateUserRequest {
  ...
  private UserNameField userName;
  ...
}

長所

  • ユーザー名の制約が変更された場合は、一度だけ修正する必要があります
  • テストが簡単なシンプルなクラスがあります

短所

  • やり過ぎのように感じる(?)

解決策#3(更新)

Hibernateバリデーターでは制約の構成が可能であるため、制約のグループに名前を付けることができます。

@NotNull
@Size(min = 4, max = 16)
@Pattern(regexp = "^[a-zA-Z0-9]+$")
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface UserName {
  String message() default "{com.loki2302.constraints.username}";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};
}
...
public class CreateUserRequest {
  ...
  @UserName
  private final String userName;
  ...
}

長所:

  • シンプルでありながら強力なアプローチ
  • 使いやすい(余分な抽象化なし)
  • テストが簡単

短所:

  • おそらくない?

ここでの一般的なアプローチは何ですか?ソリューション#2は問題ないように見えますか?どうしますか?

4

1 に答える 1

3

私は間違いなくソリューション#2に行きます。UserNameField上で示したように、リクエストではないクラスで使用することをお勧めします。これにより、AbstractRequestクラスは少し悪い選択肢のように感じられます。
重複コードを回避し、すべてのロジックを同じ場所に配置するためのクラスを作成することは、私には優れたアイデアのように思えます。

[ソリューション#3の追加後に編集]
ソリューション#3は、ソリューション#2の非常に優れたバリエーションのように見えます。どちらが好きかを本当に決めることはできません。どちらもロジックをカプセル化するという素晴らしい仕事をしています。

于 2012-07-11T05:10:16.357 に答える