O desenvolvimento de BPM não é fácil. Isso se deve ao fato de que o processo deve ser legível e compreensível para o cliente, e não apenas correto do ponto de vista técnico.
Nem todas as ferramentas para o desenvolvimento de processos de negócios permitem encontrar um compromisso entre uma descrição clara e a funcionalidade técnica. Muitas ferramentas de desenvolvimento avançadas e descrições de processos geralmente têm mais uma desvantagem: elas são tão legais, poderosas e complexas que, enquanto estavam sendo criadas, as tecnologias deram um grande passo à frente e o desenvolvimento com essa ferramenta se tornou irrelevante.
2018 mudou fundamentalmente nossa abordagem ao desenvolvimento de processos de negócios. Abaixo, é sobre como essa abordagem evoluiu e como mudamos.
Em vez de um prólogo
Nosso departamento está envolvido no desenvolvimento de processos de negócios - do menor ao menor, ao maior e extremamente lucrativo. Até recentemente, usamos um produto da IBM para desenvolvimento, o que nos permite iniciar rapidamente um processo de negócios em funcionamento na produção.
O IBM BPM é uma plataforma poderosa que inclui um rico conjunto de recursos, como uma descrição dos próprios processos, formulários de UI e módulos de integração. Além disso, esta plataforma tem um limite de entrada bastante baixo, o que permite que desenvolvedores iniciantes mergulhem imediatamente no projeto. Mas este produto também tem desvantagens que, se não inibem o desenvolvimento, certamente não contribuem para a velocidade e a qualidade:
- Não há controle de versão são. O IBM BPM simplesmente não fornece a capacidade de armazenar processos (código) corretamente no repositório e usa seu próprio repositório, que não conhece um conceito como mesclagem, por exemplo.
- Desenvolvendo em Java 6. Talvez no momento da redação deste texto, já seja possível desenvolver em Java 7, mas em 2019 isso é um pouco de conforto.
- O IBM BPM está girando no WebSphere, como resultado, os desenvolvedores precisam ter paciência com cada atualização de seu módulo. Além disso, essa é uma dor de cabeça adicional para administradores que periodicamente precisam trazer esse monstro de volta à vida se ele travar.
- O desenvolvimento de módulos de integração no ambiente do Integration Designer, que na verdade é obscurecido não para o melhor Eclipse.
- Não há capacidade normal de teste de unidade.
- O alto custo da plataforma.
Essas deficiências, além da inconveniência puramente técnica do desenvolvimento, criaram outro problema, que talvez seja muito mais sério do que todos os itens acima. Nos dias de Java 12, Kotlin, microsserviços e outras tendências e peças de moda, todas essas nuances desmotivam a equipe. É difícil experimentar a alegria de desenvolver o sempre suspenso Integration Designer para Java 6 em 2019.

Com todas essas limitações, é difícil permanecer à tona. Há pouco menos de um ano, havia uma oferta para experimentar o mecanismo Camunda para descrever os processos de negócios. Para começar, foi selecionado um processo não muito grande, mas bastante importante para registrar terminais para pessoas jurídicas.
Como reescrevemos completamente, quase não havia código antigo, praticamente não nos limitamos a nada e, portanto, escolhemos o Kotlin como a linguagem de desenvolvimento. Foi interessante experimentar este novo idioma, que foi ouvido principalmente por críticas positivas. Em alguns outros projetos em nosso departamento, houve uma experiência de implementação bem-sucedida. A pilha final ficou assim: Camunda, Spring Boot 2, Kotlin, Postgre.
O que é Camunda?

