Neste artigo vamos expor algumas ideias sobre Windows Workflow Foundation e como este notável recurso está mudando pouco a pouco a maneira dos programadores.NET trabalharem.

No passado tínhamos ferramentas de processo para mapearmos atividades de maneira mais funcional e menos técnica. Já tínhamos também ferramentas de “Orchestration” como o BizTalk Server da Microsoft, onde já era possível criar em versões mais antigas, processos de negócio visando a interoperabilidade e troca de mensagens entre sistemas e aplicações de maneira dinâmica, conectando pontas de diferentes sistemas ou aplicações, facilitando assim a integração entre sistemas.

Bom, e onde entra o Workflow? Basicamente falando, desenhar um workflow no Visual Studio é uma experiência prática semelhante às estas ferramentas de BPEL, porém, com todo o poder, robustez e estabilidade do Visual Studio, aliado aos diversos recursos disponíveis na BCL do .NET Framework.

Iniciar o desenvolvimento de Workflows utilizando o Visual Studio já era possível com a versão 2005, com as extensões do WWF, inclusive a Microsoft disponibilizou suporte à BPEL com uma extensão BPEL para o Windows Workflow Foundation.

O que muda para os programadores e arquitetos?

Em essência, para os programadores que estão habituados a canais, fluxos de programação, interoperabilidade, camada de apresentação e todos estes paradigmas que utilizamos para representar parte do mundo real em um mundo sistêmico orientado a objetos e eventos, logo quando se deparar com um Workflow não estão muito errados se pensar: “ei, isto é semelhante à programação via código, não tenho muito porque me assustar quanto ao entendimento técnico”.

Hoje criamos bibliotecas de componentes e isto não muda muito: teremos bibliotecas de workflows. Deem uma olhada no meu novo projeto no CodePlex. Estou pregando o conceito de Workflow-DNA, onde você tem todas as suas operações corporativas mapeadas em Workflows, criando o que eu chamo de a identidade funcional da empresa. Assim, cada empresa é única em seus processos, como uma impressão digital.

O conceito de Workflows é bastante simples e é só se habituar a uma maneira de pensar onde você desenha processos e fluxos de trabalho e não sai mais codificando. Os workflows podem substituir quase, se não totalmente, toda a camada de regra de negócio, geralmente intitulada “Business Tier”, e ter importantes funções e outras camadas também. Os recursos encontrados no WWF são ótimos a ponto de podermos definir completamente como as telas da camada de apresentação devem ser sequenciadas. Sim, podemos colocar workflows em quase tudo!

Para exemplificar a utilização, vamos criar um workflow simples, mas completo no VS 2008 fazendo o seguinte:

  1. Solicitar ao usuário para entrar com sua idade;
  2. Processar a idade do usuário, decidindo a faixa etária;
  3. Responder ao usuário, baseado na idade respondida, qual é a faixa etária.

Para testar o projeto do artigo será necessário o Visual Studio 2008. Se você não o tem ainda pode baixar uma versão trial.

Task sequence brainstorming:

  1. Criar um projeto de “Workflow Activity Library” chamado Workflow.Library.Activities;
  2. Criar um projeto de “Sequential Workflow Console Application” chamado Workflows.Host;
  3. No projeto “Workflow.Library.Activities” criaremos três atividades customizadas:
    • LerIdade
    • ProcessarIdade
    • EscreverResultado
  4. No projeto Workflows.Host criaremos um workflow e faremos com que as três atividades descritas no item “3” sejam totalmente integradas sequencialmente.

Iniciando a construção da aplicação

Para o item 1 da lista apresentada devemos iniciar o Visual Studio 2008 e criar um novo projeto do tipo Workflow Activity Library, como na Figura 1.

Projeto Workflow
Figura 1. Projeto Workflow

Nomeie este projeto como Workflow.Library.Activities. Nele criaremos os dois workflows customizados.

Para o item 2 da lista crie agora um projeto do tipo “Workflow Console Application” e nomeie-o como Workflows.Host, como na Figura 2.

Workflows.Host
Figura 2. Workflows.Host

O que teremos com a criação dos dois projetos deverá ser igual a Figura 3 a seguir, sem nenhuma customização ainda:

