DAO- Duvida Teorica

Opa pessoal, estou com umas duvidas teoricas de como trabalhar com DAO.

Pensando no contexto web, tenho tres pacotes:

/servlets
/beans
/dao

Os beans são apenas objetos pojo, sem nenhum método de negócio, somente com getters e setters, como estamos falando de sistema pequenos, é basicamente CRUD com poucas regras de negócios, então basicamente o que se faz nos servlets é instanciar os DAO’s e passar o bean para ele persistir, porém de vez em quando tem algumas sutilezas da regra de negócios que são tratadas diretamente no servlet isso fica errado em termos de OO ?

Valeu

Fala mrxrsd blz contigo cara, voce esta lembrado do conceito do que e um bean? Entao um bean nd mais eh do que uma classe com um construtor vazio e seus metodos acessadores, portanto nao tem problema nenhum vc fz alguma logica de negocio no servlet, mesmo pq ele esta sendo na estrutura que vc montou, seu controller, onde toda a requisicao e resposta estara passando por ele.

vlws

Alessandro Alves

Muitas pessoas dizem que dependendo do caso não vale a pena criar uma camada de negócio, eu discordo totalmente disso.

Acredito que sempre vale a pena criar uma camada de negócio antes dos DAOs, afinal mesmo que sua regra de negócio seja muito simples, você não sabe o quanto o seu sistema pode crescer ou ser modificado, seja por pedidos do cliente ou pela própria evolução do sistema.

Respodendo a sua pergunta. Sim na minha opinião fica errado chamar os DAOs diretamente de uma Servlet ou página JSP.

Opa!

Nao que fique errado, mas imagine que tenha regras de negocio no seu servlet e vc tenha q usar em outra tela a mesma regra como vc faria? Copy Paste? NAOOO!!!
Entao a idéia do conceito de ter uma classe que controla essas regras vc teria uma maior reutlização (mais sinergia, integração). O q vc acha?
Espero q tenha ajudado.

Abs!

Cara seguinte, pelos padroes de projeto o interessante eh deixar o maximo suas camadas bem divididas, por exemplo, ter um cara para conversar com seus beans sem que que vc os manipule, um cara para convesar com seus daos com o mesmo intuito dos beans, deixar tudo em camadas, para que no futuro ou quando o projeto crescer n ter problemas, mas na realidade tudo isso vai depender muito do projeto que vc esteja criando, arquitetura e etc , mas n fica errado vc manipular as daos atraves de um servlet, vai depender do seu projeto.

vlws.

Em minha opinião:

  • Ao invés de Beans burros apenas com getters and setters, que tal entidades um pouco mais espertas? Boa parte da regra de negócio pode ser colocado nestas entidades! :wink:

  • Não esqueça que DAO só salva o estado da entidade. Por isso, não vejo problemas do servlet conhecer o DAO, mas a regra de negócio deve ficar em um local de fácil reuso. Por exemplo, se precisar implementar alguma regra de negócio que envolva N entidades você pode criar uma fachada para tratar esta regra de negócio.

É comum encontrar o pessoal fazendo algo mais ou menos assim:
servlet --> Service (ou Manager) --> DAO

Veja este link aqui: http://appfuse.org/display/APF/Services

quote=mrxrsd
regra de negócios que são tratadas diretamente no servlet isso fica errado em termos de OO ?
[/quote]

Como a sua dúvida é teórica então, em teoria , sim, é errado.
Na prática é errado da mesma forma, mas pode ser admissível em certas circunstâncias:
se vc tem pouco tempo, poucos recursos ou pouco interesse na evolução do sistema, por exemplo.

Outra duvida que sempre tive em relação ao DAO é se é aconselhavel criar vários métodos mas todos com idéia de persistencia ou se o ideal é criar apenas um método salvar e ele se vira para ver o que já está no banco referente ao objeto e o que não está e fazer as atualizações necessárias.
Por exemplo vou usar o escopo do meu trabalho da faculdade para explicar.

Eu tenho um congresso e o congresso tem uma lista de pessoas que são o comitê, tem o chair e o coordenador basicamente. Entao eu poderia muito bem criar um método salvar no congresso e esse método verifica o objeto em memoria comparando com os dados que estão persistido no banco e reflete as atualizações da memoria para o banco, mas acho que isso geraria um processamento desnecessário, pois toda vez que tiver alguma atualização em algum item de congresso ele faria várias verificações, a outra maneira que pensei, que foi a que eu usei foi dividir tudo em vários métodos, Ex.: incluirComite() IncluirChair() IncluirCoordenador() e assim em diante, isso é errado?

Não sei se consegui ser bem claro, vou colocar aqui um link de um trabalho da faculdade que estou fazendo, se alguem tiver tempo para olhar e ver se o que eu estou fazendo é um absurdo, agradeço hehehe

www.amazingworks.net/pss.war

Estou acostumado a usar VB e Asp, então voces devem imaginar qual paradigma que eu estou acostumado né? =)

