Dúvida quanto a onde colocar um método

21 respostas
E

Boa tarde pessoas,

Vou resumir, pra não dar voltas.

Tenho um sistema que faz controle de relatórios que transitam pela empresa em que trabalho. O único propósito desse sistema é:

Os usuários recebem e enviam os relatórios entre os setores da empresa, e fica armazenada um histórico de toda movimentação.

Então, tenho basicamente três classes: Usuario, Relatorio e Setor.

Em Usuario ficam as informações do mesmo:

public class Usuario { private String nome; private String login; private Setor setor; //etc, etc }

public class Relatorio { private Date dataEmissao; private Setor setorAtual; }

public class Setor { private int codigo; private String nome; }

Tenho também minhas classes DAO - que não acho necessário mostrar aqui - e tô desenvolvendo utilizando DDD.
Agora a dúvida: eu tenho uma movimentação de relatórios de um setor a outro. Primeiramente tive a idéia mais simples: colocar o método movimentarRelatorio na classe Relatorio.
Mas ontem vi um post de um usuário em outro tópico ontem que me fez ver a coisa de outra forma: um (ou mais) relatório(s) são movimentados entre setores, e a partir de um Usuario.

Então tenho as seguintes opções, quanto a onde fica o método movimentarRelatorio:

1 - Na classe Relatorio. Mas acho muito estranho, pois um relatorio não se movimenta.
2 - Na classe Usuario, já que é uma operação que o usuário realiza. Também há o fato de que um relatório tem um Setor origem e um Setor destino, tornando, no meu ponto de vista, essa opção a mais correta.

O que vocês acham? Opção 1 ou 2? E porque?

Muito obrigado desde já, forte abraço!

21 Respostas

E

Caso esteja mal explicado, é só falar!

E

Você tem aquela famosa dúvida:

Temos 3 objetos, Usuario, Relatorio e Setor.

Em português, a movimentação de relatórios tem um sujeito (Usuario), um objeto (Relatorio) e dois lugares (Setor 1 e Setor 2).

Ou seja:

Usuário João movimenta o relatório de Vendas do setor de Alimentos para o setor de Vestuário.

Mas se seu modelo for muito anêmico, a classe Usuário não tem praticamente nenhum método.

Então você criaria uma outra classe, que é a que realmente efetuaria as ações. Só para dar um nome bonitinho, vamos chamar essa classe de Ator.

Pensando em orientação para objetos, você tem a dúvida se você faz algo como:

Mandar a mensagem movimentar-Relatorio para usuário João com parâmetros relatório Vendas, setor Alimentos, setor Vestuario

Ou

Mandar a mensagem movimentar-Relatorio para Ator X com parãmetros usuário João, relatório Vendas, setor Alimentos, setor Vestuario

E

entanglement,

É exatamente isso! Porém, tô tentando fazer um modelo mais rico, o código que postei é apenas de exemplo.

Qual das duas opções você recomenda, levando em questão exatamente esse problema de objetos anêmicos.

E

Reli e fiquei na dúvida: o que seria o Ator x? Um tipo de um service? Se a resposta for sim, não é esta a segunda opção. A segunda opção seria na classe Relatorio ter o método movimentarRelatorio().

E

Apenas ressaltando que tô evitando modelo anêmico, usando DDD. Ou seja: o método movimentarRelatorio fica na própria classe Relatorio ou na classe Usuario - essa última opção é a que me parece mais correta.

E

Chamo “Ator” um Service mesmo. É que estava sem imaginação na hora :slight_smile:

D

Eu consigo ver de algumas maneiras.
Usuario pode sim “movimentarRelatorio”, recebendo como argumentos o relatorio, setorOrigem e setorDestino.
Porém, também podemos ter em Setor os métodos enviar e receber.

public void enviar(Relatorio relatorio, Setor destino){}
public void receber(Relatorio relatorio, Setor origem){}

E fazer isso de forma direta, não?

E

Ótima solução, drsmachado!

Então você concorda comigo que o método movimentarRelatorio não deveria de forma alguma ficar na classe Relatorio?

Muito obrigado! Abraços!

D

$ERVER:
Ótima solução, drsmachado!

Então você concorda comigo que o método movimentarRelatorio não deveria de forma alguma ficar na classe Relatorio?

Muito obrigado! Abraços!


Exato.
Relatórios não tem a capacidade de sair do departamento A e ir até o departamento B sem que alguma força aja (terceira pessoa do singular do presente do indicativo do verbo agir, ele/ela aja) sobre ele.

E

hehe … Entendi.

Então, não quero usar service pra isso, quero deixar esse método dentro de uma dessas classes de domínio: Relatorio, Usuario ou Setor. Pelo que o drsmachado citou, eu ficaria entre Usuario ou Setor. E você, o que acha?

E

Exato.
Relatórios não tem a capacidade de sair do departamento A e ir até o departamento B sem que alguma força aja (terceira pessoa do singular do presente do indicativo do verbo agir, ele/ela aja) sobre ele.

Agora fico muito mais tranquilo! Muito obrigado por sempre estar me ajudando, amigo! Eu tenho apenas mais um dúvida quanto a esse assunto, vou postar daqui a pouco, se puder ajudar quando estiver disponível, agradeço muito!

Um grande abraço, até logo!

E

Agora a grande dúvida:

public class Usuario {

