sábado, 29 de março de 2008

[ADO.NET] Estendendo ADO.NET: Parte 1- Projeto dos provedores de persistência.

Alguns dos aspectos criticados por alguns colegas na API ADO.NET seriam: (a) a dependência sintática do SQL e (b) a arquitetura orientada a dados no modelo de referência sugerido pela Microsoft para a camada de persistência. Uma vez que a dependência sintática do SQL é plenamente suprimida pela API LINQ do framework 3.5, pensei em escrever alguns artigos neste escopo de adaptação dos componentes da ADO.NET. O modelo de referência citado obtem grande produtividade pela modelagem visual do componente DataSet “tipado”. No entanto, os objetos definidos no componente DataSet para representação dos objetos de transferência (DataTable) e serviços (TableDataAdapter) são selados (i.e. selead), não permitindo sua herança, ou mesmo composição de tipos por referência.

Desta forma, apresentações alternativas e relatórios podem eventualmente exigir a definição de Value Objects (VO) auxiliares para transporte vertical de dados à camada de apresentação. Tal estrutura condiciona fortemente as camadas superiores ao modelo de entidades, definindo um grande esforço de refatoração no caso da mudança das definições da base de dados, ou na extensão de relatórios.

Neste escopo, um primeiro ponto de interessante seria a possibilidade da referência por reflection/remoting aos service factories de persistência, de forma tal que extensões em assemblies distintos possam ser adaptados em tempo de execução. Tal feature teria alto valor agregado em sistemas de alta disponibilidade com baixa resistência a mudança.


A arquitetura proposta é apresentada na figura ao lado, onde o seu principal componente consiste da classe DaoProvider, projetada conforme o design pattern provider. Tal classe possui a responsabilidade de gerenciar os service factories concretos para os objetos de persistência.

Para tanto, tal classe possui uma composição de objetos DaoProviderSettings (estrutura que representa a configuração para um service factory concreto dos objetos de persistência), onde estes objetos podem ser acessados de forma aleatória, adicionados na lista de provedores ou interpretados a partir de uma string de conexão fornecida.


A tabela ao lado apresenta descrição da interface da classe DaoProviderSettings proposta, que consiste de uma extensão da classe System.Configurations.ConfigurationSection. A classe pai define a associação entre um identificador textual único (“Name”), a string de conexão (“ConnectionString”) e a classe do provedor de acesso ao banco de dados (“ProviderName”), responsável por implementar a interface de tratamento das queries SQL sobre a string de conexão. Na classe estendida, proposta neste estudo, são adicionadas a existência de uma classe proxy para o provider (“ProxyName”), que implementa de forma concreta um mapeamento objeto relacional. Tal proxy pode ainda ser definido no contexto da aplicação ou em um assembly externo (DLL), neste caso, sendo referenciado pelo atributo “ProxyAssemblyName”. Desta forma, a extensão provê uma interface consistente para atendimento do requisito de referência por reflection aoa service factories de persistência.

Os parâmetros dos provedores de persistência da plataforma proposta são definidos no contexto da aplicação pelos arquivos padrões de configuração das APIs da plataforma.NET. (arquivo web.config em contexto ASP.NET e app.config em contexto Windows Forms). A listagem abaixo ilustra a marcação do arquivo web.config de uma aplicação web implementando o modelo proposto. Observa-se a sintaxe padrão para a definição de strings de conexão sobre o nó . A string de conexão de nome “Prevalente (default)” não apresenta um atributo “providerName” conforme definido no padrão ADO.NET. Neste caso não é necessário, pois será empregado um proxy (provedor concreto de serviços de persistência) da plataforma proposta. As marcações relativas aos atributos “ProxyName” e “ProxyAssemblyName” são definidos sobre o atributo “ConnectionString”. A marcação “Default” indica qual o provedor corrente.

<connectionstrings>
<add connectionstring="ProxyName=net.jorgealbuquerque.pedweb.Dao.ConcreateFactories.XMLDaoFactoryProxy; Data Source=data.xml; ProxyAssemblyName=prevalentDao.dll; Default; " name="Prevalente (default)" providername="">

<add connectionstring="Integrated Security=SSPI; Persist Security Info=False;Initial Catalog=pedweb; User ID=sa; password=; Data Source=.\SQLSERVER;" name="Microsoft SQL Server 2000" providername="System.Data.SqlClient">

</connectionstrings>


Desta forma, a classe DaoProvider, realiza a leitura dos arquivos de configuração das APIs da plataforma .NET, interpreta seus parâmetros e mantêm referências aos seus provedores, que podem ser livremente criados, alterados ou removidos em tempo de execução e instanciados de forma estática.


A Tabela ao lado apresenta uma descrição resumida da interface da classe DaoProvider. A interpretação dos arquivos de configuração o ocorre durante a chamada do método GetInstance(). O carregamento somente é definido se a própria classe não contiver uma instância desta (design pattern singleton). Neste contexto, caso não exista uma instância, o método GetInstance() chama o método privado FillFromConfigManager() que, por sua vez, delega a leitura dos arquivos de configuração a classe nativa da plataforma .NET System.Configuration.ConfigurationManager (propriedade ConnectionStrings). Uma vez obtidas as strings de conexão (definidas nos arquivos web.config ou app.config), a responsabilidade da interpretação das mesmas é delegada a classe DaoProviderSettingsParse (método Parse), retornando os objetos DaoProviderSettings, que são adicionados a lista de provedores existentes (método Add). A seqüência de mensagens descritas é representada em notação UML na figura abaixo.

Nos próximos posts pretendo implementar estas primeiras classes de serviço e a seguir projetar o serviço de prevalência propriamente dito...

Nenhum comentário: