DAO- Duvida Teorica

[quote]Acho melhor esquecermos a palavra entities por enquanto para não prejudicar a comunicação. Vamos pensar em objetos, dá uma olahda neste texto:

http://blog.fragmental.com.br/wiki/index.php/Fantoches
[/quote]

Interessante o artigo… já tinha visto pedaços dele.

Mais voltando um pouco mais… Olhando para os padrões GRASP, o padrão Controller então não é OO? Já que pelo que sei GRASP é ponto inicial ao Design Patterns…

http://en.wikipedia.org/wiki/GRASP_(Object_Oriented_Design)

É. Direto da fonte:

o Controller do Larman age como um application/session façade, apenas delega as operações para os objetos de domínio.

Ele age sobre Camadas, não tem tanta relação com OO em si. Você pode ter uma classe que faz interface, acesso a banco, regra de negócio e etc. e se ela contêr dados e funções ela é OO, só possui um péssimo projeto.

[quote=ignacio83]
Já que pelo que sei GRASP é ponto inicial ao Design Patterns…

http://en.wikipedia.org/wiki/GRASP_(Object_Oriented_Design)[/quote]

GRASP é apenas uma sigla para um conjunto de padrões e práticas catalogados pelo Larman.

Eu não sei eu sou cabeça dura… ou se ninguem consegue me convencer…

Essa idéia de colocar regras de negócio em objetos, pra mim realmente faz muito sentido.

Porém não consigo visualizar uma aplicação WEB ou pior ainda EJB com esta estrutura.

Perguntas:
1: Quase todos os padrões J2EE então são considerados procedurais e não OO? Ou seja todos eles possuem uma péssima modelagem? Grande parte deles são simplemente delegates…

