Por que a Lógica não pode ficar nos DAOs

Olá galera, existe algum impacto realmente negativo em colocar a Logica nos DAOs ?

Pq tipo vejo muita gente por ai criando Services(que cuida das regras da aplicação) para cada Entidade e DAOs para cada uma delas,
só que acho que codificar isso é muito chato, e repetitivo…

Eu imagino assim: Tenho uma Classe BaseDao<T>, que é responsavel pela persistência em sí, e os DAOs que estendem esse BaseDao
, mas acho esses DAOs meio obsoletos e sem nenhuma funcionalidade (a mais), tava pensando em trazer a regra de negócio para eles e mandar para o espaço os Services, isso me pouparia mais tempo e deixaria a programação Java mais prazerosa.

E ai o que vocês me dizem ?

Esse assunto pode ser extenso, mas vou resumir no seguinte:

Orientação a Objeto em um de seus requisitos diz que nosso software deve ser coeso quanto as nossas classes, ou seja, uma classe deve fazer somente o papel dela, logo o padrão DAO, como o próprio nome diz, vai oferecer um objeto para acesso aos dados. Outro ponto, DAO é infra-estrutura, colocar lógica do negócio nele é pedir para sofrer com a manutenção futura, pois terá classes muito acopladas (aqui ferindo outro requisito da OO). Acredito que esses argumentos são suficientes para evitar o que você sugeriu.

Acredito que rafaelgauber !
Falou tudo …
É isso ai .
Viva a OO

rafaelglauber, é os argumentos são suficientes, até tenho Conciência disso …

deixar eu fazer então outra pergunta, existe vantagem de se ter interfaces de DAOs e duas implementações ?
Pq percebo que uma implementação(sem uso de interface) pro Hibernate já seja suficiente, já que ele trabalha com diversos bancos…

É pq como eu disse isso é repetitivo e chato…

Utilizar uma interface DAO separada de sua implementação é muito adequado para evitar alto acoplamento entre as classes que utilizam o DAO e a implementação do DAO em si, de forma que se um dia você mudar de estratégia de ORM ou mesmo mudar de tecnologia de persistência, o impacto no restante do sistema será o mínimo possível.

Então pense no seguinte: o que é mais chato e repetitivo? Ter que modificar vários pontos do sistema que dependem da implementação do DAO, ou simplesmente reescrever as implementações e não modificar nada nesses pontos? Um dos principais objetivos de aplicar padrões, dividir os componentes em camadas, etc etc, é diminuir os recursos gastos durante a manutenção do software, pois sabe-se que mantê-lo demanda muito mais recursos do que criá-lo.

Porém, uma das coisas que mais se repetem aqui no GUJ é o seguinte: a otimização prematura é a fonte de todo o mal. Resumindo, sua obrigação como desenvolvedor ou arquiteto é conhecer tudo aquilo que você pode aplicar, mas ter cuidado com as situações onde essas técnicas são aplicáveis. Se você sabe que no seu projeto o Hibernate nunca será trocado, até mesmo a existência de um DAO é questionável.

É verdade, vou consultar um pessoal da equipe para discutir isso…

Eu até “sabia” que isso tudo tinha que ser feito, mas não sabia qual o possivel efeito de não seguir a risca essas recomendações… pois
não tenho muita esperiência no desenvoltimento para web.
Eu estou treinando uma equipe (kkkkkkk podem rir, foi o jeito) e precisava de um argumento real para demonstrar pros caras os benefícios de
seguir esses padrões de desenvolvimento.

Bem, hoje mesmo ou amanhã vou dar uma lida no livro que pegei sobre padrões de projeto. :smiley:

Agradeço a atenção de todos…

Complementando… Crie BO’s(Business Objects) para colocar toda sua lógica(regras de negócio)…

Talvez a pergunta não seja necessariamente se se pode jogar regras de negócio no persistência, mas o contrário: se se pode jogar alguma regra de persistência em objetos de negócio. Nesse caso, pode, mas aí não seria mais o padrão DAO, mas o padrão [google]Active Record[/google].

Para esse padrão, uma classe, por exemplo, Vendedor, poderia ter, ao mesmo tempo, regras de negócio, como:
:arrow: String getNome();
:arrow: BigDecimal getPercentual();
:arrow: void adicionaProdutoVendido(Produto produto, Calendar quando);

e regras de persistência, como:
:arrow: void salvar();
:arrow: static Vendedor procurar(Long id);

Uma terceira altenativa ao DAO e ActiveRecord é o [google]Data Mapper[/google], que é bem complicado de fazer, e é mais visto como ferramenta (ex.: Hibernate).