Fiquei com bastante duvidas porque li assuntos sobre DAO e sempre foi meio contraditórios então no fim das contas não sei se estou fazendo o certo ou não.

PS: Antes que alguem comente hehehe, não usei Prepared Statement porque acho mais chato e isso não era um item que seria avaliado. hehehe

[quote=mrxrsd]Pensando no contexto web, tenho tres pacotes:
/servlets
/beans
/dao
[/quote]

Lembra do modelo MVC? seu pacote servlets compõem a camada Controller da sua aplicação. Os pacotes beans e dao ficam na camada Model e as JSPs e TagLibs ficam na View.

Acontece que você está confundindo dois conceitos:
[list]JavaBeans: Componentes reutilizáveis que possam ser manipulados visualmente por ferramentas.[/list]
[list]POJOs: Classes java que não possuem dependência de nenhuma tecnologia específica, neste caso a tecnologia citada era EJB do tipo EntityBeans, mas não restritivo a eles.[/list]
Portanto, POJOs possuem, sim, regras de negócio definidas nele. E é um conceito diferente de JavaBeans.

Concordo com o sergiotaborda. Lembra a história de que um Objeto possui estado e comportamento. Pois é, o estado são os atributos da classe e o comportamento os métodos com a implementação da regras de negócio.

Apesar de concordar com essa sua opinião, não acho que isso deve valer para entidades (objetos que representam um registro no banco de dados).

Quando se coloca regras de negócio em uma entidade, raramente é possível aproveitar a mesma entidade em um outro sistema, porque colocando as regras de negócio na entidade amarramos totalmente o sistema a entidade.

Sei que esse tipo de coisa gera muita polêmica… :slight_smile:

O DAO não deve conter regras de negócio, somente operações de CRUD, portanto na minha opnião o ideal é criar apenas um método salvar e ele ser virar para fazer um insert ou um update. Mais nunca no mesmo DAO, métodos do tipo: salvar(x), salvarSeAtivo(x).

Repare que no segundo método existem regras de negócio, ou seja, o método só salva a entidade em questão se estiver ativa. Esse tipo de regra deve ficar preferenciamente em uma camada de negócio. Facilitando assim o reaproveitamente deste DAO em outro contexto, ou mesmo outra aplicação.

Minha sugestão é que você pense ± assim;

[code]
public class Cliente{
private Long id;
private String nome;
private String endereco;
private String telefone;

public void save() throws NegocioException {
    /* Executa alguma regra de negócio. Por exemplo o cliente não pode ter um telefone com DDD de fora do Rio de Janeiro.
      * Caso o telefone informado não seja do Rio, lança uma NegocioException informando que o telefone não é do Rio.
      */
    ...

    try{
        //Abre uma conexão e inicia a transação...
        ...

        //Cria o dao e passa a conexão, aberta anteriormente, para ele. Estou assumindo que você não está usando uma DAOFactory.
        ClienteDAO dao = new JdbcClienteDAO(conn);

        //Manda o dao salvar o objeto cliente
        dao.save(this);

        //Commita a transação.
        ...
    }catch (DAOException e){
        //Dá rollback na transação e lança uma Exception que caracterize erro no sistema.
        ...
    }finally{
        //Fecha a conexão
    }
}
//Getters e Setters.

}[/code]

E no DAO:

[code]public class JdbcClienteDAO implements ClienteDAO {
private final Connection conn;

/**
 * Receber a Connection para que eu possa usar os métodos do DAO em mais de um lugar, sem que ele atrapalhe uma transação.
 */
public JpaClienteDAO(Connection conn) {
    this.conn = conn;
}

public int save(Cliente cliente){
    //Código para inserir um cliente no banco de dados usando a Connection recebida no Construtor.
}

}[/code]

Assim você poderá usar o método save do JdbcClienteDAO em outra classe, que não a que você pensou originalmente: Cliente.

Qual a vantagem disso?
Simples, em uma situação em que o método save esteja em uma transação maior do que salvar um Cliente.

Um exemplo?
Imagina o método creditar e debitar. Criados na classe ContaCorrente de um sistema para um Banco.
No método creditar você informa o valor e é feito um crédito na ContaCorrente com o valor informado.
No método debitar você informa o valor e é feito um débito na ContaCorrente com o valor informado.

Usando minha sugestão, o método transferirPara(ContaCorrente cc, BigDecimal valor) será uma chamada aos dois métodos, só que em uma transação sendo iniciada antes do primeiro e sendo commitada depois do segundo.

[code]transferirPara(ContaCorrente cc, BigDecimal valor){
try{
//Abre uma conexão e inicia a transação…

	//Cria o dao e passa a conexão, aberta anteriormente, para ele. Estou assumindo que você não está usando uma DAOFactory.
	ContaCorrenteDAO dao = new JdbcContaCorrenteDAO(conn);
	
	//Creditar na atual
	dao.creditar(this, valor);
	//Debitar da CC informada
	dao.debitar(cc, valor);

	//Commita a transação.
	...
}catch (DAOException e){
	//Dá rollback na transação e lança uma Exception que caracterize erro no sistema.
	...
}finally{
	//Fecha a conexão
}

}[/code]

