Olá a todos, eu estava pesquisando algo sobre DDD e coisas relacionadas como entidades anêmicas,modelos ricos, excesso de gets e sets e encontrei esse post bem legal http://blog.fragmental.com.br/2008/05/18/objetos-nao-sao-atributos-funcoes/ mas me surgiu uma dúvida. No exemplo dele temos uma entidade Pedido e esse pedido tem um status para ilustrar como evitar um set que seria desnecessário, para finalizar um pedido no lugar de ter um
ele adicionou uma regra de negócio na entidadepedido.finalizar();
e para saber se o pedido foi finalizado bastaria fazer
p.isFinalizado();,
imagino que no exemplo o status seja representado por uma string no banco de dados, supondo a mesma situação de pedido e status mas agora considerando que Status também é uma entidade que está persistida no banco, como eu faria para finalizar um pedido seguindo esse modelo?me passou pela cabeça eu ter algo do tipo
public void finalizar(){
Status status = algumServiceInjetado.recuperarStatus(Status.FINALIZADO);
pedido.status = status;
outroSerivice.atualizar(pedido);
}
mas ter métodos que fazem acesso banco de dados dentro de entidades pra mim é algo que soa bem feio, pra mim isso é gambiarra, qual uma boa solução pra este tipo de caso? ou deveria ter esse método finalizar(Pedido pedido)
para dentro de um Service(http://www.guj.com.br/java/75388-fugindo-do-modelo-anemico) e na minha entidade ficar apenas com o isFinalizado() ?
Eu não li o post do link que vc passou… mas pelo seu post, eu acho que vc entendeu errado… Ele não quis dizer que a lógica ficaria aí mesmo… o método finalizar() faria apenas o que o método setStatus(FINALIZAR) faria…
public void finalizar() {
status = Pedido.Status.FINALIZADO;
}
O meu ponto de vista sobre isso é: as regras ficam na entidade, exatamente como o post mostra.
Se você quer persistir, alterar, deletar, isso não faz parte da entidade, mas do repository. (Se você não quiser seguir o modelo ActiveRecord.)
Por exemplo, só podem ser finalizados pedidos Status.NOVO.
Com setter ficaria assim:
public void setStatus(Status status) {
if (!Status.NOVO.equals(this.status) && Status.FINALIZADO.equals(status))
throw new IllegalArgumentException("Não é permitido finalizar um pedido que não seja novo.");
this.status = status;
}
Ou seja, seu teste desse método começa a ficar complexo… Pois a complexidade do seu método é maior. Precisa verificar se o parametro não é nulo, também.
Se, algum dia, você quiser finalizar pedidos Status.PENDENTE, você vai aumentar muito mais a complexidade desse método.
No meu caso que uso EJB se por exemplo simplista eu tiver minha entidade Pedido:
@Entity
public class Pedido{
@Id
private long id;
@ManyToOne
private Status status
private Date data;
public Pedido(){
this.data = new Date();
}
//get de data suprimido
//get e set de id suprimido
public boolean isFinalizado(){
if(this.status != null){
if(this.status.getNome().equals("FINALIZADO")){
return true;
}
return false;
}
public String dataFormatada(){
return Formater.formatarDataBrasil(this.data);
}
}
e tenho meu SessionBean :
@Stateless
public Class PedidoSessionBean(){
@PersistenceContext
private EntityManager em;
@EJB
private StatusSessionBean statusSessionBean;
public void finalizarPedido(Pedido pedido){
Status status = statusSessionBean.getPedido("FINALIZADO");
pedido.setStatus(status);
em.merge(pedido);
}
}
seria esta também uma forma correta de se trabalhar? estou ferindo OO em algum ponto?