Esse modelo seria um Active Record?

Olá, li um post no GUJ, sobre arquiteturas de Sistemas do qual foi falado que a maneira correta de acessar, um SGBD ém uma aplicação J2EE é :

Requisição Web -> Action -> Modelo de Negócios -> DAO -> Implementação de DAO

A minha dúvida é a seguinte, seguindo este padrão, eu iria acabar usando ActiveRecord e não DAO, por exemplo se eu recebo da view o comando para salvarUsuario, o Controller teria que invocar este método no ModeloDeNegocio, que é o unico lugar onde ele conhece, entao o Modelo teria que ter um metodo save deste jeito, o que acabaria sendo um AR(ActiveRecord), pois ele teria o método Save mesmo que só fossse um delegate para o DAO.

Ex:

class Usuario {
private UsuarioDao;
public void save{
usuarioDao.save(this);
}
}

Eu faço da seguinte forma

Requisição Web -> Action -> DAO -> Implementação de DAO >Banco

Quando a view me manda o comando, o Controller instancia o model com os dados que estacao view, depois invoca o Dao que ele tem por composição;

É errado trabalhar assim???

Att

Daniel não existe maneira correta quando falamos em arqutietura. Arquitetura é sempre tentar procurar o mais adequado e o mais adequado varia muito.

No seu exemplo você pode inserir uma Façade entre a Action e o objeto usuário. Esta Façade coordena o fluxo do caso de uso e -provavelmente- é quem chama o DAO no final.

Note que num mundo ideal nem AR nem DataMapper seriam necessários.

[quote=pcalcado]Daniel não existe maneira correta quando falamos em arqutietura. Arquitetura é sempre tentar procurar o mais adequado e o mais adequado varia muito.

No seu exemplo você pode inserir uma Façade entre a Action e o objeto usuário. Esta Façade coordena o fluxo do caso de uso e -provavelmente- é quem chama o DAO no final.

Note que num mundo ideal nem AR nem DataMapper seriam necessários.[/quote]

Philip, então essa fachada é que instanciaria o model, com os dados da view ex:

public class Action {
  private Façade façade;

  public final String saveUser(){
     return façade.saveUser();
   }
}
public class Façade{
    private UsuarioRepository usuarioRepository;    
    String login=request.getParametre("login);
    String senha=request.getParameter("senha); 
    Usuario usuario = new Usuario(login,senha);

  
    usuarioRepository.add(usuario); //aqui poderia chamar o DAO direto??
   //ou seja o CRUD ficaria no DAO ou no Repository???
   
    //Eu faria o try{catch} aqui??? e colocaria o erro na view para o usuário, ou faria isso em outro lugar???
   
}

Obrigado

Esquece repositório por enquanto, se mantêm no DAO apenas, você precisa entender um pouco melhor arquitetura de Camadas. O Façade que falei não recebe request ou qualquer coisa relacionada com HTTP/MVC/etc. Ele faz parte da Camada de Negócios (de Aplicação, na verdade, mas vamos simplificar) e precisa receber algo que faça sentido nessa Camada. Tente algo assim:

class AdicionaUsuarioAction{
 public void execute(HttpRequest request){
   Usuario novo  = new Usuario(request.get('login'), request.get('senha'));
   servicoUsuarios.adicionar(novo);
 }
}
class ServicoUsuarios
 public void adicionar(Usuario novoUsuario){
    usuarioDao.adicionar(usuario);
 }
}

Por que criar a Façade (ServicoUsuario)? A rigor você não precisa dela, a Action poderia chamar o DAO, mas ela quem controla o caso de uso. Digamos que você precise que um email seja enviado para o adminsitrador do sistema quando o usuário é criado, isso faz parte do caso de uso e pode ser adicionado à Façade. Outra coisa interessante é para controlar transações.

[quote=pcalcado]Esquece repositório por enquanto, se mantêm no DAO apenas, você precisa entender um pouco melhor arquitetura de Camadas. O Façade que falei não recebe request ou qualquer coisa relacionada com HTTP/MVC/etc. Ele faz parte da Camada de Negócios (de Aplicação, na verdade, mas vamos simplificar) e precisa receber algo que faça sentido nessa Camada. Tente algo assim:

class AdicionaUsuarioAction{
 public void execute(HttpRequest request){
   Usuario novo  = new Usuario(request.get('login'), request.get('senha'));
   servicoUsuarios.adicionar(novo);
 }
}
class ServicoUsuarios
 public void adicionar(Usuario novoUsuario){
    usuarioDao.adicionar(usuario);
 }
}

