Secondo i principi del DDD, utilizzo metodi di fabbrica per creare oggetti coerenti e assicurare che gli oggetti siano nello stato giusto.
Ora sono in dubbio sulla logica interna dei metodi setter. Sono legato a un oggetto, simile al seguente frammento di codice, quindi prendiamolo come esempio:
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();
...
}
}
Abbiamo un invariante: il nome utente delle credenziali deve essere sempre in maiuscolo. Ora voglio assicurarmi che cambiare il nome utente non violi l'invariante.
Ma come posso garantire la regola?
-
Riscrivo il metodo setter e aggiungo la logica di conversione al setter. Inconveniente: il setter contiene la logica.
-
Mi affido ai client, che forniscono sempre il nome utente in maiuscolo e pubblicherò eccezioni di coerenza in caso di violazione. Svantaggio: l'origine dell'uso sbagliato è difficile da scoprire, oltretutto la sua cattiva pratica.
-
Rimuovo il metodo setter e lo sostituisco con un metodo di dominio come
changeUsername(String username)
che contiene la logica di conversione. Inconveniente: gli sviluppatori esterni possono perdere il metodo setter.
A causa dell'affermazione "il nome utente delle credenziali deve sempre essere maiuscolo" tendo a preferire l'alternativa 3.
Ma esiste una soluzione più intelligente?