Opinião sobre essa arquitetura!

Olá a todos.

Estou montando um framework para fins estudantis e gostaria que vocês do fórum criticassem ou dessem opiniões sobre ele, irei detalhar suas funcionalidades abaixo.

Camada de Persistência

Para cada entidade(tabela) do banco tem as seguintes Classes e Interfaces.

  1. IEntidadeDao(Interface que contém as acões CRUD para a tabela).

  2. EntidadeDao(Classe que implementa a IEntidadeDao), classe que executa as ações usando o JDBC.

  3. hibernate.EntidadeDao(Classe que implementa a IEntidadeDao), classe que executa as ações usando o Hibernate.


Beans

Para cada entidade(tabela) do banco tem as seguintes Classes e Interfaces.

  1. IEntidadeBean(Interface que contém os métodos get set dos campos da entidade).

  2. EntidadeBean(Classe que implementa a IEntidadeBean), classe Bean para transportar as informações entre as camadas(menos na view), ela tanb é utilizada para mapeamento do hibernate.


Camada de Regra de Negócios

Para cada entidade(tabela) do banco tem as seguintes Classes e Interfaces.

  1. IEntidadeBusiness(Interface que contém as regras das ações CRUD para a tabela)

  2. EntidadeBusiness(Classe que implementa IEntidadeBusiness), classe que contém as regras da tabela(entidade).


Factorys

  1. Factory para gerar os Daos.

  2. Factory para gerar as Regras de Negócios.

  3. Factory para gerar os Beans.


Transações

  1. Classe que gera uma única transação para diversos business e daos(inclusive para o hibernate), mas por enquanto ainda não estou usando o JTA.

Conexão

  1. Classe q abre uma conexão via JDBC ou Hibernate(sem afetar a camada de business)

Obs: Na nomenclatura das Classes e Interfaces onde for “Entidade” seria o nome verdadeiro da tabela do banco.

Sobre a camada View ainda não criei porq estou meio indeciso ao usar Struts, WebWork ou Servlets, se crio custom tags ou utilizo JSTL, tiles, velocity entre outros…

Entaum pessoal sugestões/críticas serão bem vindas.

Obrigado.

Sem mais, Rodrigo.

Hmm, isso da mais ou menos 10 classes pra cada entidade. Nao da pra fazer nada mais simples, nao? :?

Concordo com o cv. Tá parecendo o ônibus do seu avatar.

Aliás, sou paulista-carioca e este ônibus, o 438, não é indicado para quem tem mais de 1,70 m, pois a distância entre os bancos é muito pequena.

Procure conforto e segurança ao definir e distribuir suas classes.

Depois mostranos como ficou o seu design. Aliás, Design Patterns é como vitamina, e você deve ter cuidados com a super-dosagem.

Abraços,

Márcio

Hum talves! :wink:

Mas em qual camada vc acha que posso retirar alguma coisa???

Obrigado.

Sem mais, Rodrigo.

Por que você tem beans e regras de negócio como coisas separadas?

Shoes

[quote=marcioa1]Concordo com o cv. Tá parecendo o ônibus do seu avatar.

Aliás, sou paulista-carioca e este ônibus, o 438, não é indicado para quem tem mais de 1,70 m, pois a distância entre os bancos é muito pequena.

Procure conforto e segurança ao definir e distribuir suas classes.

Depois mostranos como ficou o seu design. Aliás, Design Patterns é como vitamina, e você deve ter cuidados com a super-dosagem.

Abraços,

Márcio[/quote]

Huahauhuaha, essa foto do busão super lotado foi na “invasão corinthiana” na final do mundial de 2000, tinha apenas “25 mil fiéis” no maracá… :smiley:

Voltando ao assunto do tópico, em qual partes da camada que posso melhorar???

1 - Programe com objetos, não tabelas
2 - Qual seu cotnexto? Quais os requisitors do sistema?

[quote=pcalcado]Por que você tem beans e regras de negócio como coisas separadas?

Shoes[/quote]

No meu caso os beans servem para fazer o mapeamento com o hibernate e tanb para transportar as informações entre as camadas, porq eu deveria usa-los ojunto com o negócio??

Obrigado a todos pela resposta, incrível vcs responderam muitoooo rápido, valew. :smiley:

Porque você está programando numa linguagem orientada a objetos, que tal usar esse paradigma ao invés de programação procedural :wink:

