Sto sviluppando una piccola applicazione, solo per praticare DDD. Per quanto ne so. invarianti sono il termine generale di convalida relativo al dominio. Quindi, per esempio, se voglio avere solo i nomi ucfirst, allora è un invariante e ho bisogno della validazione nel setter della proprietà per assicurarmi che questo invariante sia protetto e rendere pubblico solo il setter, non la proprietà stessa.
Il mio problema attuale è che ho bisogno di nomi utente, che vengono generati da nome, cognome, data di nascita e probabilmente alcuni elementi casuali, se questi non sono abbastanza unici. Per quanto ne so, avere un nome utente univoco è un problema relativo al dominio, perché è molto importante se si desidera effettuare il login o semplicemente associare alcuni dati a un utente reale. Quindi avere una tabella di database con pk sul nome utente e attendere la violazione dell'errore di vincolo non è sufficiente, dovrei inserire del codice nel dominio, il che assicura che il nome utente generato sia unico. Immagino che il codice entri in qualche modo nel repository o nell'entità. Puoi mostrarmi un esempio di come potrebbe apparire in una vera app? Il dominio e l'implementazione del servizio app sono ciò di cui sono curioso.
Potrei non avere ragione su questo. Ogni entità ha un identificatore univoco e ha un repository, quindi probabilmente dovrei inserire la generazione del nome utente nel repository, e questo è tutto. Potrei aver bisogno di riformulare questo per esempio cosa succede se non abbiamo un identificatore univoco, solo una proprietà che dovrebbe essere unica?
Ho creato una piccola bozza di codice:
class CustomerService {
// ...
public createCustomerFromNameAndYear(name, year){
try {
transaction.begin();
username = generateUsername(name, year);
while (repo.findByUsername(username))
username = addSomeRandomChar(username, 1);
password = "";
password = addSomeRandomChar(password, 6);
customer = new Customer(username, password, name, year);
repo.save(customer);
transaction.commit();
dto = new CustomerDTO(customer.getUsername(), customer.getPassword());
return dto;
}
catch(exception) {
transaction.rollback();
throw new ExceptionWithCauses(CUSTOMER_CREATION_FAILED, exception.getMessage());
}
}
}
Se inserisco questo nel servizio app, assicurerà che il nome sia univoco a meno che non si verifichi una concomitanza, ma l'invio di un messaggio di errore è ok in quel raro caso. Non sono sicuro che sia ok. Non è corretto se gli invarianti devono essere parti del codice di dominio.
Un'altra possibile soluzione per avere un metodo di creazione nel repository.
class CustomerService {
// ...
public createUserFromNameAndYear(name, year){
try {
transaction.begin();
customer = repo.create(name, year);
transaction.commit();
dto = new CustomerDTO(customer.getUsername(), customer.getPassword());
return dto;
}
catch(exception) {
transaction.rollback();
throw new ExceptionWithCauses(CUSTOMER_CREATION_FAILED, exception.getMessage());
}
}
}
class CustomerRepository implements iCustomerRepository {
// ...
public create(name, year){
username = generateUsername(name, year);
while (this.findByUsername(username))
username = addSomeRandomChar(username, 1);
password = "";
password = addSomeRandomChar(password, 6);
customer = new Customer(username, password, name, year);
this.save(customer);
return customer;
}
}
Potrebbe essere meglio.