Windows Workflow Foundation (WF) – Parte 4 – Code?! Xaml ?! Diagram?!

Publicado em 16/01/2012

7


Olá pessoal. Tudo certo?!

Nos primeiros posts dessa série, apresentei alguns fundamentos do Windows Workflow Foundation. Vimos como criar fluxos simples através de código, Xaml e do editor do Visual Studio (diagramas). Também vimos que podemos criar fluxos baseados em sequênciass ou decisões. Entretanto, surge uma dúvida: qual é a melhor abordagem?!

A resposta mais honesta para essa pergunta, creio eu, é, mais uma vez, depende! Vejamos o porquê.

Um fluxo muito simples no editor do VS

Comecemos nosso processo analisando um fluxo muito simples. Criemos um “flowchart” que conta de 10 até 0 e, no final, imprime Fire. Veja:

image

Veja o terceiro post dessa série para ver detalhes de como editar e criar fluxos usando o editor do visual studio.

Como você pode perceber, trata-se de um fluxo simples. Temos um fluxo simples que imprime o valor de uma variável (counter), inicializado com 10, aguarda 1 segundo, decrementa a variável e decide entre um “loop” e o encerramento (com uma mensagem “Fire!”). Entendido?

A execução, após completada, desse fluxo resulta em um console com as impressões que foram realizadas.

image

Beleza!

O mesmo fluxo em Xaml

Como você já deve ter notado, o editor do Visual Studio persiste o workflow em Xaml. Ou seja, essa é a representação padrão do fluxo (quando não for escrito algum código). Entretanto, além do fundamental para executar o fluxo, o VS também salva uma série de informações relacionadas a representação visual.

Apresento agora, o mesmo fluxo que elaboramos anteriormente, somente em Xaml (limpo).

<Flowchart
  xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  
  <Flowchart.Variables>
    <Variable x:TypeArguments="x:Int32" Default="10" Name="counter" />
  </Flowchart.Variables>

  <Flowchart.StartNode>
    <FlowStep x:Name="startpoint">
      <WriteLine Text="[counter.ToString()]" />
      <FlowStep.Next>
        <FlowStep>
          <Delay Duration="00:00:01"/>
          <FlowStep.Next>
            <FlowStep>
              <Assign>
                <Assign.To>
                  <OutArgument x:TypeArguments="x:Int32">[counter]</OutArgument>
                </Assign.To>
                <Assign.Value>
                  <InArgument x:TypeArguments="x:Int32">[counter - 1]</InArgument>
                </Assign.Value>
              </Assign>
              <FlowStep.Next>
                <FlowDecision Condition="[counter = 0]">
                  <FlowDecision.True>
                    <FlowStep >
                      <WriteLine Text="fire from Xaml!" />
                    </FlowStep>
                  </FlowDecision.True>
                  <FlowDecision.False>
                    <x:Reference>startpoint</x:Reference>
                  </FlowDecision.False>
                </FlowDecision>
              </FlowStep.Next>
            </FlowStep>
          </FlowStep.Next>
        </FlowStep>
      </FlowStep.Next>
    </FlowStep>
  </Flowchart.StartNode>
</Flowchart>

Perceba que essa representação parece bem mais complexa que aquela que vimos no segundo post dessa série. Isso aconteceu porque optamos por utilizar Flowchart que é, naturalmente, mais complexo por estabelecer a relação entre os nodos.

O importante, nesse momento, pelo menos, é entender que o Xaml está diretamente relacionado com qualquer iniciativa para alterar fluxos sem a necessidade de mexer no programa. Podemos usar o editor do VS, ou criar o nosso editor, mas, seja de uma forma ou de outra, acabamos persistindo em Xaml. Certo?!

O mesmo fluxo em código

Xaml é uma forma inteligente (?!) para persistir dados relacionados a objetos em Xml. Nada nos impede de criar os mesmos objetos e alimentar os dados diretamente no código. Observe:

public Activity CreateWorkflow()
{
            
    var counter = new Variable<int>("counter", 10);

    var startnode = new FlowStep()
        {
            Action = new WriteLine() { Text = new InArgument<string>(ctx => counter.Get(ctx).ToString()) }
        };

    var delay = new FlowStep()
        {
            Action = new Delay() { Duration = TimeSpan.FromSeconds(1) }
        };
    startnode.Next = delay;

    var assign = new FlowStep()
        {
            Action = new Assign()
            {
                To = new OutArgument<int>(counter),
                Value = new InArgument<int>(ctx => counter.Get(ctx) - 1)
            },
        };
    delay.Next = assign;

    var decision = new FlowDecision()
        {
            Condition = new VisualBasicValue<bool>("counter = 0"), 
            True = new FlowStep()
            {
                Action = new WriteLine() { Text = "Fire from code!" }
            },
            False = startnode
        };
    assign.Next = decision;
               

    var result = new Flowchart()
    {
        Variables = { counter },
        StartNode = startnode 
    };

    return result;
}

Lindo! Não acha?!

Mas, afinal, quando usar cada uma das abordagens?

Vamos por partes. Considere:

  • Se os fluxos que você está criando não mudam com muita frequência. Ou, de outra forma, implicam na mudança de mais coisas no programa. Então, o melhor é escrever código diretamente em C#.
  • Se os fluxos mudam e/ou você deseja poder fazer isso sem mudar o código. Então, você deve considerar a utilização de Xaml.
  • Se o seu cliente, ou um “leigo” for fazer alterações no fluxo. Então, considere utilizar o editor do Visual Studio ou desenvolver o seu editor.

Vamos pensar um pouco mais.

  • Se o seu fluxo for relativamente “estável”, a ponto de você resolver mantê-lo em código, pode ser que você não precise, mesmo, usar WF. Ou seja, pode ser que você esteja querendo “atacar uma formiga com uma bazuca!”
  • Se for fornecer um ambiente para que seu cliente modifique/crie fluxos, deve considerar o desenvolvimento de um editor alternativo. O editor do VS não está conforme com as principais notações de processo.

Estamos entendidos?!

Era isso.

Etiquetado:
Publicado em: Post