quinta-feira, 15 de março de 2012

Design Patterns: Singleton

O Design Pattern Singleton tem um dos desenhos mais simples. Ele tem como objetivo restringir a quantidade de instâncias de um tipo para apenas uma na aplicação. Ele faz isso controlando e centralizando a sua criação e o acesso a essa instância.

Imagine que você tenha um tipo que ocupa muito espaço na memória, ou que requer muitos recursos para ser instanciado. Se uma instância deste tipo puder ser reutilizada em diferentes lugares da aplicação, isso diminuiria o consumo de memória ou dos recursos consumidos para criação.

A descrição formal do Singleton é a seguinte: O Singleton garante que uma classe tenha apenas uma instância e fornece um ponto global de acesso a ela.

Um exemplo seria uma classe de geração de log. Dentro de uma aplicação, faria sentido haver apenas uma instância da classe responsável por escrever em um arquivo (ou base de dados) de log. Isso reduziria problemas de concorrência no acesso ao arquivo de log, pois a mesma seria tratada dentro do próprio Singleton, uma vez que haveria apenas uma única instância da classe de log acessando o arquivo.

Neste exemplo, teríamos o seguinte desenho:

Observe que temos o método construtor privado, o que não permite que a classe seja instanciada com o comando new por outras classes. Temos também um atributo estático que armazena a única instância de Log na aplicação, e o método ObterInstância() que retorna essa única instância.

O Singleton pode trazer problemas em alguns aspectos: ele pode ser um ponto de gargalo em aplicações que usam threads, devido à concorrência no acesso à instância única. Outro ponto que deve ser considerado: é interessante para a sua aplicação que o estado do objeto singleton seja compartilhado? Se não, você deve evitar o singleton, pois ele pode trazer problemas que serão difíceis de rastrear.

Baixe o código-fonte do exemplo em C# (requer o Visual Studio 2010)

Clique aqui para voltar à Intradução aos Design Patterns, com a lista de todos os Patterns apresentados.

sexta-feira, 9 de março de 2012

Design Patterns: Decorator

O Design Pattern Decorator tem como objetivo acrescentar responsabilidades a um objeto de forma dinâmica (em runtime), de forma mais flexível do que seria feito utilizando herança. O decorator permite que sejam criados vários comportamentos “adicionais” para um objeto e que eles sejam combinados conforme a necessidade da aplicação.

A descrição formal do Decorator é a seguinte: Anexa responsabilidades adicionais a um objeto dinamicamente. Decorators fornecem uma alternativa flexìvel à herança para extender as funcionalidades de um objeto.

Um exemplo clássico é a programação de janelas em aplicativos de interface gráfica. Imagine a janela como um objeto básico, nele os demais elementos gráficos são adicionados conforme a necessidade: barra de rolagem vertical, barra de rolagem horizontal, barras de menus, botões de maximizar, minimizar, etc. Cada um destes elementos gráficos seria uma “decoração” adicionada à janela, podendo ser combinados de acordo com a necessidade.

Um exemplo também comum e mais elucidativo é o sistema da cafeteria. Existem muitos tipos de café, combinandodiferentes ingredientes o preço do café muda. Em vez de criarmos uma nova classe para cada tipo de café, podemos usar o decorator para que, com um pequeno conjunto de classes, possamos representar todos os tipos de café servidos.

Baixe o código-fonte do exemplo (requer Visual Studio 2010).

Com este exemplo, podemos entender como os decorators estendem a funcionalidade básica da classe Café, e como todos eles implementam uma mesma interface, podem ser escolhidos e atribuídos em runtime, ou seja, dinamicamente.

Clique aqui para voltar à Intradução aos Design Patterns, com a lista de todos os Patterns apresentados.

terça-feira, 7 de fevereiro de 2012

Design Patterns: Strategy

O Design Pattern (ou Padrão de Projeto) Strategy é um dos Patterns mais básicos e dá origem a diversos outros Patterns, como o Iterator, por exemplo. Ele foi concebido para separar um pedaço do algoritmo e torná-lo intercambiável permitindo que o comportamento do objeto possa ser modificado em tempo de execução, sem que seja necessário alterar as classes que executavam o comportamento anterior.

