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:
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.
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.






xawe
17/01/2012
Caro Elemar , tenho acompanhado seus posts desde o Dnad11 e devo agradece-lo por compartilhar seu tempo e conhecimento conosco.
A serie sobre WF me chamou mais a atenção, já que estou brincando um pouco mais com essa tecnologia para uso com o Dynamics CRM.
Gostaria de pedir ( Se possivel ) que desse suas considerações em relação a performance do WF , uma vez que em alguns testes simples, notei uma queda altissima de performance quando utilizo alta recursividade usando as atividades de loop nativas.
Criando algumas atividades customizadas, a performance melhorou, mas ainda fica muito abaixo de uma simples classe.
Abraço
elemarjr
17/01/2012
Olá,
Muito obrigado pelo feedback e cumprimentos. Fico feliz em saber que esta série está te interessando.
Quanto a performance, acredito que o problema esteja no uso que você está dando ao WF. Ele definitivamente não foi feito para implementar algoritmos. A ideia central é automatizar processos. Preferencialmente, os de longa duração. Nesses casos, o impacto é menos perceptível.
Não acha?!
[]s
xawe
18/01/2012
Hmmmmmm
Perfeito Elemar.
Novamente , obrigado.
Abs.
Marcus Alexandre
17/01/2012
Elemar, Vai ai um artigo da MSDN que você poderia considerar para complementar sua série de posts: http://msdn.microsoft.com/en-us/library/aa480213.aspx
elemarjr
17/01/2012
Fantástico, man. Obrigado
Giovanni Bassi
10/02/2012
Po, perdi meu comentário. Mas lá vai de novo:
Eu concordo com as ressalvas, mas faço mais uma: tem uma diferença entre código feito com C# e workflows feitos com WF: você pode testar C#. Já WF, você precisa esperar que funcionem. Enquanto não houver uma maneira de testar o workflow desenhado em um sandbox, e garantir que ele funciona confome o esperado, ele é muito perigoso.
Então fica aqui a provocação pra um próximo post: que tal mostrar como seria tal sandbox de testes para um workflow deste?
Até lá, prefiro meu Good Old C#.
Rafael Da Silva
19/03/2012
Boa Tarde Elemar,
Gostei do seus posts, agora tenho um dúvida, quando trabalhar com o fluxo de longa duração com interação humana (Flowchart) como identificar em qual etapa do processo o usuário está? ou como identificar os próximos passos que ele deve seguir?
Exemplo: Iniciei um atividade onde o usuário vai analisar um erro, caso negativo esse erro volta ao atendente, mas caso negativo deve seguir para desenvolvimento > teste > homologação… isso ainda não está claro.
Pode dar uma dica?