O Time BigBross
Copyright © 2003 OpenBR Sistemas S/C Ltda.
Resumo
Neste artigo nós descrevemos a filosofia por trás do Bossa, a
poderosa, leve e livre (como em liberdade) máquina de workflow
escrita em Java. Nós brevemente explicamos nossa visão de
workflow, como representar workflows usando redes de Petri e
como uma aplicação é construída usando os serviços de workflow
do bossa.
Bossa é uma máquina de workflow escrita em Java. A máquina é
muito rápida e leve, sem sacrificar a funcionalidade. Seus pontos
fortes são a grande expressividade baseada na notação de rede
Petri para definir workflows e um poderoso mecanismo para seleção
de recursos. Além disso, ela é software livre licenciado sob a
GNU GPL.
Bossa não requer um SGBDR e é muito simples de usar e integrar com
aplicações java. Na verdade, foi projetado
para ser reutilizado. Para tanto, o Bossa é organizado como uma
biblioteca para ser usada por servidores de aplicação
(especialmente web) que precisam de serviços de workflow.
A característica que faz do Bossa ao mesmo tempo simples e
poderoso é a clara separação entre lógica de workflow
e lógica de aplicação. Nós
acreditamos que a lógica de workflow deve ser abstraida da
aplicação da mesma maneira que os SGBDRs abstraem os aspectos de
armazenamento e recuperação de dados.
Neste artigo nós descrevemos a filosofia por trás do Bossa. Nós
começamos explicando nossa visão de workflow em “Workflow”. Em seguida, mostramos como representar
workflows usando redes de Petri em “Redes de Petri e Workflow”. E
finalmente, descrevemos como uma aplicação é construída usando os
serviços de workflow do bossa em “Bossa”.
Dentro de uma organização, pessoas interagem entre si para
executar um trabalho. Cada uma tem sua própria lista de tarefas à
cumprir. Jorge deve encontrar clientes em potencial e dar entrada
na base de dados. Então, Natália entrará em contato com o
cliente. Mais tarde, Paulo escreverá um projeto para o cliente e
Alice fará a revisão. Nós podemos ver aqui que o trabalho deles
está fluindo. Cada pessoa realiza seu trabalho e passa algo
adiante para que os outros possam prosseguir com sua parte.
Workflow é um conjunto de regras que governam
a seqüência de atividades para completar um trabalho que envolve
diversos participantes. Sistemas de Gerenciamento de
Workflow automatizam total ou parcialmente um workflow.
É comum o termo "workflow" ser usado com significados mais
abrangentes. O significado alternativo mais comum está
relacionado a troca de informações entre os participantes de um
trabalho colaborativo. Sistemas de Gerenciamento de
Documentos são usualmente chamados de sistema de
workflow, principalmente porque possibilitam a troca de
informações em geral de maneira ordenada. Sistemas
Colaborativos as vezes são chamados de sistema de
workflow pelas mesmas razões, troca organizada de informações.
Não estamos dizendo que gerenciamento de documentos ou sistemas
colaborativos não sejam capazes de realizar
workflow, mas acreditamos que processar documentos ou mensagens
entre usuários não seja necessariamente uma responsabilidade de
sistemas de workflow. Sistemas de workflow rastreiam atividades e
ajudam a pessoa certa executar a atividade certa na hora certa,
sem interferir nas informações sendo trocadas.
Certamente, a troca de informação é
necessária para toda aplicação colaborativa, mas nós vemos isso
como um assunto separado, assim como o workflow em si. Aplicações
devem deixar que o SGBD armazene os dados, servlets façam a
apresentação, o sistema de gerenciamento de workflow organize as
atividades e o gerenciamento de documentos cuide da troca de
informação.
O Bossa objetiva prover serviços de workflow da maneira mais
simples possível, sem sacrificar qualquer funcionalidade. Para
tanto, o Bossa é totalmente alheio ao tipo de dado sendo
processado, manipulado ou trocado pela aplicação. O Bossa se
preocupa apenas com a seqüência das atividades e com a pessoa
certa para realiza-las.
Pela nossa definição de workflow, virtualmente toda aplicação
colaborativa, e mesmo algumas não colaborativas, precisam de
serviços de workflow. Uma vez que o Bossa provê estes serviços de
maneira leve e sem interferência, nós criamos a possibilidade de
workflow em toda parte.
Redes de Petri e Workflow
Antes de nos aprofundarmos no modelamento de workflows usando
redes de Petri, nós precisamos de uma breve explicação sobre como
um workflow é normalmente visto por um sistema de gerenciamento de
workflow e o que são redes de Petri.
A definição abstrata de um workflow é chamada tipo de
caso. Por exemplo, um processo de compra de suprimentos
que define como todas as compras serão realizadas em um
departamento é um tipo de caso. Tipos de caso são compostos por
tarefas conectadas por
condições. Por exemplo, uma "análise inicial"
é uma tarefa do tipo de caso "compra de suprimentos". Após essa
tarefa ser executada, outras tarefas serão ativadas dependendo do
resultado da "análise inicial", essas tarefas são conectadas
usando pré e pós condições.
Um tipo de caso define todas as possíveis execuções ou instâncias
de um processo. Uma instância individual de um tipo de caso é um
caso. Por exemplo, a compra de uma caixa de
clips é um caso de "compra de suprimentos". Em um caso as tarefas
de um tipo de caso tem dois estados diferentes: uma tarefa ativa é
um ítem de trabalho, uma tarefa em andamento
é uma atividade. Por exemplo, após a tarefa
de "solicitação de compra" ser completada a "análise inicial"
torna-se um ítem de trabalho, isso é, pode ser executada por algum
usuário do sistema. Quando um usuário realmente executa um ítem de
trabalho, uma ação não-instantânea, a tarefa é uma atividade até
ser completada.
Redes de Petri são uma ferramenta para modelar e analisar
processos dinâmicos. Uma rede de Petri é composta por
lugares e transições e
tem uma representação gráfica padrão onde lugares são círculos e
transições são quadrados. Lugares e transições são conectados por
arestas dirigidas, formando um grafo bipartido dirigido, isso é,
seguindo a direção de uma aresta só é possível ir de um lugar para
uma transição ou de uma transição para um lugar. Figura 1. Uma rede de Petri simples. mostra a representação gráfica de uma rede de
Petri simples.
Lugares e transições representam o aspecto estático de uma rede de
Petri, o aspecto dinâmico é representado por
fichas. Uma ficha é uma marca que só pode
ocupar lugares e que muda de lugar de acordo com o
disparo das transições. Na rede de Petri
clássica, quando uma transição dispara ela consome uma ficha de
cada entrada (lugares com arestas chegando na transição) e produz
exatamente uma ficha em cada saída (lugares com arestas deixando a
transição).
Redes de Petri clássicas não são suficientes para modelar os
roteamentos mais sofisticados que um tipo de caso demanda, então
nós usamos rede de Petri colorida. A
discussão de redes de Petri clássica e colorida vai além do escopo
desse documento. Em resumo, em uma rede de Petri colorida, cada
ficha tem uma cor e o disparo de uma transição consome e produz um
número de fichas que é uma função da cor da ficha, enquanto em uma
rede de Petri clássica é consumida e produzida exatamente uma
ficha para cada aresta. Para representar quantas fichas uma
transição consome e produz nós usamos arestas com
peso, onde o peso é uma expressão
inteira. Então, quando uma transição dispara ela consome um número
de fichas igual ao peso da aresta de cada entrada e produz um
número de fichas igual ao peso da aresta de cada saída.
Uma representação de workflow em rede de Petri mapeia lugares aos
possíveis estados da execução de um caso, transições às tarefas e
fichas ao estado atual do caso. Figura 2. Tipo de caso de um departamento de compras. mostra
o tipo de caso "compra de suprimentos" como uma rede de Petri.
Vamos analisar uma tarefa do tipo de caso "compra de
suprimentos". A tarefa "b" é a "análise inicial". Sua entrada vem
do lugar "B", "aguardando análise inicial", com peso constante de
1. Isso significa que sempre que houver uma ou mais fichas no
lugar "B" a tarefa "b" é um ítem de trabalho pronto para ser
disparado.
As tarefas (transições) em um tipo de caso não disparam
aleatoriamente como na rede de Petri clássica, mas elas são
acionadas por um recurso. A tarefa "b" deve ser executada pelo
recurso "compras - $a", isso significa que somente os usuários do
grupo "compras" menos os usuários que executaram a tarefa "a"
podem acionar (disparar) essa tarefa estando ela ativa. Recursos
são definidos por expressões de conjunto (com operações de
exclusão, união e intersecção) usando grupos de usuários e grupos
especiais "$" dos usuários que executaram uma tarefa.
A tarefa "b" tem como saída os lugares "C", "D" e "E". O lugar
"C", "aguardando revisão", tem como peso de saída "!SOK". O lugar
"D", "aguardando aprovação do diretor", tem como peso de saída
"SOK && DIR". O lugar "E", "aguardando execução de
compra", tem como peso de saída "SOK && !DIR". Aqui nós
começamos a explorar a maneira específica como o Bossa define um
tipo de caso. Cada peso é uma expressão JavaScript que será
resolvida para um inteiro usando as variáveis definidas durante a
execução do caso.
De acordo com as ações realizadas pelos recursos, a aplicação
atribuirá valores apropriados para as variáveis do caso. Depois da
tarefa "b", se a solicitação de compra não passar pela análise
inicial, a variável SOK conterá falso. Se passar pela análise
inicial, SOK conterá verdadeiro e DIR será verdadeiro ou falso se
a aprovação do diretor for necessária ou não. Então, quando a
tarefa "b" dispara uma ficha será removida do
lugar "B" e uma ficha será colocada no lugar
"C", "D" ou "E" dependendo dos valores das variáveis do caso.
A tarefa "b" representa o que em modelamento de workflow é
usualmente conhecido como and-split. O Bossa
não está restrito aos elementos básicos de roteamento de
workflow. O uso de expressões no peso das arestas e variáveis nos
casos permite rotear as fichas de um caso com grande poder e
flexibilidade.
Agora que nós apresentamos o que é workflow e como modelar tipos
de caso usando a notação de rede de Petri do Bossa, nós podemos
falar um pouco mais sobre o que é o Bossa e
como usá-lo.
Bossa é uma máquina de workflow organizada como uma biblioteca em
Java. Isso significa que o Bossa não é um servidor por si só, mas
um conjunto de classes que podem ser usadas para criar uma máquina
de workflow particular embutida em aplicações
Java. Logo, o Bossa não se preocupa com vários problemas que
processos servidores devem lidar, como: conexões, sessões,
autenticação, etc. Ele confia na aplicação para lidar com esse
problemas. A aplicação por sua vez provavelmente usará algum
ambiente, como um servidor de aplicação J2EE, para ajudar prover
esses serviços. Isso permite ao desenvolvedor maior liberdade para
construir sua aplicação com qualquer tecnologia que ele tenha
disponível ou prefira utilizar.
Para o Bossa, um usuário é conhecido como recurso e é representado
apenas por um nome que o identifica. O Bossa usa esse
identificador para mapear o recurso em grupos e testar se um
recurso está contido em uma expressão de recurso. O bossa não
registra ou autentica usuários nem armazena qualquer informação,
como nome ou endereço, sobre os usuários. O Bossa apresenta os
ítens de trabalho que um recurso pode executar, mas não verifica
se o recurso realmente pode executar um ítem de trabalho. Ficando
sob responsabilidade da aplicação a autenticação e autorização de
seus usuários, bem como, o mapeamento para recursos do Bossa.
Associado à cada tarefa ativa (ítem de trabalho) estão os
identificadores de caso e de tarefa. O Bossa não armazena outras
informações sobre um ítem de trabalho e não sabe como efetivamente
executá-lo. Especialmente, não há informação
relevante para a execução do ítem de trabalho, nem é o Bossa que
executa qualquer lógica de negócio associada ao ítem de trabalho
ou faz a persistência de sua execução. A aplicação é responsável
por estas atividades, usando as melhores ferramentas disponíveis,
escolhendo o que fazer com os dados do ítem de trabalho e, uma vez
terminado, notificar o Bossa de sua conclusão.
O comportamento esperado de uma aplicação que usa o Bossa deveria
ser algo como: a aplicação cria uma instância do Bossa e registra
os tipos de caso e recursos se necessário. Após essa
inicialização, a aplicação recebe e autentica seus usuários como
desejado, então pergunta ao Bossa quais são os ítens de trabalho
disponíveis para o usuário, a aplicação escolhe entre os possíveis
ítens de trabalho (possivelmente perguntando ao usuário) e informa
o Bossa que o usuário vai executá-lo. Somente a aplicação sabe
como ajudar o usuário na realização do ítem de trabalho e, uma vez
concluído (ou cancelado), a aplicação notifica o Bossa do evento,
atribuindo valores a variáveis do caso se necessário.
Neste artigo nós explicamos a filosofia por trás do Bossa e demos
uma breve descrição de como modelar workflows usando redes de
Petri e como integrar a máquina de workflow Bossa em uma
aplicação.
O projeto Bossa ainda é novo e nós ainda não provemos documentação
tão aprofundada quanto gostaríamos. No momento, além desse
documento, a melhor fonte de informação é o API
HOWTO, a completa documentação da
API do Bossa e o próprio código fonte (especialmente os
testes e exemplos).