Por que criar a Façade (ServicoUsuario)? A rigor você não precisa dela, a Action poderia chamar o DAO, mas ela quem controla o caso de uso. Digamos que você precise que um email seja enviado para o adminsitrador do sistema quando o usuário é criado, isso faz parte do caso de uso e pode ser adicionado à Façade. Outra coisa interessante é para controlar transações.
[/quote]

Philip, eu realmente estou com dificuldade em entender camadas, como neu inglês não é muito bom e não tem praticamente nenhum material em portugês, fica difícil comprrender certos conceitos, mas obrigado pelas dicas;
Então resumindo eu continuaria instanciando os objetos dentro da Action, como vc fez no metodo execute:

class UsuarioAction{
 public void saveUser(HttpRequest request){   //InnerAction
   Usuario novo  = new Usuario(request.get('login'), request.get('senha'));
   servicoUsuarios.adicionar(novo);
 }
}

Agora na façade

class ServicoUsuarios
 public void adicionar(Usuario novoUsuario){
    usuarioDao.adicionar(usuario); //eu faria o try{catch } aqui????
 }
}

Mais uma coisa, você disse que seria interessante controlar as transações na façade, mas no caso por exemplo eu tenho um filtro de controle de transações, então eu só usuaria façade se precisa de um controle a mais no meu Usário certo??

Então não tem problema nenhum a action acessar o DAO em algumas ocasiões como o CRUD simples??

Att

Philip o que me deixou em dúvida foi que li o seguinte modo de acessar, um SGBD

Requisição Web -> Action -> Modelo de Negócios -> DAO -> Implementação de DAO

Seguindo este modelo, minha action teria que ter por composição minhas classes de negócio, por isso eu falei que no fundo estaria trabalhando com ActiveRecord, porque da Action eu faria o seguinte


public class Action {
   private Usuario usuario;
  
    public saveUser(HttpRequest request) {  
        Usuario usuario= new Usuario(request.get("login"), request.senha("senha"));
        usuario.save(usuario);
   }
}

public class Usuario{
  private UsuarioDao usuarioDao;

    public save() {
        usuarioDao.save(this);
   }
}

Por isso achei estranho, já que não gosto de ActiveRecord, mas é uma opinião pessoal.

Teria outra maneira de fazer baseado neste modelo acima, ou seria assim mesmo a implementaçao??

Att

try/catch de que exatamente?

Filtro == Servlet Filter? São soluções diferentes, você pode escolher uma ou outra -ou alguma outra! Não sei te dizer qual a melhor, vai depender de outros requisitos do sistema.

Se tem problema ou não também depende de outros critérios. Eu normalmente evitaria ao máximo fazer isso para que a arqttietura não tenha exceções (quando é algo X eu sigo o caminho X1, quaaaando é um CRUD eu sigo Y1, quaaaaaaando é relatório eu sigo R1…). Para mim uma arquitetura -ou um design- elegante é o que consegue resolver casos especiais sem criar exceções.

[quote=danielbussade]Philip o que me deixou em dúvida foi que li o seguinte modo de acessar, um SGBD

Requisição Web -> Action -> Modelo de Negócios -> DAO -> Implementação de DAO

[/quote]

Esse esquema é uma abstração. Ele apenas te mostra possíveis componentes envolvidos mas não como eles se envolvem. O modelo que te dei antes é compatível com este.

E em alguma edicao da MundoJava, 15 ou 17, acho, eu escrevi uma rtigo sobre Camadas. Pode te ajudar.

[quote=pcalcado]try/catch de que exatamente?

Filtro == Servlet Filter? São soluções diferentes, você pode escolher uma ou outra -ou alguma outra! Não sei te dizer qual a melhor, vai depender de outros requisitos do sistema.

Se tem problema ou não também depende de outros critérios. Eu normalmente evitaria ao máximo fazer isso para que a arqttietura não tenha exceções (quando é algo X eu sigo o caminho X1, quaaaando é um CRUD eu sigo Y1, quaaaaaaando é relatório eu sigo R1…). Para mim uma arquitetura -ou um design- elegante é o que consegue resolver casos especiais sem criar exceções.

