segunda-feira, 23 de março de 2009

Integrando Drools (Rules Engine) e Groovy ao jBPM

Uma das coisas mais comuns quando você cria processos de negócio, é não ter certeza total sobre todas as nuances do processo a ser criado. Isso significa que, a medida que você cria e/ou melhora processos, a duvida sobre "será que eu fecho todas as possibilidades" ainda existe ao decorrer do processo de automação.

O que isso significa? que você nã
o está tão capacidado a criar processos de negócio? que você não capturou adequadamente a essência do problema? Não há razões lógicas para se torturar com estas perguntas, pois, com o passar dos anos e a prática de BPM em algumas empresas, percebi que isso é comum. Ninguem, mesmo um especialista no negócio, está isento de qualquer evento que altere a forma de como o processo deve se comportar quanto ao negócio. Processos são organismos vivos, eles mudam constantemente e são movidos a estímulos externos.

A forma mais interessante de lidar com esta questão, é estar preparado qua
nto a mudanças. Se você projetar aplicações pensando em mudanças, você lidará com elas de uma forma muito mais rápida e eficaz. Da mesma forma, você deve lidar com processos de negócio.

Através do princípio básico da mudança, sempre que usei o jBPM em meus projetos, criei diversas soluções diverentes e um tanto quanto "mirabolantes" para contorna
r os desafios da mudança. Ao vender soluções de BPM, você não deve garantir que seus processos serão eficientes e mapeados adequadamente, isso é mentira. Você deve vender que seus processos, quando corretamente realizados, irão reagir a mudanças com muito mais facilidade e menor impacto. Com esta filosofia em mente, criei diversas soluções para o jBPM que providenciavam este comportamento.

Dentre as diversas soluções que criei, destaco as que dão origem a este post: A integração do jBPM com mecanismos de regras e scripts. Observando algumas coisas nos meus primeiros projetos com jBPM, vi que o uso de ActionHandlers (e todas as suas aplicações ex: DecisionHandlers) são pouco eficientes quanto a mudança. Isso se deve porque, mesmo que seja um técnico ao começar um processo de negócio, será uma pessoa normal que o mudará quando a mudança ocorrer pois neste momento, o projeto já estará entregue, e a pessoa que criou e manteve o processo, já terá abandonado o barco. Além disso, nenhuma empresa gosta de idéia de pagar
Change-Requests sobre processos, pois o que foi vendido, é que a filosofia de BPM torna mudanças mais simples e baratas. Quem vende soluções de BPM e SOA, deve tomar muito cuidado com o que diz no inicio de um projeto ou demanda, porque no final dele(a), você será cobrado disso.

Imagine portanto, uma pessoa de uma empresa, abrindo o Eclipse (ou outra ferramenta Java), configurando o classpath do mesmo para questões de Java, alterando a classe que implementa a interface ActionHandler, e acima de tudo isso, pondo as alterações de volta pra funcionar, o que implica em questões de deployment, configuração de XML's, classLoading, etc. Pelo menos aqui em Belo Horizonte, este tipo de cenário é inconcebível. Acredito que t
odos concordamos com isso.

Mas como lidar com isso? Eu particularmente, tenho o hábito de estudar num processo, que tipo de mudança o processo deve esperar. Felizmente, eu não sou nenhum super-analista BPM pra saber de todas as situações, elas são facilmente identificadas com algumas horas de debate. Exemplos clássicos de coisas que mudam num processo, usando o jarguão do jBPM são:

- O fluxo das atividades (Nodes) quanto as transições
- O processamento dos dados dentro de uma atividade
- As opções de transição de uma decisão
- O processamento de dados dentro de uma transição
- A atividade inicial de uma fase (Super State)
- Os manipuladores de exceção de um dado processo


Para contornar estes casos, criei ao longo do tempo um conjunto de mecanismos que tornam estas tarefas simples e baratas de manter, usando pra isso, as tecnologias de engine de regras e scripts como apoio a isso. Neste post, irei falar um pouco sobre esta solução que criei.

Usando Drools como mecanismo de processamento de dados

Se formos olhar atentemente sobre as vantagens da solução Drools da JBoss, iremos ver claramente que uma delas é: A capacidade de manter fracamente acoplado os dados de uma aplicação, e suas regras de negócio. No contexto de um processo de negócio, isso também se aplica. Neste caso, se você optar por realizar o processamento dos seus dados usando Drools, você estará criando uma forma em que a regra poderá ser mantida em alteração no projeto
da aplicação, ou processo de negócio.

Para atender a este requisito no contexto do jBPM, criei um ActionHandler genérico que pode, através de Drools, fazer com que os dados de contexto de um processo do jBPM sejam executados dentro de uma Agenda do Drools. A listagem abaixo mostra como este handler é aplicado, dentro de um processo jPDL.


A listagem abaixo mostra os arquivos de regras mencionados no processo de negócio, os arquivos salaryRules.drl e productRules.drl respectivamente.




Usando Drools para flexibilizar decisões dentro de um processo de negócio

