Camada de acesso dados - DAO e seus métodos

Bom dia pessoas,

Uma dúvida que creio ser muito básica pra vocês, mas que me deixou com a pulga atrás da orelha nos últimos dias:
nos meus DAOs, eu posso ter métodos com assinaturas como “enviarRelatorio(Relatorio relatorio)”, sendo que minha classe/service tem um método com o mesmo nome?

Um exemplo:

public class Relatorio {
  
  private long id;
  private Setor setorOrigem;
  private Setor setorDestino;
  
}
public class RelatorioService {

  //aqui injeta o dao
  private RelatorioDAO dao;

  public void enviarRelatorio(Relatorio relatorio) {
    dao.enviarRelatorio(Relatorio relatorio);
  }

}
public class RelatorioDAO {

  public void enviarRelatorio(Relatorio relatorio) {
    //aqui executa todo o sql necessário pra salvar o relatório
  }

}

Eu sei que se trata do modelo anêmico, e que tenho que ler muito sobre modelos ricos pra poder consertar isso ai - estou inclusive com o livro do Eric Evans em mãos pra ler, mas primeiro preciso terminar urgentemente um projeto pequeno aqui pra voltar a estudar tranquilamente.

O que acham dessa forma de tratar POJO/SERVICE/DAO?

Qualquer sugestão e crítica será muito bem vinda.

Muito obrigado desde já, abraços!

Bom, como o seu comentário diz: “aqui executa todo o sql necessário pra salvar o relatório”, nada mais justo que esse método se chamar salvar(Relatorio relatorio)…

Mas não, não tem problema nenhum eles terem o mesmo nome. Exemplo disso é a Lei de Demeter (ou sugestão de Demeter).

Basicamente, ao invés de você acessar algo assim:

cliente.getEndereco().getCEP();

Você pode fazer isso:

cliente.getCEP(); // Dentro desse método, você faz return this.endereco.getCEP();

Isso evita que vc espalhe o cliente.getEndereco() desnecessariamente por ai… Se tiver que mudar, muda menos…

Rafael Guerreiro,

Primeiramente, muito obrigado! Como sempre ajudando e muito!

Então, esse ai foi só um exemplo, pois tenho métodos com assinaturas iguais nas classes de domínio e DAOs.
Eu não me recordo onde li, mas vi uma vez a recomendação que os DAOs não deveriam em momento algum “refletir” ou terem nomes parecidos aos métodos das classes de domínio, pois isso estaria transmitindo a ideia de execução de regra de negócio nos DAOs. O problema é que não me recordo onde li isso, e se realmente faz algum sentido. O que você acha sobre isso?

Muito obrigado novamente, um abração!

Acho que o correto mesmo é o que você consegue explicar o motivo de ter feito daquele jeito. Sempre com bons argumentos.
Quando alguém te mostrar algo contrário, você precisa pensar e admitir caso seja melhor.

Tento isso em mente, eu não diria o que é certo ou errado. Enquanto o código compila e tem o comportamento esperado…

Eu não vejo problema nenhum que um método tenha um nome que pareça regra de negócio. Se você parar para pensar, temos regras em todas as camadas. Por exemplo, uma auditoria nos registros, isso é uma regra que pode acontecer no DAO. Então por que não dizer que ele vai auditar o seu objeto?
Inclusive, o seu objeto tem que ser auditável… Isso dá pano para muita manga.

EU, particularmente, não tenho classes de Serviço (pelo menos não com o nome Service). Eu não trabalho com modelos anêmicos. Eu tenho regras de modelo no modelo, regras de controllers nos controllers e regras de DAO nos DAOs…

Analisando bem, um select é uma regra de negócio. Um DAO não deveria construir um select então? Fica estranho.

Por isso, eu voto sempre na seguinte ideia:
1- O nome do método explica exatamente o que ele faz.
2- Se você precisar colocar um “And”, “E”, “Or”, “Ou” é sinal de que você precisa dividir seu método em 2 (ou mais).

Exemplo:

public void saveAndGenerateReportAndSendIt(Modelo m) {
   // tá fazendo 3 coisas...
}

Outra coisa, eu sempre crio MUITAS classes, uma classe para cada coisinha, por menor que seja essa coisinha. No exemplo acima, eu teria 4 classes…

Existem algumas métricas que podem te ajudar a ter métodos e classes melhores:
1- Método com mais de 10~15 linhas é sinal de que está fazendo muita coisa e pode ser dividido (existem EXCEÇÕES, mas cuidado para não transformá-las em regra);
2- Se o nome do seu método indica que ele faz mais de uma coisa, então ele pode ser dividido.
3- Se a classe tem 1 atributo, esse atributo deve ser usado por todos os métodos dessa classe. O motivo é que se você tem 2 atributos e um método para cada um, então você tem uma classe para cada atributo. (Modelos são exceções pois servem para trafegar dados)

