DDD, Regras de Negócio e Repositories

Galera em um tópico anterior me convenceram a usar Hibernate. :lol:
Eu tava na nóia de fazer tudo em JDBC, mas logo no começo do projeto vi que daria muito trabalho e a produtividade seria menor.
Bom, agora que ja desenvolvi algumas classes gostaria de pedir a opinião de vcs quanto ao código que estou desenvolvendo.
Opiniões de pessoas mais experientes em DDD, pra saber se estou errando em algum ponto.
Ai vai:

1 - Adicionando um Solicitação de Serviço (Uma OS - Ordem de Serviço em um sistema de chamados técnicos)

public class OSFacade {
  public void adicionarOS() {
     OS os = new OS(); //To pensando em mudar pra Factory
     os.setData(Calendar.getInstance());
     ...
     repositorioOS.adicionar(os);
  }
}

Ao meu ver está do jeito correto tendo em vista que isso é uma operacao CRUD simples.
2 - Agora vou mostrar um exemplo de quando uma OS é aprovada, ela gera um Chamado de Assistencia Tecnica.

public class OSFacade {
   public void aprovarOS(int idOS, int idUsuario) {
       Usuario usuario = repositorioUsuario.getUsuario(idUsuario);
       OS os = repositorioOS.getOS(idOS);
       os.aprovar(usuario);
   }
}

public class OS {
   public void aprovar(Usuario usuario) {
      if(valorOrcamento <= usuario.getValorMaxAprovacaoOrcamento()) {
         this.status = APROVADA;
         //Aqui eu preciso criar uma objeto ChamadoAssistenciaTecnica.
      } else {
         throw new UsuarioAprovarOSException("Usuário não pode aprovar pois ele so pode aprovar OS com valores abaixo de " + usuario.getValorMaxAprovacaoOrcamento());
      }
   }
}

A minha pergunta e dúvida aqui é: Eu criaria o objeto ChamadoAssistenciaTecnica e passaria pra um repositorio de ChamadoAssistenciaTecnica. Por exemplo:

public class OS {
   public void aprovar(Usuario usuario) {
      if(valorOrcamento <= usuario.getValorMaxAprovacaoOrcamento()) {
         this.status = APROVADA;
         ChamadoAssistenciaTecnica chamadoAssistenciaTecnica = new ChamadoAssistenciaTecnica(this);
         repositorioChamadoAssistenciaTecnica.adicionar(chamadoAssistenciaTecnica);
      } else {
         throw new UsuarioAprovarOSException("Usuário não pode aprovar pois ele so pode aprovar OS com valores abaixo de " + usuario.getValorMaxAprovacaoOrcamento());
      }
   }
}

Isto está correto?

3 - Outra dúvida, corrijam-me se estiver errado
Meus repositório no domínio são Interfaces, na camada de infra eu as implemento em classes concretas utilizando Hibernate e as injeto quando vou criar minha Entidades ou Services do DDD.
Está correto? Minha interfaces não estão apenas sendo criadas para evitar a depedência da Camada de Dominio da Camada de Infra?

public interface RepositorioUsuario {
    void adicionar(Usuario usuario);
}

public class RepositorioUsuarioImpl implements RepositorioUsuario {
    public void adicionar(Usuario usuario) {
        ...
        //Instancio Session do Hibernate
        session.save(usuario);
    }
}

//Injetando no Service que Gerencia Usuarios - Código da minha camada de Aplicacao
GerenciadorUsuario gerenciadorUsuario = new GerenciadorUsuario();
gerenciadorUsuario.setRepositorio(new RepositorioUsuarioImpl());

Galera sei que são muitas dúvidas, porém eu só quero ter certeza que estou fazendo as coisas no caminho certo.
Sei q nao existe um caminho completamente certo, mas quero que esteja o mais próximo do DDD possível.
Obrigado a todos

recomendo uma breve olhada no grails, no fim ele gerar .class e vira java byte code…

ali vc verá a real implementação de DDD

[s]

[quote=lucasap2005]A minha pergunta e dúvida aqui é: Eu criaria o objeto ChamadoAssistenciaTecnica e passaria pra um repositorio de ChamadoAssistenciaTecnica. Por exemplo:

Isto está correto?
[/quote]
Tirando o fato de que deveria estar usando uma fábrica pra instanciar o objeto, na minha opinião está certo.

[quote=lucasap2005]3 - Outra dúvida, corrijam-me se estiver errado
Meus repositório no domínio são Interfaces, na camada de infra eu as implemento em classes concretas utilizando Hibernate e as injeto quando vou criar minha Entidades ou Services do DDD.
Está correto? Minha interfaces não estão apenas sendo criadas para evitar a depedência da Camada de Dominio da Camada de Infra?[/quote]
Eu costumo usar uma camada de interfaces de infra pra não acoplar os repositórios ao hibernate ou seja lá o que eu estiver usando. Mas na minha opinião, isso é opcional. você isolando sua infra apenas nos repositórios já é uma boa coisa.

[]'s

Rodrigo Auler

[quote=georgesq]recomendo uma breve olhada no grails, no fim ele gerar .class e vira java byte code…

ali vc verá a real implementação de DDD

[s][/quote]

Hã?

Seu design parece razoável. Tente descrever isso para o usuário e veja se ele entende os conceitos que você está usando.

:smiley: Vou descrever…
Quanto aos repositórios, alguém ae sabe como eu posso trabalhar com Criteria do Hibernate?
Criteria do Hibernate eu sei fazer, mas como faria para o dominio ser independente disso?

Phillip, vc tem alguma sugestão para melhorá-lo? Queria saber onde posso melhora-lo

[code]public class OS {
public void aprovar(Usuario usuario) { …

throw new UsuarioAprovarOSException("Usuário não pode aprovar …[/code]
Não tem um erro de “semântica” aí no seu código? Não é o usuário que aprova a OS? Então acho que o correto seria:

public class Usuario { public void aprovar(OS os) { ...

Axo q a solução ideal seria melhor assim mesmo…
Vou repensar essa parte…vlw :wink:

[quote=lucasap2005] :smiley: Vou descrever…
Quanto aos repositórios, alguém ae sabe como eu posso trabalhar com Criteria do Hibernate?
Criteria do Hibernate eu sei fazer, mas como faria para o dominio ser independente disso?[/quote]

Acho que vc poderia usar queryObject no domínio (em casos de consultas dinâmicas por exemplo). E usar Specification para explicitar conceitos conhecidos do dominio … A especification pode usar queryObjects internamente. No repositório vc poderia converter esses caras em sqls/criteria.

No seu caso, vc poderia ter um specification para representar um usuário que pode aprovar uma OS.

Acho que assim fica bom.

[]s