Desenvolvimento - C#
Proxy - Padrão de Projeto com Microsoft .NET CSharp
O padrão de projeto proxy tem como objetivo proporcionar um espaço reservado para outro objeto controlar o acesso a ele. A classe proxy teoricamente pode se conectar a qualquer objeto, ou seja, normalmente quando existe uma instância grande/complexa pode-se criar vários proxies, todos contendo uma única referencia.
por Flávio Secchieri MariottiIntrodução
Padrão de Projeto ou em inglês Design Patterns, é uma forma organizada de criar soluções para os problemas recorrentes do dia a dia de um programador.
1 Porque devo usar Padrão de Projeto
Todos sabemos que é possível desenvolver software sem utilizar padrão de projeto, e o fato de usar ou não padrão de projeto não característica um software de qualidade, padrão de projeto é somente um dos vários detalhes que compõem um software. Usar padrão de projeto é uma escolha que cabe a cada empresa, existem casos onde as empresas desenvolvem seus próprios padrões de projetos e suas framework de trabalho.
O conceito de padrão de projeto foi criado na década de 70 pelo arquiteto e matemático Christopher Alexander um australiano que foi um dos principais críticos da arquitetura moderna. Alexander definiu dois pontos fundamentais para criação de um padrão, apontando as características e formato básico que um "objeto" deve ter para ser classificado como padrão.
Características
· Encapsulamento
· Generalidade
· Equilíbrio
· Abstração
· Abertura
· Combinatoriedade
Formato
· Nome
· Exemplo
· Contexto
· Problema
· Solução
Agora podemos entender o que existe em comum no trabalho de Alexander com o desenvolvimento de software, podemos compreender o que é necessário para criação de um padrão. Agora vamos entender quais os benefícios e vantagens que ao desenvolver software utilizando padrões de projetos a empresa pode ganhar.
Alguns acontecimentos são comuns no dia a dia das fabricas de software, tais como: giro de funcionários; mudanças no sistema em produção; correção de erros; implementação de novos recursos; customizações especificas e etc. Os padrões de projetos tem como objetivo facilitar o desenvolvimento de software com a reutilização de soluções já implementadas, não estamos falando de reutilização de código e sim em um desenvolvimento padronizado com: vocabulário unificado; facilidade para comunicação e leitura do código; documentação padronizada; compreensão rápida do código para novos e antigos integrantes do time de TI.
2. Proxy - Padrão de Projeto
O padrão Proxy tem como objetivo proporcionar um espaço reservado para outro objeto controlar o acesso a ele. A classe proxy teoricamente pode se conectar a qualquer objeto, ou seja, normalmente quando existe uma instância grande/complexa pode-se criar vários proxies, todos contendo uma única referencia.
2.1 Classificação
Padrão de projeto descreve 23 modelos de desenho, porem cabe ressaltar que existem centenas de padrões. No famoso livro Design Patterns dos autores Gamma, Helm, Johnson e Vlissides é apresentado 23 padrões de projeto, documentados e já conhecidos no mundo do desenvolvimento de software. É importante saber que isso não significa que esses padrões são os mais uteis para se implementar, sendo assim vale a pena pesquisar padrões de outras fontes.
Esses 23 padrões são divididos em padrões de criação, padrões estruturais e padrões comportamentais. Vamos explorar os 23 padrões de projeto na serie de artigo sobre o assunto. O padrão de projeto Proxy está classificado como padrão estrutural.
3. Implementando padrão Proxy
Geralmente os objetos comuns fazem seu próprio trabalho e oferecem suporte as interfaces públicas declaradas no objeto. Porem existem casos que essa responsabilidade precisa ser transferida para um objeto adequado. Isto pode ocorrer em diversos casos, vamos para alguns exemplos: quando um objeto necessita de um longo tempo para carregar; quando o programador precisa intercepatar a mensagem do objeto; quando o processo precisa ser executado em outro computador/servidor e etc. Nestes casos, um objeto proxy pode assumir a responsabilidade, assim criando uma instância cliente que aguarda e encaminha solicitações de forma adequada a um objeto alvo.
Com isso podemos entender o principal objetivo do padrão Proxy, que em resumo é fornecer uma solução substituta ou espaço reservador para outro objeto controlar a solicitação.
3.1 Simple Proxy
Um objeto proxy geralmente possui uma interface que é praticamente idêntica à interface do proxy que ira substituí-lo. O proxy vai realizar seu trabalho criteriosamente por encaminhamento de solicitações para o objeto subjacente. Um exemplo prático do proxy refere-se a evitar a utilização inadequada do espaço em memória. Suponhamos que arquivos/dados em um aplicativo pertencem a tarefas que inicialmente não serão executadas, sendo assim, precisamos evitar o carregamento desnecessário de todos os arquivos/dados antes que eles sejam solicitados, neste caso pode deixar os proxies para os arquivos. Essa atividade funciona como um espaço reservado para carregar os arquivos requeridos na demanda, vamos desenvolver um exemplo simples que ilustra essa situação.
Figure 1. Diagrama de classes, com representação gráfica do que vamos desenvolver
Abaixo o código da classe principal, fazendo a chamada a classe que carrega o arquivo solicitado.
class Program
{
static void Main(string[] args)
{
Arquivo arq01 = new ArquivoProxy("Arquivo01");
Arquivo arq02 = new ArquivoProxy("Arquivo02");
Arquivo arq03 = new ArquivoProxy("Arquivo03");
Console.ReadKey();
}
}
Interface para implementação do padrão proxy.
interface Arquivo
{
void getArquivo();
}
Classe que contém o método que será executado pelo proxy virtual.
public class ArquivoReal:Arquivo
{
private string NomeDoArquivo;
public ArquivoReal(string _nomedoarquivo)
{
this.NomeDoArquivo = _nomedoarquivo;
loadArquivo();
}
private void loadArquivo()
{
Console.WriteLine("Carregando: " + this.NomeDoArquivo);
}
public void getArquivo()
{
Console.WriteLine(this.NomeDoArquivo);
}
}
Classe que ilustra uma forma simples de proxy virtual. A classe abaixo será utilizada para acessar um método remoto.
public class ArquivoProxy : Arquivo {
private string NomeDoArquivo;
private Arquivo vrArquivo;
public ArquivoProxy(string _nomedoarquivo)
{
this.NomeDoArquivo = _nomedoarquivo;
getArquivo();
}
public void getArquivo()
{
vrArquivo = new ArquivoReal(this.NomeDoArquivo);
vrArquivo.getArquivo();
}
}
Abaixo o resultado do programa:
Carregando: Arquivo01
Arquivo01
Carregando: Arquivo02
Arquivo02
Carregando: Arquivo03
Arquivo03
Este exemplo ilustra de uma forma simples a implementação do pradrão proxy, porem ainda não deixa claro a total justificatica para utilizar esse padrão. No próximo exemplo vamos desenvolver um proxy com chamada remota, justificando os beneficios em se usar o padrão proxy.
3.2 Remote Proxies
Em algumas situações precisamos chamar um método que está sendo executado em outro computador, neste caso é interessante encontrar uma maneira de se comunicar com o objeto remoto sem chamá-lo diretamente. Uma forma de executar essa atividade seria abrir um socket no servidor remoto e elaborar algum protocolo para transferir mensagens entre os objetos. Este processo permite passar mensagens para os objetos remotos como fossem hospedados no servidor local.
Existem objetos bem conhecidos que é capaz de chamar métodos que estão sendo executados em máquinas remotas. Alguns componentes são: Common Object Request Broker Architecture (CORBA), Java Remote Method (RMI), Active Server Pages em ASP.NET.
3.3 Exemplo
Mão na massa, este exemplo requer os seguintes passos:
· Internet Information Server (IIS)
· Relacionar um diretório no disco com um endereço Uniform Resource Locator (UML)
· Web services (vamos desenvolver juntos)
· Criar um proxy para o serviço de web (vamos criar juntos)
Passo 1: Instalar o IIS, caso a ferramenta ainda não esteja disponível.
Passo 2: Criar um diretório como por exemplo "c:\exemplo" e o diretório onde será hospedado nossa pagina como por exemplo "c:\exemplo\bin". Execute o IIS e crie um diretório virtual apontando para pasta "c:\exemplo" e informe o alias name "exemploproxy".
Passo 3: Vamos criar um Web service
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {
public WebService () {
}
[WebMethod]
public string OlaMundo() {
return "Web service. Olá mundo";
}
}
Passo 4: Teste! Execute o projeto e verifique se o resultado está parecido com a ilustração abaixo.
Passo 5: Capturar a interface do serviço de Web service disponível. Com o Web Services Description Language (WSDL), este recurso faz parte do conteúdo disponível no kit de ferramentas do .NET framework. Execute o seguinte comando:
c:\exemplo>wsdl http://localhost/exemplo/WebService.asmx?wsdl
Após executar esse comando o arquivo Webservice.cs seré criado contendo o proxy que os clientes porem utilizar para chamar o serviço. Podemos traduzir essa processo da seguinte forma. O arquivo criado irá conter uma chamada ao método OlaMundo() que vai operar de forma diferente da OlaMundo() implementada no WebService.asmx. Quando o método for solicitado será criado um pedido no formato texto correspondente ao protocolo Simples Object Access Protocol (SOAP), passando essa mensagem para o servidor IIS que envia a resposta para o cliente que está aguardando.
Figure 2. Ilustração da utilização do Proxy com protocolo SOAP
Passo 6: No ultimo passo, basta então criar o cliente que irá utilizar o proxy. Crie um novo projeto, adicione a ele a classe WebService.cs (criada com o comando wsdl) e implemente o código abaixo no método Main().
class MostraCliente
{
static void Main()
{
// Metodo disponível no arquivo webservice.cs,
//criado pelo comando wsdl
OlaMundo _olamundo =
new WebService.OlaMundo();
}
}
Um dos benefícios do ASP.NET é que a framework permite que aplicativo cliente possa interagir com um objeto local, no caso o proxy para o objeto remoto. Com isso os desenvolvedores dificilmente precisam estar ciente das chamadas remotas que acontecem, sendo que o ASP.NET fornece um meio de comunicação e isola o servidor do cliente.
Conclusão
O proxy na computação distribuída é um avanço permanente em computação orientada a objeto. É recomendado então implementar o padrão proxy, quando existe a necessidade de estabelecer um objeto reservado que controla/gerencia o acesso a outra tarefa. O objeto proxy tem a habilidade de isolar o cliente a partir de uma mudança no estado do objeto, como vimos nos exemplos acima.
O padrão proxy tem alguns problema, podemos perceber que o objeto depende de uma ligação entre o espaço reservado e o objeto em proxy. Geralmente na prática, o uso de proxy pode trazer benefícios, porem os projetos alternativos muitas vezes oferecem outras soluções mais estáveis. O uso de proxy é recomendado para computação remota, onde realmente justifica o uso do mesmo. Ao invés de depender de algum outro protocolo ou sistema de computação distribuída. Como o ASP.NET estabelece comunicação com objetos remotos em uma chamada de método normal, este recurso permite que o cliente se comunique com outro objeto utilizando o proxy como referencia, caracterizando como se o acesso fosse local.
Comunicado Importante
Espero que tenham gostado do conteúdo explorado neste artigo, caso exista interesse em conhecer um pouco mais sobre padrão de projeto proxy, como por exemplo: como utilizar proxy no acesso a dados. Informe seu interesse usando o recurso de "comentários" neste artigo ou qualquer dúvida relacionada ao conteúdo do mesmo.
Referência
Eric T Freeman; Elisabeth Robson; Bert Bates; Kathy Sierra. Head First Design Patterns, O'Reilly Media, Inc 2004.
Steven John Metsker. Design Patterns in C#, Addison-Wesley Professional, 2004.
ERL, Thomas.SOA:Design Patterns. Vancouver: Prentice Hall, 2008. 500 p.