Analisando o Microsoft PetShop 3.0


Para quem não conhece, o Microsoft PetShop 3.0 é uma aplicação de uma loja virtual fictícia que vende pequenos animais que a Microsoft construiu com o propósito de um caso de estudo baseado no Java Pet Store da Sun, mas construindo-a sob a Plataforma .NET. Mas este artigo não tem o intuito de mostrar esta comparação e sim abordar a estrutura em que o mesmo foi construído. Para quem se interessar, poderar ver o estudo/análise desta comparação através deste link: http://www.middleware-company.com/buzz/buzz0703.jsp.

Microsoft PetShop 3.0 é uma aplicação Web, construída em ASP.NET, que comunica com componentes de negócios escritos em C#, quais compõem a Camada de Negócios (Business Logic Layer). ADO.NET é utilizado para acessar as Base de Dados, acesso qual está abstraído em uma camada de acesso a dados (Data Access Layer (DAL)), separando-se da camada de negócios.

Figura 1 – Microsoft PetShop 3.0.

Estrutura da Solução

Como podemos ver abaixo na Figura 2, a solução da Aplicação e constituída de diversos projetos, sendo 1 projeto do tipo WebApplication (User Interface), 8 projetos do tipo Class Library e 2 projetos “Build” para efetuar algumas configurações no ato da instalação. Veremos abaixo, a descrição de cada um deles.

Figura 2 – Estrutura da Solução.

 

Projeto Finalidade
BLL Contém as regras do negócio da aplicação.
ConfigTool Utilizado para Encriptar/Descriptar ConnectionString e fazer entradas no Event Log.
DALFactory Classe que determina qual Database será utilizada.
IDAL Interfaces que deverão ser implementadas para cada DAL.
Model Classes de dados ou objetos de negócio.
OracleDAL Implementação específica para acesso a fonte de dados Oracle.
Post-Build Responsável por adicionar os Assemblies no GAC e COM+.
Pre-Build Remove Assemblies do GAC e COM+.
SQLServerDAL Implementação específica para acesso a fonte de dados SQL Server 2000.
Utility Classes utilitárias.
Solution Items StrongKey para assinar os Assemblies.

Aplicação Distribuída

Para que a solução atenda o cenário de uma aplicação distrubuída, são criados duas Base de Dados (MSPetShop e MSPetShopOrders). Em uma delas, são armazenadas as informações referentes aos Produtos, Clientes, Banners, entre outros. Já na segunda Base de Dados, são armazenados os pedidos dos clientes e seus repectivos Items. Veremos abaixo a finalidade de cada uma das tabelas:

Tabela Descrição
Account Informações sobre o Cliente.
BannerData Armazena informações sobre Banners.
Category Categorias dos Produtos.
Inventory Estoque dos Produtos.
Item Detalhes dos Produtos.
LineItem Detalhes dos Items dos Pedidos.
Orders Pedidos realizados por um determinado Cliente.
OrderStatus Status do Pedido.
Product Catalogo dos Produtos.
Profile Perfil do Cliente.
Signon Login dos Usuários.
Supplier Informações dos Fornecedores.

OBS.: As linhas que estão com o fundo cinza, pertencem a Base de Dados “MSPetShopOrders”.

Arquitetura

Figura 3 – Arquitetura da Solução.

Como vemos na figura acima, a aplicação está dividida em três grandes camadas: Camada de Apresentação, Camada de Negócios e Camada de Acesso a Dados. O COM+ entra no jogo para garantir a integridade dos pedidos, ou seja, quando efetuamos uma compra, se algo falhar durante a transação, o mesmo será desfeito, mantendo assim a integridade dos dados.

Os componentes de negócios fazem as devidas manipulações para serem exibidas no Front-End, mas tudo começa a ficar interessante a partir daqui.

A idéia é de deixar a aplicação independente de Base de Dados. Isso não seria tão difícil, pois poderíamos utilizar OleDb para acessar qualquer uma das Bases de Dados, criando assim uma única classe genérica de acesso. Mas isso torna a aplicação pouco performática, pois não utiliza os Providers específicos para cada Base de Dados. Um dos requirementos ao construir esta aplicação era justamente obter alta performance, e em virtude disso, é indiscutível o uso dos Providers nativos: SqlClient e OracleClient.

Com essa meta, uma forma de simplicar o acesso aos dados, foi utilizar a Pattern Abstract Factory [Gof], juntamente com Reflection que cria e instancia o objeto correto em runtime. É criado uma Interface genérica, que contém os métodos necessários que deve ser implementada em cada classe de acesso a dados. Para cada classe de acesso a dados, você deve implementar esta Interface, utilizando as classes e o Provider específico para o Banco de Dados que está sendo requisitado.