A descrição formal do Strategy é a seguinte: Define uma família de algoritmos, encapsula cada um e os torna intercambiáveis, independentemente de quem os utiliza.

Por exemplo, imagine que você tenha uma classe para validar dados. Você poderia, utilizando o Pattern Strategy, trocar o algoritmo de validação dependendo do dado que deverá ser validado (número, data, CPF, etc).

Um outro exemplo, mais elucidativo: imagine que exista uma classe Carro, ao apertar o pedal de freio, o carro deverá frear, todos os carros possuem este comportamento. Porém, um carro com freio comum se comporta de forma ligeiramente diferente de um carro com freio ABS. Neste caso, em vez de colocar o código destes dois comportamentos na classe Carro, podemos utilizar o Strategy e separar os comportamentos do freio comum e do freio com ABS. A classe Carro se encarregará de escolher o freio correto de acordo com o modelo do carro. O diagrama de classes deste exemplo seria o seguinte:


Além de isolarmos a parte do carro que muda (neste caso o freio), também temos a vantagem de, caso queiramos incluir um novo tipo de freio (FreioEBD, por exemplo), teremos apenas que criar uma nova classe que implemente a interface IFreio, e não teremos que testar novamente a classe FreioComum e FreioABS, nem o método ApertarFreio da classe Carro.

Para entender melhor, poderíamos aplicar o exemplo sobre a definição do Strategy: Define uma família de algoritmos (nossa família de algoritmos é representada pela interface IFreio), encapsula cada um (encapsulamos os tipos de freio nas classes FreioComum e FreioABS) e os torna intercambiáveis (criando o atributo Freio do tipo IFreio na classe Carro, tornamos o freio interfambiável), independentemente de quem os utiliza (quem se preocupa em escolher o freio correto é a própria classe Carro - no seu construtor, por exemplo - e quem a instancia e a utiliza não precisa se preocupar com a implementação do freio).


Design Patterns: Introdução

Design Patterns (ou Padrões de Projeto, em português) são modelos de como resolver algumas situações comuns na programação orientada a objetos. Eles descrevem de forma abstrata e apenas indicam classes a serem criadas e as relações entre elas. Dessa forma, são "receitas de bolo" genéricas que podem auxiliar o desenvolvimento em diversas situações. Normalmente eles reforçam os Princípios de Design Orientado a Objetos.

Possuir o conhecimento destes patterns pode ajudar muito um desenvolvedor a resolver rapidamente os problemas encontrados na programação do dia-a-dia e também pode ajudá-lo a construir softwares cujo desenvolvimento e manutenção sejam mais fáceis.

Porém, é necessário utilizar estes patterns com cautela. Muitos desenvolvedores e até mesmo arquitetos privilegiam a "conformidade" com os Design Patterns no lugar do fácil desenvolvimento e manutenção. Temos que utilizar o conhecimento que temos visando diminuir os custos do software (que está ligado ao tempo que ele demora para ser desenvolvido e ao tempo que se dispende na sua manutenção).

Outra vantagem de se utilizar os Design Patterns é a comunicação: entre duas pessoas que conhecem Design Patterns é muito simples descrever um software que os utilizou. Por exemplo: em vez de explicar o que cada classe faz, basta dizer "aqui eu usei o pdrão Observer".

Um Design Pattern sempre será descrito da seguinte forma:
  • Nome;
  • O problema que se propõe resolver;
  • A solução proposta;
  • Quando aplicá-lo;
  • Consequências da sua aplicação.
Nos próximos posts, pretendo apresentar os principais e mais comumente utilizados Design Patterns. Manterei este post atualizado com a lista dos Patterns apresentados.

Patterns de Criação:
Patterns Comportamentais:
Patterns Estruturais:

Um abraço.

quinta-feira, 19 de janeiro de 2012

Tutorial: Instalar workflows no Sharepoint programaticamente

