Dúvida quanto a onde colocar um método

21 respostas
ERVER

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

ERVER

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

ERVER

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.

ERVER

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().

ERVER

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:

drsmachado

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?

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!

drsmachado

$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.

ERVER

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?

ERVER

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!

ERVER

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!

ERVER

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

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?

natanaelv

$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.

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!

drsmachado

$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.

ERVER

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.

gus.ehr

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+

ERVER

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