Depois das classes de acesso a dados de Bases diferentes, cria-se uma Factory, que em runtime, utilizando Reflection, vai identificar qual das classes de acesso a dados irá instanciar, baseando-se em uma chave definida no arquivo Web.Config da aplicação Web. A figura abaixo, ilustra o processo:

Figura 4 – Escolhendo qual DB utilizar.

Se algum dia tivermos a necessidade de que a aplicação atenda a mais um tipo diferente de Base de Dados, por exemplo Microsoft Access, teríamos que seguir o seguinte procedimento:

1 – Criar classes de acesso a dados, utilizando OleDb e nela implementar as Interfaces IDAL;

2 – Compilar estas novas classes e fazer Deploy para o servidor;

3 – Alterar a configuração no arquivo Web.Config para chamá-la.

DAO – Data Access Objects

Data Access Objects ou DAO, é um padrão de projeto que é utilizado para abstrair o acesso a dados da camada de negócios (Business Layer), que por sua vez, acessa a Base de Dados através de Data Access Objects, tornando assim transparente o acesso. A DAO é uma DAL específica para um determinado objeto, fazendo com que a camada de negócios fique sem conhecimento da Base de Dados, pois isto está tudo encapsulado.

Esta abstração encapsula a implementação utilizada para acesso, gravação, gerenciamento da conexão referente a fonte de dados, que realmente não interessa a Business Layer qual o tipo de armazenamento de dados está sendo utilizado.

Figura 5 – Diagrama de Classe da Pattern DAO.

Abstract Factory

Abstract Factory fornece uma Interface ou Classe Abstrata para criar uma família de objetos relacionados dependentes sem especificar a classe concreta. Sendo assim, no projeto PetShop 3.0, é criado uma Interface chamada IDAL, que contém os métodos de manipulação de dados, qual é implementada em todas as classes concretas para accesso à diferentes Base de Dados.

Com isso, ao invés do Cliente instanciar a classe concreta, chama-se método de criação (Factory Method), que invoca a Abstract Factory, e utiliza este objeto para chamar os métodos e/ou propriedades da classe concreta. Ganhamos bastante flexibilidade, pois baseado em uma Key (no caso, chamada de WebDAL) dentro do arquivo Web.Config, em runtime ele saberá qual dos objetos concretos deverá instanciar.

Traduzindo em Código

Para que as coisas fiquem um pouco mais claras, veremos abaixo, como é feito isso. Sabendo que temos que implementar as Interfaces contidas na IDAL, veremos uma delas (Account):

1
2
3
4
5
6
7
 
public interface IAccount
{
    AccountInfo SignIn(string userId, string password);
    AddressInfo GetAddress(string userId);
    void Insert(AccountInfo account);
    void Update(AccountInfo account);
}
 
Código 1 – Interface IAccount.

Na camada de acesso a dados, deve-se implementar esta interface (IAccount) e codificar utilizando o Provider específico para aquela Base de Dados. No caso do PetShop, a implementação foi realizada utilizando o DAAB (Data Access Application Block) que utiliza SqlClient e também implementando para acesso a Base de Dados Oracle, utilizando OracleClient.

1
2
3
4
 
public class Account : IAccount
{
    //…
}
 
Código 2 – Implementado Interface IAccount.

Feito isso, a Factory se encarrega de verificar qual dos objetos instanciar, verificando no Web.Config qual a Base de Dados a ser utilizada, e através de Reflection, carrega a cria a instância da mesma através do Factory Method:

1
2
3
4
5
6
7
8
9
10
 
public class Account
{
    public static PetShop.IDAL.IAccount Create()
    {
        string path = System.Configuration.ConfigurationSettings.AppSettings[“WebDAL”];
        string className = path + “.Account”;
 
        return (PetShop.IDAL.IAccount) Assembly.Load(path).CreateInstance(className);
    }
}
 
Código 3 – Factory Method.

E finalmente em nossa camada de negócios, utilizamos nossa Factory para que ela gere a instância correta da classe de acesso e manipulação da Base de Dados a ser utilizada no Projeto:

1
2
3
4
5
6
7
8
9
10
11
 
public class Account
{
    public void Update(AccountInfo account)
    {
        if (account.UserId.Trim() == string.Empty)
            return;
        
        IAccount dal = PetShop.DALFactory.Account.Create();
        dal.Update(account);
    }
}
 
Código 4 – “Chamando” o Factory Method na Camada de Negócios.

Conclusão: Como vimos a utilização da Orientação à Objetos no Design de nossas aplicações, nos traz grande produtividade e facilidade em uma posterior manutenção. No caso do PetShop que vimos acima, é um ótimo exemplo, onde precisamos gerar independência de Base de Dados, mas existem vários cenários onde podemos utilizar Abstract Factory e principalmente DAO.

Anúncios

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s