Voltando ao seu problema: fiquei curioso com seu BaseDao, é realmente uma abstração do tipo em que os usuários desta classe não precisam fazer mais nada no que se refere a pesistência? Se pelo menos faz uma boa parte, pode usá-lo como um atributo nos objetos de negócio (composição, não herança!). E sempre que houver a necessidade de salvar dados, basta delegar para esse BaseDao.

Uma última coisa: como você separa Service de Entity? Se essa separação for do tipo: o service tem a lógica e o entity tem os getters/setters, saiba que é uma implementação ingênua. O melhor é quando o service for que-nem um maestro de um concerto: não possui nenhum instrumento para fazer a música, mas tem a batuta para indicar quem e em que ritmo canta. Ou seja, o service não tem regra, nem atributos de negócio, mas conhece os entities certos (que possuem regras e atributos) para fazer o sistema funcionar.

Nao crie BO’s e nem VO’s (link).

Acredito que SIM.

Eu tenho pro Exemplo : [b]Pessoa /b , PessoaDAO (que extende o BaseDaoImpl), PessoaService (Regras de Negócio) , PessoaAction (do Mentawai)

Como vê resolvi optar por usar só uma implementação de DAO pois acho que não vou precisar(nem quero) trocar o Hibernete.

Acho que vou seguir seu conselho e usar só o BaseDaoImpl(os outros DAOs caem fora) como atributo do PessoaService , que na verdade deve se chamar PessoaBO (ou é a mesma coisa ?)


[color=red]Alguem tem(ou conhece) uma aplicação seguindo esse paradigma que possa me arrumar ? [/color]

Codigo do DAO : BaseDaoImpl.class

** 
 * Classe Gnenérica de Persistência
 * 
 * @author Ricardo Jorge (ricardo.jl.rufino@gmail.com )
 * @date 21:13 11/07/2008
 * @update 
 */
public class BaseDaoImpl&lt;T&gt; implements BaseDao&lt;T&gt; {
	private Session session;
	
	/** Classe que está sendo persistida */
	private Class&lt;T&gt; persistentClass;
	
	/** Determina se as exceções lançadas por essa classe devem ser exibidas no console */
	public static boolean traceException = false;
	
	public BaseDaoImpl(Session session, Class&lt;T&gt; persistentClass) {
		this.session = session;
		this.persistentClass = persistentClass;
	}

	public  T create() throws Exception {
		return persistentClass.newInstance();
	}

	public Criteria createCriteria() throws HibernateException   {
		return session.createCriteria(persistentClass);
	}

	/**
	 * Retorna o nome da Classe.
	 * @return
	 */
	public String getClassName(){
		return persistentClass.getSimpleName();
	}

	@SuppressWarnings("unchecked")
	public List&lt;T&gt; listAll() throws HibernateException  {
		Query query = session.createQuery("FROM " + persistentClass.getName());
		LinkzApplicationManager.logger.debug("listAll : " + query.getQueryString());
		try {
			return  query.list();
		}
		catch (Exception e) {
			if(traceException) e.printStackTrace();
			throw new HibernateException(e);
		}
	}
	
	@SuppressWarnings("unchecked")
	public List&lt;T&gt; listAll(int max) throws HibernateException  {
		Query query = session.createQuery("FROM " + persistentClass.getName());
		LinkzApplicationManager.logger.debug("listAll : " + query.getQueryString());
		try {
			query.setMaxResults(max);
			return  query.list();
		}
		catch (Exception e) {
			if(traceException) e.printStackTrace();
			throw new HibernateException(e);
		}
	}

	@SuppressWarnings("unchecked")
	public List&lt;T&gt; listByQuery(String condition, String orderBy) throws HibernateException {
		StringBuffer sb = new StringBuffer("From " + persistentClass.getName());
		if (condition != null)
			sb.append(" Where ").append(condition);
		if (orderBy != null)
			sb.append(" Order By ").append(orderBy);
		Query query = session.createQuery(sb.toString());
		LinkzApplicationManager.logger.debug("listByQuery : " + query.getQueryString());
		try {
			return query.list();
		}
		catch (Exception e) {
			if(traceException) e.printStackTrace();
			throw new HibernateException(e);
		}
	}
	
	@SuppressWarnings("unchecked")
	// FIXME: pode ter um bug, verificar o mais rápido possivel.
	public List&lt;T&gt; listByExample(T beanExample) throws HibernateException {
		try {
			LinkzApplicationManager.logger.debug("loadByExample : " + beanExample);
			Criteria criteria = this.createCriteria();
			Example example = Example.create(beanExample);
			example.enableLike(MatchMode.ANYWHERE);
			example.ignoreCase();
			criteria.add(example);
			return criteria.list();
		}
		catch (Throwable e) {
			if(traceException) e.printStackTrace(); 
			throw new HibernateException(e);
		}		
	}

	@SuppressWarnings("unchecked")
	public T loadByID(long id) throws HibernateException {
		LinkzApplicationManager.logger.debug("loadByID : " + id);
		return (T) session.get(persistentClass, id);
	}
	
