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

quarta-feira, 17 de agosto de 2011

Thread was being aborted e HttpWebResponse.Redirect

Olá, gostaria de retomar as postagens neste blog com um tema simples, mas que pode ser muito útil.


O problema:


Recentemente um colega expos um problema comum ao utilizar o Responde.Redirect(url) no ASP.NET. O cenário era o seguinte: ele possuía um trecho de código com try...catch...finally, e dentro dele havia um Response.Redirect(url). Ele notou que a página sempre dava erro. Eis um exemplo que ilustra o cenário:




Protected Sub btnGo_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnGo.Click
Dim _Connection As SqlConnection = Nothing
Try
_Connection = New SqlConnection("Data Source=.;Initial Catalog=master;Integrated Security=SSPI;")
Dim _Command As New SqlCommand("Select Count(*) From Sys.Objects Where Type = 'U'", _Connection)
Dim _Result As Int32

_Connection.Open()
_Result = Convert.ToInt32(_Command.ExecuteScalar())

Response.Redirect("Result.aspx?r=" & _Result.ToString())
Catch ex As Exception
Response.Redirect("Result.aspx?r=" & Server.UrlEncode("Erro ao buscar os dados. " & ex.Message))
Finally
If _Connection IsNot Nothing Then
_Connection.Close()
End If
End Try
End Sub

O erro gerado pela página era sempre o mesmo: Thread was being aborted.


Solução:


A solução é substituir os dois Response.Redirect(url) do código por Response.Redirect(url, False). Desta forma, por exemplo:




Response.Redirect("Result.aspx?r=" & _Result.ToString(), False)

Explicação:


O Response.Redirect(url) apenas chama o método Response.Redirect(url, True). Este segundo parâmetro do tipo Boolean indica se, antes de enviar o HTTP Redirect para o Browser do cliente, a execução da página deve ser interrompida ou não.


Caso passemos True, o método Redirect tentará interromper a execução, porém, devido ao bloco Try...Catch...Finally, ele obterá um erro: pois a thread na qual a página está sendo executada só poderá ser interrompida após o Finally ser executado.


Passando False no segundo parâmetro, o método aguardará o ciclo de vida da página ser executado por completo antes de enviar o HTTP Redirect ao browser.


Atenção: Em muitos casos é interessante interromper o processamento da página no Redirect, principalmente quando há algum processamento pesado que não precise ser executado caso haja o Redirect. Não é à toa que o comportamento padrão (quando não passamos o parâmetro) é o de interromper o processamento.

terça-feira, 7 de outubro de 2008

Mini-tutorial SharePoint Smart Part

Aqueles que já desenvolveram Web Parts para o Microsoft Office SharePoint Services puderam notar que a Microsoft não facilitou em nada esta tarefa para o Desenvolvedor. A criação de uma Web Part é muito parecida com a criação de um Server Control: isso significa que todo o HTML que a Web Part irá exibir no browser deve ser gerado no código (VB.Net ou C#). Para Web Parts complexas, com formulários, validações, AJAX e etc. ,isso pode acabar com a produtividade no desenvolvimento.

Para contornar essa dificuldade, existe um projeto Open-Source chamado Smart Part. Nesse projeto, foi criada uma Web Part que nada mais faz do que injetar um User Control dentro de si mesma, ou seja: nos dá a opção de criar Web Parts como User Controls (ascx). Isso ajuda muito a produtividade e torna bem mais simples o desenvolvimento de novas funcionalidades para o Sharepoint.

A seguir, mostrarei como criar uma Smart Part simples:

  1. Baixe e descompacte o Smart Part neste link: http://www.codeplex.com/smartpart/Release/ProjectReleases.aspx?ReleaseId=10697
  2. Crie um novo projeto Web Application no Visual Studio e adicione uma referência para o assembly ReturnOfSmartPart.dll.
  3. Crie um User Control (ascx) da mesma forma como você faria num projeto de Web Site comum.
  4. Instale o Smart Part no servidor onde está o SharePoint. Se houver mais de uma Aplicação do Sharepoint instalada, você poderá escolher em quais deseja instalar.
  5. Abra o diretório do Sharepoint para o qual o IIS aponta, por exemplo: “C:\Inetpub\wwwroot\wss\VirtualDirectories\[NumeroDaPorta]”. Onde [NumeroDaPorta] é o número da porta que a Aplicação Sharepoint está configurada (80, por exemplo).
    1. Jogue as DLLs que seu projeto gerou na pasta Bin.
    2. Crie uma pasta chamada User Controls na raiz e copie o ascx para ela.
  6. Abra uma página no Sharepoint e adicione a Web Part Smart Part nela.
  7. Clique no menu da Web Part (seta no canto superior-direito da Web Part), e clique em “Modify Shared Web Part”.
  8. No Tool Part que apareceu à direita, deve existir um campo chamado “User Control to Display”, ele exibe todos os User Controls encontrados na pasta UserControls da raiz da pasta do Sharepoint, selecione o seu ascx.

Pronto! Muito mais simples do que desenvolver uma Web Part, com a vantagem de poder utilizar o designer do Visual Studio para criar o XHTML do ascx.

Referência:
Site do projeto: http://www.codeplex.com/smartpart