[/quote]

Olá, quando ao filter sim é um servlet filter, ele intercepta todas as chamas, e onde tem uma annnotation criada por mim, ele injeta a transação e inicia ela baseada na classe ThreadLocal.

Quando ao tryCatch, digamos que meu Dao lanca um DAOException deste jeito:


  public class UsuarioDao {
     private EntityManager em;

     public void save(Usuario entidade){ 

      try {
        em.persist(usuario);
      }catch(Exception)  {
           throw new DAOException(e.getMessage(),e); 
       }
   }
}


Ai na façade eu faria o tryCatch assim:

class ServicoUsuarios   
public void adicionar(Usuario novoUsuario){  

 try {
    usuarioDao.adicionar(usuario); 

}catch(DaoException){
      //adciona a mensagem ao output da view, para mostrar ao usário, 
    //ou relanço ele pra Action, e  a Action mostra a mensagem ao Usuario;???
   }
    }   
}  

Quanto a Arquitetura não ter excessões, então mesmo que minha façade sirva apenas como delegate para o DAO, é melhor usar em todos casos, do que ter casos com Façade e outros invocando o DAo direto correto

Obrigado!

[quote=pcalcado][quote=danielbussade]Philip o que me deixou em dúvida foi que li o seguinte modo de acessar, um SGBD

Requisição Web -> Action -> Modelo de Negócios -> DAO -> Implementação de DAO

[/quote]

Esse esquema é uma abstração. Ele apenas te mostra possíveis componentes envolvidos mas não como eles se envolvem. O modelo que te dei antes é compatível com este.[/quote]

Entendi ModeloDeNegocios aqui ,é o model do MVC, o que é CamadaDeAplicacao + CamadaDeNegocios+CamaPersistencia;

Assim , se encaixaria no modelo que voce disse;

Eu prefiro ACTION -> SERVICE -> DAO. A action pode ser acoplada ao framework (ou não) e o service não deve ser acoplado ao framework.

Paga-se o preço de uma maior burocracia e algumas vezes sua action acaba sendo uma "ponte burra".

Entretanto eu considero isso como um seguro para o futuro, caso o seu sistema venha a crescer em tamanho e complexidade. Melhor fazer a coisa certa desde o início, mesmo que no início você não precise dela.

E se mais tarde tb não for necessário… bom… quantos aqui usam o seguro do seu carro?

Eu fiz um blog sobre isso há algum tempo atrás:

http://blogs.mentaframework.org/posts/list/14.page

Acabei de entrar no site da revista e comprei a ediçao anterior 15 e 17;

Ah e, parabéns pelos artigos no fragmental, estão me ajudando muitooo a entender certos conceitos;

Att

[quote=saoj]Eu prefiro ACTION -> SERVICE -> DAO. A action pode ser acoplada ao framework (ou não) e o service não deve ser acoplado ao framework.

Paga-se o preço de uma maior burocracia e algumas vezes sua action acaba sendo uma "ponte burra".

Entretanto eu considero isso como um seguro para o futuro, caso o seu sistema venha a crescer em tamanho e complexidade. Melhor fazer a coisa certa desde o início, mesmo que no início você não precise dela.

E se mais tarde tb não for necessário… bom… quantos aqui usam o seguro do seu carro?

Eu fiz um blog sobre isso há algum tempo atrás:

http://blogs.mentaframework.org/posts/list/14.page
[/quote]

Fala sérgio tudo bom? Então essa discussão de Service ou não é eterna, ou alguns dizem que não vale a pena abstrair, porque na maioria das vezes o Façade ou Service, serveria apenas como voce mencionou uma “ponte burra”, mas do outro lado , e se na hora de cadastrar o usuario eu tivesse que mandar o e-mail como o philip observou seria interessante fazer na façade e não na Action.
Atualmente tenho acesso o DAo direto da Action, mas estou pensando em criar essa façade mesmo que me custe umas classes a mais.
Que modelo você usa atualmente??

Obrigado

Daniel, independente de service/façade, quem poderia mandar um email ou outra coisa, acho que o modelo que vc DEVE EVITAR e creio que seja uma unânimidade aqui, é acessar o DAO direto da Action. Action -> DAO
Prefira:
Action -> OUTRO_COMPONENTE -> DAO

