In general, I like to favour immutability where possible and not allow objects to be created in an invalid state or get into an invalid state. Sometimes though it feels like it might go too far.
Example: I have a User domain object (JPA/Hibernate entity). I only allow the object to be constructed in a valid state, all required fields must be used to instantiate the object and cannot be NULL
. On bigger objects, this can sometimes make the constructor look noisy with lots of validation going on. In this case, I am only validating the arguments are not null. I'm not checking to make sure the user name is between 5 - 30 characters, or any other rules that might go with the class properties.
Is it reasonable to do the following? Would it be sensible to take it a step further and ensure the arguments also meet any length, min, max, format validation? Or is making an argument as @Nonnull
good enough?
In cases where there are setters, the same validation logic would need to be present as well.
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotBlank
@Column(name = "user_name", unique = true)
private String userName;
@Column(name = "password")
private String password;
@Email
@NotBlank
@Column(name = "email")
private String email;
@Column(name = "locked")
private boolean locked;
@Enumerated(EnumType.STRING)
@Column(name = "role")
private Role role;
@ManyToOne(optional = true, fetch = FetchType.LAZY)
@JoinColumn(name = "dealer_id", referencedColumnName = "id")
private Dealer delaer;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private List<EventLog> events;
protected User() {
this.events = new ArrayList<>();
}
/**
* Constructor for User.
*
* @param userName Username of the user
* @param password Encrypted password
* @param email Email of the user
* @param locked Determines if user account if locked or not
*/
public User(@Nonnull String userName, @Nonnull String password, @Nonnull String email, boolean locked, @Nonnull Role role) {
this();
Preconditions.checkArgument(userName != null);
Preconditions.checkArgument(password != null);
Preconditions.checkArgument(email != null);
Preconditions.checkArgument(role != null);
this.userName = userName;
this.password = password;
this.email = email;
this.locked = locked;
this.role = role;
}
}