Camunda é uma plataforma de modelagem de processos de negócios de código aberto escrita em Java e que usa Java como linguagem de desenvolvimento. É um conjunto de bibliotecas que permitem executar os processos descritos. Para integrar o Camunda em um projeto, basta adicionar algumas dependências. Para armazenar processos, você pode escolher DBMS persistente ou na memória - dependendo das tarefas. Escolhemos o Postgre, porque a história é importante para nós "debriefing". Por padrão, a plataforma é implantada no H2.
O desenvolvimento consiste em duas partes: criar um processo de fluxo em um utilitário especial do Camunda Modeler e escrever código java que processa as etapas do processo descritas no diagrama. Para chamar o código java do processo, basta implementar a interface JavaDelegate, elevar este Bean (você pode especificar delagate pelo nome completo, mas através do Bean é mais conveniente e flexível) no contexto e especificar seu ID na etapa do processo desejada. Em Kotlin, o delegado parece ainda mais sucinto. A lógica dos delegados é bastante simples: eles subtraíram algo do contexto, realizaram algumas ações e o colocaram de volta ao contexto.
Janela pop-up do Camunda ModelerExemplo de delegado Java:
import org.camunda.bpm.engine.delegate.DelegateExecution; import org.camunda.bpm.engine.delegate.JavaDelegate; public class JavaExampleDelegate implements JavaDelegate { @Override public void execute(DelegateExecution execution) { String someVar = (String) execution.getVariable("someVariable");
Exemplo de delegado Kotlin:
import org.camunda.bpm.engine.delegate.DelegateExecution import org.camunda.bpm.engine.delegate.JavaDelegate class KotlinExampleDelegate: JavaDelegate { override fun execute(execution: DelegateExecution) { val someVar = execution.getVariable("someVariable")
No delegado, você pode descrever a lógica de negócios, a integração e tudo o que seu coração deseja.
Tentamos criar uma camada na forma de um componente de negócios com lógica e usamos o delegado apenas como um link para o fluxo do processo, para que o código e o processo sejam combinados o mínimo possível.
Na maioria dos casos, essa abordagem é conveniente e funciona com sucesso. A interação com o processo ocorre por meio de DelegateExecution, que permite, por exemplo, trabalhar com contexto, incidentes e assim por diante.
É isso que queríamos?
No início, ao escolher uma ferramenta, procurávamos uma solução com os seguintes recursos:
- Recuperação do processo exatamente do local onde ocorreu a falha e é desejável que esteja pronto para uso.
- Alguma GUI onde você pode ver o que acontece com o processo em geral.
- A capacidade de escrever testes de unidade não apenas para lógica e integração, mas também para o próprio processo.
- Java 8 e acima.
- Comunidade desenvolvida.
Camunda está bem com a recuperação e análise de erros.
Um rastreio bem legível, a capacidade de definir o número de tentativas de executar uma etapa antes de cair, um manipulador personalizado ao cair - por exemplo, se durante uma queda queremos alterar o status de alguma entidade para Erro. É fácil fazer o último, implementando DefaultIncidentHandler. É verdade que há um momento engraçado em que esse manipulador funciona: o código de recuperação de erro é acionado toda vez que você entra na etapa do processo. Não posso dizer que isso seja uma superbactéria ou um problema. Em vez disso, você só precisa se lembrar e considerar isso ao desenvolver.
Resolvemos assim:
override fun resolveIncident(context: IncidentContext) { val incidentList = Context.getCommandContext().incidentManager.findIncidentByConfiguration(context.configuration) if (incidentList.isNotEmpty()) {
Camunda tem uma interface gráfica e não é ruim.
Mas se você quiser um pouco mais, por exemplo, a migração de instâncias entre versões de processo, precisará trabalhar duro. A interface do usuário padrão tem apenas uma funcionalidade mínima, mas existe uma API de descanso muito poderosa que permite criar seu próprio painel de administração - legal e sofisticado.
Foi no caminho do nosso painel de administração que seguimos. Nosso arquiteto de processos de negócios em um curto espaço de tempo diminuiu, incluindo as funções de visualizar o histórico de processos já concluídos, migração entre versões e assim por diante.
O descanso de Camunda é realmente poderoso e permite fazer praticamente qualquer coisa com processos. Por exemplo, você pode iniciar um processo usando
/ process-definition / key / aProcessDefinitionKey / start com uma solicitação tão simples:
{ "variables": { "aVariable" : { "value" : "aStringValue", "type": "String" }, "anotherVariable" : { "value" : true, "type": "Boolean" } }, "businessKey" : "myBusinessKey" }
O exemplo é retirado da documentação oficial, que contém uma descrição extensa dos vários casos de uso desta API.
Para testes de unidade, usamos o Junit usual. Além disso, existe uma biblioteca bastante interessante para testar o próprio processo - 'org.camunda.bpm.extension', nome: 'camunda-bpm-assert'. Com ele, você pode descrever testes para verificar o processo de fluxo.
Isso é bastante conveniente, pois geralmente é mais difícil procurar problemas com erros no fluxo do que no código. Tais testes protegem, por exemplo, de refatoração imprecisa e realmente nos ajudaram várias vezes.
A necessidade do Java 8 desapareceu parcialmente, pois o uso do Kotlin em muitos processos eliminou a necessidade do G8. O Kotlin se encaixa muito bem no projeto e permite que você se concentre apenas na escrita da lógica de negócios. É difícil de acreditar, mas basicamente tudo o que Kotlin diz sobre a frieza é verdade. Entidades com um grande número de campos, conhecidas por quase todos os aplicativos com integrações, agora não parecem tão assustadoras, e os mapeamentos entre entidades se tornaram muito mais legíveis. Muitas vezes, a segurança nula criticada realmente funciona e ajuda na maioria dos casos.
A comunidade de Camunda é bastante desenvolvida. Isso é evidenciado pelo fato de que novas bibliotecas no GitHub estão aparecendo constantemente para testes e métricas.
É bom que Camunda se integre perfeitamente ao Spring. Adicione as dependências necessárias, algumas anotações e alguns beans de configuração - na verdade, essa é toda a integração! Como resultado, escrevemos um aplicativo de primavera comum ao qual todos estão acostumados, adicionando o fluxo de um processo de negócios. A interação ocorre através da API Java, que permite manipular processos a partir do código java.
Por exemplo, você pode iniciar o processo com apenas um comando:
runtimeService.startProcessInstanceByKey( "MyTestProcess", "MyBusinessKey", mapOf( "key1" to "value1", "key2" to "value2", ) )
Aqui MyTestProcess é o Id-shnik do processo, não a instância. MyBusinessKey é uma chave exclusiva para uma instância de processo em execução. Geralmente usamos algum valor comercial para esse campo - para uma navegação mais rápida entre instâncias e pesquisa.
Da mesma maneira, você pode ativar um processo "sonolento".
Pontos negativos notáveis ou quaisquer problemas que encontramos, especialmente não podem ser recuperados. Como resultado, por um período bastante curto, acabou sendo um processo completamente funcional e o colocou em produção com segurança. Outros processos estão sendo implementados na plataforma e com bastante sucesso. Agora, na Camunda, lançamos cerca de 15 aplicativos nos quais cerca de 100 mil processos rodam por vez.

Em vez de um epílogo
Aqui estão alguns recursos que foram úteis na implementação da pilha descrita acima. Eu recomendo que você os leia se estiver interessado em informações adicionais sobre o tópico.