2: Vamos supor a seguinte situação dentro de uma action. (é apenas uma abstração, sei que as actions não recebem estes atributos.

public void saveAluno( Aluno a )
{
a.save(); //Perfeito, pra mim faz sentido
}

public List<Aluno> findAlunos(String nome)
{
...
return dao.findAlunosByNome(nome); //Não estamos pulando uma camada aqui?
}

Ou isso:

public List<Aluno> findAlunos(String nome)
{
...
Aluno aluno = new Aluno();
return aluno.findAlunosByNome(nome); //O q me parece pior ainda..
}

Faz sentido. É um padrão de projeto chamado ActiveRecord.
Agora tente implementar isso num sistema complexo…

Sim, está. Que tal :

public List<Aluno> findAlunos(String nome)
{
...
return Aluno.findAlunosByNome(nome);
}


class Aluno {

  public static  List<Aluno> findAlunosByNome(String nome){

         Query q = cria query que é capaz de pesquisar alunos com base no nome

         Collection<DataRow> ralunos =   dao.findAll(q); 
 
         List<Alunos> alunos = new ArrayList<Alunos>();
         for (DataRow r : alunos){
            alunos.add(createFrom(row));
        }
        return alunos;
  }

  private Aluno createFrom(DataRow row){
          Aluno a = new Aluno(row.getString("nome"));
          
          // inicializa os outros atributos de aluno. 
          a.nascimento = row.getDate("nascimento");
         // poderia ser feito via reflection por uma classe utilitária

         return a;
  }
}

[/quote]

[quote=sergiotaborda][quote=ignacio83]

public void saveAluno( Aluno a )
{
a.save(); //Perfeito, pra mim faz sentido
}

[/quote]
Faz sentido. É um padrão de projeto chamado ActiveRecord.
Agora tente implementar isso num sistema complexo…
[/quote]

Não entendi o problema de implementar isso em um “sistema complexo”.

[quote=acdesouza][quote=sergiotaborda][quote=ignacio83]

public void saveAluno( Aluno a )
{
a.save(); //Perfeito, pra mim faz sentido
}

[/quote]
Faz sentido. É um padrão de projeto chamado ActiveRecord.
Agora tente implementar isso num sistema complexo…
[/quote]

Não entendi o problema de implementar isso em um “sistema complexo”.[/quote]

Se vc não entendeu não tem problema, é porque não passou por isso.
Na teoria o ActiveRecord (atenção à palavra Record) é um objeto de dados simples que se auto-persiste.
Esse padrão é explicitamente definido para objetos simples.
Esse padrão é explicitamente definido para objetos simples.

Num sistema complexo, por definição, os objetos de dados não são simples. E portanto, o ActiveRecord está condenado a ser um empecilho em vez de uma ajuda.

A implementação padrão de um ActiveRecord é o mapeamento direto dos campos para uma tabela usando JDBC puro. Afinal é super simples fazer isto quando os campos são fixos. Se os campos mudam, a logica jdbc muda junto porque está tudo no mesmo arquivo. Mas e a transação ?
Se fizer a.save();b.save();c.save(); em sequencia o objeto garante proprieades ACID para o conjunto das 3?
Não, ele garante para cada uma em separado. Bom ai vc resolve encapsulando as 3 num método auxiliar onde vc controla a transação. Mas pera ai, o objetivo de ActiveRecord é não precisar desse tipo de método. Ups , agora ficou complexo.


public void saveAll (ActiveRecord[]  all){

   Transaction t = ...
   t.begin();
   for (ActiveRecord a : all){
          a.save();
   }
   t.commit()

}

O codigo save() tem que estar consicente de que existe uma transação global acontecendo. Lá se vai o JDBC puro. A conexão não pode mais ser aberta no método save() , tem que usar algum DataSource. Bom, mas ai eu acabei de amarrar meu ActiveRecord muito-simples-à-primeira-vista com um mecanismo de controle de transação e um de lookup de connections. Qual é a vantagem do save() estar definido no ActiveRecord neste momento ? Bom, é lá que defino o statement de save que depende dos campos.
Convenhamos que hoje em dia isso não é uma boa já que esse statemente pode (e deve) ser criado sem intervenção do programado da classe.

Vejamos agora por outro lado. O ActiveRecord é um objeto que se auto-persiste. Mas qual é a responsabildiade principal dele ? Bom, é um agrupador de dados apenas. Será que um agrupador de dados precisa saber como se persistir ? Separação de Responsabilidade: coloque essa responsavilidade noutra classe.

Como muita gente vem do tempo do Delphi e da filosofia microsoft em que apenas existe a tela, o banco e uma ligação promiscua entre as duas. A diferença entre isso e java é que nessas plataformas os padrões de projeto já foram escolhidos e implementados. A flexibilidade é pouca e a implementação é de “confiança”, logo não ha porque inventar camadas no meio. Em java é quase que obrigatório inventar essas camadas. Logo, activeRecord , que é um padrão muito usado em VB , Delphi , etc… em java é quase um anti-pattern.

como disse no inicio: Esse padrão é explicitamente definido para objetos simples.
Vc pode usar tb em java se os seu objetos e o seu sistema são simples.
Os seus sistemas são simples ? :wink:

[quote]Se fizer a.save();b.save();c.save(); em sequencia o objeto garante proprieades ACID para o conjunto das 3?
Não, ele garante para cada uma em separado. Bom ai vc resolve encapsulando as 3 num método auxiliar onde vc controla a transação.[/quote]

Minha sugestão não é exatamente um ActiveRecord. Sugiro algo mais ou menos como comentei anteriormente, neste tópico.
Como a transação será controlada dentro do método da classe de domínio, usando os DAOs, não entendi o problema de implementar isso em um “sistema complexo”.

No caso do meu exemplo, isso deixaria de ser um ActiveRecord, uma vez que sugiro a utilização de um DAO para encapsular o trato com o banco.

[quote] Vc pode usar tb em java se os seu objetos e o seu sistema são simples.
Os seus sistemas são simples ?[/quote]
No meu trabalho eu acho que são sim. A maioria é de cadastros, sem nenhuma lógica muito pesada por trás. :cry:
Para compensar estou fazendo um freelance que está exigindo que meus dois neurônios voltem a fazer sinapse. :lol:

[quote=ignacio83]Eu não sei eu sou cabeça dura… ou se ninguem consegue me convencer…

Essa idéia de colocar regras de negócio em objetos, pra mim realmente faz muito sentido.

Porém não consigo visualizar uma aplicação WEB ou pior ainda EJB com esta estrutura.
[/quote]

Não seja tão duro com você mesmo :smiley:

Todos fomos doutrinados a pensar com objetos burros pela indústria nos últimos dez anos, agora estamos exatamente correndo atrás do prejuízo.

A maioria dos padrões dos catálogos de Java EE são utilizados unicamente para lidar com as dificuldades impsotas pleo design procedural do framework de EJBs. Dê uma olhada nas descrições dos padrões para ver que eles se aplicam em situações muito específicas e não para programação em geral.

Existem dois problemas aqui: objetos burros e camadas. Este ponto fala sobre Camadas e antes de mais nada é bom lembrar que não é porque uma arquitetura não segue Camadas que ela é ruim, pode ser exatamente o ideal apra um dado cenário.

No seu exemplo, para implementar camadas precisamos fazer com que o controlador delegue a tarefa de criar e procurar objetos para a Camada de negócios e esta é quem decide se tem que invocar otura camada ou não. para o controlador é transparente.

No caso, teríamos no meio do código do controlador:

//recebe parametros http

String login = request.getParameter("login");

Aluno alunoProcurado = gerenciadorDeAlunos.encotnrar(login);

//coloca o objeto em escopo apra ser lido pela JSP ou o que quer que seja
request.setAttribute("aluno", alunoprocurado);

//faz forward...

Como o aluno é bsucado? usa DAO? Vai procurar no oracle? Tá tudo em memória?

O controlador não sabe e nem deve saber.

Sobre o exemplo específico do aluno.save() é uma implementação válida de persistência e muito utilizada, por exemplo, por Ruby on Rails e pelo grails. Se é a melhor solução depende do caso.

O que faz o objeto ser um active record é ter um método na sua interface cujo resultado final é a persistência do próprio objeto. Independente de como o método se chame ou de como o método seja implementado.
Lá porque vc substitui o codigo jdbc por um DAO isso não muda nada. Do ponto de vista do contrato (interface) do objeto ele continua tendo um método save() cujo resultado final é a persistência do próprio objeto.
Portanto, não se engane pensando que seu mecanismo não é um activerecord, porque é. A única forma de não ser é não existir o método save() no objeto,

[quote=sergiotaborda]Faz sentido. É um padrão de projeto chamado ActiveRecord.
Agora tente implementar isso num sistema complexo…[/quote]

Espero ter colaborado… :mrgreen:

Obrigado Thiago é isso mesmo a que me referia.