Outro dia respondi uma pergunta no fórum MSDN sobre desenvolvimento em camadas. Meu único conselho para o rapaz foi isolar os objetos de acesso a dados na camada de dados. Para mim toda referência a biblioteca System.Data fora da camada de dados deveria ser tratada como um code smell.
No dia seguinte outro desenvolvedor respondeu minha resposta com a seguinte questão:
"No page-load da grid chamo um método de popular grid que se encontra na minha camada de negócios, essa por sua vez irá receber os parâmetros necessário, validar informações, montar a query e enviar para a camada de Dados executar. A camada de dados me retornar um conjunto de dados que é recebido pela camada de negócio que então popular a grid.
Neste processo como deixar a camada de negócio não enxergar o que a camada de dados me retornou? Teria que transformar o datareader/dataset/datatable em alguma outra coisa? De repente dizer diretamente que gv.datasource = CamadaNegocio.recuperaPedidos()."
Como acho que outras pessoas devem ter este mesmo “problema”, achei que a resposta para o questionamento merecia um post no meu blog.
A resposta para esta pergunta é simples: existem diversas formas de evitar a manipulação de objetos de dados (residentes da biblioteca System.Data) em sua camada de UI, aqui vão duas:
Não utilizar a funcionalidade de data binding do ASP.Net. Você pode criar seu próprio mecanismo de binding, utilizar algum framework que implementa data binding, como o Monorail ou implementar sua interface utilizando o Model View Presenter pattern em sua versão Passive view.
Utilizar a funcionalidade de object datasource do .Net 2.0 e fazer o data binding com seus próprios objetos ao invés de utilizar as estruturas de dados do ADO.Net.
Mas neste momento não quero descrever a solução, mas sim ir um pouco mais a fundo no problema. Afinal antes de termos uma solução temos que ter um problema. (Já estou eu criando problemas para quem já tem tantos outros...)
Em dos primeiros livros que li sobre OO aplicado na prática o autor sugeria a utilização de uma estrutura de dados própria para a comunicação entre as camadas de uma aplicação. A coisa era simples, nada mais que strings com separadores e um parser para ler e construir as strings. O objetivo dele era abstrair toda e qualquer tecnologia da comunicação de dados, desta forma a evolução de sua aplicação seria mais fácil. Achei aquilo interessante, mas um pouco exagerado.
Quando eu mostrava esta solução para outros desenvolvedores só faltavam chamar a ambulância do manicômio. Para que isto??!! É só passar um recordset, era a resposta padrão. Estávamos no início do reinado do ADO, o mundo finalmente tinha descoberto a API definitiva para acesso e manipulação de dados...
Antes disto tínhamos o DAO, depois disto tivemos o ADO.Net, ADO.Net 2.0...O Linq e suas variações começam a surgir no horizonte...E ainda temos as soluções de ORM correndo por fora...
Isto tudo em um espaço de tempo de 6 anos, no máximo! Para cada desenvolvedor que adotou uma destas API’s e a espalhou ao longo das camadas, como por exemplo uma página ASP lendo dados de um recorset, temos hoje uma aplicação com seus dias contados. Eu certamente tenho algumas destas na minha conta :)
Aplicações de negócios são essencialmente movidas de acesso a dados, é de se esperar que estas API’s evoluam, melhorando performance e trazendo novas funcionalidades. Não há nada de errado com isto, pelo contrário, isto é muito bem-vindo (Eu não tenho nenhuma saudade do DAO)
Mas justamente para que a sua aplicação possa se aproveitar destas evoluções e garantir uma vida longa é necessário abstrair a utilização destas API’s e isolá-las na camada de dados. Desta forma a migração e evolução do acesso a dados se dá forma mais “tranquuml;ila”.
Baixo acoplamento é uma característica sempre desejada. Principalmente se estamos falando de componentes de terceiros e de tecnologia tão voláteis, como é o caso do acesso a dados.
Agora sim seguem algumas referências para solucionar o problema:
Model View Presenter:
Monorail:
ASP.Net data binding: