According to DDD-principles I use factory-methods to create consistent objects and to ensure that the objects are in the right state.
Now I'm in doubt about inner logic of setter methods. I'm tied up with an object, that's similar to the following code snippet, so let's take it as an example:
public class UserCredentials {
private String username;
private UserCredentials() {
super();
}
public static UserCredentials create (final String username) {
String username = username.toUpperCase();
UserCredentials newInstance = new UserCredentials(username);
return newInstance;
}
private UserCredentials(final String username) {
this.username = username;
}
public String getUsername() {
return this.username;
}
public void setUsername(final String username) {
this.username = username;
}
public void checkConsitency() {
...
isUppercase();
...
}
}
We do have an invariant: The username of the credentials must always be uppercase. Now I want to make sure, that changing the username doesn't violate the invariant.
But how do I guarantee the rule?
I do rewrite the setter method and add the conversion logic to the setter. Drawback: Setter contains logic.
I rely on clients, that they always provide uppercase username and I will throw consistency exceptions in the case of violation. Drawback: Origin of the wrong usage is hard to discover, moreover its bad practice at all.
I remove the setter method and replace it with a domain method like
changeUsername(String username)
that contains the conversion logic. Drawback: external developers may miss the setter method.
Because of the statement "username of credential must always be uppercase" I tend to prefer alternative 3.
But is there a smarter solution?