Você está falando sobre ActiveRecord? Mesmo neste caso os comportamentos ficam junto com os dados.

E a idéia não era essa?
Pensa, só… Quando que um conjunto de dados de um conceito de negócio - os atributos da entidade - vão fazer sentido em outro contexto, que não o que ele representa?

Tem alguma assunto em desenvolvimento de software que não gere? :smiley:

O DAO serve para acessar os dados de uma entidade sem que ela fique sabendo de detalhes de onde ela está persistida. É possível imaginar o DAO como uma(os puristas vão me matar) “entidade fraca” em relação a Entidade que ela provê serviços de persistencia. Portanto ele só será reaproveitado nos casos em que precisar prover o serviço de persistencia para o meio(arquivo texto, banco de dados Oracle, qualquer banco de dados relacional) que ela conhece para a Entidade que ela serve.
Resumindo: Um DAO é, no máximo, tão reaproveitável quanto a Entidade que ele serve. Podendo ser menos, quando o meio que ele conhece não será usado.

Não porque OO não diz quais objetos criar ou como, apenas diz sobre o que são objetos e suas características. O que você vai possuir é métricas como acoplamento e coesão bem ruins neste design, seria interessante evoluir para o padrão conhecido como Domain Model.

Não confunda entidades relacionais com objetos, eles são bem diferentes.Entidades relacionais normalmente são apenas uma representação de comod ados são persistidos.

E como você utilizaria dados sem lógica? Repetindo a lógica em outros sistemas?

O princípio básico da orientação a objetos é que você possui estado (dados) e comportamento (lógica) no mesmo componente, o objeto. Sem isso você não tem um sistema OO.

Tem razão talvez tenha misturado um pouco as coisas, mais como estavámos falando de DAOs, achei que os objetos em questão eram as entidades.

Hehehe… Essa discussão vai longe, prefiro utilizar objetos do tipo Bean, do que POJO, costumo ter uma classe “controladora” (com regras de negócio) para a entidade em questão.

Não sei respondi a sua pergunta mais a lógica de dados fica em outra classe, se forem as mesmas regras utilizo a mesma classe controladora.

Acho que isso é mais uma questão de preferência mesmo…

Acho que tem um problema de conceitos aí. Não existem “obejtos do tipo bean”, JavaBeans são componentes editáveis por ferramentas gráficas, com o empo o nome passou a designar a convenção de usar métodos set/get mas ser um “Bean” não tem relacionamento com o tipo d eproblema que discutimos aqui. POJOs também são não relacionados, um POJO pode ser um JavaBean, um JavaBean pode ser ou POJO, ou não. São conceitos bem diferentes: http://blog.fragmental.com.br/2006/05/16/strict-pojos/

Imagine que eu tenho dois sistemas que utilizam as mesmas “classes de dados”. Imagina uma regra d negócio spbre estes dados qualquer. Imagina que os dois sistemas devem fazer este processamento. Como você faria? Criaria (ou copiaria) a mesma lógica nas duas “classes de lógica”?

[quote=ignacio83]
Acho que isso é mais uma questão de preferência mesmo…[/quote]

Na verdade é uma questão de ter orientação a objetos ou não :wink:

Tem ocasiões onde faz sentido uma abordagem procedural como você está descrevendo mas na maioria das vezes você está abrindo mão das funcionalidades OO a toa. Cuidado.

Acho que entendi…

Agora vms debater mais sobre a idéia de regras de negócio…

Onde você normalmente coloca as regras de negócio? Suas Entitys contém as regras de negócio? Ou algum outro objeto as contém? Como um VO?

Acho “estranho” colocar essas nas Entitys.

Colocar lógica de negócio nas entidades seria estranho por que? A própria OO não diz que dados e comportamento caminham juntos? Se a lógica de negócio vai manipular os dados desta entidade, o lugar certo de colocar a lógica de negócio é na própria entidade.

Chamar um DAO direto do servlet não é uma boa.

Já tive experiências ruins com isso, pois no dia em que for necessário ampliar o caso de uso para utilizar outros DAOs, o servlet passa a ter uma complexidade maior do que deveria ter.

Além disso, o fato de você não poder reaproveitar a regra de negócio em outro caso de uso já é uma justificativa para criar uma camada intermediária… como diria meu chefe, cada coisa no seu porta-coisa :smiley:

Acho que um Service ou um Business Delegator funcionaria legal neste caso.

[quote=ignacio83]
Agora vms debater mais sobre a idéia de regras de negócio…

Onde você normalmente coloca as regras de negócio? Suas Entitys contém as regras de negócio? Ou algum outro objeto as contém? Como um VO?

Acho “estranho” colocar essas nas Entitys.[/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