[quote=Luiz Aguiar]Daniel, independente de service/façade, quem poderia mandar um email ou outra coisa, acho que o modelo que vc DEVE EVITAR e creio que seja uma unânimidade aqui, é acessar o DAO direto da Action. Action -> DAO
Prefira:
Action -> OUTRO_COMPONENTE -> DAO

[/quote]

Luiz, pelo que vi e unanime mesmo esta decisão de a Action não acessar o DAO, a principio a maior vantagem que vejo é não acoplar classe nenhuma ao prefixo DAO, porque automaticamente subtende que tem um SGBD ligado direto, por isso a idéia do Repository que o Philip explicou ou seja um lugar onde estão os Objetos, agora se o DataMapper é o DAO ai já é outra coisa, poderia ser em Memory, do qual não precisaria do DAO.
Fora isso, existe alguma outra vantagem em a action não acessar o DAO direto??

Obrigado

Acredito sim que essa implementação seja realmente a melhor, ou muito próxima disso, mais tenho uma pequena dúvida ainda.

Se tratando de métodos complexos, que dependem de várias validações e outras coisas referentes ao modelo e ao acesso ao banco, realmente vejo necessário criar a camada intermediária entre a action e o Dao.

Mais se tratando de métodos mais simples, com nenhuma validação, como save, update e etc, não vejo a real necessidade dessa terceira camada ser criada.

Teríamos basicamente isso


public class UserAction{
   public void save{
     User user = new User("parametro");
     userFacade.save(user);
   }
}

public class FacadeUser {
    public void save(User user){
        userDao.save(user);
    }
}

Acredito que como demonstrado acima isso só seria delegação de camada. Na verdade não vejo vantagem real de se utilizar esse tipo de arquitetura para todas as minhas actions ou meu modelo de negócios.

Na minha opinião isso vai da caso a caso, sempre levando em consideração o que realmente é necessário e o que é “padrão” para seu projeto.

O que acham dessa minha abordagem?

[quote=Luiz Aguiar]Daniel, independente de service/façade, quem poderia mandar um email ou outra coisa, acho que o modelo que vc DEVE EVITAR e creio que seja uma unânimidade aqui, é acessar o DAO direto da Action. Action -> DAO
Prefira:
Action -> OUTRO_COMPONENTE -> DAO
[/quote]

E o YAGNI fica aonde?

Se ele não precisa de um OUTRO_COMPONENTE agora, não precisa ficar aumentando o nível de indireção por causa de “complementos futuros”. Acho que tomar o caminho da Action acessando o DAO (ou um reposotório) é bem mais simples e resolve o problema de forma direta, em vez de criar uma camada sem “motivo de ser” a mais que não faz nada além de complicar o design da aplicação.

[quote=Maurício Linhares][quote=Luiz Aguiar]Daniel, independente de service/façade, quem poderia mandar um email ou outra coisa, acho que o modelo que vc DEVE EVITAR e creio que seja uma unânimidade aqui, é acessar o DAO direto da Action. Action -> DAO
Prefira:
Action -> OUTRO_COMPONENTE -> DAO
[/quote]

E o YAGNI fica aonde?

Se ele não precisa de um OUTRO_COMPONENTE agora, não precisa ficar aumentando o nível de indireção por causa de “complementos futuros”. Acho que tomar o caminho da Action acessando o DAO (ou um reposotório) é bem mais simples e resolve o problema de forma direta, em vez de criar uma camada sem “motivo de ser” a mais que não faz nada além de complicar o design da aplicação.[/quote]

Maurício, eu sempre fiz assim ,Action > DAo/Repository, só que quase todos os tópicos que li aqui no GUJ, dizem para não fazer isso, e sim criar uma Façade, acontece que na maioria das vezes a façade se comporta com uma camada sem sentido, embora em alguns casos faço sentido;
Ai entra outro problema, alguns pontos ter o façade e outros não, isso sim eu acho complicado, porque tirar a padronização da aplicação.

Att

Qual o problema em se ter façades para certas coisas e para outras não? O que pode ser necessário para uma situação pode não ser para outra. Fazer overengine só para dizer que é padrão não me parece uma boa estratégia.