Métodos CRUD em classes de negócio

Caro colegas,

 Estou modelando um sistema de informação que basicamente possui os métodos CRUD tradicionais, contudo, por exemplo, uma inclusão deve contemplar uma série de regras de negócio. Minha dúvida fica quanto a necessidade de criar os métodos CRUD nas classes de negócio e além deles criar os métodos que irão validar as regras de negócio da inclusão. Neste caso terei que ter um orquestrador para efetuar a chamada na ordem certa de um conjunto de métodos que levam a uma inclusão no sistema. A outra forma seria modelar simplesmente os métodos CRUD e "dentro" do método de inclusão, por exemplo, contemplar as regras de negócio. Minha forma de raciocínio está correta? Alguém tem alguma dica sobre o assunto.

Abraços.

Dependendo da complexidade do domínio você pode optar por Transaction Scripts, que deixam a implemenção de coisas simples como CRUDs muito fácil, apesar de não tornar os objetos de negócio flexíveis e de fácil manutenção como pode ser necessário.

Se você optar por TS cada operação vira um script dentro de uma ou mais classes, o próprio script executa as regras e valida os objetos.

Caso opte por um Domain Model, a alternativa mais completa e mais complexa, você deve tentar chegar com seus objetos o mais próximo do domínio possível, e neste caso a resposta depende do seu domínio. Lembre-se apenas que neste caso regras de negócio ficam apenas nos objetos de negócio e os ‘orquestradores’ não executam nenhuma regra em si, apenas delegam.

A literatura padrão é Martin Fowler, Meilir Page-Jones e Eric Evans.

Caro Marcelo, os métodos CRUD, devem estar relacionados com seus objetos de persistência. É necessário um orquestrador para gerenciar as associações entre as suas classes de persistência. Assim, como exemplo, suponha que você tenha uma classe Cliente e outra Pedido. Não se esqueça que em OO a reutilização e flexibilidade de manutenção e expansão de código são as estrelas do processo. Logo, teríamos:

  • a classe Cliente
  • uma classe de persistência ClienteDAO
  • a classe Pedido
  • uma classe PedidoDAO
  • e um orquestrador para associação entre ClienteDAO e PedidoDAO, esta poderia ser a ClientePedidoDLO. Esta classe apenas “chama” as respectivas DAOS da transação.

abraços.

Que a força esteja com você… 8)

Caro amisgos,

Acreidto que tenha me expressado mal. Os métodos que estou comentando seriam tipo incluirCliente(), alterarCliente(), etc… estes métodos não seriam os de persistências e sim relacionados ao ne~gócio. Por exemplo, para uma inclusão de cliente é necessário diversas regras de negócio.

Teria duas opções, uma seria criar o método incluirCliente() e este método faria o chamado as diversas regras. O outro seria colocar as regras em métodos fora do incluir e um orquestrador externo faria a chamada na ordem que o negócio precisa ser realizado.

O que vocês acham?

Abraços.

[quote=pcalcado]Dependendo da complexidade do domínio você pode optar por Transaction Scripts, que deixam a implemenção de coisas simples como CRUDs muito fácil, apesar de não tornar os objetos de negócio flexíveis e de fácil manutenção como pode ser necessário.

Se você optar por TS cada operação vira um script dentro de uma ou mais classes, o próprio script executa as regras e valida os objetos.

Caso opte por um Domain Model, a alternativa mais completa e mais complexa, você deve tentar chegar com seus objetos o mais próximo do domínio possível, e neste caso a resposta depende do seu domínio. Lembre-se apenas que neste caso regras de negócio ficam apenas nos objetos de negócio e os ‘orquestradores’ não executam nenhuma regra em si, apenas delegam.

A literatura padrão é Martin Fowler, Meilir Page-Jones e Eric Evans.[/quote]

Vamos trabalhar com um exemplo? Suponha que pra inserir o usuário existam os passos:

1 - Criar objeto usuário
2 - Colocar usuário num grupo
3 - Colcoar como gerente do usuário o gernete do grupo
4 - Chamar o DAo que persiste a coisa toda

Como você pensa nisso implementado?

Alguém poderia descrever em código a utilização do modelo MVC para aplicações desktop, com seus respectivos objetos de controle, de fronteira e de entidade?

Exemplo para ser usado: Cadastrar nome e telefone de um cliente!

[quote=pcalcado]Vamos trabalhar com um exemplo? Suponha que pra inserir o usuário existam os passos:

1 - Criar objeto usuário
2 - Colocar usuário num grupo
3 - Colcoar como gerente do usuário o gernete do grupo
4 - Chamar o DAo que persiste a coisa toda

Como você pensa nisso implementado?[/quote]
Aproveitando a duvida do amigo acima. Eu acho que as coisas poderiam ser implementadas assim

public class UserBean{
   public void insert(){
      User user = new User("fulano");
      user.setGrupo(grupoA);
      user.setGerente(pessoaA);
      user.save();
   }
}

public class User{
   private Grupo grupo;
   private Pessoa gerente;
   //geters and seters

   public void save(){
      repositorio.save(this);
   }
}

No exemplo acima os CRUD nao ficam na classe de negocio, mas ainda permanecem dentro do dominio, porem parte da logica de negocio fica exposta ao cliente.

O exemplo abaixo acho que descreve como as coisas deveriam ser segundo as boas regras do DDD

public class UserBean{
   public void insert(){
      UserTO userTO = new UserTO("fulano");
      userTO.setGrupo(grupoA);
      userTO.setGerente(pessoaA);
      UserService.save(userTO);
   }
}