Você consegue usar bem esses 3 pontos se você fizer testes de unidade… Pois assim fica mais fácil de testar…

Só da um pitaco aqui:

Para toda regra há exceções. Inclusive ao uso de “modelos ricos”. Nem toda aplicação (no meu entendimento a grande maioria) se encaixa bem em domain driven design. Somente aplicações onde as entidades tem realmente muitas regras de negócio.

Rodrigo, eu concordo…

Eu já cheguei a fazer um cadastro de usuários totalmente em domain driven design. Não ficou bom e a melhor saída foi um modelo “um pouco mais anêmico”. Na verdade meio que fiz um modelo de usuário com algumas regras e outras (de senha) fora.

Pois é. Só comentei isso porque nosso amigo que abriu o tópico parecia preocupado demais com essa questão de adequar o design dele ao DDD. Mas pode nem ser o caso.

Olá rodrigo.uchoa,

Muito obrigado por estar ajudando cara! Então, estou e não estou muito preocupado com DDD! rs

A verdade é que nesse projeto estou usando o modelo anemico mesmo, por falta de tempo. Mas eu queria o parecer de pessoas mais experientes sobre isso msm. Tanto que o Rafael Guerreiro já tirou muitas outras dúvidas minhas sobre isso em outros tópicos, hehe.

Rafael Guerreiro,

O meu projeto está assim msm, todas as classes DAO tem métodos salvar, e algumas possuem métodos do tipo listarTodos(), buscarPorId(), buscarPorNome(), etc … Tem alguns raros casos em que os nomes parecem de métodos de classes modelo, isso que me deixa intrigado: parece que ficaram destoando dos demais, como se eu tivesse começado com um padrão (nomes dos métodos das DAO diferentes dos métodos dos service), mas deixei de seguir ele em algum momento (colocando nomes iguais em alguns).

Muito obrigado desde já, abraços!

Sinto lhe dizer, mas eu acabo de implementar uma manutenção que não levou nem 1 minuto. Justamente pela FALTA do modelo anêmico.

O modelo anêmico, quando usado no projeto inteiro, PARECE que é mais rápido. Mas só parece… A manutenção fica comprometida e é mais fácil de surgir bugs…

Pois é, já ando vendo que dá problemas, pois umas poucas modificações aqui já me deram dor de cabeça.
O problema maior é que tenho uma semana de prazo, e parar o projeto pra estudar a fundo DDD, não há como.

Aqui eu sou um faz tudo quanto a informática. Mas ainda me esforço, arrumando tempo a noite e em fim de semana pra estudar programação de verdade, já que o que aprendi na faculdade num era nem a ponta do iceberg, e isso porque minha mulher é muito compreensiva. Ando muito desanimado dessa área …

Minha opinião sobre a camada Dao é a seguinte:
Há algum tempo deixamos de usar camadas Dao pois usamos Hibernate.
Achamos que o hibernate acabou se tornando o nosso Dao, por esta razão expomos diretamente o objeto Session para o domínio.

Por que chegamos a esta conclusão?
Em um projeto .Net tivemos diversas situações em que alguns modelos de dados estavam emaranhados
com regras de negócio, inclusive via triggers e procedures.
Usávamos o Entity Framework e, ao passo que o conjunto de entidades passou a ser mais complexo, vimos que o EF atrapalhava mais do que ajudava, por esta razão voltamos para o NHibernate, e se deus quiser jamais tocaremos no EF novamente.

Tínhamos um DAO bem isolado, porém, mesmo com um determinado nível de isolamento, levamos muito tempo para refatorar a camada dao, e ainda ocorrem alguns problemas aqui e acolá por conta da migração não estar completamente finalizada.

Acabamos que, por conta dos recursos apresentados pelo NHibernat e e pelo Hibernate, isolá-los na camada Dao penaliza o potencial do framework no sentido de trabalhar com coleções, grafos complexos de entidades, cargas e descargas de dados, em fim.

Adotamos de vez o Hibernate como nosso Dao, e nosso projeto só possui uma camada de domínio agora.

No início tínhamos medo da manutenabilidade dos nossos sitemas, visto que poderíamos ter criterions e linqs envolvidos com as regras de negócios, porém a coisa ficou bem mais simples, visto que o time trabalha de forma bastante organizada.

O resultado disso foi que ganhamos, de acordo com nosso atual sprint, um acréscimo de 29% de agilidade na manutenção de rotinas com domínio misto, em relação a nossos colegas que usam camadas de DataAccess isoladas.