	@SuppressWarnings("unchecked")
	public T loadByID(String id) throws HibernateException {
		if(Validator.validString(id))
			return this.loadByID(new Long(id));
		else
			return null;
	}

	// FIXME: não está carregando...
	@SuppressWarnings("unchecked")
	public T loadByExample(T beanExample) throws HibernateException {
		try {
			Criteria criteria = this.createCriteria();
			Example example = Example.create(beanExample);
			example.enableLike(MatchMode.ANYWHERE);
			example.ignoreCase();
			criteria.add(example);
			Object loaded = criteria.uniqueResult();
			
			LinkzApplicationManager.logger.debug("loadByExample : " + loaded);
			return (T) loaded;
		}
		catch (Throwable e) {
			if(traceException) e.printStackTrace(); 
			throw new HibernateException(e);
		}		
	}

	@SuppressWarnings("unchecked")
	public T loadByQuery(String queryStr) throws HibernateException {
		StringBuffer sb = new StringBuffer("From " + persistentClass.getName());
		if (queryStr != null)
			sb.append(" Where ").append(queryStr);
		Query query = session.createQuery(sb.toString());
		LinkzApplicationManager.logger.debug("loadByQuery : " + query.getQueryString());
		try {
			return (T) query.uniqueResult();
		}
		catch (Exception e) {
			if(traceException) e.printStackTrace();
			throw new HibernateException(e);
		}
	}

	public boolean refresh(T bean) throws HibernateException {
		try {
			LinkzApplicationManager.logger.debug("Refresh : " + bean);
			session.refresh(bean);
			return true;
		}
		catch (Throwable e) {
			if(traceException) e.printStackTrace(); 
			throw new HibernateException(e);
		}
	}

	public boolean save(T bean) throws HibernateException {
		try {
			LinkzApplicationManager.logger.debug("Save : " + bean);
			session.save(bean);
			return true;
		}
		catch (Throwable e) {
			if(traceException) e.printStackTrace(); 
			throw new HibernateException(e);
		}
	}
	
	public boolean saveOrUpdate(T bean) throws HibernateException {
		try {
			LinkzApplicationManager.logger.debug("Save : " + bean);
			session.saveOrUpdate(bean);
			return true;
		}
		catch (Throwable e) {
			if(traceException) e.printStackTrace(); 
			throw new HibernateException(e);
		}
	}

	public boolean update(T bean) throws HibernateException {
		try {
			LinkzApplicationManager.logger.debug("Update : " + bean);
			session.update(bean);
			return true;
		}
		catch (Throwable e) {
			if(traceException) e.printStackTrace(); 
			throw new HibernateException(e);
		}
	}
	
	public boolean delete(T bean) throws HibernateException {
		try {
			LinkzApplicationManager.logger.debug("Delete : " + bean);
			session.delete(bean);
			return true;
		}
		catch (Throwable e) {
			if(traceException) e.printStackTrace(); 
			throw new HibernateException(e);
		}
	}
	
	public Class&lt;T&gt; getPersistentClass() {
		return persistentClass;
	}
	
	public void setSession(Session session) {
		this.session = session;
	}
	
	public Session getSession() {
		return session;
	}

	public void traceException(boolean trace) {
		BaseDaoImpl.traceException = trace;
	}
}

Olá galera, eu elaborei um modelo para vcs me dizerem se ele é viável / Aplicavel…

Tenham em consideração que eu não sei “nada” de UML (não estou seguindo as convenções), só ler e olhe lá… pode ter coisa muito “grotesca” ai… heheheh :lol:

Tou lendo um livro de Padrões de Projeto, e agora isso que vocês disseram está realmente fazendo sentido… heheh
A questão do Acoplamento, Baixa Coesão, etx…

Acredito que SIM.

Eu tenho pro Exemplo : [b]Pessoa /b , PessoaDAO (que extende o BaseDaoImpl), PessoaService (Regras de Negócio) , PessoaAction (do Mentawai)

Como vê resolvi optar por usar só uma implementação de DAO pois acho que não vou precisar(nem quero) trocar o Hibernete.
[/quote]

Cuidado com isto. Você está infectado com o Sindrome de DAO.
Se vc sabe que a persistência não vai mudar porque raios precisa do DAO ? Arranque esse DAO fora do seu projeto e subtitua-o por um repositorio ( aka renomeio o seu dao para repositorio e faça-o uma classe final em vez de uma interface. Remova todas as classes que o herdem).

Foi mais ou menos o que eu fiz (na imagem que postei), uso o BaseDaoHbm que trata da presistencia.
Mas tou deixando espaço para usar outra implementação para um possivel caso em que o hibernate não de conta, já que pretendo
seguir esse modelo em outros projetos.

hilário!