http://www.fragmental.com.br/arquivos/fantoches.pdf

[quote=pcalcado][quote=rodrigo_corinthians]
No meu caso os beans servem para fazer o mapeamento com o hibernate e tanb para transportar as informações entre as camadas, porq eu deveria usa-los ojunto com o negócio??
[/quote]

Porque você está programando numa linguagem orientada a objetos, que tal usar esse paradigma ao invés de programação procedural :wink:

http://www.fragmental.com.br/arquivos/fantoches.pdf[/quote]

Blz vou olhar esse link mas não entendi muito bem ainda do porq procedural?? Em qual parte da arquitetura q não estou aplicando oo corretamente??

Obrigado.

Sem mais, Rodrigo.

Na parte onde você coloca lógica de um lado e dados de outro :wink:

Outra coisa, é preciso uma interface para cada entidade?
Para que elas vao servir visto que serao unica para cada entidade?

]['s

Jóia valew, irei pesquisar mais sobre o assunto e depois altero os códigos.

[quote=fabgp2001] Outra coisa, é preciso uma interface para cada entidade?
Para que elas vao servir visto que serao unica para cada entidade?

]['s[/quote]

Entaum estou usando uma interface(IDao) pai para trabalhar junto com o factory e sobre uma interface pra cada entidade eu até poderia fazer uma “genérica” mas quando eu fizer uma consulta ela me retornaria o que??? Object? :?

Irei postar um exemplo do código.

Suponhamos que temos a tabela tb_pessoa com 2 campos(id_pessoa, nm_pessoa).

A parte do bean ficará assim.

package br.com.rodrigo.stp.bean;

import br.com.rodrigo.stp.infra.factory.IBean;

public interface IPessoaBean extends IBean {

    public Integer getPessoaPK();
    
    public void setPessoaPK(Integer pessoaPK);

    public String getNomePessoa();
    
    public void setNomePessoa(String nomePessoa);
    
}

package br.com.rodrigo.stp.bean;

public class PessoaBean implements IPessoaBean {
    
    private Integer pessoaPK;
    private String nomePessoa;
    
    public PessoaBean() {
        super();
    }

    public Integer getPessoaPK() {
        return pessoaPK;
    }

    public String getNomePessoa() {
        return nomePessoa;
    }

    public void setNomePessoa(String nomePessoa) {
        this.nomePessoa = nomePessoa;
    }

    public void setPessoaPK(Integer pessoaPK) {
        this.pessoaPK = pessoaPK;
    }

}

A parte da persistência.

package br.com.rodrigo.stp.dao;

import java.util.Collection;

import br.com.rodrigo.stp.bean.IPessoaBean;
import br.com.rodrigo.stp.infra.exception.SystemException;
import br.com.rodrigo.stp.infra.factory.IDao;

public interface IPessoaDao extends IDao {
    
    public void insert(IPessoaBean pessoaBean) throws SystemException;
    
    public void update(IPessoaBean pessoaBean) throws SystemException;
    
    public IPessoaBean selectPrimaryKey(Integer pessoaPK) throws SystemException;
    
    public Collection select(IPessoaBean pessoaBean) throws SystemException;
    
    public void delete(Integer pessoaPK) throws SystemException;
    
}

// JDBC
package br.com.rodrigo.stp.dao;

import java.sql.*;
import java.util.*;

import br.com.rodrigo.stp.bean.*;
import br.com.rodrigo.stp.infra.connection.*;
import br.com.rodrigo.stp.infra.exception.SystemException;
import br.com.rodrigo.stp.infra.factory.AbstractBeanFactory;

public class PessoaDao implements IPessoaDao {

    private IConexao conexao;
    
    private Connection connection;
    
    private PreparedStatement preparedStatement;
    
    private ResultSet resultSet;
    
    public PessoaDao() throws SystemException {
        
        conexao = Conexao.getInstance();
        
    }
    
    public void insert(IPessoaBean pessoaBean) throws SystemException {
        
        try {
        
	        connection = (Connection) conexao.getConnection();
	        
	        int pk = ConexaoUtils.createSequence("id_pessoa", "tb_pessoa");
	        
	        preparedStatement = connection.prepareStatement("INSERT INTO tb_pessoa(id_pessoa, nm_pessoa) VALUES(?, ?)");
	        
	        preparedStatement.setInt(1, pk);
	        
	        preparedStatement.setString(2, pessoaBean.getNomePessoa());
	        
	        preparedStatement.executeUpdate();
	        
	        preparedStatement.close();
	        
	        pessoaBean.setPessoaPK(new Integer(pk));
	        
        } catch(SQLException sqle) {
            
            throw new SystemException(sqle);
            
        }
        
    }
    
    public void update(IPessoaBean pessoaBean) throws SystemException {
        
        try {
            
            connection = (Connection) conexao.getConnection();
            
            preparedStatement = connection.prepareStatement("UPDATE tb_pessoa SET nm_pessoa = ? WHERE id_pessoa = ?");
            
            preparedStatement.setString(1, pessoaBean.getNomePessoa());
            
            preparedStatement.setLong(2, pessoaBean.getPessoaPK().intValue());
            
            preparedStatement.executeUpdate();
            
            preparedStatement.close();
            
        } catch(SQLException sqle) {
            
            throw new SystemException(sqle);
            
        }
        
    }
    
    public IPessoaBean selectPrimaryKey(Integer pessoaPK) throws SystemException {
        
        try {
            
            connection = (Connection) conexao.getConnection();
            
            preparedStatement = connection.prepareStatement("SELECT nm_pessoa FROM tb_pessoa WHERE id_pessoa = ?");
            
            preparedStatement.setInt(1, pessoaPK.intValue());
            
            resultSet = preparedStatement.executeQuery();
            
            IPessoaBean pessoaBean = (IPessoaBean) AbstractBeanFactory.createBean(PessoaBean.class);
            
            if(resultSet.next()){
                
                pessoaBean.setPessoaPK(pessoaPK);
                
                pessoaBean.setNomePessoa(resultSet.getString(1));
                
            }
            
            resultSet.close();
            
            preparedStatement.close();
            
            return pessoaBean;
            
        } catch(SQLException sqle) {
            
            throw new SystemException(sqle);
            
        }
        
    }
    
    public Collection select(IPessoaBean pessoaBean) throws SystemException {
        
        Collection collection = null;
        
        try {
            
            connection = (Connection) conexao.getConnection();
            
            preparedStatement = connection.prepareStatement("SELECT id_pessoa, nm_pessoa FROM tb_pessoa");
            
            resultSet = preparedStatement.executeQuery();
            
            IPessoaBean pessoaBeanDao = null;
            
            collection = new ArrayList();
            
            while(resultSet.next()){
                
                pessoaBeanDao = (IPessoaBean) AbstractBeanFactory.createBean(PessoaBean.class);
                
                pessoaBeanDao.setPessoaPK(new Integer(resultSet.getInt(1)));
                
                pessoaBeanDao.setNomePessoa(resultSet.getString(2));
                
                collection.add(pessoaBeanDao);
                
            }
            
            resultSet.close();
            
            preparedStatement.close();
            
            return collection;
            
        } catch(SQLException sqle) {
            
            throw new SystemException(sqle);
            
        }
        
    }
    
    public void delete(Integer pessoaPK) throws SystemException {
        
        try {
            
            connection = (Connection) conexao.getConnection();
            
            preparedStatement = connection.prepareStatement("delete from tb_pessoa WHERE id_pessoa = ?");
            
            preparedStatement.setInt(1, pessoaPK.intValue());
            
            preparedStatement.executeUpdate();
            
            preparedStatement.close();
            
        } catch(SQLException sqle) {
            
            throw new SystemException(sqle);
            
        }
        
    }
    
}

// Hibernate
package br.com.rodrigo.stp.dao.hibernate;

import java.util.*;
import br.com.rodrigo.stp.bean.*;
import br.com.rodrigo.stp.dao.IPessoaDao;
import br.com.rodrigo.stp.infra.connection.*;
import br.com.rodrigo.stp.infra.exception.SystemException;
import br.com.rodrigo.stp.infra.factory.AbstractBeanFactory;
import net.sf.hibernate.*;

public class PessoaDao implements IPessoaDao {

    private IConexao hibernateDao;
    
    private Session session;
    
    public PessoaDao() throws SystemException {

        hibernateDao = Conexao.getInstance();
        
        session = (Session) hibernateDao.getConnection();
        
    }
    
    public void insert(IPessoaBean pessoaBean) throws SystemException {
        
        try {
        
            session.save(pessoaBean);
            
            session.flush();
            
        } catch(HibernateException hibernateException) {
            
            throw new SystemException(hibernateException);
            
        }
        
    }
    
    public void update(IPessoaBean pessoaBean) throws SystemException {

        try {
            
            session.update(pessoaBean);
            
            session.flush();
            
        } catch(HibernateException hibernateException) {
            
            throw new SystemException(hibernateException);
            
        }
        
    }

    public Collection select(IPessoaBean pessoaBean) throws SystemException {
        
        try {
            
            String sql = "from PessoaBean as pessoaBean";
            
            if(pessoaBean != null){
                
                if(pessoaBean.getNomePessoa() != null && pessoaBean.getNomePessoa().length() > 0){
                    
                    sql += " where nm_pessoa like '%"+pessoaBean.getNomePessoa()+"%'";
                    
                }
                
            }
            
            List listPessoa = session.find(sql);
            
            session.flush();
            
            Collection collection = new ArrayList(listPessoa);
            
            return collection;
            
        } catch(HibernateException hibernateException) {
            
            throw new SystemException(hibernateException);
            
        }
        
    }
    
    public IPessoaBean selectPrimaryKey(Integer pessoaPK) throws SystemException {
        
        IPessoaBean pessoaBean = (IPessoaBean) AbstractBeanFactory.createBean(PessoaBean.class);
        
        try {
        
            pessoaBean = (IPessoaBean) session.load(PessoaBean.class, pessoaPK);

            session.flush();
            
            return pessoaBean;
            
        } catch(HibernateException hibernateException) {
            
            throw new SystemException(hibernateException);
            
        }
        
    }

    public void delete(Integer pessoaPK) throws SystemException {
        
        try {
            
            IPessoaBean pessoaBean = (IPessoaBean) AbstractBeanFactory.createBean(PessoaBean.class);
            
            pessoaBean.setPessoaPK(pessoaPK);
            
            session.delete(pessoaBean);
            
            session.flush();
            
        } catch(HibernateException hibernateException) {
            
            throw new SystemException(hibernateException);
            
        }
        
    }

}

E por último as regras.

package br.com.rodrigo.stp.business;

import java.util.Collection;

import br.com.rodrigo.stp.bean.IPessoaBean;
import br.com.rodrigo.stp.infra.exception.SystemException;
import br.com.rodrigo.stp.infra.factory.IBusiness;

public interface IPessoaBusiness extends IBusiness {

    public void create(IPessoaBean pessoaBean) throws SystemException;
    
    public void save(IPessoaBean pessoaBean) throws SystemException;
    
    public Collection get(IPessoaBean pessoaBean) throws SystemException;
    
    public IPessoaBean getPrimaryKey(Integer pessoaPK) throws SystemException;
    
    public void remove(Integer pessoaPK) throws SystemException;
    
}


package br.com.rodrigo.stp.business;

import java.util.Collection;

import br.com.rodrigo.stp.bean.IPessoaBean;
import br.com.rodrigo.stp.dao.*;
import br.com.rodrigo.stp.infra.exception.SystemException;
import br.com.rodrigo.stp.infra.factory.AbstractDaoFactory;

public class PessoaBusiness implements IPessoaBusiness {
    
    private IPessoaDao pessoaDao;

    public PessoaBusiness() throws SystemException {
        
        super();
        
        pessoaDao = (IPessoaDao) AbstractDaoFactory.getInstance().createDao(PessoaDao.class);

    }
    
    private void fieldPessoaPK(Integer pessoaPK) throws SystemException {
        
        if(pessoaPK == null || pessoaPK.intValue() <= 0){
            
            throw new SystemException("Campo ID_PESSOA está inválido.");
            
        }
        
    }

    private void fieldNomePessoa(IPessoaBean pessoaBean) throws SystemException {
        
        if(pessoaBean.getNomePessoa() == null || pessoaBean.getNomePessoa().length() <= 0 && pessoaBean.getNomePessoa().length() > 255){
            
            throw new SystemException("Campo NM_PESSOA está inválido.");
            
        }
        
    }
    
    private void isEmpty(IPessoaBean pessoaBean) throws SystemException {
        
        if(pessoaBean == null){
            
            throw new SystemException("Bean PessoaBean está inválido.");
            
        }
            
    }
    
    public void create(IPessoaBean pessoaBean) throws SystemException {
        
        isEmpty(pessoaBean);
        
        fieldNomePessoa(pessoaBean);
        
        pessoaDao.insert(pessoaBean);
            
    }

    public void save(IPessoaBean pessoaBean) throws SystemException {

        isEmpty(pessoaBean);
        
        fieldPessoaPK(pessoaBean.getPessoaPK());
        
        fieldNomePessoa(pessoaBean);
        
        pessoaDao.update(pessoaBean);
        
    }

    public Collection get(IPessoaBean pessoaBean) throws SystemException {
        
        isEmpty(pessoaBean);
        
        return pessoaDao.select(pessoaBean);
        
    }
    
    public IPessoaBean getPrimaryKey(Integer pessoaPK) throws SystemException {

        fieldPessoaPK(pessoaPK);
        
        return pessoaDao.selectPrimaryKey(pessoaPK);
        
    }

    public void remove(Integer pessoaPK) throws SystemException {

        fieldPessoaPK(pessoaPK);
        
        pessoaDao.delete(pessoaPK);
        
    }

}

Valew.

Sem mais, Rodrigo.

Perguntas rapidas:

  • Quem esta fechando suas conexoes? Statements? ResultSets?

  • Essa tonelada e meia de codigo eh soh pra fazer o backend de um objeto Pessoa que tem 2 propriedades. O que vai acontecer quando vc tiver 150 entidades diferentes?

  • As suas regras de negocio nao sao conhecidas ainda, ou elas sao so isso mesmo, no geral?

Por enquanto quem fecha a minha conexão é a transação, mas em breve pretendo melhorar criando um pool de conexões, segue um exemplo usando a transação.

public class TestMain {

    public static void main(String[] args) {
        
        ITransaction t = null;
        try {

            t = SimpleTransaction.getInstance();
            t.start(); // Inicia a transação
            
            // Monta o objeto Pessoa -> tabela tb_pessoa
            IPessoaBusiness pessoaBusiness = (IPessoaBusiness) AbstractBusinessFactory.getInstance().createBusiness(PessoaBusiness.class);
            IPessoaBean pessoaBean = (IPessoaBean) AbstractBeanFactory.createBean(PessoaBean.class);

            pessoaBean.setNomePessoa("Pessoa Hibernate");
            
            pessoaBusiness.create(pessoaBean);

	    t.commit(); // Comita a transação

        } catch(SystemException se) {
            t.rollback(); // Rollback na transação
            se.printStackTrace();
        } finally {
            t.close(); // Finaliza a transação
        }
        
    }
    
}

Eu fecho dentro do próprio método, está errado??

Pra falar a verdade essa arquitetura eu fiz baseada numa empresa(Gelre) onde trabalhava, participei de um projeto ERP que tinha nada menos que “500 tabelas”, afê pra vc ter uma idéia usavamos(e usam até hoje) só JDBC e vish tinha umas 10 toneladas a mais de código lá. :lol:

Sim não existem ainda, por enquanto tem apenas as regras referente ao cadastro da entidade(validações dos campos nulos, tamanhos…).

Quando vc disse essa tonelada de código era exatamente isso que estava pensando no almoço, acho que vou começar a criar genéricos para as classes Daos e suas interfaces, tanb para o Business entre outros, irá reduzir bastante o código.

Valew.

Sem mais, Rodrigo.

Para fechar os ResultSets e Statements, fecha em um bloco finally, que garante que eles sejam fechados mesmo que ocorra uma exceção durante o método.

Acho que em um projeto com muitas tabelas no banco com vc citou, poderia ser feito um Dao por use case do sistema, alguém tem alguma opnião sobre esta aboradagem?

[quote=maikonaraujo]Para fechar os ResultSets e Statements, fecha em um bloco finally, que garante que eles sejam fechados mesmo que ocorra uma exceção durante o método.

Acho que em um projeto com muitas tabelas no banco com vc citou, poderia ser feito um Dao por use case do sistema, alguém tem alguma opnião sobre esta aboradagem?[/quote]

Jóia bem lembrado, eu só estava usando o bloco finally na transação, agora irei implementar nos Dao’s JDBC’s, valew :slight_smile:

Concordo se por isso que vou implementar um Dao genérico, se fomos pensar o Hibernate por dentro faz isso, já que no core ele usa jdbc, me corrijam por favor se estiver errado.

O osso mesmo é fazer um Dao genérico pra JDBC, como montar as querys? :roll:

Sem mais, Rodrigo.

O CV deu umas boas respostas sobre o assunto Dao genérico aqui.