Primeiro é preciso deixar claro que VO (Value Object : Objecto de Valor) não é um TO. Exemplos de VO são : Adress , CPNJ , Range , Money , quase todas as classes principais da biblioteca TimeAndMoney e da Joda Time. São objetos com estado e opeações sobre esse estado. São muito uteis e normalmente podem ser usados para muitos fins. O que os distingue das entidades é que não têm chave e como tal podem ser usados em muitas funções.
Os VO são normalmente campos das entidades que visam simplificar operações do dominio. Outra caracteristica comum dos VO é que são imutáveis. Java tem alguns VO genericos como String , Integer e todos os Number e Date.
Por outro lado, TO não têm chave e além disso não são VO, ou seja, eles são puramente agregadores de dados que visam diminuir a quantidade de parametros de métodos e podem atravessar diferentes andares (tiers) da aplicação por serem serializáveis. Contudo, isto não significa que são sempre necessários. Uma simples string ou um int podem fazer esse papel.
Dito isto, no seu exemplo abaixo LogonTO tem chave. Isso é uma contradição. Se tem chave é uma entidade. Se é um TO não tem chave.
Não ha verdadeira necessidade de usar get/set num TO já que como ele não contém nenhuma lógica , não teriamos o que escrever nesses métodos e portanto não ha necessidade de encapsulamento. Mas isto é um detalhe. No final das contas os get/set nem pesam na JVM, então melhor usá-los por padrão. O ponto aqui é só chamar a atenção que devido ao objetivo do TO não precisamos deles.
Uma coisa que achei estranho é o repositorio ter um metodo para salvar dois argumentos ao mesmo tempo. Eu estava pensando que o uso do repositorio deveria ser
Repository.save(login);
Repository.save(person);
Pois reutiliza o mesmo método.
Eu não entendi muito bem o objetivo do seu serviço (é logar a pessoa, registrar o login da pessoa, ou os dois ?) mas … suponho que se está criando um login para a pessoa. Eis como eu faria:
class UserService {
public void createLoginFor (String username, byte[] password) {
// estou pedindo dados em bruto pq este´e um serviço do dominio
// será chamado pelo servlet facilmente sem definir TO
Person p = Repositoy.find(Person.class, username); // username é unico, então atua como chave
if (p==null) {
// essa pessoa não existe
throw new PersonNotFoundException(username);
}
PersonLogin login = PersonLogin.valueFor (p);
login.setPassword(password);
Repositoy.store(login);
}
// outro serviço com os mesmos parametros.
// serve para mostrar que quem sabe o que fazer com os parametros é o serviço (o método)
public void autenticate (String username , byte[] password ) {
Person p = Repositoy.find(Person.class, username); // username é unico, então atua como chave
if (p==null) {
// essa pessoa não existe
throw new IncorrectUserCredentialsException(username);
}
PersonLogin login = PersonLogin.valueFor (p);
if (!login.accept(password)){
throw new IncorrectUserCredentialsException(username);
}
// se está tudo ok, continua. não precisa retornar nada.
}
}
@Entity // o uso desta anotação , introduzido pelo Thiago Senna é uma
boa, mas eu não usaria a anotação de JPA (persistencia) e sim uma
anotação puramente de dominio. Mas isso ai é gosto e implementação,
por agora entenda-se que @Entity significa
apenas "isto é um entidade de dominio"
class PersonLogin {
private Key key; // Key é um VO
private Person p
private byte[] password;
public PersonLogin valueFor (Person p) {
PersonLogin login = Repository,find ( PersonLogin.class, p.getUsername())
if (login == null){
login = new PersonLogin (p , new byte[0]);
}
return login;
}
private PersonLogin (Person p, byte[] password){
// atribuções
}
public boolean accept( byte[] password) {
return Arrays.equals(this.password, password);
}
}
A seguir o codigo a que se refere este post.
[quote=ronildobraga]So retratando um exemplo rapido para corrigir o primeiro exemplo que eu postei
//Meu servlet ou algo do genero
public class Beta {
private void usandoDDDCorretamente(){
LogonTO to = new LogonTO();
to.setName("fulano");
to.setKey(1);
to = new UserService().saveUser(to);
System.out.println(to.getName());
}
}
//Servico do dominio, contem a logica de negocio do dominio
class UserService{
public LogonTO saveUser(LogonTO to){
LoginEntity login = new LoginEntity();
PersonEntity person = new PersonEntity();
login.setName(to.getName());
person.setKey(to.getKey());
Repositorio.save(login, person);
return new LogonTO("fulano gravado com sucesso", to.getKey());
}
}
//Meio de como persistir os dados do dominio
class Repositorio{
public static void save(LoginEntity login, PersonEntity person){
System.out.println("gravando: " + login.getName() + " chave: " + person.getKey() );
}
}
[/quote]