Neste post pretendo apresentar como “instalar” um workflow declarativo (como os workflows criados no Sharepoint Designer) no Sharepoint programaticamente. Os testes que fiz de instalação foram feitos no Sharepoint Foundation 2010, porém acredito que se aplicam ao Windows Sharepoint Services 3.0 e também ao Microsoft Office Sharepoint Server 2007.

Arquivos que compõe o workflow declarativo

Primeiramente, para instalar o worflow no Sharepoint, é necessário ter os seguintesarquivos:

  1. Desenho do workflow. (obrigatório)
    Este arquivo possui extensão XOML. É um xml que onde estão declarados os passose as ações do workflow.
  2. Configurações do workflow. (obrigatório)
    Este arquivo normalmente possui o mesmo nome do arquivo XOML, porém com o seguintesufixo: wfconfig.xml, por exemplo, se seu XOML se chama MeuWorkflow.xoml, este arquivose chamaria MeuWorkflow.xoml. wfconfig.xml
  3. Formulário de abertura do workflow. (opcional)
    Este é um arquivo aspx, com o formulário de abertura do workflow. Usado em workflowspossuem a opção de serem iniciados manualmente.
  4. Arquivo Rules. (opcional)
    Este arquivo contem um XML com regras e possui extensão .RULES. Estas regras sãoutilizadas como condições em IFs criados dentro do workflow.
  5. Arquivo [Content_Types].xml (opcional)
    Este arquivo possui exatamente este nome e nele podem ser incluídos content typesque serão utilizados nas tarefas do workflow. Lembre-se que se você irá criar tarefascom content types, estes deverão sempre herdar do content type “Workflow Task”.

Instalação do workflow

A instalação do workflow no Sharepoint é dividida em três passos. Parecem simples,porém existem alguns detalhes muito importantes que se não observados podem gerarmuita dor de cabeça, pois se não seguidos, o workflow não será instalado ou atualizadoe o Sharepoint não dará nenhuma pista do que pode estar ocorrendo. Os três passossão:

  1. Upload dos arquivos do workflow no Sharepoint;
  2. Validação dos XMLs e criação dos objetos necessários;
  3. Criação ou atualização do workflow.

A seguir estão os detalhes de como fazer cada passo:

Upload dos arquivos do workflow no Sharepoint

Os arquivos dos workflows declarativos ficam armazenados numa biblioteca específicano Sharepoint. Esta biblioteca não pode ser visualizada pela interface do Sharepoint,porém é possível ver os arquivos que estão lá através do Windows Explorer. Se vocêdigitar “\\[endereco _sharepoint]\Workflows” verá as pastas e arquivos dos workflowsinstalados no Sharepoint.

Por algum motivo, o Sharepoint não consegue ler o arquivo do workflow se ele é inseridopela forma habitual, usando o SPWeb.Files.Add(). Portanto, devemos utilizar a interfaceFrontPage RPC, a mesma que o Sharepoint Designer utiliza para enviar os arquivosdo workflow criados dentro dele. Como o código para isso é muito complexo e nãofui eu que criei (ele está disponível na internet em diversos blogs), não colocareino corpo deste post. Porém você pode baixá-lo no exemplo anexo a este post. A classeDocLibHelper é a classe responsável pelo upload utilizando o FrontPage RPC.

Validação dos XMLs e criação dos objetos necessários

O Sharepoint expõe um serviço com métodos para a validação e instalação dos workflows.Estes métodos fazem parte do serviço WebPartPages. Portanto, será necessário adicionaruma Service Reference no projeto apontando para o seguinte endereço: http://[endereço_sharepoint]/_vti_bin/Webpartpages.asmx

O método utilizado para a validação e criação dos objetos é o ValidateWorkflowMarkupAndCreateSupportObjects

O serviço precisa ser executado utilizando um usuário com permissão administrativano site no qual o workflow será instalado. Este método retorna uma string, na qualserá retornado um XML com uma mensagem de sucesso, caso esteja tudo OK com o mark-updo workflow, ou com mensagens de erro apontando problemas no mark-up. O código parachamar o serviço ficará assim:



string response;
WebPartPages.WebPartPagesWebServiceSoapClient service = new WebPartPages.WebPartPagesWebServiceSoapClient();
service.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
service.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;

response = service.ValidateWorkflowMarkupAndCreateSupportObjects(xomlMarkup, null, configMarkup, "2");

Analisando o código, podemos observer que:

  • Primeiro instanciamos o serviço e atribuímos uma credencial de usuário. No caso,o usuário que está executando o programa.
  • A variável xomlMarkup é uma string com o XOML do workflow que será instalado.
  • O parâmetro null seria uma string com o mark-up do arquivo RULES. Como neste exemplonão temos nenhum IF no workflow, não precisamos deste arquivo.
  • O parâmetro configMarkup é uma string com o XML de configurações do workflow.
  • O último parâmetro que o método espera identifica se queremos apenas validar o workflowou validar e criar os objetos dos quais o workflow poderá depender (como site columns,contente types ou outros). “1” significa apenas validar. “2” significa validar ecriar os objetos.

Criação ou atualização do workflow

O próximo passo é instruir o Sharepoint a instalar o workflow. O serviço WebPartPagestem outro método para isso: AssociateWorkflowMarkup Assim como o método anterior,ele retorna uma string com um XML que possui mensagens de erro ou o GUID do workflowcriado, caso a instalação seja feita com sucesso. O código ficará assim:



string response;
WebPartPages.WebPartPagesWebServiceSoapClient service = new WebPartPages.WebPartPagesWebServiceSoapClient();
service.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
service.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;

response = service.AssociateWorkflowMarkup("Workflows/Teste-Deploy-By-Code/Teste-Deploy-By-Code.xoml.wfconfig.xml", version);

Analisando o código, podemos observar:

  • O primeiro parâmetro é o caminho relativo ao site do arquivo de configuração doworkflow.
  • O segundo parâmetro é a versão do arquivo e é muito importante. Caso a versão doarquivo não seja passada corretamente, o workflow não será instalado, o método dowebservice dará erro e não gerará nenhuma linha no log. Passei muito tempo paradescobrir que eu tinha problemas nessa parte do código, porque tive até que usaro reflector e debugar a DLL do Sharepoint para entender qual era o problema. Olhandoo exemplo completo anexo ao post, você poderá ver como pode ser tratado este detalheda versão.
  • Importante: Dentro do arquivo de configuração (wfconfig.xml) há uma referência parao arquivo XOML, e alí também há uma configuração de versão, que deve bater com aversão do arquivo XOML.
  • Todas essas strings de versão são sempre no formato VX.X, exemplo: V1.0, V2.0, etc.

Recapitulando os pontos mais críticos:

Os pontos nos quais tive dificuldade de resolver e que para tal gastei mais tempoforam os seguintes:

  • Precisamos usar o FrontPage RPC para enviar os arquivos do workflow para o Sharepoint.Tentei outras duas formas de subir arquivos no Sharepoint e o serviço WebPartPagesnão conseguiu ler os arquivos do workflow em nenhuma delas.
  • O Sharepoint versiona os arquivos automaticamente, e precisamos passar a versãocorreta do arquivo que será utilizada pelo serviço. Isso vale para o parâmetro dométodo AssociateWorkflowMarkup e para as referências no arquivo wfconfig.xml, comoXomlVersion, por exemplo.
  • O formato dessas strings de versão é VX.X, se a versão for passada em outro formato,o serviço WebPartPages vai dar erro.

Abaixo você pode baixar uma aplicação console que fiz de teste, que pode ser usadacomo exemplo. Nela eu instalo um workflow simples no Sharepoint. Este workflow apenastem uma atividade que muda o seu próprio status para a string “Terminou :)”. Paratestar este exemplo no seu próprio Sharepoint, você deverá alterar a linha 3 doarquivo “Teste-Deploy-By-Code.xoml.wfconfig.xml”, você deverá colocar o ID de umalista que exista no seu Sharepoint, o workflow de teste será associado à esta lista.

Baixar código de exemplo