Usando a mesma metáfora arquitetural, criei também um handler específico para lidar com questões de decisão dentro do jBPM. Em verdade, este deve ser um recurso até mais interessante do que o processamento de dados usando Drools. Isso se dá porque decisões são complexas de mapear, e temos um receio grande sobre as possibilidades que damos a uma decisão.

Neste caso, observe o modelo do processo de negócio abaixo:


Na decisão, temos duas possibilidades: Ir para a opção A ou para a opção B. Dois grandes fatores podem mudar ai com frequência. Uma é a regra sobre a escolha, fato este que deve mudar com grande frequência. Outra coisa é a inserção de novas possibilidades, o que acarretará na mudança tanto do processo (gerando uma nova versão deste) quanto da própria regra. A mudança do processo é simples, tendo em vista que no jPDL ele nada mais é do que um XML. Mas e as regras?

Para este cenário, pode ser aplicado o decision handler personalizado baseado em Drools que criei, como mostrado na listagem abaixo:


Abaixo, segue a listagem das regras de decisão (o arquivo decisionUsingDrools.drl) usados no processo de negócio mostrado acima.


Usando Groovy para flexibilizar decisões dentro de um processo de negócio

Usando o mesmo racíocinio do mecanismo de decisão baseado em Drools, criei também um mecanismo semelhante, só que baseado em Groovy. O Funcionamento é o mesmo, a diferença é que é fornecido um arquivo Groovy ao invés de um arquivo de regras do Drools. Observa o processo de negócio abaixo:


Para satisfazer as regras de decisão usando Groovy, segue a listagem do arquivo Groovy (o arquivo decisionUsingGroovy.groovy) usado no processo de negócio.


E como meus dados podem ser trabalhados via Drools ou Groovy?

Uma dúvida que você talvez tenha, é como, seja via Groovy ou Drools, você manipula os dados de um processo. Para os handlers, isso é bem simples. Antes de executar efetivamente as regras, independente de qual mecanismo for (Groovy, Drools, etc) os dados que estão no escopo do seu processo são transferidos para estes automaticamente. Neste caso, baste que você adicione variáveis ao processo usando a construção padrão do jBPM, o recurso org.jbpm.context.exe.ContextInstance.

Neste caso, se você adicionar uma ou mais variáveis no contexto do seu processo, estas serão transferidas para o recurso de processamento. Caso seja Groovy, eles serão transferidos via bindings, caso seja Drools, eles serão inseridos no WorkingMemory antes de disparar as regras, e com a segurança de que estes serão removidos depois que as regras forem executadas, usando o recurso de FactHandle, garantindo assim, que as referências usadas não serão "viciadas".

Percebi nos arquivos de regras do Drools, que nenhuma importação é feita. E ai?

Usando estes handlers automáticos, você não precisa se preocupar em fazer adequadamente todos os imports em seus arquivos de regras. Como os fatos são passados para o working memory automaticamente, durante este processo a engine interna dos handlers valida se no arquivo das regras, as importações referentes ao fatos inseridos (no caso do jBPM, as variáveis de contexto) foram feitas. Caso ele detecte que não, ele mesmo insere no arquivo da regra a declaração de cada importação de classe.

Este é um processo caro em termos de desempenho, assim como a leitura do arquivo de regras. Para evitar problemas de desempenho, existe a propriedade ruleReload. Setando esta propriedade como false, você instrui o handler a fazer uma cache da regra, tornando a segunda execução da mesma extremamente mais rápida. Note que é feito o cache somente da regra em si (Working Memory) mas não dos fatos. A cada execução, os fatos são passados para a agenda novamente. Caso os fatos processados pela regra mudem com frequência, é importante configurar a propriedade ruleReload para true.

E como posso ter acesso a estes handlers?

Como disse antes, todos estes recursos são reflexos de "engenhocas" que usei em meus projetos baseados em jBPM. Tenho uma solução bem grande rodando num cliente de construção civil com performance invejável e com o OK dos mantenedores das regras (pessoas não técnicas) que o processo de mudança é realmente simples, dado o uso do recurso.

Como não criei estas coisas pensando em compartilhar no contexto open-source, pois foram frutos de horas de projeto e/ou consultorias pagos pelos meus clientes, estou portando gradativamente tais recursos para compor uma solução open-source chamada de BPM Tools. Estou fazendo isso porque a idéia original de tais soluções pertence aos meus clientes, seria desonesto e anti ético da minha parte simplesmente por o código open-source. Por isso, o trabalho de portar para uma solução totalmente nova e desconectada do contexto dos clientes.

Assim que eu tiver portado completamente, eu porei no source-forge sob a licença LGPL, por hora, tenho alguns releases (que chamo-os de beta) comigo, trata-se de um arquivo JAR de apenas 8KB. Claro, as demais dependências para que o recurso funcione, as coisas do Drools e/ou Groovy respectivamente, são muito maiores.

Boas melhorías de processo ;)

1 comentários:

Ruiz disse...

Ricardo,

Muito interessante o seu post. Gostei bastante do modo simples como você aborda as soluções. Estou começando agora com jBPM e tenho muito interesse em usar Drools também.

Ganhou um leitor assíduo!