Resultado do item 2
Figura 3. Resultado do item 2

Já para o item 3 da lista criaremos três atividades customizadas para nosso workflow. Assim, adicione um item do tipo “Activity” e nomeie-o como LerIdade, conforme a Figura 4.

Inserindo “Activity
Figura 4. Inserindo Activity

Agora repita os passos para criar a atividade “Leridade” e posteriormente as atividades ProcessarIdade e EscreverResultado.

Customizando a atividade “LerIdade”

Selecionando a atividade “LerIdade” arraste da Toolbar o item “CodeActivity” e nomeie esta atividade de código para LerIdadeDoConsole, semelhante à representação da Figura 5.

Inserindo CodeActivity
Figura 5. CodeActivity

Dê um duplo-clique sobre o CodeActivity LerIdadeDoConsole e digite o código da Listagem 1.

private void LerIdadeDoConsole_ExecuteCode(object sender, EventArgs e)
  {
    Console.WriteLine("Digite a idade:");
    Idade = Console.ReadLine();
  }
Listagem 1. Código de CodeActivity LerIdadeDoConsole

Antes de compilar será necessário criar um atributo chamado Idade, conforme a Listagem 2.

public string Idade{get;set;}
Listagem 2. Atributo Idade

Simples não? Já criamos nossa primeira atividade e agora vamos para a segunda atividade.

Criando a atividade “Processa Idade”

O objetivo desta atividade é receber a idade digitada do console, e definir o valor de seu atributo “FaixaEtaria” com os textos “menor de idade”, “adulto”, “idoso”, tendo como base a idade digitada na primeira atividade.

Para isto, vamos começar escrevendo o atributo Idade, que terá suporte para “DataBinding” com expressões, configurado em tempo de design. Para isto vá para o código da atividade ProcessaIdade, criando sua Dependency Property, e o atributo digitando o seguinte código da Listagem 3.


public static DependencyProperty IdadeProperty = 
   System.Workflow.ComponentModel.DependencyProperty.Register("Idade", 
    typeof(string), typeof(ProcessarIdade));
[Description("Idade a processar")]
[Category("Custom Binding")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible]
public string Idade
{
  get
  {
    return base.GetValue(IdadeProperty).ToString();
  }
  set
  {
    base.SetValue(IdadeProperty,value);
  }
}
Listagem 3. Código da ProcessaIdade

Como queremos que haja Binding e todas as facilidade de integração com outras atividades através de Binding Expressions, precisamos criar este código para que em tempo de design e execução o atributo seja acessado conforme precisamos. Observaremos que quando criamos atributos com a classe DependencyProperty da maneira como fizemos, eles podem ser configurados com o Assistente do Visual Studio.

No fluxo de trabalho para a Custom Activity de ProcessarIdade, precisamos fazer o seguinte:

  • Se Idade < 18, atribuir FaixaEtaria=”MenorDeIdade”;
  • Senão Se Idade <59, atribuir FaixaEtaria=”Adulto”;
  • Senão se idade >=60, atribuir FaixaEtaria=”Idoso”;

O fluxo de trabalho visualmente terá a mesma aparência da Figura 6.

fluxo de trabalho
Figura 6. Fluxo de trabalho

Todas as conditions utilizam Declarative Rule Condition para avaliar as expressões e “entender” o que fazer caso as condições sejam satisfeitas. As três “Conditions” serão configuradas da seguinte maneira:

  • SeMenorDe18:
    • Declarative Rule Condition
    • Expressão: System.Convert.ToInt32(this.Idade) < 18
  • SeAdulto:
    • Declarative Rule Condition
    • Expressão: System.Convert.ToInt32(this.Idade) <= 59
  • SeNaoSeIdoso:
    • Declarative Rule Condition
    • Expressão: System.Convert.ToInt32(this.Idade) >= 60

A Policy AtribuiValorMenorDeIdade deve ser configurada da seguinte maneira:

  • RuleSet name: AtribuiValorMenorDeidade
  • Condition: True
  • Then Actions: this.FaixaEtaria = “Menor de idade”

As duas atividades de “Code Activity”, AtribuiValorAdulto e AtribuiValorIdoso devem ter o código da Listagem 4 em seus eventos “ExecuteCodigo”.

private void AtribuiValorAdulto_ExecuteCode(object sender, EventArgs e)
{
  this.FaixaEtaria = "Adulto";
}
private void AtribuiValorIdoso_ExecuteCode(object sender, EventArgs e)
{
  this.FaixaEtaria = "Idoso";
}
Listagem 4. Atividades de Code Activity

Com isto terminamos a atividade customizada ProcessaIdade. Vamos criar agora a nossa última Custom Activity.

Criando a última atividade deste projeto: Atividade “EscreverResultado”

Esta atividade é tão simples quando à primeira e muito semelhante. Criaremos um atributo com recursos de “Binding” de expressões chamado “FaixaEtariaExibir”, e exibirá uma mensagem indicando qual a faixa etária.

Primeiro, vamos criar o atributo FaixaEtariaExibir e para isto precisamos criar sua Dependency Property e o atributo, com o seguinte código da Listagem 5.

public static DependencyProperty FaixaEtariaExibirProperty = 
   System.Workflow.ComponentModel.DependencyProperty.Register("FaixaEtariaExibir", 
    typeof(string), typeof(EscreverResultado));
[Description("Faixa etaria a exibir")]
[Category("Custom Binding")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible]
public string FaixaEtariaExibir
{
  get
  {
    return base.GetValue(FaixaEtariaExibirProperty).ToString();
  }
  set
  {
    base.SetValue(FaixaEtariaExibirProperty,value);
  }
}
Listagem 5. Atributo FaixaEtariaExibir

Depois, vamos inserir uma “code activity” com o nome EscreverFaixaEtariaNoConsole, que terá seu evento “ExecuteCode” com a aparência da Listagem 6.

private void EscreverFaixaEtariaNoConsole_ExecuteCode(object sender, EventArgs e)
{
  System.Console.WriteLine("A pessoa é: " + this.FaixaEtariaExibir);
  System.Console.WriteLine("Pressione ma tecla para encerrar o Workflow...");
  System.Console.Read();
}
Listagem 6. Evento ExecuteCode

Assim terminamos nosso componente Workflows.Library.Activities. Compile-o para se certificar que não há erros de build.

Vamos agora configurar o projeto Workflows.Host, o item 4 de nossa lista inicial. Primeiro renomeie o Workflow padrão de “Workflow1” para ProcessaIdade.

Ao abrir o workflow no designer, adicione uma referência para a biblioteca de atividades, a toolbar passa a apresentar as três novas atividades que criamos, conforme a Figura 7.

Três novas atividades
Figura 7. Três novas atividades

Dentro do seu workflow ProcessaIdade, coloque as três novas atividades na seguinte sequência:

  1. LerIdade
  2. ProcessarIdade
  3. ExcreverResultado

O workflow ficará com a aparência semelhante à Figura 8.

Aparência do workflow
Figura 8. Aparência do workflow

Agora configure os atributos das atividades da seguinte maneira:

  • Atividade processarIdadeActivity:
    • Atributo Idade: ”Activity=lerIdadeActivity, Path=Idade”
  • Atividade escreverResultadoActivity
    • Atributo FaixaEtariaExibir: “Activity=processarIdadeActivity, Path=FaixaEtaria”

Compile a solução utilizando CTRL + SHIFT + B e execute a solução com F5.

Observe que o fluxo será executado na sequência correta e será totalmente processado. A idade passou da primeira atividade para a segunda, a segunda atividade processou a idade, definindo uma faixa etária, e então a terceira atividade recebeu a faixa etária da segunda atividade, exibindo ao usuário o resultado.

Conclusão

Começar a criar Workflows é uma tarefa simples, embora tenhamos uma abordagem um pouco diferente da codificação tradicional, as vantagens em se utilizar workflows para construção de fluxos de trabalho é enorme. É possível extender bastante o sistema de workflows, criando novas atividades, regras, conectando workflows e fazendo com que eles interajam com o mundo externo sem maiores dificuldades.

Os Workflows vieram para facilitar nossa vida e é muito mais fácil e intuitivo termos diversos deles interconectados ou oferecendo serviços específicos, do que termos códigos densos e por natureza menos legível, se comparados à clareza por excelência dos Workflows.