public class UserService{
   public static void insert(UserTO userTO){
      User entity = new User();
      entity.setGrupo( userTO.getGrupo() );
      entity.setGerente( userTO.getGerente() );
      repositorio.save(entity);
   }
}

public class User{
   private String name;
   private Grupo grupo;
   private Pessoa gerente;
   //geters and seters
}

public class UserTO{
   private String name;
   private Grupo grupo;
   private Pessoa gerente;
   //geters and seters
}

Observacoes:
O repositorio presenta o nosso conhecido DAO, mas pode ser qualquer outra coisa, para criar a instancia disso eu deixo a cargo de nossa imaginação

O exemplo sugerido é bem simples, mas se vc nao se prender ao exemplo vc pode enxergar cituações onde isso é necessário.

[quote=pcalcado]Vamos trabalhar com um exemplo? Suponha que pra inserir o usuário existam os passos:

1 - Criar objeto usuário
2 - Colocar usuário num grupo
3 - Colcoar como gerente do usuário o gernete do grupo
4 - Chamar o DAo que persiste a coisa toda

Como você pensa nisso implementado?[/quote]

Aproveitando a oportunidade de você olhar a imagem que eu tenho de MODELO DE DOMÍNIO e critica-lo, vou postar um código.


public class Usuario {
	
	private Grupo grupo;
	private String nome;
	
	/*
	 * Levei em conta que usuário deve participar
	 * de um grupo para existir
	 */
	public Usuario(String _nome, Grupo _grupo){  
		// Asserts para verificar se os parametros foram 
		// passados corretamente
		
		nome = _nome;
		grupo.adicionar(this);
	}
	
	public Usuario getGerente(){
		return grupo.getGerente();
	}

}

public class Grupo {

	private List<Usuario> usuarios; //Acho que poderia ser um repositorio! Será?
	private Usuario gerente;

        //Construtor omitido
	
	public void adicionar(Usuario _usuario){
		usuarios.add(_usuario);
	}
	
	public Usuario getGerente(){
		return gerente;
	}
}

public class FachSistema {

	public void criarUsuário(String _nome, long _idGrupo){
		Repositorio<Usuario> usuRepositorioL;
		Repositorio<Grupo> grpRepositorioL;
		Grupo grupoL;
		Usuario usuarioL;
		
		usuRepositorioL = Registro.getRepositorio(Usuario.class);
		grpRepositorioL = Registro.getRepositorio(Grupo.class);
		
		grupoL = grpRepositorioL.getById(_idGrupo);
		
		usuarioL = new Usuario(_nome, grupoL);
		
		usuRepositorioL.adicionar(usuarioL);
	}
}

Será que após usuRepositorioL.adicionar(usuarioL) eu precisaria colocar grpRepositorioL.atualizar(grupoL)?

Críticas são muito bem vindas para o meu aprendizado! Manda bala ai galera!

[quote=marcelovvm]Caro colegas,

 Estou modelando um sistema de informação que basicamente possui os métodos CRUD tradicionais, contudo, (...)[/quote]

Aquilo que vc quer não são os métodos crud, mas sim aquilo que em banco de dados seria chamado de trigger.
A sua logica é assim "quando um X for incluido faça Y"
Este tipo de lógica é remanescente do trigger porque a palavra chave é “quando”

Vc tem várias hipoteses:

  1. Pre-processamento
    Aqui vc manda gravar um objeto e executa um codigo sobre ele antes de enviar para a persistência. Vc está interceptando a gravação. Para resolver isto não deixe a logica nos objectos do modelo.
    Ou vc deixa essa logica no repositorio da classe em causa, ou vc cria um serviço especialmente para isso.

  2. Reação
    Aqui vc manda o objecto normalmente para ser gravo. Ele é gravado sem alteração. Depois disso o repositorio avisa (por um mecanismo de eventos/listener) um outro objeto interessado que essa inclusão aconteceu. O objeto responde, por exemplo, alterando o objeto original e persistindo de novo (o que causará novo evento)

Eu estou falando em inclusão, mas a logica é aplicavel a qq ação.

3)Vc pode criar um mecanismo de cadeia (chain)
Que funciona assim: Vc sempre passa o objeto que vc quer persistir para um mesmo objecto ( digamos que é o repositirio). Vc pode configurar o repositório com um conjunto de interceptores (filtros) dizendo se o interceptor deve ser usado antes ou depois da persistencia, propriamente dita, ser feita. Os interceptores estão em cadeia, então as alterações serão em cadeira. O processo seria assim:

grava objeto no-> repositorio ->
invoca interceptor 1 sobre o objeto ->
invoca interceptor 2 sobre o objeto ->
invoca interceptor 3 sobre o objeto ->
invoca interceptor … sobre o objeto ->
invoca interceptor n sobre o objeto ->
persiste
invoca interceptor n sobre o objeto ->
invoca interceptor … sobre o objeto ->
invoca interceptor 3 sobre o objeto ->
invoca interceptor 2 sobre o objeto ->
invoca interceptor 1 sobre o objeto ->
retorna o objeto persistido e transformado (optional)

Conforme o interceptor é configurado para trabalhar na entrada , na saida, ou ambos, ele será , ou não invocado nos passsos respetivos.

Este mecanismo é semelhante aos filtros da Servlet API e é uma fusão das opções 1 e 2.

Conceitualmente uma operação Entidade.salvar() ou Entidade.excluir() é no mínimo estranho, pois é natural da entidade manter estado persistente (é desse jeito nos FW ORM atuais, uma entidade sabe o momento que deve ser salva no banco).

Falo um pouco sobre isso no meu artigo da MundoJava que está nas bancas.