  private String nome;
  private String login;
  //restante

  public Usuario(String nome, String login) {
    //setando os atributos aqui 
  }

  public void encaminharRelatorio(Relatorio relatorio, Setor setorOrigem, Setor setorDestino, Date dataMovimentacao) {

  }

}

Notem que, como a classe Usuario não tem qualquer atributo relacionado a relatório - a lista de relatórios fica na classe Setor, já que cada Usuario pertence a um Setor - me parece que não preciso desse método aqui, ficando apenas no DAO - o que jogaria a lógica no DAO, o que acho péssimo. Alguma solução pra isso?

Só pra deixar claro, não estou pedindo pra ninguem fazer trabalho em meu lugar, quero apenas idéias, já que sou novo em Java, e fiz apenas dois projetos anteriores apenas com Servlets e JSP. Mas estou com muitas dúvidas sobre como utilizar DDD.

Abraços!

E

O máximo que eu conseguiria seria setar os valores, mas seriam perdidos, pois o método retorna void.

E

Tô começando a achar que mesmo aplicando DDD não preciso desse método nos domínios, pois a única coisa que o método faria seriam:

salvar a movimentação no banco de dados e gerar um pdf.

Que acham?

N

$ERVER:
Tô começando a achar que mesmo aplicando DDD não preciso desse método nos domínios, pois a única coisa que o método faria seriam:

salvar a movimentação no banco de dados e gerar um pdf.

Que acham?

Concordo. A lógica é tão simples que não é necessário aplicar DDD, matendo assim o KISS principle.

E

Olá natanaelv,

Primeiramente, muito obrigado por ajudar!

Então, tô chegando a essa conclusão.

Mas estranho é que a OO deixa uns buracos em alguns casos, parece. Repare bem que a operação de encaminhar um relatório pertence ao usuário, mas pode ficar de fora classe Usuario.

Quem tiver uma opinião contrária é só dizer. Abraços!

D

$ERVER:
Olá natanaelv,

Primeiramente, muito obrigado por ajudar!

Então, tô chegando a essa conclusão.

Mas estranho é que a OO deixa uns buracos em alguns casos, parece. Repare bem que a operação de encaminhar um relatório pertence ao usuário, mas pode ficar de fora classe Usuario.

Quem tiver uma opinião contrária é só dizer. Abraços!


Na verdade, não é bem a OO que está deixando o buraco. Mas a forma que você escolheu empregar a OO.
Embora modelos anêmicos sejam coisas ultrapassadas, nele você teria um Service que seria o responsável por fazê-lo.
Se optasse por aplicar o pattern Façade, teria um Façade encobrindo a lógica, isolando-a da camada de apresentação, sem envolver um método no bean/pojo para isso.
Como você está trabalhando com o DDD, você assume que o método responsável por mover um documento deve estar associado a uma das classes que está no modelo.
Mas, note que você vai precisar determinar alguma classe para que esta ação (mover o documento do setor a para o setor b) seja realizada.
Se formos analisar as responsabilidades no mundo real, quem move o documento de a para b é uma pessoa. O próprio documento não faz isso sozinho, tampouco um setor envia e outro recebe sozinho.
Ok, mas você não vai criar uma classe “Continuo” ou “OfficeBoy” apenas para mover o documento de um setor a outro. Você precisa de algo mais simples.
Quando eu, em outra resposta anterior, disse que poderia colocar os métodos enviar e receber no próprio setor, foi sob a ótica de que você pode “enviar” o documento gravando-o em um diretório, banco de dados, fila ou o que seja e depois lê-lo no método “receber”. Isso daria mais dinâmica ao processo, afinal, não é por que o office boy entregou os malotes que o relatório será lido imediatamente. Ele será lido quando for a hora.
Claro, esta é uma visão externa, não conheço os pormenores nem as regras que ditam como tua aplicação deve ser criada.

E

Então drsmachado, não acho ultrapassado, acho que é uma má prática. Segundo o próprio Fowler, ele não entende porque começaram a usar isso, como está no link ai pra trás.

No caso, seria apenas a movimentação lógica - informar ao sistema que o relatório irá ser movimento de a para b - e não o momento que o relatório sai ou entra fisicamente em um setor.

G

Gostei da solução do drsmachado.

Criar uma classe responsável pela movimentação de relatórios deixa o design mais coeso.
O usuário acaba existindo somente pra fins de autenticação e autorização, e o “EnviadorDeRelatorios” se preocupa apenas com essa movimentação.

falows t+

E

Olá gus.ehr,

E é isso mesmo, segundo o livro que tô lendo: Object Oriented Software Construction do Bertrand Meyer. Um trecho traduzido pra provar: “Em programação orientada a objetos, nós modelamos os objetos em termos do que eles fazem e não do que eles são.”

Levando em conta também que uma classe deve possuir a lógica de negócio, a qual opera sobre os atributos, eu não posso ter um método em uma classe que não aja sobre os atributos dela, e sim de outra. DDD trata também disso, basta ler este texto: http://www.codeproject.com/Articles/339725/Domain-Driven-Design-Clear-Your-Concepts-Before-Yo

Da forma como eu estava fazendo, estava totalmente procedural, e não guiada pelo domínio - já que estava separando os módulos por funções.

O correto seria eu ter a classe Usuario apenas para casos de autenticação e uma classe Relatorio ou Movimentacao a qual faz a movimentação do relatório - como vocês já apontaram anteriormente.

Pelo que andei lendo, DDD parece ser mais fácil do que parece, única coisa que parece um pouco complicada é a persistência - pelo conceito de repository, que ainda é muito controverso o modo de implementação, ainda.

Vou continuar lendo e postando aqui, ou criar outro tópico se necessário.

Muito obrigado a todos, grande abraço!

J

Sei que a discussão já esfriou, mas tenho um ponto de vista bem simples sobre sua conclusão $erver. Bem, o que busco modelar é quem detêm o domínio do comportamento sobre o objeto. Aplicando em seu caso, o processo de enviar o relatório apenas começa e termina com o usuário, porém quem detêm o conhecimento sobre todo o ciclo é objeto em questão, no caso o Relatório. Por si só ele não movimenta-se, contudo quem pode saber mais da movimentação (onde está, quem começou, para onde vai) que o próprio. Se houvessem diversos tipos de movimentações, claro, poderíamos ter algum objeto encapsulando todo esse comportamento.

É a minha opinião, se estiver furada, fiquem a vontade.

Criado 19 de julho de 2013
Ultima resposta 15 de out. de 2013
Respostas 21
Participantes 6